83 lines
2.5 KiB
JavaScript
83 lines
2.5 KiB
JavaScript
import { nanoid } from "nanoid";
|
|
import { build } from "esbuild";
|
|
import { mkdir, readFile, rm, writeFile } from "fs/promises";
|
|
import { cwd } from "process";
|
|
import { basename, dirname, join } from "path";
|
|
import h from "vhtml";
|
|
|
|
globalThis.vhtml = h;
|
|
|
|
export default class JsTransformer {
|
|
/**
|
|
* @param {string} inputPath
|
|
* @param {string} outputPath
|
|
*/
|
|
static async build(inputPath, outputPath) {
|
|
outputPath = join(
|
|
dirname(outputPath),
|
|
basename(outputPath, ".s.jsx") + ".html"
|
|
);
|
|
const outfile = join(cwd(), `${nanoid()}.mjs`);
|
|
await mkdir(dirname(outfile), { recursive: true });
|
|
try {
|
|
await build({
|
|
entryPoints: [join(cwd(), inputPath)],
|
|
outfile,
|
|
format: "esm",
|
|
loader: {
|
|
".json": "json",
|
|
},
|
|
|
|
bundle: true,
|
|
platform: "node",
|
|
plugins: [
|
|
{
|
|
name: "svg-jsx",
|
|
setup(build) {
|
|
build.onLoad({ filter: /\.svg$/ }, async (args) => {
|
|
const f = await readFile(args.path, "utf-8");
|
|
const js = `
|
|
export default (props) => {
|
|
let s = \`${f}\`;
|
|
if (props.class)
|
|
s = s.replace("<svg", \`<svg class="\${props.class}"\`);
|
|
return (
|
|
<div
|
|
class={props.containerClass}
|
|
dangerouslySetInnerHTML={{ __html: s }}
|
|
></div>
|
|
);
|
|
};
|
|
`;
|
|
return { contents: js, loader: "jsx" };
|
|
});
|
|
},
|
|
},
|
|
{
|
|
name: "relative-import-path",
|
|
setup(build) {
|
|
build.onResolve({ filter: /./ }, (args) => {
|
|
if (args.path.endsWith(".json") || args.path.endsWith(".svg"))
|
|
return { path: join(args.resolveDir, args.path) };
|
|
else if (args.path.startsWith("."))
|
|
return {
|
|
path: join(args.resolveDir, args.path),
|
|
external: true,
|
|
};
|
|
else return { path: args.path, external: !!args.importer };
|
|
});
|
|
},
|
|
},
|
|
],
|
|
|
|
jsxFactory: "h",
|
|
banner: { js: `const h = globalThis.vhtml;` },
|
|
});
|
|
const file = await import(outfile);
|
|
const html = "<!doctype html>" + (await file.render());
|
|
await writeFile(outputPath, html);
|
|
} finally {
|
|
}
|
|
await rm(outfile);
|
|
}
|
|
}
|