css-mangle-webpack-plugin
Version:
This webpack plugin package is a CSS mangler that globally optimizes and shortens identifier names.
94 lines (81 loc) • 3.5 kB
text/typescript
import { StringUtil } from "../utils/string";
import { Mangler } from "./mangler";
import { ManglerAsset, ManglerAssetType } from "./mangler_asset";
import { ManglerContext } from "./mangler_context";
import { CSSQueryManglerContext } from "./mangler_transpiler";
export abstract class ManglerDeclaration<T = Mangler> {
abstract transform(asset: ManglerAsset, context: ManglerContext<T>): string;
}
export class CSSVariableDeclaration extends ManglerDeclaration {
/**
* Parse a given syntex strings and based on declare identifier
* name to [Mangler].
*/
transform(asset: ManglerAsset, context: ManglerContext<Mangler>): string {
// In CSS variable declarations, a unique syntax is generally used,
// making identification relatively straightforward.
//
// This patterns matched by the following are:
//
// --background: white;
// --rearground: rgb(240, 242, 246);
// --foreground: black;
//
// @property --logo-color { ... }
//
// See Also, where "background" is a unique identifier,
// so any character form is acceptable.
//
const result1 = asset.syntaxText.matchAll(/--[\w-]+(?=\s*: *.+(;|[\n\s]*}))/g);
const result2 = asset.syntaxText.matchAll(/(?<=@property )--[\w-]+(?=\s*{[^{}]*})/g);
const result = [...result1, ...result2];
let replacedLength = 0;
let syntaxText = asset.syntaxText;
for (const global of result) {
const index = global.index + replacedLength;
const mangler = context.parent;
const oldName = global[0];
const newName = mangler.transform(oldName);
const result = StringUtil.replaceRange(
syntaxText,
index,
index + oldName.length,
`--${newName}`
);
replacedLength += StringUtil.replacedLength(syntaxText, result);
syntaxText = result;
}
return syntaxText;
}
}
export class CSSQueryDeclaration extends ManglerDeclaration<CSSQueryManglerContext> {
transform(asset: ManglerAsset, context: ManglerContext<CSSQueryManglerContext>): string {
let syntaxText = asset.syntaxText;
let syntaxType = asset.syntaxType;
if (syntaxType != ManglerAssetType.STYLE) {
return syntaxText;
}
return this.transformStyle(syntaxText, context);
}
transformStyle(syntaxText: string, context: ManglerContext<CSSQueryManglerContext>): string {
const syntaxInst = /[.#][\w-]+(?=[^}]+?{[^]*?})/g;
const syntaxList = syntaxText.matchAll(syntaxInst);
let replacedLength = 0;
for (const global of syntaxList) {
const index = global.index + replacedLength;
const oldName = global[0];
const newName = oldName.startsWith("#")
? "#" + context.parent.idMangler.transform(oldName)
: "." + context.parent.classMangler.transform(oldName);
const result = StringUtil.replaceRange(
syntaxText,
index,
index + oldName.length,
newName
);
replacedLength += StringUtil.replacedLength(syntaxText, result);
syntaxText = result;
}
return syntaxText;
}
}