UNPKG

@virtualstate/examples

Version:
327 lines (325 loc) 12.2 kB
import * as Examples from "./examples/index.js"; import { isVNode, h, Fragment } from "@virtualstate/fringe"; import { dirname, join, relative } from "path"; import { promises as fs } from "fs"; import { getEnv, getExampleNameFromKey, isWantedExampleKey } from "./log.util.js"; import { Static } from "./examples/index.js"; import { readAllDrain } from "./examples/transform/read.js"; import { EngineURLSymbol } from "./examples/compile-transform/source.engine.js"; import { SourceInterfaceURLSymbol } from "./examples/compile-transform/source.transform.js"; // const obs = new PerformanceObserver((items) => { // console.log(items.getEntries()); // performance.clearMarks(); // }); // obs.observe({ entryTypes: ['measure'] }); let finalLog; async function isFile(file) { try { return (await fs.stat(file)).isFile(); } catch { return false; } } async function recreate(node, root, known = new WeakMap(), injectStrings = true) { if (!node.options && !node.children) { if (typeof node.source === "string" && !injectStrings) { return node.source; } const value = getSourceValue(node); if (root) { return value; } return `{${value}}`; } const knownPromise = known.get(node); if (knownPromise) { return knownPromise; } const promise = doRecreate(node, root); known.set(node, promise); return promise; async function doRecreate(node, root) { if (!node.children) { if (root) { return `"No output"`; } return `<${getChildrenHeaderStart(node)} />`; } const parts = []; for await (const children of node.children) { if (parts.length) { console.warn("Expected single iteration static input"); parts.length = 0; } const almost = await Promise.all(children.map(child => { return recreate(child, false, known, injectStrings); })); parts.push(...almost.filter(Boolean)); } if (root) { if (!parts.length) { return `"No output"`; } if (parts.length === 1) { return parts[0].replace(/^{(.+)}$/, "$1"); } return [ "<>", ...parts.map(indent), "</>" ].join("\n"); } if (!parts.length) { return `<${getChildrenHeaderStart(node)} />`; } if (node.reference === Fragment) { return parts.join("\n"); } return [ `<${getChildrenHeaderStart(node)}>`, // indent ...parts.map(indent), `</${getSource(node)}>` ].join("\n"); } function getChildrenHeaderStart(node) { const source = getSource(node); const options = getOptionLines(node); if (options.length > 2) { return [ `${source}`, ...options.map(indent), "" ].join("\n"); } if (options.length) { return `${source} ${options.join(" ")}`; } return `${source}`; } function indent(part) { return part.split("\n").map(line => ` ${line}`).join("\n"); } function getOptionLines(node) { if (!node.options) { return []; } return Object.entries(node.options) .map(([key, value]) => { if (typeof value === "string") { return `${key}=${JSON.stringify(value)}`; } try { return `${key}={${getSourceValue({ reference: "", source: value })}}`; } catch (error) { if (typeof value === "object") { return `${key}={{}}`; } throw error; } }); } function getSource(node) { if (typeof node.source === "function") { return node.source.name; } if (typeof node.source === "string") { return node.source; } if (typeof node.source === "undefined") { return typeof node.reference === "symbol" ? symbol(node.reference) : node.reference.toString(); } if (typeof node.source === "symbol") { return symbol(node.source); } if (typeof node.source === "object") { return ""; } throw new Error(`Unimplemented non scalar source type ${typeof node.source}`); function symbol(value) { const key = Symbol.keyFor(value); if (key) { if (!key.includes(" ")) { return key; } return `Symbol.for(${JSON.stringify(key)})`; } else { const string = String(value); const stringKey = getSymbolKey(value); if (stringKey && !stringKey.includes(" ")) { return stringKey; } return string; } } } function getSymbolKey(symbol) { const string = String(symbol); const matched = string.match(/^Symbol\(([^)]+)\)$/); if (matched && matched[1]) { return matched[1]; } return undefined; } function getSourceValue(node) { if (typeof node.source === "undefined") { return getString(node.reference); } return getString(node.source); function getString(value) { if (typeof value === "string" && !injectStrings) { return value; } if (value instanceof Set) { return `new Set()`; } if (value instanceof Map) { return `new Map()`; } if (typeof value === "function") { return '() => undefined'; } return typeof value === "symbol" ? Symbol.keyFor(value) ? `Symbol.for(${JSON.stringify(Symbol.keyFor(value))})` : `Symbol(${JSON.stringify(getSymbolKey(value))})` : typeof value === "undefined" ? "undefined" : typeof value === "bigint" ? `${value}n` : JSON.stringify(value); } } } async function build(exampleKey) { const id = exampleKey.split("_").find(Boolean); const urlString = Examples[`_${id}_URL`]; if (typeof urlString !== "string") { throw new Error(`${id} has no URL defined`); } const url = new URL(urlString); const output = await fs.readFile(url.pathname, "utf8"); let sourceFile = url.pathname .replace(/(packages\/[^\/]+\/)lib/, "$1src"); const sourceTsxFile = sourceFile.replace(/\.js$/, ".tsx"); if (await isFile(sourceTsxFile)) { sourceFile = sourceTsxFile; } else { sourceFile = sourceFile.replace(/\.js$/, ".ts"); } const source = (await fs.readFile(sourceFile, "utf8")); let cleanerSource = source; const baseCleanerSource = cleanerSource.split("\n"); const infoIndex = baseCleanerSource.findIndex(value => /\d+_(Info|URL) =/.test(value)); if (infoIndex > -1) { cleanerSource = baseCleanerSource.slice(0, infoIndex).join("\n"); } cleanerSource = cleanerSource // Replace any unknown types, for clarity .replace(/: unknown/g, "") .replace(/^export const _[A-Z]*\d+_URL.+$/gm, "") .replace(/^(export const )_[A-Z]*\d+_[A-Z]+( =.+)$/igm, "$1Example$2"); const buildUrl = new URL(import.meta.url); const buildDirectory = dirname(buildUrl.pathname); const targetImport = relative(buildDirectory, url.pathname); const module = await import(`./${targetImport}`); const staticNode = module[`_${id}_IsResolving`] ? module[exampleKey] : (h(Static, null, module[exampleKey])); const looping = exampleKey.includes("Loop"); if (!looping) { await readAllDrain(staticNode); } const info = module[`_${id}_Info`]; const engineURL = hasEngine(info) ? info[EngineURLSymbol] : undefined; const sourceInterfaceURL = hasInterface(info) ? info[SourceInterfaceURLSymbol] : undefined; const engineImport = engineURL ? relative(buildDirectory, new URL(engineURL).pathname) : undefined; const sourceInterface = sourceInterfaceURL && (await fs.readFile(new URL(sourceInterfaceURL).pathname, "utf8")); const nonLoopingStructure = !looping ? await recreate(staticNode, true, new WeakMap(), !exampleKey.includes("HTML")) : undefined; if (nonLoopingStructure && isWantedExampleKey(exampleKey)) { const { EXAMPLES_MATCH: match } = getEnv(); if (match) { finalLog = nonLoopingStructure; } else { console.log(nonLoopingStructure); } } return `export const _${id}_ExampleInformation: ExampleInformation = { name: ${JSON.stringify(getExampleNameFromKey(exampleKey))}, id: ${JSON.stringify(id)}, exportedAs: ${JSON.stringify(exampleKey)}, source: ${JSON.stringify(source)}, sourceURL: ${JSON.stringify(url.toString().replace(process.cwd(), "/workspaces/x"))}, output: ${JSON.stringify(output)}, cleanerSource: ${JSON.stringify(cleanerSource)}, structure: ${looping ? '""' : JSON.stringify(nonLoopingStructure)}, info: ${module[`_${id}_Info`] ? JSON.stringify(module[`_${id}_Info`]) : "undefined"}, engineURL: ${engineURL ? JSON.stringify(engineURL.toString().replace(process.cwd(), "/workspaces/x")) : "undefined"}, sourceInterfaceURL: ${sourceInterfaceURL ? JSON.stringify(sourceInterfaceURL) : "undefined"}, sourceInterface: ${sourceInterface ? JSON.stringify(sourceInterface) : "undefined"}, import: async (context?: Record<string, unknown>, state?: VNode): Promise<VNode> => { ${engineImport ? (` const { Engine, SourceURLSymbol, EngineURLSymbol, SourceSymbol, SourceInterfaceURLSymbol, SourceInterfaceSymbol } = await import("./${engineImport}"); return h( Engine, { ..._${id}_ExampleInformation.info, ...context, [SourceURLSymbol]: _${id}_ExampleInformation.sourceURL, [EngineURLSymbol]: _${id}_ExampleInformation.engineURL, [SourceInterfaceURLSymbol]: _${id}_ExampleInformation.sourceInterfaceURL, [SourceInterfaceSymbol]: _${id}_ExampleInformation.sourceInterface, [SourceSymbol]: _${id}_ExampleInformation.source, }, state );`.trim()) : (process.env.INCLUDE_IMPORT && !/[A-Z]/.test(id) ? ` const module = await import("./${targetImport}"); return module.${exampleKey};`.trim() : `throw new Error("Not available");`)} } }`; function hasEngine(value) { return !!value && typeof value[EngineURLSymbol] === "string"; } function hasInterface(value) { return !!value && typeof value[SourceInterfaceURLSymbol] === "string"; } } const parts = []; for (const exampleKey in Examples) { const example = Examples[exampleKey]; if (!isVNode(example)) continue; const name = getExampleNameFromKey(exampleKey); if (isWantedExampleKey(exampleKey)) { console.log(`Building: ${name}`); } const part = await build(exampleKey); parts.push(part); } const information = ` import { VNode, h, createFragment } from "@virtualstate/fringe"; export interface ExampleInformation { name: string; id: string; exportedAs: string; source: string; sourceURL: string; engineURL?: string; sourceInterfaceURL?: string; sourceInterface?: string; output: string; cleanerSource: string; structure: string; info?: Record<string, unknown>; import?(context?: Record<string, unknown>, state?: VNode): Promise<VNode> } ${parts.join("\n")} `; await fs.writeFile(join(dirname(new URL(import.meta.url).pathname), "../src/information.built.ts"), information); if (finalLog) { console.log(finalLog); } export default 2; export const isBuild = 1; //# sourceMappingURL=build.js.map