147 lines
3.9 KiB
JavaScript
147 lines
3.9 KiB
JavaScript
import fs from "node:fs";
|
|
import camelCase from "camelcase";
|
|
import { outdent } from "outdent";
|
|
|
|
const PLACEHOLDER = "__PLACEHOLDER__";
|
|
function getUmdWrapper({ name }, build) {
|
|
const path = name.split(".");
|
|
const { minify } = build.initialOptions;
|
|
const temporaryName = minify ? "m" : camelCase(name);
|
|
|
|
let globalObjectText = [];
|
|
for (let index = 0; index < path.length; index++) {
|
|
const object = ["root", ...path.slice(0, index + 1)].join(".");
|
|
if (index === path.length - 1) {
|
|
globalObjectText.push(object);
|
|
} else {
|
|
globalObjectText.push(`${object} = ${object} || {};`);
|
|
}
|
|
}
|
|
globalObjectText = globalObjectText
|
|
.map((text) => `${" ".repeat(4)}${text}`)
|
|
.join("\n");
|
|
|
|
let wrapper = outdent`
|
|
(function (factory) {
|
|
function interopModuleDefault() {
|
|
var module = factory();
|
|
return module.default || module;
|
|
}
|
|
|
|
if (typeof exports === "object" && typeof module === "object") {
|
|
module.exports = interopModuleDefault();
|
|
} else if (typeof define === "function" && define.amd) {
|
|
define(interopModuleDefault);
|
|
} else {
|
|
var root =
|
|
typeof globalThis !== "undefined"
|
|
? globalThis
|
|
: typeof global !== "undefined"
|
|
? global
|
|
: typeof self !== "undefined"
|
|
? self
|
|
: this || {};
|
|
${globalObjectText.trimStart()} = interopModuleDefault();
|
|
}
|
|
})(function () {
|
|
"use strict";${PLACEHOLDER}
|
|
});
|
|
`;
|
|
|
|
if (minify) {
|
|
wrapper = build.esbuild
|
|
.transformSync(wrapper, { loader: "js", minify })
|
|
.code.trim();
|
|
if (!wrapper.includes(PLACEHOLDER)) {
|
|
throw new Error("Unexpected code");
|
|
}
|
|
}
|
|
|
|
const [intro, outro] = wrapper.split(PLACEHOLDER);
|
|
|
|
return {
|
|
name: temporaryName,
|
|
intro,
|
|
outro,
|
|
expectedOutput: {
|
|
start: minify
|
|
? `var ${temporaryName}=(()=>{`
|
|
: `var ${temporaryName} = (() => {`,
|
|
end: "})();",
|
|
},
|
|
};
|
|
}
|
|
|
|
export default function esbuildPluginUmd(options) {
|
|
return {
|
|
name: "umd",
|
|
setup(build) {
|
|
const esbuildOptions = build.initialOptions;
|
|
const { globalName, format, outfile } = esbuildOptions;
|
|
|
|
if (globalName) {
|
|
throw new Error("'globalName' in esbuildOptions cannot be set.");
|
|
}
|
|
|
|
if (format !== "umd") {
|
|
throw new Error("'format' esbuildOptions must be 'umd'.");
|
|
}
|
|
|
|
if (!outfile) {
|
|
throw new Error("'outfile' esbuildOptions is required.");
|
|
}
|
|
|
|
const {
|
|
name: temporaryName,
|
|
intro,
|
|
outro,
|
|
expectedOutput,
|
|
} = getUmdWrapper(options, build);
|
|
esbuildOptions.globalName = temporaryName;
|
|
esbuildOptions.format = "iife";
|
|
|
|
build.onEnd((result) => {
|
|
if (result.errors.length > 0) {
|
|
return;
|
|
}
|
|
|
|
if (!fs.existsSync(outfile)) {
|
|
throw new Error(`${outfile} not exists`);
|
|
}
|
|
let text = fs.readFileSync(outfile, "utf8").trim();
|
|
// We already insert `"use strict";` in the wrapper
|
|
if (text.startsWith('"use strict";')) {
|
|
text = text.slice('"use strict";'.length).trimStart();
|
|
}
|
|
|
|
const actualOutput = {
|
|
start: text.slice(0, expectedOutput.start.length),
|
|
end: text.slice(-expectedOutput.end.length),
|
|
};
|
|
for (const property of ["start", "end"]) {
|
|
if (actualOutput[property] !== expectedOutput[property]) {
|
|
console.log();
|
|
console.error(outdent`
|
|
Expected output ${property}s with:
|
|
${expectedOutput[property]}
|
|
|
|
Got:
|
|
${actualOutput[property]}
|
|
`);
|
|
throw new Error("Unexpected output");
|
|
}
|
|
}
|
|
|
|
fs.writeFileSync(
|
|
outfile,
|
|
intro +
|
|
text
|
|
.slice(expectedOutput.start.length, -expectedOutput.end.length)
|
|
.trimEnd() +
|
|
outro,
|
|
);
|
|
});
|
|
},
|
|
};
|
|
}
|