Files
test-repo/scripts/build/esbuild-plugins/umd.js
T

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,
);
});
},
};
}