Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | 2x 38x 38x 38x 33x 33x 24x 24x 38x 38x 38x 34x 34x 33x 23x 23x 23x 21x 29x 24x 33x 32x 5x 4x 30x 4x 4x 7x 7x 1x 6x | import { readFile } from "node:fs/promises";
import path from "node:path";
import {
fromTerserNameCache,
type MangleCache,
readMangleCache,
serializeMangleCache,
toTerserNameCache,
} from "./cache";
import { type ResolvedInput, resolveInputs } from "./inputs";
import { transformJavaScript } from "./transform";
import { type PendingWrite, readMode, writeBatch } from "./write";
export interface MangleOptions {
/** Cache file owned by the consuming project. @default "mangle-cache.json" */
cache?: string;
/** Working directory used to resolve all relative paths. @default process.cwd() */
cwd?: string;
/** Files, directories, or glob patterns. @default ["dist"] */
inputs?: readonly string[];
/** Enable Terser compression and identifier mangling in addition to property mangling. */
minify?: boolean;
/** Write a single input to this file instead of changing it in place. */
outFile?: string;
/** Write inputs beneath this directory instead of changing them in place. */
outDir?: string;
/** Property names matched by this expression are eligible for mangling. @default /[^_]_$/ */
pattern?: RegExp;
/** Property names that must remain unchanged. */
reserved?: readonly string[];
}
export interface MangleFileResult {
input: string;
output: string;
}
export interface MangleResult {
cache: Readonly<MangleCache>;
cachePath: string;
files: readonly MangleFileResult[];
}
const defaultPattern = /[^_]_$/;
export async function mangle(options: MangleOptions = {}): Promise<MangleResult> {
const cwd = path.resolve(options.cwd ?? process.cwd());
const cachePath = path.resolve(cwd, options.cache ?? "mangle-cache.json");
const inputs = await resolveInputs(options.inputs ?? [], cwd);
const outputs = resolveOutputs(inputs, cwd, options);
const sourceCache = await readMangleCache(cachePath);
const nameCache = toTerserNameCache(sourceCache);
const pattern = normalizePattern(options.pattern ?? defaultPattern);
const reserved = [...new Set(options.reserved ?? [])];
const transformed: PendingWrite[] = [];
for (const [index, input] of inputs.entries()) {
const source = await readFile(input.path, "utf8");
const content = await transformJavaScript({
filePath: input.path,
minify: options.minify ?? false,
nameCache,
pattern,
reserved,
source,
});
transformed.push({
content,
mode: await readMode(input.path),
target: outputs[index],
});
}
const cache = fromTerserNameCache(nameCache);
transformed.push({
content: serializeMangleCache(cache),
mode: await readMode(cachePath),
target: cachePath,
});
await writeBatch(transformed);
return {
cache,
cachePath,
files: inputs.map((input, index) => ({ input: input.path, output: outputs[index] })),
};
}
function normalizePattern(pattern: RegExp): RegExp {
return new RegExp(pattern.source, pattern.flags.replace(/[gy]/g, ""));
}
function resolveOutputs(inputs: readonly ResolvedInput[], cwd: string, options: MangleOptions): string[] {
if (options.outFile && options.outDir) throw new Error("outFile and outDir cannot be used together");
if (options.outFile) {
if (inputs.length !== 1) throw new Error("outFile requires exactly one input file");
return [path.resolve(cwd, options.outFile)];
}
if (!options.outDir) return inputs.map((input) => input.path);
const outDir = path.resolve(cwd, options.outDir);
return inputs.map((input) => {
const relativePath = path.relative(input.root, input.path);
if (relativePath.startsWith(`..${path.sep}`)) {
throw new Error(`Cannot preserve ${input.path} beneath output directory ${outDir}`);
}
return path.join(outDir, relativePath);
});
}
export type { MangleCache } from "./cache";
|