feat: static .html fragments

This commit is contained in:
Ayo 2023-10-19 12:07:43 +02:00
parent feea346f73
commit 655debf193
4 changed files with 60 additions and 16 deletions

View file

@ -28,9 +28,9 @@ We want a way to:
- use `<script server:setup>` to define logic that runs on the server, which then gets stripped away
**2. `src/components`**
- custom element constructor class files go here (only `.js` files for now)
- all components are automatically registered using their file names (e.g., a `hello-world.js` component can be used as `<hello-world>` element)
- the idea is, if it is a valid custom element constructor, just throw it in the `components` directory and it will work... vanilla, Lit, Stencil, or our own totally optional [Base Class](https://ayco.io/n/web-component-base) -- your choice!
- custom element constructor files (only `.js` files for now)
- all components are automatically registered using their file names; a `hello-world.js` component can be used as `<hello-world>`
- static `.html` fragments; a `my-header.html` fragment can be directly used as `<my-header>`
## Setting up

View file

@ -2,16 +2,23 @@
* McFly SSR logic
*/
import { ELEMENT_NODE, parse, render, renderSync, walkSync } from "ultrahtml";
import {
Node as UltraNode,
ELEMENT_NODE,
parse,
render,
renderSync,
walkSync,
} from "ultrahtml";
import { parseScript } from "esprima";
import config from "../mcfly.config";
const { components: componentType } = config();
export default eventHandler(async (event) => {
const { path } = event;
let html = await getHtml(path);
const { components: componentType } = config();
// transforms
const transforms = [doSetUp, deleteServerScripts];
if (html) {
@ -20,6 +27,8 @@ export default eventHandler(async (event) => {
}
}
html = await useFragments(html.toString());
if (!!componentType && !!html) {
html = await insertRegistry(html.toString(), componentType);
}
@ -48,9 +57,7 @@ async function insertRegistry(
type: "js" | "ts"
): Promise<string> {
const ast = parse(html);
const componentFiles = (await useStorage().getKeys("assets:components"))
.map((key) => key.replace("assets:components:", ""))
.filter((key) => key.includes(type));
const componentFiles = await getFiles(type);
const availableComponents = componentFiles.map((key) =>
key.replace(`.${type}`, "")
);
@ -193,3 +200,39 @@ function removeComments(script: string) {
});
return script;
}
async function useFragments(html: string) {
const fragmentFiles = await getFiles("html");
const availableFragments = fragmentFiles.map((key) => {
return {
key: key.replace(".html", ""),
text: "",
};
});
const ast = parse(html);
for (const fragment of availableFragments) {
fragment.text = await useStorage().getItem(
"assets:components:" + fragment.key + ".html"
);
}
walkSync(ast, (node) => {
const usedFragment = availableFragments.find(
(fragment) => fragment.key === node.name
);
if (node.type === ELEMENT_NODE && !!usedFragment) {
node.children.push(parse(usedFragment.text));
}
});
return render(ast);
}
async function getFiles(type: string) {
return (await useStorage().getKeys("assets:components"))
.map((key) => key.replace("assets:components:", ""))
.filter((key) => key.includes(type));
}

View file

@ -0,0 +1,6 @@
<header>
<a href="https://ayco.io/gh/mcfly">
<h1>McFly</h1>
</a>
<span>Back to the Basics. Into the Future.</span>
</header>

View file

@ -44,12 +44,7 @@
</style>
</head>
<body>
<header>
<a href="https://ayco.io/gh/mcfly">
<h1>McFly</h1>
</a>
<span>Back to the Basics. Into the Future.</span>
</header>
<awesome-header></awesome-header>
<main>
<p>
<strong>McFly</strong> is a full-stack no-framework framework that assists developers in leveraging the web platform.