From 7b1fc863eff6911a15b8509c676508146b8f3ddf Mon Sep 17 00:00:00 2001 From: Ayo Date: Sat, 14 Oct 2023 23:41:07 +0200 Subject: [PATCH] feat: on-route component registry resolution --- mcfly.config.ts | 3 +- {plugins => packages}/_mcfly-plugin.ts | 0 packages/define-config.ts | 1 + packages/register-components.ts | 46 ------------------- public/favicon.ico | Bin 1150 -> 0 bytes routes/[...index].ts | 61 ++++++++++++++++++++----- src/components/clickable-text.js | 4 +- src/components/hello-world.js | 4 +- src/components/something-else.ts | 1 + 9 files changed, 54 insertions(+), 66 deletions(-) rename {plugins => packages}/_mcfly-plugin.ts (100%) delete mode 100644 packages/register-components.ts delete mode 100644 public/favicon.ico create mode 100644 src/components/something-else.ts diff --git a/mcfly.config.ts b/mcfly.config.ts index a6110d9..54487ef 100644 --- a/mcfly.config.ts +++ b/mcfly.config.ts @@ -1,6 +1,5 @@ import defineConfig from "./packages/define-config"; -// import registerComponents from "./packages/register-components"; export default defineConfig({ - // onBuild: [registerComponents()], + components: "js", }); diff --git a/plugins/_mcfly-plugin.ts b/packages/_mcfly-plugin.ts similarity index 100% rename from plugins/_mcfly-plugin.ts rename to packages/_mcfly-plugin.ts diff --git a/packages/define-config.ts b/packages/define-config.ts index 13532ce..a09ac00 100644 --- a/packages/define-config.ts +++ b/packages/define-config.ts @@ -2,6 +2,7 @@ import { NitroApp } from "nitropack"; export type McFlyConfig = { onBuild?: Array<(event: NitroApp) => void>; + components: "js" | "ts"; }; export default function defineConfig(config: McFlyConfig) { return () => config; diff --git a/packages/register-components.ts b/packages/register-components.ts deleted file mode 100644 index 013d3af..0000000 --- a/packages/register-components.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { existsSync, promises as fsp } from "node:fs"; - -export default function registerComponents() { - return () => { - copyComponents(); - buildRegistry(); - }; -} - -const copyComponents = async () => { - const rawKeys = await useStorage().getKeys("assets:components"); - rawKeys.forEach(async (key) => { - const cleanKey = key.replace("assets:components:", ""); - const content = await useStorage().getItem(key); - if (!existsSync("./public/.output")) await fsp.mkdir("./public/.output"); - await fsp.writeFile(`./public/.output/${cleanKey}`, content.toString()); - }); -}; - -const buildRegistry = async () => { - console.log("Building registry of custom elements..."); - const rawKeys = await useStorage().getKeys("/assets/components"); - const keys = rawKeys.map((key) => key.replace("assets:components:", "")); - console.log("Found components:", keys); - const imports = keys.map((key, index) => { - return `import C${index} from "./${key}"`; - }); - - const registryObject = `const registry = { - ${keys - .map((key, index) => { - const name = key.replace(".js", "").replace(".ts", ""); - return `"${name}": C${index}`; - }) - .join(",")}}`; - - const customElementsDefine = `Object.keys(registry).forEach((key) => {if(window?.hasOwnProperty("customElements"))customElements.define(key, registry[key]);})`; - - if (!existsSync("./public")) await fsp.mkdir("./public"); - if (!existsSync("./public/.output")) await fsp.mkdir("./public/.output"); - - await fsp.writeFile( - "./public/.output/registry.js", - [...imports, registryObject, customElementsDefine].join(";") - ); -}; diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index edb0e4b60d048c92e395d1b447d148ab40376ee0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1150 zcmZQzU<5(|0R|wcz>vYhz#zuJz@P!dKp~(AL>x#lH~{6afd4=-s^f%&g#V^)0a(oi z$;AROK70Q|0lFGipj$ye+dc@d{;~)QusU@8pI+R+DvquW#K#4mzW;{TZkSo0U*Ey7 z3nak6z)6&Tm>YmG2v-04?r9A3V0Pi6K^jioe*@MJVsAQemuR~|W(J81fwaN(GkV20Dv;001`bWIg}@ diff --git a/routes/[...index].ts b/routes/[...index].ts index 25b470b..a3ec3b8 100644 --- a/routes/[...index].ts +++ b/routes/[...index].ts @@ -2,21 +2,28 @@ * McFly SSR logic */ -import { ELEMENT_NODE, parse, renderSync, walkSync } from "ultrahtml"; +import { ELEMENT_NODE, parse, render, renderSync, walkSync } from "ultrahtml"; import { parseScript } from "esprima"; +import config from "../mcfly.config"; export default eventHandler(async (event) => { const { path } = event; let html = await getHtml(path); + const { components: componentType } = config(); + // transforms - const transforms = [doSetUp, deleteServerScripts, insertRegistry]; + const transforms = [doSetUp, deleteServerScripts]; if (html) { for (const transform of transforms) { html = transform(html.toString()); } } + if (!!componentType) { + html = await insertRegistry(html.toString(), componentType); + } + return html ?? new Response("Not found", { status: 404 }); }); @@ -36,30 +43,60 @@ function getPath(filename: string) { return `assets/pages${filename}`; } -function insertRegistry(html: string): string { - // temporary; use ultrahtml later - const registryScript = - ''; - +async function insertRegistry( + html: string, + type: "js" | "ts" +): Promise { const ast = parse(html); + const componentFiles = (await useStorage().getKeys("assets:components")) + .map((key) => key.replace("assets:components:", "")) + .filter((key) => key.includes(type)); + const availableComponents = componentFiles.map((key) => + key.replace(`.${type}`, "") + ); - let hasCustomElements = false; + const usedCustomElements = []; walkSync(ast, (node) => { - if (node.type === ELEMENT_NODE && node.name.includes("-")) { - hasCustomElements = true; + const usedElement = availableComponents.find((name) => name === node.name); + + if (node.type === ELEMENT_NODE && !!usedElement) { + usedCustomElements.push(usedElement); } }); // insert registry script to head - if (hasCustomElements) + if (usedCustomElements.length > 0) { + const registryScript = await buildRegistry(usedCustomElements, type); walkSync(ast, (node) => { if (node.type === ELEMENT_NODE && node.name === "head") { node.children.push(parse(registryScript)); } }); + } - return renderSync(ast); + return render(ast); +} + +async function buildRegistry(usedCustomElements: string[], type: "js" | "ts") { + let registryScript = `"; + + return registryScript; } function doSetUp(html: string) { diff --git a/src/components/clickable-text.js b/src/components/clickable-text.js index 68945ae..4ecda96 100644 --- a/src/components/clickable-text.js +++ b/src/components/clickable-text.js @@ -1,6 +1,4 @@ -import { WebComponent } from "https://unpkg.com/web-component-base@1.6.15/WebComponent.js"; - -export default class ClickableText extends WebComponent { +class ClickableText extends WebComponent { onInit() { this.onclick = () => alert("Thank you for clicking the text!"); } diff --git a/src/components/hello-world.js b/src/components/hello-world.js index 90701de..b309614 100644 --- a/src/components/hello-world.js +++ b/src/components/hello-world.js @@ -1,6 +1,4 @@ -import { WebComponent } from "https://unpkg.com/web-component-base@1.6.15/WebComponent.js"; - -export default class HelloWorld extends WebComponent { +class HelloWorld extends WebComponent { name = ""; static properties = ["name"]; diff --git a/src/components/something-else.ts b/src/components/something-else.ts new file mode 100644 index 0000000..8cc9b1a --- /dev/null +++ b/src/components/something-else.ts @@ -0,0 +1 @@ +const hey = "AYO";