Rewrite build script (#18427)
This commit is contained in:
1 parent
e8e21135ab
commit
f6bd3cbd8a
24 files changed
+990
-975
No files matched your search
+1
-1
@@ -345,6 +345,6 @@
|
||||
"website/static/playground.js",
|
||||
"website/src/css/custom.css",
|
||||
"website/blog/authors.yml",
|
||||
"scripts/build/typescript-unused-specifiers.js"
|
||||
"scripts/build/hacks/typescript-unused-specifiers.js"
|
||||
]
|
||||
}
|
||||
+2
-2
@@ -18,8 +18,8 @@ const config = {
|
||||
],
|
||||
project: ["src/**", "scripts/**"],
|
||||
ignore: [
|
||||
"scripts/build/config.js",
|
||||
"scripts/build/build-javascript-module.js",
|
||||
"scripts/build/packages/*",
|
||||
"scripts/build/builders/javascript-module.js",
|
||||
"scripts/tools/**",
|
||||
"src/experimental-cli/**",
|
||||
"src/universal/*.browser.js",
|
||||
|
||||
@@ -1,185 +0,0 @@
|
||||
import path from "node:path";
|
||||
import {
|
||||
PRODUCTION_MINIMAL_NODE_JS_VERSION,
|
||||
PROJECT_ROOT,
|
||||
readJson,
|
||||
writeJson,
|
||||
} from "../utilities/index.js";
|
||||
|
||||
const keysToKeep = [
|
||||
"name",
|
||||
"version",
|
||||
"description",
|
||||
"bin",
|
||||
"repository",
|
||||
"funding",
|
||||
"homepage",
|
||||
"author",
|
||||
"license",
|
||||
"main",
|
||||
"browser",
|
||||
"unpkg",
|
||||
"exports",
|
||||
"engines",
|
||||
"files",
|
||||
"preferUnplugged",
|
||||
"sideEffects",
|
||||
];
|
||||
|
||||
const publishConfig = {
|
||||
access: "public",
|
||||
registry: "https://registry.npmjs.org/",
|
||||
};
|
||||
|
||||
async function buildPrettierPackageJson({ packageConfig, file }) {
|
||||
const { distDirectory, files } = packageConfig;
|
||||
const packageJson = await readJson(path.join(PROJECT_ROOT, file.input));
|
||||
|
||||
const bin = files.find(
|
||||
(file) =>
|
||||
path.join(PROJECT_ROOT, packageJson.bin) ===
|
||||
path.join(PROJECT_ROOT, file.input),
|
||||
).output.file;
|
||||
|
||||
const overrides = {
|
||||
bin: `./${bin}`,
|
||||
main: "./index.cjs",
|
||||
engines: {
|
||||
...packageJson.engines,
|
||||
// https://github.com/prettier/prettier/pull/13118#discussion_r922708068
|
||||
// Don't delete, event it's the same in package.json
|
||||
node: `>=${PRODUCTION_MINIMAL_NODE_JS_VERSION}`,
|
||||
},
|
||||
type: "commonjs",
|
||||
exports: {
|
||||
".": {
|
||||
types: "./index.d.ts",
|
||||
require: "./index.cjs",
|
||||
browser: {
|
||||
import: "./standalone.mjs",
|
||||
default: "./standalone.js",
|
||||
},
|
||||
default: "./index.mjs",
|
||||
},
|
||||
"./*": "./*",
|
||||
...Object.fromEntries(
|
||||
files
|
||||
.filter((file) => file.output.format === "umd")
|
||||
.map((file) => {
|
||||
const basename = path.basename(file.output.file, ".js");
|
||||
return [
|
||||
file.isPlugin ? `./plugins/${basename}` : `./${basename}`,
|
||||
{
|
||||
types: `./${file.output.file.replace(/\.js$/u, ".d.ts")}`,
|
||||
// `module-sync` condition can prevent CJS plugins from working: https://github.com/prettier/prettier/issues/17139
|
||||
// Perform a test before re-adding it.
|
||||
require: `./${file.output.file}`,
|
||||
default: `./${file.output.file.replace(/\.js$/u, ".mjs")}`,
|
||||
},
|
||||
];
|
||||
}),
|
||||
),
|
||||
// Legacy entries
|
||||
// TODO: Remove bellow in v4
|
||||
"./esm/standalone.mjs": "./standalone.mjs",
|
||||
...Object.fromEntries(
|
||||
files
|
||||
.filter(
|
||||
(file) =>
|
||||
file.isPlugin &&
|
||||
file.output.format === "umd" &&
|
||||
file.output.file !== "plugins/estree.js",
|
||||
)
|
||||
.flatMap((file) => {
|
||||
let basename = path.basename(file.output.file, ".js");
|
||||
if (basename === "acorn") {
|
||||
basename = "espree";
|
||||
}
|
||||
return [
|
||||
[`./parser-${basename}`, `./${file.output.file}`],
|
||||
[`./parser-${basename}.js`, `./${file.output.file}`],
|
||||
[
|
||||
`./esm/parser-${basename}.mjs`,
|
||||
`./${file.output.file.replace(/\.js$/u, ".mjs")}`,
|
||||
],
|
||||
];
|
||||
}),
|
||||
),
|
||||
},
|
||||
files: files.map(({ output: { file } }) => file).sort(),
|
||||
scripts: {
|
||||
prepublishOnly:
|
||||
"node -e \"assert.equal(require('.').version, require('..').version)\"",
|
||||
},
|
||||
};
|
||||
|
||||
await writeJson(
|
||||
path.join(distDirectory, file.output.file),
|
||||
Object.assign(pick(packageJson, keysToKeep), overrides),
|
||||
);
|
||||
}
|
||||
|
||||
async function buildPluginOxcPackageJson({ packageConfig, file }) {
|
||||
const { distDirectory, files } = packageConfig;
|
||||
const packageJson = await readJson(path.join(PROJECT_ROOT, file.input));
|
||||
const projectPackageJson = await readJson(
|
||||
path.join(PROJECT_ROOT, "package.json"),
|
||||
);
|
||||
|
||||
const overrides = {
|
||||
engines: {
|
||||
...packageJson.engines,
|
||||
// https://github.com/prettier/prettier/pull/13118#discussion_r922708068
|
||||
// Don't delete, event it's the same in package.json
|
||||
node: `>=${PRODUCTION_MINIMAL_NODE_JS_VERSION}`,
|
||||
},
|
||||
// Use `commonjs` since we may provide browser build in future.
|
||||
type: "commonjs",
|
||||
files: files.map(({ output: { file } }) => file).sort(),
|
||||
dependencies: {
|
||||
"oxc-parser": projectPackageJson.dependencies["oxc-parser"],
|
||||
},
|
||||
publishConfig,
|
||||
};
|
||||
|
||||
await writeJson(
|
||||
path.join(distDirectory, file.output.file),
|
||||
Object.assign(pick(packageJson, keysToKeep), overrides),
|
||||
);
|
||||
}
|
||||
|
||||
async function buildPluginHermesPackageJson({ packageConfig, file }) {
|
||||
const { distDirectory, files } = packageConfig;
|
||||
const packageJson = await readJson(path.join(PROJECT_ROOT, file.input));
|
||||
|
||||
const overrides = {
|
||||
engines: {
|
||||
...packageJson.engines,
|
||||
// https://github.com/prettier/prettier/pull/13118#discussion_r922708068
|
||||
// Don't delete, event it's the same in package.json
|
||||
node: `>=${PRODUCTION_MINIMAL_NODE_JS_VERSION}`,
|
||||
},
|
||||
// Use `commonjs` since we may provide browser build in future.
|
||||
type: "commonjs",
|
||||
files: files.map(({ output: { file } }) => file).sort(),
|
||||
publishConfig,
|
||||
};
|
||||
|
||||
await writeJson(
|
||||
path.join(distDirectory, file.output.file),
|
||||
Object.assign(pick(packageJson, keysToKeep), overrides),
|
||||
);
|
||||
}
|
||||
|
||||
function pick(object, keys) {
|
||||
keys = new Set(keys);
|
||||
return Object.fromEntries(
|
||||
Object.entries(object).filter(([key]) => keys.has(key)),
|
||||
);
|
||||
}
|
||||
|
||||
export {
|
||||
buildPluginHermesPackageJson,
|
||||
buildPluginOxcPackageJson,
|
||||
buildPrettierPackageJson,
|
||||
};
|
||||
+25
-31
@@ -3,16 +3,13 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import readline from "node:readline";
|
||||
import createEsmUtils from "esm-utils";
|
||||
import styleText from "node-style-text";
|
||||
import prettyBytes from "pretty-bytes";
|
||||
import prettyMilliseconds from "pretty-ms";
|
||||
import { DIST_DIR } from "../utilities/index.js";
|
||||
import packageConfigs from "./config.js";
|
||||
import { DIST_DIR, PROJECT_ROOT } from "../utilities/index.js";
|
||||
import packageConfigs from "./packages/index.js";
|
||||
import parseArguments from "./parse-arguments.js";
|
||||
|
||||
const { require } = createEsmUtils(import.meta);
|
||||
|
||||
const statusConfig = [
|
||||
{ color: "bgGreen", text: "DONE" },
|
||||
{ color: "bgRed", text: "FAIL" },
|
||||
@@ -47,21 +44,14 @@ const clear = () => {
|
||||
|
||||
async function buildFile({ packageConfig, file, cliOptions, results }) {
|
||||
const { distDirectory } = packageConfig;
|
||||
let displayName = file.output.file;
|
||||
if (
|
||||
(file.platform === "universal" && file.output.format !== "esm") ||
|
||||
(file.output.file.startsWith("index.") && file.output.format !== "esm") ||
|
||||
file.output.file.endsWith(".browser.mjs") ||
|
||||
file.kind === "types"
|
||||
) {
|
||||
displayName = ` ${displayName}`;
|
||||
}
|
||||
const displayName = ` ${file.output}`;
|
||||
const fileAbsolutePath = path.join(distDirectory, file.output);
|
||||
|
||||
process.stdout.write(fitTerminal(displayName));
|
||||
|
||||
if (
|
||||
(cliOptions.files && !cliOptions.files.has(file.output.file)) ||
|
||||
(cliOptions.playground && !file.playground)
|
||||
(cliOptions.playground && !file.playground) ||
|
||||
(cliOptions.files && !cliOptions.files.has(fileAbsolutePath))
|
||||
) {
|
||||
console.log(status.SKIPPED);
|
||||
return;
|
||||
@@ -76,14 +66,12 @@ async function buildFile({ packageConfig, file, cliOptions, results }) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
result ??= {};
|
||||
|
||||
if (result.skipped) {
|
||||
if (result?.skipped) {
|
||||
console.log(status.SKIPPED);
|
||||
return;
|
||||
}
|
||||
|
||||
const outputFile = cliOptions.saveAs ?? file.output.file;
|
||||
const outputFile = cliOptions.saveAs ?? file.output;
|
||||
|
||||
const sizeMessages = [];
|
||||
if (cliOptions.printSize) {
|
||||
@@ -92,9 +80,12 @@ async function buildFile({ packageConfig, file, cliOptions, results }) {
|
||||
}
|
||||
|
||||
if (cliOptions.compareSize) {
|
||||
// TODO: Use `import.meta.resolve` when Node.js support
|
||||
const stablePrettierDirectory = path.dirname(require.resolve("prettier"));
|
||||
const stablePrettierDirectory = path.join(
|
||||
PROJECT_ROOT,
|
||||
`node_modules/${packageConfig.packageName}/`,
|
||||
);
|
||||
const stableVersionFile = path.join(stablePrettierDirectory, outputFile);
|
||||
|
||||
let stableSize;
|
||||
try {
|
||||
({ size: stableSize } = await fs.stat(stableVersionFile));
|
||||
@@ -172,19 +163,22 @@ async function run() {
|
||||
}
|
||||
|
||||
console.log(
|
||||
styleText.inverse`[${index + 1}/${packagesToBuild.length}] Building package '${packageConfig.packageName}'`,
|
||||
styleText.blue`[${index + 1}/${packagesToBuild.length}] Building package '${packageConfig.packageName}'`,
|
||||
);
|
||||
|
||||
const startTime = performance.now();
|
||||
const results = [];
|
||||
for (const file of packageConfig.files) {
|
||||
const result = await buildFile({
|
||||
packageConfig,
|
||||
file,
|
||||
cliOptions,
|
||||
results,
|
||||
});
|
||||
results.push(result);
|
||||
for (const module of packageConfig.modules) {
|
||||
console.log(styleText.gray(module.name));
|
||||
for (const file of module.files) {
|
||||
const result = await buildFile({
|
||||
packageConfig,
|
||||
file,
|
||||
cliOptions,
|
||||
results,
|
||||
});
|
||||
results.push(result);
|
||||
}
|
||||
}
|
||||
console.log(
|
||||
`Build package '${packageConfig.packageName}' success in ${prettyMilliseconds(performance.now() - startTime)}`,
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import path from "node:path";
|
||||
import { copyFile } from "../../utilities/index.js";
|
||||
|
||||
const copyFileBuilder = ({ packageConfig, file }) =>
|
||||
copyFile(
|
||||
path.isAbsolute(file.input)
|
||||
? file.input
|
||||
: path.join(packageConfig.sourceDirectory, file.input),
|
||||
path.join(packageConfig.distDirectory, file.output),
|
||||
);
|
||||
|
||||
export { copyFileBuilder };
|
||||
+32
-27
@@ -2,7 +2,7 @@ import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { outdent } from "outdent";
|
||||
import rollupPluginLicense from "rollup-plugin-license";
|
||||
import { PROJECT_ROOT } from "../utilities/index.js";
|
||||
import { PROJECT_ROOT } from "../../utilities/index.js";
|
||||
|
||||
const separator = `\n${"-".repeat(40)}\n\n`;
|
||||
|
||||
@@ -20,7 +20,7 @@ function getDependencies(results) {
|
||||
modules: Object.fromEntries(
|
||||
results
|
||||
.flatMap((result) =>
|
||||
Object.keys(result.esbuildResult?.metafile.inputs ?? {}),
|
||||
Object.keys(result?.esbuildResult?.metafile.inputs ?? {}),
|
||||
)
|
||||
.map((file) => [file, { renderedLength: 1 }]),
|
||||
),
|
||||
@@ -42,7 +42,7 @@ function getDependencies(results) {
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
function getLicenseText(packageConfig, dependencies) {
|
||||
function getLicenseText(packageConfig, dependencies, packageDisplayName) {
|
||||
dependencies = dependencies.filter(
|
||||
(dependency, index) =>
|
||||
// Exclude self
|
||||
@@ -72,7 +72,7 @@ function getLicenseText(packageConfig, dependencies) {
|
||||
const head = outdent`
|
||||
# Licenses of bundled dependencies
|
||||
|
||||
The published ${packageConfig.packageDisplayName ?? packageConfig.packageName} artifact additionally contains code with the following licenses:
|
||||
The published ${packageDisplayName ?? packageConfig.packageName} artifact additionally contains code with the following licenses:
|
||||
${new Intl.ListFormat("en-US", { type: "conjunction" }).format(licenses)}.
|
||||
`;
|
||||
|
||||
@@ -120,35 +120,40 @@ function getLicenseText(packageConfig, dependencies) {
|
||||
return [head, content].join("\n\n");
|
||||
}
|
||||
|
||||
async function buildDependenciesLicense({
|
||||
packageConfig,
|
||||
file,
|
||||
results,
|
||||
cliOptions,
|
||||
}) {
|
||||
const { distDirectory, files } = packageConfig;
|
||||
function createDependenciesLicenseBuilder({ packageDisplayName }) {
|
||||
return async function buildDependenciesLicense({
|
||||
packageConfig,
|
||||
file,
|
||||
results,
|
||||
cliOptions,
|
||||
}) {
|
||||
const files = packageConfig.modules.flatMap((module) => module.files);
|
||||
const fileName = file.output;
|
||||
|
||||
const fileName = file.output.file;
|
||||
if (files.at(-1) !== file) {
|
||||
throw new Error(`${fileName} should be last file to build.`);
|
||||
}
|
||||
|
||||
if (files.at(-1) !== file) {
|
||||
throw new Error(`${fileName} should be last file to build.`);
|
||||
}
|
||||
const shouldBuildLicense = !cliOptions.files;
|
||||
|
||||
const shouldBuildLicense = !cliOptions.files;
|
||||
if (!shouldBuildLicense) {
|
||||
return { skipped: true };
|
||||
}
|
||||
|
||||
if (!shouldBuildLicense) {
|
||||
return { skipped: true };
|
||||
}
|
||||
const dependencies = getDependencies(results);
|
||||
|
||||
const dependencies = getDependencies(results);
|
||||
if (dependencies.length === 0) {
|
||||
throw new Error("Fail to collect dependencies.");
|
||||
}
|
||||
|
||||
if (dependencies.length === 0) {
|
||||
throw new Error("Fail to collect dependencies.");
|
||||
}
|
||||
const text = getLicenseText(
|
||||
packageConfig,
|
||||
dependencies,
|
||||
packageDisplayName,
|
||||
);
|
||||
|
||||
const text = getLicenseText(packageConfig, dependencies);
|
||||
|
||||
await fs.writeFile(path.join(distDirectory, fileName), text);
|
||||
await fs.writeFile(path.join(packageConfig.distDirectory, fileName), text);
|
||||
};
|
||||
}
|
||||
|
||||
export default buildDependenciesLicense;
|
||||
export { createDependenciesLicenseBuilder };
|
||||
+72
-68
@@ -3,30 +3,23 @@ import url from "node:url";
|
||||
import browserslistToEsbuild from "browserslist-to-esbuild";
|
||||
import esbuild from "esbuild";
|
||||
import createEsmUtils from "esm-utils";
|
||||
import {
|
||||
PRODUCTION_MINIMAL_NODE_JS_VERSION,
|
||||
PROJECT_ROOT,
|
||||
} from "../utilities/index.js";
|
||||
import esbuildPluginAddDefaultExport from "./esbuild-plugins/add-default-export.js";
|
||||
import esbuildPluginEvaluate from "./esbuild-plugins/evaluate.js";
|
||||
import esbuildPluginPrimitiveDefine from "./esbuild-plugins/primitive-define.js";
|
||||
import esbuildPluginReplaceModule from "./esbuild-plugins/replace-module.js";
|
||||
import esbuildPluginShimCommonjsObjects from "./esbuild-plugins/shim-commonjs-objects.js";
|
||||
import esbuildPluginStripNodeProtocol from "./esbuild-plugins/strip-node-protocol.js";
|
||||
import esbuildPluginThrowWarnings from "./esbuild-plugins/throw-warnings.js";
|
||||
import esbuildPluginUmd from "./esbuild-plugins/umd.js";
|
||||
import esbuildPluginVisualizer from "./esbuild-plugins/visualizer.js";
|
||||
import transform from "./transform/index.js";
|
||||
import { getPackageFile } from "./utilities.js";
|
||||
import projectPackageJson from "../../../package.json" with { type: "json" };
|
||||
import { PRODUCTION_MINIMAL_NODE_JS_VERSION } from "../../utilities/index.js";
|
||||
import esbuildPluginAddDefaultExport from "../esbuild-plugins/add-default-export.js";
|
||||
import esbuildPluginEvaluate from "../esbuild-plugins/evaluate.js";
|
||||
import esbuildPluginPrimitiveDefine from "../esbuild-plugins/primitive-define.js";
|
||||
import esbuildPluginReplaceModule from "../esbuild-plugins/replace-module.js";
|
||||
import esbuildPluginShimCommonjsObjects from "../esbuild-plugins/shim-commonjs-objects.js";
|
||||
import esbuildPluginStripNodeProtocol from "../esbuild-plugins/strip-node-protocol.js";
|
||||
import esbuildPluginThrowWarnings from "../esbuild-plugins/throw-warnings.js";
|
||||
import esbuildPluginUmd from "../esbuild-plugins/umd.js";
|
||||
import esbuildPluginVisualizer from "../esbuild-plugins/visualizer.js";
|
||||
import transform from "../transform/index.js";
|
||||
import { getPackageFile } from "../utilities.js";
|
||||
|
||||
const {
|
||||
readJsonSync,
|
||||
require,
|
||||
resolve: importMetaResolve,
|
||||
} = createEsmUtils(import.meta);
|
||||
const packageJson = readJsonSync("../../package.json");
|
||||
const { require, resolve: importMetaResolve } = createEsmUtils(import.meta);
|
||||
|
||||
const universalTarget = browserslistToEsbuild(packageJson.browserslist);
|
||||
const universalTarget = browserslistToEsbuild(projectPackageJson.browserslist);
|
||||
const getRelativePath = (from, to) => {
|
||||
const relativePath = path.posix.relative(path.dirname(`/${from}`), `/${to}`);
|
||||
if (!relativePath.startsWith(".")) {
|
||||
@@ -36,8 +29,8 @@ const getRelativePath = (from, to) => {
|
||||
return relativePath;
|
||||
};
|
||||
|
||||
function getEsbuildOptions({ packageConfig, file, cliOptions }) {
|
||||
const { distDirectory, files } = packageConfig;
|
||||
function getEsbuildOptions({ packageConfig, file, cliOptions, buildOptions }) {
|
||||
const { sourceDirectory, distDirectory } = packageConfig;
|
||||
|
||||
// Save dependencies to file
|
||||
file.dependencies = [];
|
||||
@@ -116,11 +109,11 @@ function getEsbuildOptions({ packageConfig, file, cliOptions }) {
|
||||
];
|
||||
|
||||
const define = {
|
||||
"process.env.PRETTIER_TARGET": file.platform,
|
||||
"process.env.PRETTIER_TARGET": buildOptions.platform,
|
||||
"process.env.NODE_ENV": "production",
|
||||
};
|
||||
|
||||
if (file.platform === "universal") {
|
||||
if (buildOptions.platform === "universal") {
|
||||
// We can't reference `process` in UMD bundles and this is
|
||||
// an undocumented "feature"
|
||||
replaceModule.push({
|
||||
@@ -144,48 +137,48 @@ function getEsbuildOptions({ packageConfig, file, cliOptions }) {
|
||||
define.__dirname = "/prettier-security-dirname-placeholder";
|
||||
}
|
||||
|
||||
if (file.platform === "node") {
|
||||
// External other bundled files
|
||||
replaceModule.push(
|
||||
...files
|
||||
.filter(
|
||||
(bundle) =>
|
||||
bundle.input === "package.json" ||
|
||||
(file.input !== bundle.input && bundle.output.format === "esm"),
|
||||
)
|
||||
.map((bundle) => {
|
||||
let output = bundle.output.file;
|
||||
if (
|
||||
file.output.file === "index.cjs" &&
|
||||
bundle.output.file === "doc.mjs"
|
||||
) {
|
||||
output = "doc.js";
|
||||
}
|
||||
// External other bundled files
|
||||
if (buildOptions.platform === "node") {
|
||||
const files = packageConfig.modules
|
||||
.flatMap((module) => module.files)
|
||||
.filter(
|
||||
(bundle) =>
|
||||
bundle.input === "package.json" ||
|
||||
(file.input &&
|
||||
file.input !== bundle.input &&
|
||||
bundle.output.endsWith(".mjs")),
|
||||
);
|
||||
const replacements = files.map((bundle) => {
|
||||
let { output } = bundle;
|
||||
if (file.output === "index.cjs" && output === "doc.mjs") {
|
||||
output = "doc.js";
|
||||
}
|
||||
|
||||
return {
|
||||
module: path.join(PROJECT_ROOT, bundle.input),
|
||||
external: getRelativePath(file.output.file, output),
|
||||
};
|
||||
}),
|
||||
);
|
||||
return {
|
||||
module: path.join(sourceDirectory, bundle.input),
|
||||
external: getRelativePath(file.output, output),
|
||||
};
|
||||
});
|
||||
replaceModule.push(...replacements);
|
||||
}
|
||||
|
||||
// Current version of `yaml` is not tree-shakable,
|
||||
// but when we update it, we may reduce size,
|
||||
// since the UMD version don't need expose `__parsePrettierYamlConfig`
|
||||
if (file.output.format === "umd" && file.output.file === "plugins/yaml.js") {
|
||||
if (buildOptions.format === "umd" && file.output === "plugins/yaml.js") {
|
||||
replaceModule.push({
|
||||
module: path.join(PROJECT_ROOT, file.input),
|
||||
module: path.join(sourceDirectory, file.input),
|
||||
text: 'export * from "../language-yaml/index.js";',
|
||||
});
|
||||
}
|
||||
|
||||
const { buildOptions } = file;
|
||||
const shouldMinify =
|
||||
cliOptions.minify ?? buildOptions.minify ?? file.platform === "universal";
|
||||
cliOptions.minify ??
|
||||
buildOptions.minify ??
|
||||
buildOptions.platform === "universal";
|
||||
|
||||
const esbuildOptions = {
|
||||
entryPoints: [path.join(PROJECT_ROOT, file.input)],
|
||||
entryPoints: [path.join(sourceDirectory, file.input)],
|
||||
bundle: true,
|
||||
metafile: true,
|
||||
plugins: [
|
||||
@@ -198,8 +191,8 @@ function getEsbuildOptions({ packageConfig, file, cliOptions }) {
|
||||
cliOptions.reports &&
|
||||
esbuildPluginVisualizer({ formats: cliOptions.reports }),
|
||||
esbuildPluginThrowWarnings({
|
||||
allowDynamicRequire: file.platform === "node",
|
||||
allowDynamicImport: file.platform === "node",
|
||||
allowDynamicRequire: buildOptions.platform === "node",
|
||||
allowDynamicImport: buildOptions.platform === "node",
|
||||
allowedWarnings: buildOptions.allowedWarnings,
|
||||
}),
|
||||
buildOptions.addDefaultExport && esbuildPluginAddDefaultExport(),
|
||||
@@ -213,10 +206,11 @@ function getEsbuildOptions({ packageConfig, file, cliOptions }) {
|
||||
...(buildOptions.target ?? [`node${PRODUCTION_MINIMAL_NODE_JS_VERSION}`]),
|
||||
],
|
||||
logLevel: "error",
|
||||
format: file.output.format,
|
||||
outfile: path.join(distDirectory, cliOptions.saveAs ?? file.output.file),
|
||||
format: buildOptions.format,
|
||||
outfile: path.join(distDirectory, cliOptions.saveAs ?? file.output),
|
||||
// https://esbuild.github.io/api/#main-fields
|
||||
mainFields: file.platform === "node" ? ["module", "main"] : undefined,
|
||||
mainFields:
|
||||
buildOptions.platform === "node" ? ["module", "main"] : undefined,
|
||||
supported: {
|
||||
...buildOptions.supported,
|
||||
// https://github.com/evanw/esbuild/issues/3471
|
||||
@@ -231,24 +225,23 @@ function getEsbuildOptions({ packageConfig, file, cliOptions }) {
|
||||
packages: "bundle",
|
||||
};
|
||||
|
||||
if (file.platform === "universal") {
|
||||
if (buildOptions.platform === "universal") {
|
||||
if (!buildOptions.target) {
|
||||
esbuildOptions.target.push(...universalTarget);
|
||||
}
|
||||
|
||||
if (file.output.format === "umd") {
|
||||
if (buildOptions.format === "umd") {
|
||||
esbuildOptions.plugins.push(
|
||||
esbuildPluginUmd({
|
||||
name: file.output.umdVariableName,
|
||||
name: buildOptions.umdVariableName,
|
||||
}),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
esbuildOptions.platform = "node";
|
||||
esbuildOptions.external.push(...files.map((file) => file.output.file));
|
||||
|
||||
// https://github.com/evanw/esbuild/issues/1921
|
||||
if (file.output.format === "esm") {
|
||||
if (buildOptions.format === "esm") {
|
||||
esbuildOptions.plugins.push(esbuildPluginShimCommonjsObjects());
|
||||
}
|
||||
}
|
||||
@@ -256,9 +249,20 @@ function getEsbuildOptions({ packageConfig, file, cliOptions }) {
|
||||
return esbuildOptions;
|
||||
}
|
||||
|
||||
async function runEsbuild(options) {
|
||||
const esbuildOptions = getEsbuildOptions(options);
|
||||
return { esbuildResult: await esbuild.build(esbuildOptions) };
|
||||
function createJavascriptModuleBuilder(buildOptions) {
|
||||
return async function runEsbuild({ packageConfig, file, cliOptions }) {
|
||||
if (typeof buildOptions === "function") {
|
||||
buildOptions = await buildOptions();
|
||||
}
|
||||
|
||||
const esbuildOptions = getEsbuildOptions({
|
||||
packageConfig,
|
||||
file,
|
||||
cliOptions,
|
||||
buildOptions,
|
||||
});
|
||||
return { esbuildResult: await esbuild.build(esbuildOptions) };
|
||||
};
|
||||
}
|
||||
|
||||
export default runEsbuild;
|
||||
export { createJavascriptModuleBuilder };
|
||||
@@ -0,0 +1,86 @@
|
||||
import assert from "node:assert/strict";
|
||||
import path from "node:path";
|
||||
import projectPackageJson from "../../../package.json" with { type: "json" };
|
||||
import {
|
||||
PRODUCTION_MINIMAL_NODE_JS_VERSION,
|
||||
readJson,
|
||||
writeJson,
|
||||
} from "../../utilities/index.js";
|
||||
|
||||
const keysToKeep = [
|
||||
"name",
|
||||
"version",
|
||||
"description",
|
||||
"bin",
|
||||
"repository",
|
||||
"funding",
|
||||
"homepage",
|
||||
"author",
|
||||
"license",
|
||||
"main",
|
||||
"browser",
|
||||
"unpkg",
|
||||
"exports",
|
||||
"engines",
|
||||
"files",
|
||||
"preferUnplugged",
|
||||
"sideEffects",
|
||||
];
|
||||
|
||||
const publishConfig = {
|
||||
access: "public",
|
||||
registry: "https://registry.npmjs.org/",
|
||||
};
|
||||
|
||||
function createPackageJsonBuilder({ process }) {
|
||||
return async function buildPackageJson({ packageConfig, file }) {
|
||||
const { distDirectory, sourceDirectory } = packageConfig;
|
||||
const original = await readJson(path.join(sourceDirectory, file.input));
|
||||
const packageFiles = packageConfig.modules.flatMap(({ files }) => files);
|
||||
|
||||
let packageJson = {
|
||||
...pick(original, keysToKeep),
|
||||
engines: {
|
||||
...original.engines,
|
||||
// https://github.com/prettier/prettier/pull/13118#discussion_r922708068
|
||||
// Don't delete, event it's the same in package.json
|
||||
node: `>=${PRODUCTION_MINIMAL_NODE_JS_VERSION}`,
|
||||
},
|
||||
type: "commonjs",
|
||||
files: packageFiles.map((file) => file.output).sort(),
|
||||
publishConfig,
|
||||
};
|
||||
|
||||
// Rewrite `bin`
|
||||
if (original.bin) {
|
||||
const originalBinFile = path.join(sourceDirectory, original.bin);
|
||||
const bin = packageFiles.find(
|
||||
(file) =>
|
||||
file.input &&
|
||||
path.join(sourceDirectory, file.input) === originalBinFile,
|
||||
).output;
|
||||
|
||||
assert.ok(typeof bin === "string");
|
||||
packageJson.bin = `./${bin}`;
|
||||
}
|
||||
|
||||
if (process) {
|
||||
packageJson = await process(packageJson, {
|
||||
packageConfig,
|
||||
originalPackageJson: original,
|
||||
projectPackageJson,
|
||||
});
|
||||
}
|
||||
|
||||
await writeJson(path.join(distDirectory, file.output), packageJson);
|
||||
};
|
||||
}
|
||||
|
||||
function pick(object, keys) {
|
||||
keys = new Set(keys);
|
||||
return Object.fromEntries(
|
||||
Object.entries(object).filter(([key]) => keys.has(key)),
|
||||
);
|
||||
}
|
||||
|
||||
export { createPackageJsonBuilder };
|
||||
@@ -3,7 +3,7 @@ import path from "node:path";
|
||||
import url from "node:url";
|
||||
import { isValidIdentifier } from "@babel/types";
|
||||
import { outdent } from "outdent";
|
||||
import { PROJECT_ROOT, writeFile } from "../utilities/index.js";
|
||||
import { writeFile } from "../../utilities/index.js";
|
||||
|
||||
async function typesFileBuilder({ packageConfig, file }) {
|
||||
/**
|
||||
@@ -20,10 +20,8 @@ async function typesFileBuilder({ packageConfig, file }) {
|
||||
for (const { from, to } of replacements) {
|
||||
text = text.replaceAll(` from "${from}";`, ` from "${to}";`);
|
||||
}
|
||||
await writeFile(
|
||||
path.join(packageConfig.distDirectory, file.output.file),
|
||||
text,
|
||||
);
|
||||
|
||||
await writeFile(path.join(packageConfig.distDirectory, file.output), text);
|
||||
}
|
||||
|
||||
function toPropertyKey(name) {
|
||||
@@ -32,7 +30,7 @@ function toPropertyKey(name) {
|
||||
|
||||
async function buildPluginTypes({ packageConfig, file: { input, output } }) {
|
||||
const pluginModule = await import(
|
||||
url.pathToFileURL(path.join(PROJECT_ROOT, input))
|
||||
url.pathToFileURL(path.join(packageConfig.sourceDirectory, input))
|
||||
);
|
||||
const plugin = pluginModule.default ?? pluginModule;
|
||||
const parserNames = Object.keys(plugin.parsers ?? {});
|
||||
@@ -55,16 +53,11 @@ async function buildPluginTypes({ packageConfig, file: { input, output } }) {
|
||||
};
|
||||
`;
|
||||
|
||||
await writeFile(
|
||||
path.join(packageConfig.distDirectory, output.file),
|
||||
`${code}\n`,
|
||||
);
|
||||
await writeFile(path.join(packageConfig.distDirectory, output), `${code}\n`);
|
||||
}
|
||||
|
||||
function buildTypes(options) {
|
||||
return options.file.isPlugin
|
||||
? buildPluginTypes(options)
|
||||
: typesFileBuilder(options);
|
||||
function createTypesBuilder({ isPlugin }) {
|
||||
return isPlugin ? buildPluginTypes : typesFileBuilder;
|
||||
}
|
||||
|
||||
export default buildTypes;
|
||||
export { createTypesBuilder };
|
||||
+7
-3
@@ -3,13 +3,12 @@ import { existsSync, promises as fs } from "node:fs";
|
||||
import url from "node:url";
|
||||
import spawn from "nano-spawn";
|
||||
import { outdent } from "outdent";
|
||||
import packageJson from "../../package.json" with { type: "json" };
|
||||
import packageJson from "../../../package.json" with { type: "json" };
|
||||
|
||||
const TEMPORARY_DIRECTORY = new URL("../../../.tmp/", import.meta.url);
|
||||
const DIRECTORY_NAME = "prettier-oxc-wasm-parser";
|
||||
const PACKAGE_NAME = "@oxc-parser/binding-wasm32-wasi";
|
||||
|
||||
const TEMPORARY_DIRECTORY = new URL("../../.tmp/", import.meta.url);
|
||||
|
||||
const runYarn = (command, options) =>
|
||||
spawn("yarn", command.split(" "), options);
|
||||
|
||||
@@ -60,6 +59,11 @@ async function inlineWasmBinary(directory) {
|
||||
${text}
|
||||
`;
|
||||
|
||||
text = text.replaceAll(
|
||||
/new URL\(".*?", import\.meta\.url\)/gu,
|
||||
"{url:undefined}",
|
||||
);
|
||||
|
||||
text = text.replace(
|
||||
"await fetch(__wasmUrl).then((res) => res.arrayBuffer())",
|
||||
`__base64ToArrayBuffer(${JSON.stringify(wasm)})`,
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
import * as path from "node:path";
|
||||
import { outdent } from "outdent";
|
||||
import { PROJECT_ROOT, writeFile } from "../utilities/index.js";
|
||||
import { PROJECT_ROOT, writeFile } from "../../utilities/index.js";
|
||||
|
||||
function esmifyTypescriptEslint(text) {
|
||||
/*
|
||||
+1
-1
@@ -2,7 +2,7 @@ import path from "node:path";
|
||||
import escapeStringRegexp from "escape-string-regexp";
|
||||
import MagicString from "magic-string";
|
||||
import { outdent } from "outdent";
|
||||
import { PROJECT_ROOT, writeFile } from "../utilities/index.js";
|
||||
import { PROJECT_ROOT, writeFile } from "../../utilities/index.js";
|
||||
import UNUSED_SPECIFIERS from "./typescript-unused-specifiers.js";
|
||||
|
||||
function* getModules(text) {
|
||||
-1
@@ -276,7 +276,6 @@ export default new Set([
|
||||
"getCommentRange",
|
||||
"getCommonSourceDirectory",
|
||||
"getCommonSourceDirectoryOfConfig",
|
||||
"getCompilerOptionsDiffValue",
|
||||
"getConditions",
|
||||
"getConfigFileParsingDiagnostics",
|
||||
"getConstantValue",
|
||||
@@ -0,0 +1,140 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { PROJECT_ROOT } from "../../utilities/index.js";
|
||||
import { copyFileBuilder } from "../builders/copy-file.js";
|
||||
import { createDependenciesLicenseBuilder } from "../builders/dependencies-license.js";
|
||||
import { createJavascriptModuleBuilder } from "../builders/javascript-module.js";
|
||||
import { createPackageJsonBuilder } from "../builders/package-json.js";
|
||||
import { createTypesBuilder } from "../builders/types.js";
|
||||
|
||||
const extensions = {
|
||||
esm: ".mjs",
|
||||
umd: ".js",
|
||||
cjs: ".cjs",
|
||||
};
|
||||
|
||||
function createPackageJsonConfig({ "package.json": process }) {
|
||||
return {
|
||||
input: "package.json",
|
||||
output: "package.json",
|
||||
build: createPackageJsonBuilder({ process }),
|
||||
};
|
||||
}
|
||||
|
||||
function createReadmeConfig() {
|
||||
return {
|
||||
input: "README.md",
|
||||
output: "README.md",
|
||||
build: copyFileBuilder,
|
||||
};
|
||||
}
|
||||
|
||||
function createLicenseConfig() {
|
||||
return {
|
||||
input: path.join(PROJECT_ROOT, "LICENSE"),
|
||||
output: "LICENSE",
|
||||
build: copyFileBuilder,
|
||||
};
|
||||
}
|
||||
|
||||
function createThirdPartyNoticeConfig({ packageDisplayName }) {
|
||||
return {
|
||||
output: "THIRD-PARTY-NOTICES.md",
|
||||
build: createDependenciesLicenseBuilder({ packageDisplayName }),
|
||||
};
|
||||
}
|
||||
|
||||
function createPackageMetaFilesConfig(options = {}) {
|
||||
return {
|
||||
name: "Meta files",
|
||||
files: [
|
||||
createPackageJsonConfig,
|
||||
createLicenseConfig,
|
||||
createReadmeConfig,
|
||||
createThirdPartyNoticeConfig,
|
||||
].map((create) => create(options)),
|
||||
};
|
||||
}
|
||||
|
||||
function createTypesConfig({ input, outputBaseName, isPlugin }) {
|
||||
const inputBasename = input.slice(0, -path.extname(input).length);
|
||||
if (!isPlugin) {
|
||||
input = `${inputBasename}.d.ts`;
|
||||
|
||||
if (!fs.existsSync(path.join(PROJECT_ROOT, input))) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
input,
|
||||
output: `${outputBaseName ?? inputBasename}.d.ts`,
|
||||
build: createTypesBuilder({ isPlugin }),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function createNodejsFileConfig(file) {
|
||||
if (typeof file === "string") {
|
||||
file = { input: file };
|
||||
}
|
||||
let { input, output, outputBaseName, ...buildOptions } = file;
|
||||
|
||||
const format = input.endsWith(".cjs") ? "cjs" : "esm";
|
||||
outputBaseName ??= path.basename(input, path.extname(input));
|
||||
|
||||
return [
|
||||
{
|
||||
input,
|
||||
output: `${outputBaseName}${extensions[format]}`,
|
||||
build: createJavascriptModuleBuilder({
|
||||
format,
|
||||
...buildOptions,
|
||||
platform: "node",
|
||||
}),
|
||||
},
|
||||
...createTypesConfig({ input, outputBaseName }),
|
||||
];
|
||||
}
|
||||
|
||||
function createUniversalFileConfig(file) {
|
||||
if (typeof file === "string") {
|
||||
file = { input: file };
|
||||
}
|
||||
let { input, outputBaseName, umdVariableName, ...buildOptions } = file;
|
||||
outputBaseName ??= path.basename(input, path.extname(input));
|
||||
umdVariableName ??= outputBaseName;
|
||||
|
||||
return [
|
||||
...[
|
||||
{
|
||||
format: "esm",
|
||||
file: `${outputBaseName}${extensions.esm}`,
|
||||
},
|
||||
{
|
||||
format: "umd",
|
||||
file: `${outputBaseName}${extensions.umd}`,
|
||||
umdVariableName,
|
||||
},
|
||||
].map((output) => ({
|
||||
input,
|
||||
output: output.file,
|
||||
build: createJavascriptModuleBuilder({
|
||||
platform: "universal",
|
||||
addDefaultExport: output.format === "esm",
|
||||
format: output.format,
|
||||
umdVariableName: output.umdVariableName,
|
||||
...buildOptions,
|
||||
}),
|
||||
})),
|
||||
...createTypesConfig({ input, outputBaseName }),
|
||||
];
|
||||
}
|
||||
|
||||
export {
|
||||
createNodejsFileConfig,
|
||||
createPackageMetaFilesConfig,
|
||||
createTypesConfig,
|
||||
createUniversalFileConfig,
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
import pluginHermesBuildConfig from "./plugin-hermes.js";
|
||||
import pluginOxcBuildConfig from "./plugin-oxc.js";
|
||||
import prettierBuildConfig from "./prettier.js";
|
||||
|
||||
export default [
|
||||
prettierBuildConfig,
|
||||
pluginHermesBuildConfig,
|
||||
pluginOxcBuildConfig,
|
||||
];
|
||||
@@ -0,0 +1,61 @@
|
||||
import path from "node:path";
|
||||
import { DIST_DIR, PACKAGES_DIRECTORY } from "../../utilities/index.js";
|
||||
import { createJavascriptModuleBuilder } from "../builders/javascript-module.js";
|
||||
import { getPackageFile } from "../utilities.js";
|
||||
import {
|
||||
createPackageMetaFilesConfig,
|
||||
createTypesConfig,
|
||||
} from "./config-helpers.js";
|
||||
|
||||
const packageConfig = {
|
||||
packageName: "@prettier/plugin-hermes",
|
||||
sourceDirectory: path.join(PACKAGES_DIRECTORY, "plugin-hermes"),
|
||||
distDirectory: path.join(DIST_DIR, "plugin-hermes"),
|
||||
modules: [],
|
||||
};
|
||||
|
||||
const mainModule = {
|
||||
name: "Entries",
|
||||
files: [
|
||||
{
|
||||
input: "index.js",
|
||||
output: "index.mjs",
|
||||
build: createJavascriptModuleBuilder({
|
||||
platform: "universal",
|
||||
addDefaultExport: true,
|
||||
replaceModule: [
|
||||
{
|
||||
module: getPackageFile("hermes-parser/dist/HermesParser.js"),
|
||||
process(text) {
|
||||
text =
|
||||
'const Buffer = globalThis.Buffer ?? require("buffer/").Buffer;' +
|
||||
text;
|
||||
return text;
|
||||
},
|
||||
},
|
||||
{
|
||||
module: getPackageFile("hermes-parser/dist/HermesParserWASM.js"),
|
||||
process(text) {
|
||||
text = text.replaceAll("process.argv", "[]");
|
||||
text = text.replaceAll('require("fs")', "undefined");
|
||||
text = text.replaceAll('require("path")', "undefined");
|
||||
text =
|
||||
'const Buffer = globalThis.Buffer ?? require("buffer/").Buffer;' +
|
||||
text;
|
||||
|
||||
return text;
|
||||
},
|
||||
},
|
||||
],
|
||||
format: "esm",
|
||||
}),
|
||||
playground: true,
|
||||
},
|
||||
|
||||
...createTypesConfig({ input: "index.js", isPlugin: true }),
|
||||
],
|
||||
};
|
||||
|
||||
packageConfig.modules.push(mainModule, createPackageMetaFilesConfig());
|
||||
|
||||
export default packageConfig;
|
||||
@@ -0,0 +1,72 @@
|
||||
import path from "node:path";
|
||||
import { DIST_DIR, PACKAGES_DIRECTORY } from "../../utilities/index.js";
|
||||
import { createJavascriptModuleBuilder } from "../builders/javascript-module.js";
|
||||
import buildOxcWasmParser from "../hacks/build-oxc-wasm-parser.js";
|
||||
import { getPackageFile } from "../utilities.js";
|
||||
import {
|
||||
createPackageMetaFilesConfig,
|
||||
createTypesConfig,
|
||||
} from "./config-helpers.js";
|
||||
|
||||
const packageConfig = {
|
||||
packageName: "@prettier/plugin-oxc",
|
||||
sourceDirectory: path.join(PACKAGES_DIRECTORY, "plugin-oxc"),
|
||||
distDirectory: path.join(DIST_DIR, "plugin-oxc"),
|
||||
modules: [],
|
||||
};
|
||||
|
||||
const mainModule = {
|
||||
name: "Entries",
|
||||
files: [
|
||||
{
|
||||
input: "index.js",
|
||||
output: "index.mjs",
|
||||
prepare: buildOxcWasmParser,
|
||||
build: createJavascriptModuleBuilder({
|
||||
input: "index.js",
|
||||
output: "index.mjs",
|
||||
format: "esm",
|
||||
platform: "node",
|
||||
external: ["oxc-parser"],
|
||||
addDefaultExport: true,
|
||||
}),
|
||||
},
|
||||
{
|
||||
input: "index.js",
|
||||
output: "index.browser.mjs",
|
||||
build: createJavascriptModuleBuilder(async () => {
|
||||
const { entry } = await buildOxcWasmParser();
|
||||
return {
|
||||
format: "esm",
|
||||
platform: "universal",
|
||||
addDefaultExport: true,
|
||||
replaceModule: [
|
||||
{
|
||||
module: getPackageFile("oxc-parser/src-js/wasm.js"),
|
||||
path: entry,
|
||||
},
|
||||
],
|
||||
allowedWarnings: ["indirect-require", "package.json"],
|
||||
};
|
||||
}),
|
||||
playground: true,
|
||||
},
|
||||
...createTypesConfig({ input: "index.js", isPlugin: true }),
|
||||
],
|
||||
};
|
||||
|
||||
packageConfig.modules.push(
|
||||
mainModule,
|
||||
createPackageMetaFilesConfig({
|
||||
"package.json"(packageJson, { projectPackageJson }) {
|
||||
return {
|
||||
...packageJson,
|
||||
dependencies: {
|
||||
"oxc-parser": projectPackageJson.dependencies["oxc-parser"],
|
||||
},
|
||||
};
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
export default packageConfig;
|
||||
@@ -0,0 +1,72 @@
|
||||
import path from "node:path";
|
||||
|
||||
function generatePackageJson(packageJson, { packageConfig }) {
|
||||
const files = packageConfig.modules.flatMap((module) => module.files);
|
||||
|
||||
return {
|
||||
...packageJson,
|
||||
main: "./index.cjs",
|
||||
exports: {
|
||||
".": {
|
||||
types: "./index.d.ts",
|
||||
require: "./index.cjs",
|
||||
browser: {
|
||||
import: "./standalone.mjs",
|
||||
default: "./standalone.js",
|
||||
},
|
||||
default: "./index.mjs",
|
||||
},
|
||||
"./*": "./*",
|
||||
...Object.fromEntries(
|
||||
files
|
||||
.filter((file) => file.output.endsWith(".js"))
|
||||
.map((file) => {
|
||||
const basename = path.basename(file.output, ".js");
|
||||
const isPlugin = file.output.startsWith("plugins/");
|
||||
return [
|
||||
isPlugin ? `./plugins/${basename}` : `./${basename}`,
|
||||
{
|
||||
types: `./${file.output.replace(/\.js$/u, ".d.ts")}`,
|
||||
// `module-sync` condition can prevent CJS plugins from working: https://github.com/prettier/prettier/issues/17139
|
||||
// Perform a test before re-adding it.
|
||||
require: `./${file.output}`,
|
||||
default: `./${file.output.replace(/\.js$/u, ".mjs")}`,
|
||||
},
|
||||
];
|
||||
}),
|
||||
),
|
||||
// Legacy entries
|
||||
// TODO: Remove bellow in v4
|
||||
"./esm/standalone.mjs": "./standalone.mjs",
|
||||
...Object.fromEntries(
|
||||
files
|
||||
.filter(
|
||||
(file) =>
|
||||
file.output.startsWith("plugins/") &&
|
||||
file.output.endsWith(".js") &&
|
||||
file.output !== "plugins/estree.js",
|
||||
)
|
||||
.flatMap((file) => {
|
||||
let basename = path.basename(file.output, ".js");
|
||||
if (basename === "acorn") {
|
||||
basename = "espree";
|
||||
}
|
||||
return [
|
||||
[`./parser-${basename}`, `./${file.output}`],
|
||||
[`./parser-${basename}.js`, `./${file.output}`],
|
||||
[
|
||||
`./esm/parser-${basename}.mjs`,
|
||||
`./${file.output.replace(/\.js$/u, ".mjs")}`,
|
||||
],
|
||||
];
|
||||
}),
|
||||
),
|
||||
},
|
||||
scripts: {
|
||||
prepublishOnly:
|
||||
"node -e \"assert.equal(require('.').version, require('..').version)\"",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export { generatePackageJson };
|
||||
@@ -1,21 +1,19 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import url from "node:url";
|
||||
import createEsmUtils from "esm-utils";
|
||||
import { outdent } from "outdent";
|
||||
import { copyFile, DIST_DIR, PROJECT_ROOT } from "../utilities/index.js";
|
||||
import buildDependenciesLicense from "./build-dependencies-license.js";
|
||||
import buildJavascriptModule from "./build-javascript-module.js";
|
||||
import buildOxcWasmParser from "./build-oxc-wasm-parser.js";
|
||||
import { DIST_DIR, PROJECT_ROOT } from "../../utilities/index.js";
|
||||
import { createJavascriptModuleBuilder } from "../builders/javascript-module.js";
|
||||
import esmifyTypescriptEslint from "../hacks/esmify-typescript-eslint.js";
|
||||
import modifyTypescriptModule from "../hacks/modify-typescript-module.js";
|
||||
import { getPackageFile } from "../utilities.js";
|
||||
import {
|
||||
buildPluginHermesPackageJson,
|
||||
buildPluginOxcPackageJson,
|
||||
buildPrettierPackageJson,
|
||||
} from "./build-package-json.js";
|
||||
import buildTypes from "./build-types.js";
|
||||
import esmifyTypescriptEslint from "./esmify-typescript-eslint.js";
|
||||
import modifyTypescriptModule from "./modify-typescript-module.js";
|
||||
import { getPackageFile } from "./utilities.js";
|
||||
createNodejsFileConfig,
|
||||
createPackageMetaFilesConfig,
|
||||
createTypesConfig,
|
||||
createUniversalFileConfig,
|
||||
} from "./config-helpers.js";
|
||||
import { generatePackageJson } from "./prettier-package-json.js";
|
||||
|
||||
const {
|
||||
require,
|
||||
@@ -24,56 +22,6 @@ const {
|
||||
} = createEsmUtils(import.meta);
|
||||
const resolveEsmModulePath = (specifier) =>
|
||||
url.fileURLToPath(importMetaResolve(specifier));
|
||||
const copyFileBuilder = ({ packageConfig, file }) =>
|
||||
copyFile(
|
||||
path.join(PROJECT_ROOT, file.input),
|
||||
path.join(packageConfig.distDirectory, file.output.file),
|
||||
);
|
||||
const oxcWasmParser = await buildOxcWasmParser();
|
||||
|
||||
function getTypesFileConfig({ input: jsFileInput, outputBaseName, isPlugin }) {
|
||||
let input = jsFileInput;
|
||||
if (!isPlugin) {
|
||||
input = jsFileInput.replace(/\.[cm]?js$/u, ".d.ts");
|
||||
|
||||
if (!fs.existsSync(path.join(PROJECT_ROOT, input))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
input,
|
||||
output: {
|
||||
file: `${outputBaseName}.d.ts`,
|
||||
},
|
||||
kind: "types",
|
||||
isPlugin,
|
||||
build: buildTypes,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} BuildOptions
|
||||
* @property {object[]?} replaceModule - Module replacements
|
||||
* @property {string[]?} target - ESBuild targets
|
||||
* @property {string[]?} external - array of paths that should not be included in the final bundle
|
||||
* @property {boolean?} minify - disable code minification
|
||||
*
|
||||
* @typedef {Object} Output
|
||||
* @property {"esm" | "umd" | "cjs" | "text" | "json"} format - File format
|
||||
* @property {string} file - path of the output file in the `dist/` folder
|
||||
* @property {string?} umdVariableName - name for the UMD file (for plugins, it'll be `prettierPlugins.${name}`)
|
||||
*
|
||||
* @typedef {Object} File
|
||||
* @property {string} input - input of the file
|
||||
* @property {Output} output - output of the file
|
||||
* @property {"javascript" | "types" | "meta"} kind - file kind
|
||||
* @property {function} build - file generate function
|
||||
* @property {"node" | "universal"} platform - ESBuild platform
|
||||
* @property {BuildOptions} buildOptions - ESBuild options
|
||||
* @property {boolean?} isPlugin - file is a plugin
|
||||
* @property {boolean?} addDefaultExport - add default export to bundle
|
||||
*/
|
||||
|
||||
const extensions = {
|
||||
esm: ".mjs",
|
||||
@@ -81,6 +29,233 @@ const extensions = {
|
||||
cjs: ".cjs",
|
||||
};
|
||||
|
||||
const packageConfig = {
|
||||
packageName: "prettier",
|
||||
sourceDirectory: PROJECT_ROOT,
|
||||
distDirectory: path.join(DIST_DIR, "prettier"),
|
||||
modules: [],
|
||||
};
|
||||
|
||||
const mainModule = {
|
||||
name: "Main",
|
||||
files: [
|
||||
createNodejsFileConfig({
|
||||
input: "src/index.js",
|
||||
replaceModule: [
|
||||
// `editorconfig` use a older version of `semver` and only uses `semver.gte`
|
||||
{
|
||||
module: require.resolve("editorconfig"),
|
||||
find: 'var semver = __importStar(require("semver"));',
|
||||
replacement: outdent`
|
||||
var semver = {
|
||||
gte: require(${JSON.stringify(
|
||||
require.resolve("semver/functions/gte"),
|
||||
)})
|
||||
};
|
||||
`,
|
||||
},
|
||||
{
|
||||
module: require.resolve("n-readlines"),
|
||||
find: "const readBuffer = new Buffer(this.options.readChunk);",
|
||||
replacement:
|
||||
"const readBuffer = Buffer.alloc(this.options.readChunk);",
|
||||
},
|
||||
// `parse-json` use another copy of `@babel/code-frame`
|
||||
{
|
||||
module: require.resolve("@babel/code-frame", {
|
||||
paths: [require.resolve("parse-json")],
|
||||
}),
|
||||
path: require.resolve("@babel/code-frame"),
|
||||
},
|
||||
{
|
||||
module: getPackageFile("json5/dist/index.mjs"),
|
||||
find: "export default lib;",
|
||||
replacement: "export default { parse };",
|
||||
},
|
||||
],
|
||||
addDefaultExport: true,
|
||||
reuseDocModule: true,
|
||||
format: "esm",
|
||||
}),
|
||||
createNodejsFileConfig("src/index.cjs"),
|
||||
createUniversalFileConfig({
|
||||
input: "src/standalone.js",
|
||||
umdVariableName: "prettier",
|
||||
replaceModule: [
|
||||
{
|
||||
module: require.resolve("@babel/code-frame"),
|
||||
process(text) {
|
||||
text = text.replaceAll(
|
||||
"var picocolors = require('picocolors');",
|
||||
"",
|
||||
);
|
||||
text = text.replaceAll("var jsTokens = require('js-tokens');", "");
|
||||
text = text.replaceAll(
|
||||
"var helperValidatorIdentifier = require('@babel/helper-validator-identifier');",
|
||||
"",
|
||||
);
|
||||
|
||||
text = text.replaceAll(
|
||||
/(?<=\n)let tokenize;\n\{\n.*?\n\}(?=\n)/gsu,
|
||||
"",
|
||||
);
|
||||
|
||||
text = text.replaceAll(
|
||||
/(?<=\n)function highlight\(text\) \{\n.*?\n\}(?=\n)/gsu,
|
||||
"function highlight(text) {return text}",
|
||||
);
|
||||
|
||||
text = text.replaceAll(
|
||||
/(?<=\n)function getDefs\(enabled\) \{\n.*?\n\}(?=\n)/gsu,
|
||||
outdent`
|
||||
function getDefs() {
|
||||
return new Proxy({}, {get: () => (text) => text})
|
||||
}
|
||||
`,
|
||||
);
|
||||
|
||||
text = text.replaceAll(
|
||||
"const defsOn = buildDefs(picocolors.createColors(true));",
|
||||
"",
|
||||
);
|
||||
text = text.replaceAll(
|
||||
"const defsOff = buildDefs(picocolors.createColors(false));",
|
||||
"",
|
||||
);
|
||||
|
||||
text = text.replaceAll(
|
||||
"const shouldHighlight = opts.forceColor || isColorSupported() && opts.highlightCode;",
|
||||
"const shouldHighlight = false;",
|
||||
);
|
||||
|
||||
text = text.replaceAll("exports.default = index;", "");
|
||||
text = text.replaceAll("exports.highlight = highlight;", "");
|
||||
|
||||
return text;
|
||||
},
|
||||
},
|
||||
// Smaller size
|
||||
{
|
||||
module: getPackageFile("picocolors/picocolors.browser.js"),
|
||||
path: path.join(dirname, "../shims/colors.js"),
|
||||
},
|
||||
],
|
||||
}),
|
||||
].flat(),
|
||||
};
|
||||
for (const file of mainModule.files) {
|
||||
if (file.output === "standalone.mjs") {
|
||||
file.playground = true;
|
||||
}
|
||||
}
|
||||
|
||||
const cliModule = {
|
||||
name: "CLI",
|
||||
files: [
|
||||
{
|
||||
input: "bin/prettier.cjs",
|
||||
outputBaseName: "bin/prettier",
|
||||
target: ["node0.10"],
|
||||
replaceModule: [
|
||||
{
|
||||
module: path.join(PROJECT_ROOT, "bin/prettier.cjs"),
|
||||
process(text) {
|
||||
text = text.replace(
|
||||
"../src/cli/index.js",
|
||||
"../internal/legacy-cli.mjs",
|
||||
);
|
||||
text = text.replace(
|
||||
"../src/experimental-cli/index.js",
|
||||
"../internal/experimental-cli.mjs",
|
||||
);
|
||||
return text;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
input: "src/cli/index.js",
|
||||
outputBaseName: "internal/legacy-cli",
|
||||
external: ["tinybench"],
|
||||
// TODO: Remove this when we drop support for Node.js v16
|
||||
replaceModule: [
|
||||
{
|
||||
module: resolveEsmModulePath("@cacheable/memory"),
|
||||
process: (text) =>
|
||||
outdent`
|
||||
const structuredClone =
|
||||
globalThis.structuredClone ??
|
||||
((value) => JSON.parse(JSON.stringify(value)));
|
||||
|
||||
${text}
|
||||
`,
|
||||
},
|
||||
],
|
||||
},
|
||||
...[
|
||||
{
|
||||
input: "src/experimental-cli/index.js",
|
||||
outputBaseName: "internal/experimental-cli",
|
||||
replaceModule: [
|
||||
{
|
||||
module: getPackageFile("@prettier/cli/dist/prettier_serial.js"),
|
||||
external: "./experimental-cli-worker.mjs",
|
||||
},
|
||||
{
|
||||
module: getPackageFile("@prettier/cli/dist/prettier_parallel.js"),
|
||||
find: 'new URL("./prettier_serial.js", import.meta.url)',
|
||||
replacement:
|
||||
'new URL("./experimental-cli-worker.mjs", import.meta.url)',
|
||||
},
|
||||
{
|
||||
module: getPackageFile("json5/dist/index.mjs"),
|
||||
find: "export default lib;",
|
||||
replacement: "export default { parse };",
|
||||
},
|
||||
{
|
||||
module: getPackageFile("js-yaml/dist/js-yaml.mjs"),
|
||||
find: "var dump = dumper.dump;",
|
||||
replacement: "var dump;",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
input: "src/experimental-cli/worker.js",
|
||||
outputBaseName: "internal/experimental-cli-worker",
|
||||
},
|
||||
].map(({ input, outputBaseName, replaceModule = [] }) => ({
|
||||
input,
|
||||
outputBaseName,
|
||||
replaceModule: [
|
||||
...replaceModule,
|
||||
{
|
||||
module: getPackageFile("@prettier/cli/dist/constants.js"),
|
||||
path: path.join(
|
||||
PROJECT_ROOT,
|
||||
"src/experimental-cli/constants.evaluate.js",
|
||||
),
|
||||
},
|
||||
...["package.json", "index.mjs"].map((file) => ({
|
||||
module: getPackageFile(`prettier/${file}`),
|
||||
external: `../${file}`,
|
||||
})),
|
||||
],
|
||||
})),
|
||||
].flatMap((file) => createNodejsFileConfig(file)),
|
||||
};
|
||||
|
||||
const docModule = {
|
||||
name: "Doc",
|
||||
files: [
|
||||
createUniversalFileConfig({
|
||||
input: "src/document/public.js",
|
||||
outputBaseName: "doc",
|
||||
umdVariableName: "doc",
|
||||
minify: false,
|
||||
}),
|
||||
].flat(),
|
||||
};
|
||||
|
||||
const pluginFiles = [
|
||||
"src/plugins/estree.js",
|
||||
{
|
||||
@@ -272,7 +447,7 @@ const pluginFiles = [
|
||||
// Only needed if `range`/`loc` in parse options is `false`
|
||||
{
|
||||
module: getPackageFile("debug/src/browser.js"),
|
||||
path: path.join(dirname, "./shims/debug.js"),
|
||||
path: path.join(dirname, "../shims/debug.js"),
|
||||
},
|
||||
{
|
||||
module: require.resolve("ts-api-utils"),
|
||||
@@ -614,521 +789,67 @@ const pluginFiles = [
|
||||
},
|
||||
"src/plugins/html.js",
|
||||
"src/plugins/yaml.js",
|
||||
].map((file) => {
|
||||
];
|
||||
|
||||
function createPluginModule(file) {
|
||||
if (typeof file === "string") {
|
||||
file = { input: file };
|
||||
}
|
||||
|
||||
let { input, umdPropertyName, outputBaseName, ...buildOptions } = file;
|
||||
const { input, ...buildOptions } = file;
|
||||
const { pluginName } = input.match(
|
||||
/\/plugins\/(?<pluginName>.*?)\.js$/u,
|
||||
).groups;
|
||||
|
||||
outputBaseName ??= input.match(/\/plugins\/(?<outputBaseName>.*?)\.js$/u)
|
||||
.groups.outputBaseName;
|
||||
const umdVariableName = `prettierPlugins.${pluginName}`;
|
||||
|
||||
const umdVariableName = `prettierPlugins.${
|
||||
umdPropertyName ?? outputBaseName
|
||||
}`;
|
||||
const files = [
|
||||
{
|
||||
format: "esm",
|
||||
file: `${pluginName}${extensions.esm}`,
|
||||
},
|
||||
{
|
||||
format: "umd",
|
||||
file: `${pluginName}${extensions.umd}`,
|
||||
umdVariableName,
|
||||
},
|
||||
].map((output) => ({
|
||||
input,
|
||||
output: `plugins/${output.file}`,
|
||||
build: createJavascriptModuleBuilder({
|
||||
platform: "universal",
|
||||
addDefaultExport: output.format === "esm",
|
||||
...buildOptions,
|
||||
format: output.format,
|
||||
umdVariableName: output.umdVariableName,
|
||||
}),
|
||||
playground: output.format === "esm",
|
||||
}));
|
||||
|
||||
return {
|
||||
input,
|
||||
outputBaseName: `plugins/${outputBaseName}`,
|
||||
umdVariableName,
|
||||
buildOptions,
|
||||
isPlugin: true,
|
||||
};
|
||||
});
|
||||
|
||||
const nonPluginUniversalFiles = [
|
||||
{
|
||||
input: "src/document/public.js",
|
||||
outputBaseName: "doc",
|
||||
umdVariableName: "doc",
|
||||
minify: false,
|
||||
},
|
||||
{
|
||||
input: "src/standalone.js",
|
||||
umdVariableName: "prettier",
|
||||
replaceModule: [
|
||||
{
|
||||
module: require.resolve("@babel/code-frame"),
|
||||
process(text) {
|
||||
text = text.replaceAll("var picocolors = require('picocolors');", "");
|
||||
text = text.replaceAll("var jsTokens = require('js-tokens');", "");
|
||||
text = text.replaceAll(
|
||||
"var helperValidatorIdentifier = require('@babel/helper-validator-identifier');",
|
||||
"",
|
||||
);
|
||||
|
||||
text = text.replaceAll(
|
||||
/(?<=\n)let tokenize;\n\{\n.*?\n\}(?=\n)/gsu,
|
||||
"",
|
||||
);
|
||||
|
||||
text = text.replaceAll(
|
||||
/(?<=\n)function highlight\(text\) \{\n.*?\n\}(?=\n)/gsu,
|
||||
"function highlight(text) {return text}",
|
||||
);
|
||||
|
||||
text = text.replaceAll(
|
||||
/(?<=\n)function getDefs\(enabled\) \{\n.*?\n\}(?=\n)/gsu,
|
||||
outdent`
|
||||
function getDefs() {
|
||||
return new Proxy({}, {get: () => (text) => text})
|
||||
}
|
||||
`,
|
||||
);
|
||||
|
||||
text = text.replaceAll(
|
||||
"const defsOn = buildDefs(picocolors.createColors(true));",
|
||||
"",
|
||||
);
|
||||
text = text.replaceAll(
|
||||
"const defsOff = buildDefs(picocolors.createColors(false));",
|
||||
"",
|
||||
);
|
||||
|
||||
text = text.replaceAll(
|
||||
"const shouldHighlight = opts.forceColor || isColorSupported() && opts.highlightCode;",
|
||||
"const shouldHighlight = false;",
|
||||
);
|
||||
|
||||
text = text.replaceAll("exports.default = index;", "");
|
||||
text = text.replaceAll("exports.highlight = highlight;", "");
|
||||
|
||||
return text;
|
||||
},
|
||||
},
|
||||
// Smaller size
|
||||
{
|
||||
module: getPackageFile("picocolors/picocolors.browser.js"),
|
||||
path: path.join(dirname, "./shims/colors.js"),
|
||||
},
|
||||
],
|
||||
},
|
||||
].map((file) => {
|
||||
const {
|
||||
input,
|
||||
outputBaseName = path.basename(input, ".js"),
|
||||
umdVariableName,
|
||||
...buildOptions
|
||||
} = file;
|
||||
|
||||
return {
|
||||
input,
|
||||
outputBaseName,
|
||||
umdVariableName,
|
||||
buildOptions,
|
||||
};
|
||||
});
|
||||
|
||||
const universalFiles = [...nonPluginUniversalFiles, ...pluginFiles].flatMap(
|
||||
(file) => {
|
||||
let { input, outputBaseName, umdVariableName, buildOptions, isPlugin } =
|
||||
file;
|
||||
|
||||
outputBaseName ??= path.basename(input);
|
||||
|
||||
return [
|
||||
...[
|
||||
{
|
||||
format: "esm",
|
||||
file: `${outputBaseName}${extensions.esm}`,
|
||||
},
|
||||
{
|
||||
format: "umd",
|
||||
file: `${outputBaseName}${extensions.umd}`,
|
||||
umdVariableName,
|
||||
},
|
||||
].map((output) => ({
|
||||
name: `Plugin[${pluginName}]`,
|
||||
files: [
|
||||
...files,
|
||||
...createTypesConfig({
|
||||
input,
|
||||
output,
|
||||
platform: "universal",
|
||||
buildOptions: {
|
||||
addDefaultExport: output.format === "esm",
|
||||
...buildOptions,
|
||||
},
|
||||
isPlugin,
|
||||
build: buildJavascriptModule,
|
||||
kind: "javascript",
|
||||
playground: output.format === "esm" && outputBaseName !== "doc",
|
||||
})),
|
||||
getTypesFileConfig({ input, outputBaseName, isPlugin }),
|
||||
];
|
||||
},
|
||||
outputBaseName: `plugins/${pluginName}`,
|
||||
isPlugin: true,
|
||||
}),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
const pluginModules = pluginFiles.map((file) => createPluginModule(file));
|
||||
|
||||
packageConfig.modules.push(
|
||||
mainModule,
|
||||
cliModule,
|
||||
docModule,
|
||||
...pluginModules,
|
||||
createPackageMetaFilesConfig({
|
||||
"package.json": generatePackageJson,
|
||||
packageDisplayName: "Prettier",
|
||||
}),
|
||||
);
|
||||
|
||||
const nodejsFiles = [
|
||||
{
|
||||
input: "src/index.js",
|
||||
replaceModule: [
|
||||
// `editorconfig` use a older version of `semver` and only uses `semver.gte`
|
||||
{
|
||||
module: require.resolve("editorconfig"),
|
||||
find: 'var semver = __importStar(require("semver"));',
|
||||
replacement: `
|
||||
var semver = {
|
||||
gte: require(${JSON.stringify(
|
||||
require.resolve("semver/functions/gte"),
|
||||
)})
|
||||
};
|
||||
`,
|
||||
},
|
||||
{
|
||||
module: require.resolve("n-readlines"),
|
||||
find: "const readBuffer = new Buffer(this.options.readChunk);",
|
||||
replacement: "const readBuffer = Buffer.alloc(this.options.readChunk);",
|
||||
},
|
||||
// `parse-json` use another copy of `@babel/code-frame`
|
||||
{
|
||||
module: require.resolve("@babel/code-frame", {
|
||||
paths: [require.resolve("parse-json")],
|
||||
}),
|
||||
path: require.resolve("@babel/code-frame"),
|
||||
},
|
||||
{
|
||||
module: getPackageFile("json5/dist/index.mjs"),
|
||||
find: "export default lib;",
|
||||
replacement: "export default { parse };",
|
||||
},
|
||||
],
|
||||
addDefaultExport: true,
|
||||
reuseDocModule: true,
|
||||
},
|
||||
{
|
||||
input: "src/index.cjs",
|
||||
},
|
||||
{
|
||||
input: "bin/prettier.cjs",
|
||||
outputBaseName: "bin/prettier",
|
||||
target: ["node0.10"],
|
||||
replaceModule: [
|
||||
{
|
||||
module: path.join(PROJECT_ROOT, "bin/prettier.cjs"),
|
||||
process(text) {
|
||||
text = text.replace(
|
||||
"../src/cli/index.js",
|
||||
"../internal/legacy-cli.mjs",
|
||||
);
|
||||
text = text.replace(
|
||||
"../src/experimental-cli/index.js",
|
||||
"../internal/experimental-cli.mjs",
|
||||
);
|
||||
return text;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
input: "src/cli/index.js",
|
||||
outputBaseName: "internal/legacy-cli",
|
||||
external: ["tinybench"],
|
||||
// TODO: Remove this when we drop support for Node.js v16
|
||||
replaceModule: [
|
||||
{
|
||||
module: resolveEsmModulePath("@cacheable/memory"),
|
||||
process: (text) =>
|
||||
outdent`
|
||||
const structuredClone =
|
||||
globalThis.structuredClone ??
|
||||
((value) => JSON.parse(JSON.stringify(value)));
|
||||
|
||||
${text}
|
||||
`,
|
||||
},
|
||||
],
|
||||
},
|
||||
...[
|
||||
{
|
||||
input: "src/experimental-cli/index.js",
|
||||
outputBaseName: "internal/experimental-cli",
|
||||
replaceModule: [
|
||||
{
|
||||
module: getPackageFile("@prettier/cli/dist/prettier_serial.js"),
|
||||
external: "./experimental-cli-worker.mjs",
|
||||
},
|
||||
{
|
||||
module: getPackageFile("@prettier/cli/dist/prettier_parallel.js"),
|
||||
find: 'new URL("./prettier_serial.js", import.meta.url)',
|
||||
replacement:
|
||||
'new URL("./experimental-cli-worker.mjs", import.meta.url)',
|
||||
},
|
||||
{
|
||||
module: getPackageFile("json5/dist/index.mjs"),
|
||||
find: "export default lib;",
|
||||
replacement: "export default { parse };",
|
||||
},
|
||||
{
|
||||
module: getPackageFile("js-yaml/dist/js-yaml.mjs"),
|
||||
find: "var dump = dumper.dump;",
|
||||
replacement: "var dump;",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
input: "src/experimental-cli/worker.js",
|
||||
outputBaseName: "internal/experimental-cli-worker",
|
||||
},
|
||||
].map(({ input, outputBaseName, replaceModule = [] }) => ({
|
||||
input,
|
||||
outputBaseName,
|
||||
replaceModule: [
|
||||
...replaceModule,
|
||||
{
|
||||
module: getPackageFile("@prettier/cli/dist/constants.js"),
|
||||
path: path.join(
|
||||
PROJECT_ROOT,
|
||||
"src/experimental-cli/constants.evaluate.js",
|
||||
),
|
||||
},
|
||||
...["package.json", "index.mjs"].map((file) => ({
|
||||
module: getPackageFile(`prettier/${file}`),
|
||||
external: `../${file}`,
|
||||
})),
|
||||
],
|
||||
})),
|
||||
].flatMap((file) => {
|
||||
let { input, output, outputBaseName, ...buildOptions } = file;
|
||||
|
||||
const format = input.endsWith(".cjs") ? "cjs" : "esm";
|
||||
outputBaseName ??= path.basename(input, path.extname(input));
|
||||
|
||||
return [
|
||||
{
|
||||
input,
|
||||
output: {
|
||||
format,
|
||||
file: `${outputBaseName}${extensions[format]}`,
|
||||
},
|
||||
platform: "node",
|
||||
buildOptions,
|
||||
build: buildJavascriptModule,
|
||||
kind: "javascript",
|
||||
},
|
||||
getTypesFileConfig({ input, outputBaseName }),
|
||||
];
|
||||
});
|
||||
|
||||
const metaFiles = [
|
||||
{
|
||||
input: "package.json",
|
||||
output: {
|
||||
format: "json",
|
||||
},
|
||||
build: buildPrettierPackageJson,
|
||||
},
|
||||
{
|
||||
input: "README.md",
|
||||
build: copyFileBuilder,
|
||||
},
|
||||
{
|
||||
input: "LICENSE",
|
||||
build: copyFileBuilder,
|
||||
},
|
||||
{
|
||||
output: {
|
||||
file: "THIRD-PARTY-NOTICES.md",
|
||||
},
|
||||
build: buildDependenciesLicense,
|
||||
},
|
||||
].map((file) => ({
|
||||
...file,
|
||||
output: { file: file.input, ...file.output },
|
||||
kind: "meta",
|
||||
}));
|
||||
|
||||
/** @type {Files[]} */
|
||||
const files = [...nodejsFiles, ...universalFiles, ...metaFiles].filter(Boolean);
|
||||
export default [
|
||||
{
|
||||
packageName: "prettier",
|
||||
// Used in THIRD-PARTY-NOTICES.md
|
||||
packageDisplayName: "Prettier",
|
||||
distDirectory: path.join(DIST_DIR, "prettier"),
|
||||
files,
|
||||
},
|
||||
{
|
||||
packageName: "@prettier/plugin-oxc",
|
||||
distDirectory: path.join(DIST_DIR, "plugin-oxc"),
|
||||
files: [
|
||||
...[
|
||||
{
|
||||
input: "packages/plugin-oxc/index.js",
|
||||
addDefaultExport: true,
|
||||
},
|
||||
].flatMap((file) => {
|
||||
let { input, output, outputBaseName, ...buildOptions } = file;
|
||||
|
||||
const format = input.endsWith(".cjs") ? "cjs" : "esm";
|
||||
outputBaseName ??= path.basename(input, path.extname(input));
|
||||
|
||||
return [
|
||||
{
|
||||
input,
|
||||
output: {
|
||||
format,
|
||||
file: `${outputBaseName}${extensions[format]}`,
|
||||
},
|
||||
platform: "node",
|
||||
buildOptions: {
|
||||
...buildOptions,
|
||||
external: ["oxc-parser"],
|
||||
},
|
||||
build: buildJavascriptModule,
|
||||
kind: "javascript",
|
||||
},
|
||||
{
|
||||
input,
|
||||
output: {
|
||||
format,
|
||||
file: `${outputBaseName}.browser${extensions[format]}`,
|
||||
},
|
||||
platform: "universal",
|
||||
buildOptions: {
|
||||
...buildOptions,
|
||||
replaceModule: [
|
||||
...(buildOptions.replaceModule ?? []),
|
||||
{
|
||||
module: getPackageFile("oxc-parser/src-js/wasm.js"),
|
||||
path: oxcWasmParser.entry,
|
||||
},
|
||||
],
|
||||
allowedWarnings: ["indirect-require", "package.json"],
|
||||
},
|
||||
build: buildJavascriptModule,
|
||||
kind: "javascript",
|
||||
playground: true,
|
||||
},
|
||||
getTypesFileConfig({ input, outputBaseName, isPlugin: true }),
|
||||
];
|
||||
}),
|
||||
...[
|
||||
{
|
||||
input: "packages/plugin-oxc/package.json",
|
||||
output: {
|
||||
file: "package.json",
|
||||
format: "json",
|
||||
},
|
||||
build: buildPluginOxcPackageJson,
|
||||
},
|
||||
{
|
||||
input: "packages/plugin-oxc/README.md",
|
||||
output: {
|
||||
file: "README.md",
|
||||
},
|
||||
build: copyFileBuilder,
|
||||
},
|
||||
{
|
||||
input: "LICENSE",
|
||||
output: {
|
||||
file: "LICENSE",
|
||||
},
|
||||
build: copyFileBuilder,
|
||||
},
|
||||
{
|
||||
output: {
|
||||
file: "THIRD-PARTY-NOTICES.md",
|
||||
},
|
||||
build: buildDependenciesLicense,
|
||||
},
|
||||
].map((file) => ({
|
||||
...file,
|
||||
output: { file: file.input, ...file.output },
|
||||
kind: "meta",
|
||||
})),
|
||||
],
|
||||
},
|
||||
{
|
||||
packageName: "@prettier/plugin-hermes",
|
||||
distDirectory: path.join(DIST_DIR, "plugin-hermes"),
|
||||
files: [
|
||||
...[
|
||||
{
|
||||
input: "packages/plugin-hermes/index.js",
|
||||
addDefaultExport: true,
|
||||
replaceModule: [
|
||||
{
|
||||
module: require.resolve("hermes-parser/dist/HermesParser.js"),
|
||||
process(text) {
|
||||
text =
|
||||
'const Buffer = globalThis.Buffer ?? require("buffer/").Buffer;' +
|
||||
text;
|
||||
return text;
|
||||
},
|
||||
},
|
||||
{
|
||||
module: require.resolve("hermes-parser/dist/HermesParserWASM.js"),
|
||||
process(text) {
|
||||
text = text.replaceAll("process.argv", "[]");
|
||||
text = text.replaceAll('require("fs")', "undefined");
|
||||
text = text.replaceAll('require("path")', "undefined");
|
||||
text =
|
||||
'const Buffer = globalThis.Buffer ?? require("buffer/").Buffer;' +
|
||||
text;
|
||||
|
||||
return text;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
].flatMap((file) => {
|
||||
let { input, output, outputBaseName, ...buildOptions } = file;
|
||||
|
||||
outputBaseName ??= path.basename(input, path.extname(input));
|
||||
const format = input.endsWith(".cjs") ? "cjs" : "esm";
|
||||
|
||||
return [
|
||||
{
|
||||
input,
|
||||
output: {
|
||||
format,
|
||||
file: `${outputBaseName}${extensions[format]}`,
|
||||
},
|
||||
platform: "universal",
|
||||
buildOptions: {
|
||||
addDefaultExport: true,
|
||||
...buildOptions,
|
||||
},
|
||||
isPlugin: true,
|
||||
build: buildJavascriptModule,
|
||||
playground: true,
|
||||
kind: "javascript",
|
||||
},
|
||||
getTypesFileConfig({ input, outputBaseName, isPlugin: true }),
|
||||
];
|
||||
}),
|
||||
...[
|
||||
{
|
||||
input: "packages/plugin-hermes/package.json",
|
||||
output: {
|
||||
file: "package.json",
|
||||
format: "json",
|
||||
},
|
||||
build: buildPluginHermesPackageJson,
|
||||
},
|
||||
{
|
||||
input: "packages/plugin-hermes/README.md",
|
||||
output: {
|
||||
file: "README.md",
|
||||
},
|
||||
build: copyFileBuilder,
|
||||
},
|
||||
{
|
||||
input: "LICENSE",
|
||||
output: {
|
||||
file: "LICENSE",
|
||||
},
|
||||
build: copyFileBuilder,
|
||||
},
|
||||
{
|
||||
output: {
|
||||
file: "THIRD-PARTY-NOTICES.md",
|
||||
},
|
||||
build: buildDependenciesLicense,
|
||||
},
|
||||
].map((file) => ({
|
||||
...file,
|
||||
output: { file: file.input, ...file.output },
|
||||
kind: "meta",
|
||||
})),
|
||||
],
|
||||
},
|
||||
];
|
||||
export default packageConfig;
|
||||
@@ -25,7 +25,9 @@ function parseArguments() {
|
||||
}
|
||||
|
||||
const result = {
|
||||
files: Array.isArray(values.file) ? new Set(values.file) : undefined,
|
||||
files: Array.isArray(values.file)
|
||||
? new Set(values.file.map((file) => path.join(DIST_DIR, file)))
|
||||
: undefined,
|
||||
playground: values.playground,
|
||||
printSize: values["print-size"],
|
||||
compareSize: values["compare-size"],
|
||||
|
||||
@@ -2,27 +2,36 @@ import assert from "node:assert";
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import eslintPluginCompat from "eslint-plugin-compat";
|
||||
import buildConfig from "./build/config.js";
|
||||
import packageBuildConfigs from "./build/packages/index.js";
|
||||
import { DIST_DIR } from "./utilities/index.js";
|
||||
|
||||
const { browserslist: targets } = JSON.parse(
|
||||
await fs.readFile(new URL("../package.json", import.meta.url)),
|
||||
);
|
||||
|
||||
function getProductionFiles(platform) {
|
||||
return buildConfig
|
||||
.flatMap((project) =>
|
||||
project.files
|
||||
.filter(
|
||||
(file) => file.kind === "javascript" && file.platform === platform,
|
||||
)
|
||||
.map((file) => path.join(project.distDirectory, file.output.file)),
|
||||
)
|
||||
.map((file) => path.relative(DIST_DIR, file).replaceAll("\\", "/"));
|
||||
}
|
||||
const jsFiles = packageBuildConfigs
|
||||
.flatMap((packageConfig) =>
|
||||
packageConfig.modules.flatMap((module) =>
|
||||
module.files
|
||||
.filter((file) => /\.[cm]?js$/u.test(file.output))
|
||||
.map((file) => path.join(packageConfig.distDirectory, file.output)),
|
||||
),
|
||||
)
|
||||
.map((file) => path.relative(DIST_DIR, file).replaceAll("\\", "/"));
|
||||
|
||||
const browserFiles = getProductionFiles("universal");
|
||||
const nodejsFiles = getProductionFiles("node");
|
||||
const nodejsFiles = jsFiles.filter(
|
||||
(file) =>
|
||||
file.endsWith(".cjs") ||
|
||||
[
|
||||
"prettier/index.mjs",
|
||||
"prettier/internal/legacy-cli.mjs",
|
||||
"prettier/internal/experimental-cli.mjs",
|
||||
"prettier/internal/experimental-cli-worker.mjs",
|
||||
"plugin-oxc/index.mjs",
|
||||
].includes(file),
|
||||
);
|
||||
|
||||
const browserFiles = jsFiles.filter((file) => !nodejsFiles.includes(file));
|
||||
|
||||
assert.ok(browserFiles.length > 0);
|
||||
assert.ok(nodejsFiles.length > 0);
|
||||
|
||||
@@ -4,8 +4,8 @@ import * as importMetaResolve from "import-meta-resolve";
|
||||
import { outdent } from "outdent";
|
||||
import * as prettier from "prettier";
|
||||
import * as typescript from "typescript";
|
||||
import { modifyTypescriptModule } from "./build/modify-typescript-module.js";
|
||||
import UNUSED_SPECIFIERS from "./build/typescript-unused-specifiers.js";
|
||||
import { modifyTypescriptModule } from "./build/hacks/modify-typescript-module.js";
|
||||
import UNUSED_SPECIFIERS from "./build/hacks/typescript-unused-specifiers.js";
|
||||
|
||||
async function getRemovedSpecifiers(code, exports) {
|
||||
let errors = [];
|
||||
@@ -47,7 +47,7 @@ async function main() {
|
||||
.sort();
|
||||
|
||||
await fs.writeFile(
|
||||
new URL("./build/typescript-unused-specifiers.js", import.meta.url),
|
||||
new URL("./build/hacks/typescript-unused-specifiers.js", import.meta.url),
|
||||
await prettier.format(
|
||||
outdent`
|
||||
export default new Set(${JSON.stringify(specifiers, undefined, 2)});
|
||||
|
||||
@@ -2,7 +2,7 @@ import { createRequire } from "node:module";
|
||||
import path from "node:path";
|
||||
import url from "node:url";
|
||||
import webpack from "webpack";
|
||||
import packageConfigs from "../../build/config.js";
|
||||
import packageBuildConfigs from "../../build/packages/index.js";
|
||||
|
||||
function runWebpack(config) {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -29,60 +29,73 @@ const TEMPORARY_DIRECTORY = url.fileURLToPath(
|
||||
new URL("./.tmp", import.meta.url),
|
||||
);
|
||||
|
||||
for (const packageConfig of packageConfigs) {
|
||||
const { packageName, distDirectory, files } = packageConfig;
|
||||
// Node.js only files
|
||||
const exclude = new Map([
|
||||
[
|
||||
"prettier",
|
||||
[
|
||||
"index.mjs",
|
||||
"internal/legacy-cli.mjs",
|
||||
"internal/experimental-cli.mjs",
|
||||
"internal/experimental-cli-worker.mjs",
|
||||
],
|
||||
],
|
||||
["@prettier/plugin-oxc", ["index.mjs"]],
|
||||
]);
|
||||
|
||||
if (packageName === "@prettier/plugin-oxc") {
|
||||
continue;
|
||||
}
|
||||
for (const packageConfig of packageBuildConfigs) {
|
||||
const { packageName, distDirectory, modules } = packageConfig;
|
||||
const excludedFiles = new Set(exclude.get(packageName));
|
||||
|
||||
/* `require` in `parser-typescript.js`, #12338 */
|
||||
for (const file of files) {
|
||||
if (file.platform !== "universal") {
|
||||
continue;
|
||||
}
|
||||
console.log(`${file.output.file}: `);
|
||||
|
||||
const stats = await runWebpack({
|
||||
mode: "production",
|
||||
entry: path.join(distDirectory, file.output.file),
|
||||
output: {
|
||||
path: TEMPORARY_DIRECTORY,
|
||||
filename: `${file.output.file}.[contenthash:7].${
|
||||
file.output.format === "esm" ? "mjs" : "cjs"
|
||||
}`,
|
||||
},
|
||||
performance: { hints: false },
|
||||
optimization: { minimize: false },
|
||||
});
|
||||
const result = stats.toJson();
|
||||
const { warnings, assets } = result;
|
||||
|
||||
if (warnings.length > 0) {
|
||||
console.log(warnings);
|
||||
throw new Error("Unexpected webpack warning.");
|
||||
}
|
||||
|
||||
if (assets.length > 1) {
|
||||
console.log(assets);
|
||||
throw new Error("Unexpected assets.");
|
||||
}
|
||||
|
||||
const outputFileName = assets[0].name;
|
||||
const outputFile = path.join(TEMPORARY_DIRECTORY, outputFileName);
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
try {
|
||||
if (file.output.format !== "esm") {
|
||||
require(outputFile);
|
||||
} else {
|
||||
await import(url.pathToFileURL(outputFile));
|
||||
for (const module of modules) {
|
||||
for (const file of module.files) {
|
||||
if (!/\.m?js$/u.test(file.output) || excludedFiles.has(file.output)) {
|
||||
continue;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`'${outputFileName}' is not functional.`);
|
||||
throw error;
|
||||
}
|
||||
console.log(`${file.output}: `);
|
||||
|
||||
console.log(" Passed.");
|
||||
const stats = await runWebpack({
|
||||
mode: "production",
|
||||
entry: path.join(distDirectory, file.output),
|
||||
output: {
|
||||
path: TEMPORARY_DIRECTORY,
|
||||
filename: `${file.output}.[contenthash:7].${
|
||||
file.output.endsWith(".mjs") ? "mjs" : "cjs"
|
||||
}`,
|
||||
},
|
||||
performance: { hints: false },
|
||||
optimization: { minimize: false },
|
||||
});
|
||||
const result = stats.toJson();
|
||||
const { warnings, assets } = result;
|
||||
|
||||
if (warnings.length > 0) {
|
||||
console.log(warnings);
|
||||
throw new Error("Unexpected webpack warning.");
|
||||
}
|
||||
|
||||
if (assets.length > 1) {
|
||||
console.log(assets);
|
||||
throw new Error("Unexpected assets.");
|
||||
}
|
||||
|
||||
const outputFileName = assets[0].name;
|
||||
const outputFile = path.join(TEMPORARY_DIRECTORY, outputFileName);
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
try {
|
||||
if (file.output.endsWith(".mjs")) {
|
||||
await import(url.pathToFileURL(outputFile));
|
||||
} else {
|
||||
require(outputFile);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`'${outputFileName}' is not functional.`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
console.log(" Passed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,15 +36,19 @@ const PROJECT_ROOT = url.fileURLToPath(new URL("../../", import.meta.url));
|
||||
const DIST_DIR = path.join(PROJECT_ROOT, "dist");
|
||||
const WEBSITE_DIR = path.join(PROJECT_ROOT, "website");
|
||||
const SOURCE_DIR = path.join(PROJECT_ROOT, "src");
|
||||
const TEMPORARY_DIRECTORY = path.join(PROJECT_ROOT, ".tmp");
|
||||
const PACKAGES_DIRECTORY = path.join(PROJECT_ROOT, "packages");
|
||||
const PRODUCTION_MINIMAL_NODE_JS_VERSION = "14";
|
||||
|
||||
export {
|
||||
copyFile,
|
||||
DIST_DIR,
|
||||
PACKAGES_DIRECTORY,
|
||||
PRODUCTION_MINIMAL_NODE_JS_VERSION,
|
||||
PROJECT_ROOT,
|
||||
readJson,
|
||||
SOURCE_DIR,
|
||||
TEMPORARY_DIRECTORY,
|
||||
WEBSITE_DIR,
|
||||
writeFile,
|
||||
writeJson,
|
||||
|
||||
Reference in new issue
Block a user