UNPKG

@virtualstate/app-history

Version:

Native JavaScript [app-history](https://github.com/WICG/app-history) implementation

133 lines (107 loc) 4.28 kB
import { createServer } from "http"; import { resolve, dirname, join } from "path"; import * as Cheerio from "cheerio"; import { promises as fs } from "fs"; const namespacePath = "/node_modules/wpt"; const buildPath = "/esnext"; const resourcesInput = "/resources"; const resourcesTarget = "/node_modules/wpt/resources"; export function startServer(port: number) { const server = createServer( (request, response) => { const url = new URL(request.url, `http://localhost:${port}`); let promise = Promise.resolve(""); response.setHeader("Access-Control-Allow-Origin", "*"); console.log({ pathname: url.pathname }); if (url.pathname.endsWith(".html.js")) { promise = createJavaScriptBundle(url); response.setHeader("Content-Type", "application/javascript"); } promise .then(contents => { response.writeHead(200); response.write(contents); }) .catch((error) => { console.log({ error }); response.writeHead(500); }) .then(() => response.end()) } ); server.listen(port, () => { console.log(`Running Web Platform Tests ECMAScript Modules server on port ${port}`) }) return () => { } } export async function createJavaScriptBundle(url: URL) { const cwd = resolve(dirname(new URL(import.meta.url).pathname), "../.."); const withoutExtension = url.pathname.replace(/\.html\.js$/, ""); console.log({ cwd, withoutExtension }); if (withoutExtension.includes(".")) throw new Error("Unexpected dot in path"); const htmlPath = join(cwd, namespacePath, `${withoutExtension}.html`); console.log({ cwd, withoutExtension, htmlPath }); const html = await fs.readFile(htmlPath, "utf-8"); if (!html) return ""; const $ = Cheerio.load(html); const dependencies = await Promise.all( $("script[src]") .map(function () { return $(this).attr("src") }) .toArray() .filter(dependency => url.searchParams.get("localDependenciesOnly") ? !dependency.startsWith("/") : true) .map(async (dependency): Promise<[string, string]> => [ dependency, await fs.readFile(join(cwd, namespacePath, new URL(dependency, url.toString()).pathname), "utf-8").catch(() => "// Could not load") ]) ); const dependenciesJoined = ` // const self = globalThis; ${dependencies .map(([name, contents]) => `// ${name.replace(cwd, "")}\n${contents}`) .join("\n")} `; const scripts = $("script:not([src])") .map(function () { return $(this).html() ?? "" }) .toArray(); let scriptsJoined = scripts.join('\n'); if (url.searchParams.get("preferUndefined")) { // eek scriptsJoined = scriptsJoined.replace(/null/g, "undefined"); } let fnName = url.searchParams.get("exportAs"); // https://stackoverflow.com/a/2008353/1174869 const identifierTest = /^[$A-Z_][0-9A-Z_$]*$/i; if (!fnName || !identifierTest.test(fnName)) { fnName = "runTests"; } let globalNames = (url.searchParams.get("globals") ?? "") .split(",") .filter(name => identifierTest.test(name)); if (!globalNames.length) { globalNames = ["______globals_object_key"] } const globalsDestructure = `{${globalNames.join(", ")}}`; const scriptHarness = ` export function ${fnName}(${globalsDestructure}) {${url.searchParams.get("debugger") ? "\nconsole.log('debugger start');debugger;\n" : ""} ${scriptsJoined} } `.trim(); if (url.searchParams.get("dependenciesOnly")) { return dependenciesJoined; } if (url.searchParams.get("scriptsOnly")) { return scriptHarness; } return `${dependenciesJoined}\n${scriptHarness}`; } if (typeof process !== "undefined" && process.argv.includes(new URL(import.meta.url).pathname)) { const portString = process.env.PORT || ''; const port = /^\d+$/.test(portString) ? +portString : 3000; void startServer(port); }