esbuild-pilet-plugin
Version:
Plugin for transforming pilets.
125 lines (121 loc) • 4.53 kB
JavaScript
// src/index.ts
import { transformFileAsync } from "@babel/core";
import { promises } from "fs";
import { resolve, basename } from "path";
// src/importmap-plugin.ts
import { stringLiteral } from "@babel/types";
function babelPlugin(importmap) {
return {
visitor: {
ImportDeclaration(path) {
path.traverse({
Literal(path2) {
if (path2.node.type === "StringLiteral") {
const name = path2.node.value;
const entry = importmap.find((m) => m.name === name);
if (entry) {
path2.replaceWith(stringLiteral(entry.requireId || entry.id));
}
}
}
});
}
}
};
}
// src/banner-plugin.ts
import template from "@babel/template";
function babelPlugin2(name, importmap, requireRef, schema, cssFiles) {
const debug = process.env.NODE_ENV === "development";
return {
visitor: {
Program(path) {
const deps = importmap.reduce((obj, dep) => {
obj[dep.id] = dep.ref;
return obj;
}, {});
if (schema === "v2") {
path.addComment("leading", `@pilet v:2(${requireRef},${JSON.stringify(deps)})`, true);
if (cssFiles.length > 0) {
const bundleUrl = `function(){try{throw new Error}catch(t){const e=(""+t.stack).match(/(https?|file|ftp|chrome-extension|moz-extension):\\/\\/[^)\\n]+/g);if(e)return e[0].replace(/^((?:https?|file|ftp|chrome-extension|moz-extension):\\/\\/.+)\\/[^\\/]+$/,"$1")+"/"}return"/"}`;
const stylesheet = [
`var d=document`,
`var __bundleUrl__=(${bundleUrl})()`,
`${JSON.stringify(cssFiles)}.forEach(cf=>{`,
`var u=__bundleUrl__+cf`,
`var e=d.createElement("link")`,
`e.setAttribute('data-origin', ${JSON.stringify(name)})`,
`e.type="text/css"`,
`e.rel="stylesheet"`,
`e.href=${debug ? 'u+"?_="+Math.random()' : "u"}`,
`d.head.appendChild(e)`,
`})`
].join(";\n");
path.node.body.push(template.ast(`(function(){${stylesheet}})()`));
}
} else if (schema === "v3") {
path.addComment("leading", `@pilet v:3(${requireRef},${JSON.stringify(deps)})`, true);
if (cssFiles.length > 0) {
path.node.body.push(template.ast(`export const styles = ${JSON.stringify(cssFiles)};`));
}
}
}
}
};
}
// src/index.ts
var piletPlugin = (options) => ({
name: "pilet-plugin",
setup(build) {
build.initialOptions.metafile = true;
build.onEnd(async (result) => {
const root = process.cwd();
if (result.metafile) {
const { outputs } = result.metafile;
const { entryPoints } = build.initialOptions;
const [name] = Object.keys(entryPoints);
const entryModule = resolve(root, entryPoints[name]);
const cssFiles = Object.keys(outputs).filter((m) => m.endsWith(".css")).map((m) => basename(m));
await Promise.all(
Object.keys(outputs).filter((m) => m.endsWith(".js")).map(async (file) => {
const { entryPoint } = outputs[file];
const isEntryModule = entryPoint && resolve(root, entryPoint) === entryModule;
const path = resolve(root, file);
const smname = `${file}.map`;
const smpath = resolve(root, smname);
const sourceMaps = smname in outputs;
const inputSourceMap = sourceMaps ? JSON.parse(await promises.readFile(smpath, "utf8")) : void 0;
const plugins = [babelPlugin(options.importmap)];
if (isEntryModule) {
plugins.push(
babelPlugin2(options.name, options.importmap, options.requireRef, options.schema, cssFiles)
);
}
const { code, map } = await transformFileAsync(path, {
sourceMaps,
inputSourceMap,
comments: isEntryModule,
plugins,
presets: [
[
"@babel/preset-env",
{
modules: "systemjs"
}
]
]
});
if (map) {
await promises.writeFile(smpath, JSON.stringify(map), "utf8");
}
await promises.writeFile(path, code, "utf8");
})
);
}
});
}
});
export {
piletPlugin
};
//# sourceMappingURL=index.mjs.map