@tailwindcss-mangle/core 4.0.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,462 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/index.ts
32
+ var src_exports = {};
33
+ __export(src_exports, {
34
+ ClassGenerator: () => shared_exports.ClassGenerator,
35
+ Context: () => Context,
36
+ cssHandler: () => cssHandler,
37
+ handleValue: () => handleValue,
38
+ htmlHandler: () => htmlHandler,
39
+ jsHandler: () => jsHandler
40
+ });
41
+ module.exports = __toCommonJS(src_exports);
42
+
43
+ // src/css/index.ts
44
+ var import_postcss = __toESM(require("postcss"), 1);
45
+
46
+ // ../../node_modules/.pnpm/defu@6.1.4/node_modules/defu/dist/defu.mjs
47
+ function isPlainObject(value) {
48
+ if (value === null || typeof value !== "object") {
49
+ return false;
50
+ }
51
+ const prototype = Object.getPrototypeOf(value);
52
+ if (prototype !== null && prototype !== Object.prototype && Object.getPrototypeOf(prototype) !== null) {
53
+ return false;
54
+ }
55
+ if (Symbol.iterator in value) {
56
+ return false;
57
+ }
58
+ if (Symbol.toStringTag in value) {
59
+ return Object.prototype.toString.call(value) === "[object Module]";
60
+ }
61
+ return true;
62
+ }
63
+ function _defu(baseObject, defaults, namespace = ".", merger) {
64
+ if (!isPlainObject(defaults)) {
65
+ return _defu(baseObject, {}, namespace, merger);
66
+ }
67
+ const object = Object.assign({}, defaults);
68
+ for (const key in baseObject) {
69
+ if (key === "__proto__" || key === "constructor") {
70
+ continue;
71
+ }
72
+ const value = baseObject[key];
73
+ if (value === null || value === void 0) {
74
+ continue;
75
+ }
76
+ if (merger && merger(object, key, value, namespace)) {
77
+ continue;
78
+ }
79
+ if (Array.isArray(value) && Array.isArray(object[key])) {
80
+ object[key] = [...value, ...object[key]];
81
+ } else if (isPlainObject(value) && isPlainObject(object[key])) {
82
+ object[key] = _defu(
83
+ value,
84
+ object[key],
85
+ (namespace ? `${namespace}.` : "") + key.toString(),
86
+ merger
87
+ );
88
+ } else {
89
+ object[key] = value;
90
+ }
91
+ }
92
+ return object;
93
+ }
94
+ function createDefu(merger) {
95
+ return (...arguments_) => (
96
+ // eslint-disable-next-line unicorn/no-array-reduce
97
+ arguments_.reduce((p, c) => _defu(p, c, "", merger), {})
98
+ );
99
+ }
100
+ var defu = createDefu();
101
+ var defuFn = createDefu((object, key, currentValue) => {
102
+ if (object[key] !== void 0 && typeof currentValue === "function") {
103
+ object[key] = currentValue(object[key]);
104
+ return true;
105
+ }
106
+ });
107
+ var defuArrayFn = createDefu((object, key, currentValue) => {
108
+ if (Array.isArray(object[key]) && typeof currentValue === "function") {
109
+ object[key] = currentValue(object[key]);
110
+ return true;
111
+ }
112
+ });
113
+
114
+ // src/css/plugins.ts
115
+ var import_postcss_selector_parser = __toESM(require("postcss-selector-parser"), 1);
116
+ var postcssPlugin = "postcss-mangle-tailwindcss-plugin";
117
+ function isVueScoped(s) {
118
+ if (s.parent) {
119
+ const index = s.parent.nodes.indexOf(s);
120
+ if (index > -1) {
121
+ const nextNode = s.parent.nodes[index + 1];
122
+ if (nextNode && nextNode.type === "attribute" && nextNode.attribute.includes("data-v-")) {
123
+ return true;
124
+ }
125
+ }
126
+ }
127
+ return false;
128
+ }
129
+ var transformSelectorPostcssPlugin = function(options) {
130
+ const { ignoreVueScoped, ctx } = defu(options, {
131
+ ignoreVueScoped: true
132
+ });
133
+ const replaceMap = ctx.replaceMap;
134
+ return {
135
+ postcssPlugin,
136
+ Once(root) {
137
+ root.walkRules((rule) => {
138
+ (0, import_postcss_selector_parser.default)((selectors) => {
139
+ selectors.walkClasses((s) => {
140
+ if (s.value && replaceMap && replaceMap.has(s.value)) {
141
+ if (ignoreVueScoped && isVueScoped(s)) {
142
+ return;
143
+ }
144
+ const v = replaceMap.get(s.value);
145
+ if (v) {
146
+ if (ctx.isPreserveClass(s.value)) {
147
+ rule.cloneBefore();
148
+ }
149
+ s.value = v;
150
+ }
151
+ }
152
+ });
153
+ }).transformSync(rule, {
154
+ lossless: false,
155
+ updateSelector: true
156
+ });
157
+ });
158
+ }
159
+ };
160
+ };
161
+ transformSelectorPostcssPlugin.postcss = true;
162
+
163
+ // src/css/index.ts
164
+ async function cssHandler(rawSource, options) {
165
+ const acceptedPlugins = [transformSelectorPostcssPlugin(options)];
166
+ const { id } = options;
167
+ try {
168
+ const { css: code, map } = await (0, import_postcss.default)(acceptedPlugins).process(rawSource, {
169
+ from: id,
170
+ to: id
171
+ });
172
+ return {
173
+ code,
174
+ // @ts-ignore
175
+ map
176
+ };
177
+ } catch (_error) {
178
+ return {
179
+ code: rawSource
180
+ };
181
+ }
182
+ }
183
+
184
+ // src/ctx/index.ts
185
+ var import_node_process = __toESM(require("process"), 1);
186
+ var import_config = require("@tailwindcss-mangle/config");
187
+ var import_fast_sort = require("fast-sort");
188
+ var import_fs_extra = __toESM(require("fs-extra"), 1);
189
+ var import_pathe = require("pathe");
190
+
191
+ // src/shared.ts
192
+ var shared_exports = {};
193
+ __reExport(shared_exports, require("@tailwindcss-mangle/shared"));
194
+
195
+ // src/ctx/index.ts
196
+ var Context = class {
197
+ options;
198
+ replaceMap;
199
+ classSet;
200
+ classGenerator;
201
+ preserveFunctionSet;
202
+ preserveClassNamesSet;
203
+ preserveFunctionRegexs;
204
+ constructor() {
205
+ this.options = {};
206
+ this.classSet = /* @__PURE__ */ new Set();
207
+ this.replaceMap = /* @__PURE__ */ new Map();
208
+ this.classGenerator = new shared_exports.ClassGenerator();
209
+ this.preserveFunctionSet = /* @__PURE__ */ new Set();
210
+ this.preserveClassNamesSet = /* @__PURE__ */ new Set();
211
+ this.preserveFunctionRegexs = [];
212
+ }
213
+ isPreserveClass(className) {
214
+ return this.preserveClassNamesSet.has(className);
215
+ }
216
+ addPreserveClass(className) {
217
+ return this.preserveClassNamesSet.add(className);
218
+ }
219
+ isPreserveFunction(calleeName) {
220
+ return this.preserveFunctionSet.has(calleeName);
221
+ }
222
+ mergeOptions(...opts) {
223
+ this.options = defu(this.options, ...opts);
224
+ this.classGenerator = new shared_exports.ClassGenerator(this.options.classGenerator);
225
+ this.preserveFunctionSet = new Set(this.options?.preserveFunction ?? []);
226
+ this.preserveFunctionRegexs = [...this.preserveFunctionSet.values()].map((x) => {
227
+ return new RegExp(`${(0, shared_exports.escapeStringRegexp)(x)}\\(([^)]*)\\)`, "g");
228
+ });
229
+ }
230
+ currentMangleClassFilter(className) {
231
+ return (this.options.mangleClassFilter ?? shared_exports.defaultMangleClassFilter)(className);
232
+ }
233
+ getClassSet() {
234
+ return this.classSet;
235
+ }
236
+ getReplaceMap() {
237
+ return this.replaceMap;
238
+ }
239
+ addToUsedBy(key, file) {
240
+ if (!file) {
241
+ return;
242
+ }
243
+ const hit = this.classGenerator.newClassMap[key];
244
+ if (hit) {
245
+ hit.usedBy.add(file);
246
+ }
247
+ }
248
+ loadClassSet(classList) {
249
+ const list = (0, import_fast_sort.sort)(classList).desc((c) => c.length);
250
+ for (const className of list) {
251
+ if (this.currentMangleClassFilter(className)) {
252
+ this.classSet.add(className);
253
+ }
254
+ }
255
+ }
256
+ async initConfig(opts = {}) {
257
+ const { cwd, classList: _classList, mangleOptions } = opts;
258
+ const { config, cwd: configCwd } = await (0, import_config.getConfig)(cwd);
259
+ if (mangleOptions?.classMapOutput === true) {
260
+ mangleOptions.classMapOutput = config.mangle?.classMapOutput;
261
+ if (typeof mangleOptions.classMapOutput === "object") {
262
+ mangleOptions.classMapOutput.enable = true;
263
+ }
264
+ }
265
+ this.mergeOptions(mangleOptions, config?.mangle);
266
+ if (_classList) {
267
+ this.loadClassSet(_classList);
268
+ } else {
269
+ let jsonPath = this.options.classListPath ?? (0, import_pathe.resolve)(import_node_process.default.cwd(), config?.patch?.output?.filename);
270
+ if (!(0, import_pathe.isAbsolute)(jsonPath)) {
271
+ jsonPath = (0, import_pathe.resolve)(configCwd ?? import_node_process.default.cwd(), jsonPath);
272
+ }
273
+ if (jsonPath && import_fs_extra.default.existsSync(jsonPath)) {
274
+ const rawClassList = import_fs_extra.default.readFileSync(jsonPath, "utf8");
275
+ const list = JSON.parse(rawClassList);
276
+ this.loadClassSet(list);
277
+ }
278
+ }
279
+ for (const cls of this.classSet) {
280
+ this.classGenerator.generateClassName(cls);
281
+ }
282
+ for (const x of Object.entries(this.classGenerator.newClassMap)) {
283
+ this.replaceMap.set(x[0], x[1].name);
284
+ }
285
+ return config;
286
+ }
287
+ async dump() {
288
+ try {
289
+ const arr = Object.entries(this.classGenerator.newClassMap).map((x) => {
290
+ return {
291
+ before: x[0],
292
+ after: x[1].name,
293
+ usedBy: Array.from(x[1].usedBy)
294
+ };
295
+ });
296
+ if (typeof this.options.classMapOutput === "function") {
297
+ await this.options.classMapOutput(arr);
298
+ } else if (typeof this.options.classMapOutput === "object" && this.options.classMapOutput.enable && this.options.classMapOutput.filename) {
299
+ import_fs_extra.default.mkdirSync((0, import_pathe.dirname)(this.options.classMapOutput.filename), { recursive: true });
300
+ import_fs_extra.default.writeFileSync(this.options.classMapOutput.filename, JSON.stringify(arr, null, 2));
301
+ }
302
+ } catch (error) {
303
+ console.error(`[tailwindcss-mangle]: ${error}`);
304
+ }
305
+ }
306
+ };
307
+
308
+ // src/html/index.ts
309
+ var import_htmlparser2 = require("htmlparser2");
310
+ var import_magic_string = __toESM(require("magic-string"), 1);
311
+ function htmlHandler(raw, options) {
312
+ const { ctx, id } = options;
313
+ const { replaceMap, classGenerator } = ctx;
314
+ const ms = typeof raw === "string" ? new import_magic_string.default(raw) : raw;
315
+ const parser2 = new import_htmlparser2.Parser({
316
+ onattribute(name, value) {
317
+ if (name === "class") {
318
+ let needUpdate = false;
319
+ const arr = (0, shared_exports.splitCode)(value, {
320
+ splitQuote: false
321
+ });
322
+ let rawValue = value;
323
+ for (const v of arr) {
324
+ if (replaceMap.has(v)) {
325
+ const gen = classGenerator.generateClassName(v);
326
+ rawValue = rawValue.replace((0, shared_exports.makeRegex)(v), gen.name);
327
+ ctx.addToUsedBy(v, id);
328
+ needUpdate = true;
329
+ }
330
+ }
331
+ needUpdate && ms.update(parser2.startIndex + name.length + 2, parser2.endIndex - 1, rawValue);
332
+ }
333
+ }
334
+ });
335
+ parser2.write(ms.original);
336
+ parser2.end();
337
+ return {
338
+ code: ms.toString()
339
+ };
340
+ }
341
+
342
+ // src/js/index.ts
343
+ var import_escape = require("@ast-core/escape");
344
+ var import_fast_sort2 = require("fast-sort");
345
+ var import_magic_string2 = __toESM(require("magic-string"), 1);
346
+
347
+ // src/babel/index.ts
348
+ var import_traverse = __toESM(require("@babel/traverse"), 1);
349
+ var import_parser = require("@babel/parser");
350
+ function _interopDefaultCompat(e) {
351
+ return e && typeof e === "object" && "default" in e ? e.default : e;
352
+ }
353
+ var traverse = _interopDefaultCompat(import_traverse.default);
354
+
355
+ // src/js/index.ts
356
+ function handleValue(raw, node, options, ms, offset, escape) {
357
+ const { ctx, splitQuote = true, id } = options;
358
+ const { replaceMap, classGenerator: clsGen } = ctx;
359
+ const array = (0, shared_exports.splitCode)(raw, {
360
+ splitQuote
361
+ });
362
+ let rawString = raw;
363
+ let needUpdate = false;
364
+ for (const v of array) {
365
+ if (replaceMap.has(v)) {
366
+ let ignoreFlag = false;
367
+ if (Array.isArray(node.leadingComments)) {
368
+ ignoreFlag = node.leadingComments.findIndex((x) => x.value.includes("tw-mangle") && x.value.includes("ignore")) > -1;
369
+ }
370
+ if (!ignoreFlag) {
371
+ const gen = clsGen.generateClassName(v);
372
+ rawString = rawString.replace((0, shared_exports.makeRegex)(v), gen.name);
373
+ ctx.addToUsedBy(v, id);
374
+ needUpdate = true;
375
+ }
376
+ }
377
+ }
378
+ if (needUpdate && typeof node.start === "number" && typeof node.end === "number") {
379
+ const start = node.start + offset;
380
+ const end = node.end - offset;
381
+ if (start < end && raw !== rawString) {
382
+ ms.update(start, end, escape ? (0, import_escape.jsStringEscape)(rawString) : rawString);
383
+ }
384
+ }
385
+ return rawString;
386
+ }
387
+ function jsHandler(rawSource, options) {
388
+ const ms = typeof rawSource === "string" ? new import_magic_string2.default(rawSource) : rawSource;
389
+ let ast;
390
+ try {
391
+ ast = (0, import_parser.parse)(ms.original, {
392
+ sourceType: "unambiguous"
393
+ });
394
+ } catch {
395
+ return {
396
+ code: ms.original
397
+ };
398
+ }
399
+ const { ctx } = options;
400
+ traverse(ast, {
401
+ StringLiteral: {
402
+ enter(p) {
403
+ const n = p.node;
404
+ handleValue(n.value, n, options, ms, 1, true);
405
+ }
406
+ },
407
+ TemplateElement: {
408
+ enter(p) {
409
+ const n = p.node;
410
+ handleValue(n.value.raw, n, options, ms, 0, false);
411
+ }
412
+ },
413
+ CallExpression: {
414
+ enter(p) {
415
+ const callee = p.get("callee");
416
+ if (callee.isIdentifier() && ctx.isPreserveFunction(callee.node.name)) {
417
+ p.traverse({
418
+ StringLiteral: {
419
+ enter(path) {
420
+ const node = path.node;
421
+ const value = node.value;
422
+ const arr = (0, import_fast_sort2.sort)((0, shared_exports.splitCode)(value)).desc((x) => x.length);
423
+ for (const str of arr) {
424
+ if (ctx.replaceMap.has(str)) {
425
+ ctx.addPreserveClass(str);
426
+ }
427
+ }
428
+ }
429
+ },
430
+ TemplateElement: {
431
+ enter(path) {
432
+ const node = path.node;
433
+ const value = node.value.raw;
434
+ const arr = (0, import_fast_sort2.sort)((0, shared_exports.splitCode)(value)).desc((x) => x.length);
435
+ for (const str of arr) {
436
+ if (ctx.replaceMap.has(str)) {
437
+ ctx.addPreserveClass(str);
438
+ }
439
+ }
440
+ }
441
+ }
442
+ });
443
+ }
444
+ }
445
+ }
446
+ });
447
+ return {
448
+ code: ms.toString(),
449
+ get map() {
450
+ return ms.generateMap();
451
+ }
452
+ };
453
+ }
454
+ // Annotate the CommonJS export names for ESM import in node:
455
+ 0 && (module.exports = {
456
+ ClassGenerator,
457
+ Context,
458
+ cssHandler,
459
+ handleValue,
460
+ htmlHandler,
461
+ jsHandler
462
+ });
@@ -0,0 +1,73 @@
1
+ import { TransformResult } from 'unplugin';
2
+ import * as _tailwindcss_mangle_config from '@tailwindcss-mangle/config';
3
+ import { MangleUserConfig } from '@tailwindcss-mangle/config';
4
+ import { ClassGenerator } from '@tailwindcss-mangle/shared';
5
+ export { ClassGenerator } from '@tailwindcss-mangle/shared';
6
+ import MagicString from 'magic-string';
7
+ import { StringLiteral, TemplateElement } from '@babel/types';
8
+
9
+ interface InitConfigOptions {
10
+ cwd?: string;
11
+ classList?: string[];
12
+ mangleOptions?: MangleUserConfig;
13
+ }
14
+ declare class Context {
15
+ options: MangleUserConfig;
16
+ replaceMap: Map<string, string>;
17
+ classSet: Set<string>;
18
+ classGenerator: ClassGenerator;
19
+ preserveFunctionSet: Set<string>;
20
+ preserveClassNamesSet: Set<string>;
21
+ preserveFunctionRegexs: RegExp[];
22
+ constructor();
23
+ isPreserveClass(className: string): boolean;
24
+ addPreserveClass(className: string): Set<string>;
25
+ isPreserveFunction(calleeName: string): boolean;
26
+ private mergeOptions;
27
+ currentMangleClassFilter(className: string): boolean;
28
+ getClassSet(): Set<string>;
29
+ getReplaceMap(): Map<string, string>;
30
+ addToUsedBy(key: string, file?: string): void;
31
+ loadClassSet(classList: string[]): void;
32
+ initConfig(opts?: InitConfigOptions): Promise<_tailwindcss_mangle_config.UserConfig>;
33
+ dump(): Promise<void>;
34
+ }
35
+
36
+ interface IClassGeneratorContextItem {
37
+ name: string;
38
+ usedBy: string[];
39
+ }
40
+ interface IClassGeneratorOptions {
41
+ reserveClassName?: (string | RegExp)[];
42
+ customGenerate?: (original: string, opts: IClassGeneratorOptions, context: Record<string, any>) => string | undefined;
43
+ log?: boolean;
44
+ exclude?: (string | RegExp)[];
45
+ include?: (string | RegExp)[];
46
+ ignoreClass?: (string | RegExp)[];
47
+ classPrefix?: string;
48
+ }
49
+ interface IHandler {
50
+ (code: string, options: IHandlerOptions): IHandlerTransformResult;
51
+ }
52
+ type IHandlerTransformResult = Exclude<TransformResult, null | undefined | string | void>;
53
+ interface IHandlerOptions {
54
+ ctx: Context;
55
+ id?: string;
56
+ }
57
+ interface IHtmlHandlerOptions extends IHandlerOptions {
58
+ }
59
+ interface IJsHandlerOptions extends IHandlerOptions {
60
+ splitQuote?: boolean;
61
+ }
62
+ interface ICssHandlerOptions extends IHandlerOptions {
63
+ ignoreVueScoped?: boolean;
64
+ }
65
+
66
+ declare function cssHandler(rawSource: string, options: ICssHandlerOptions): Promise<IHandlerTransformResult>;
67
+
68
+ declare function htmlHandler(raw: string | MagicString, options: IHtmlHandlerOptions): IHandlerTransformResult;
69
+
70
+ declare function handleValue(raw: string, node: StringLiteral | TemplateElement, options: IJsHandlerOptions, ms: MagicString, offset: number, escape: boolean): string;
71
+ declare function jsHandler(rawSource: string | MagicString, options: IJsHandlerOptions): IHandlerTransformResult;
72
+
73
+ export { Context, type IClassGeneratorContextItem, type IClassGeneratorOptions, type ICssHandlerOptions, type IHandler, type IHandlerOptions, type IHandlerTransformResult, type IHtmlHandlerOptions, type IJsHandlerOptions, cssHandler, handleValue, htmlHandler, jsHandler };
@@ -0,0 +1,73 @@
1
+ import { TransformResult } from 'unplugin';
2
+ import * as _tailwindcss_mangle_config from '@tailwindcss-mangle/config';
3
+ import { MangleUserConfig } from '@tailwindcss-mangle/config';
4
+ import { ClassGenerator } from '@tailwindcss-mangle/shared';
5
+ export { ClassGenerator } from '@tailwindcss-mangle/shared';
6
+ import MagicString from 'magic-string';
7
+ import { StringLiteral, TemplateElement } from '@babel/types';
8
+
9
+ interface InitConfigOptions {
10
+ cwd?: string;
11
+ classList?: string[];
12
+ mangleOptions?: MangleUserConfig;
13
+ }
14
+ declare class Context {
15
+ options: MangleUserConfig;
16
+ replaceMap: Map<string, string>;
17
+ classSet: Set<string>;
18
+ classGenerator: ClassGenerator;
19
+ preserveFunctionSet: Set<string>;
20
+ preserveClassNamesSet: Set<string>;
21
+ preserveFunctionRegexs: RegExp[];
22
+ constructor();
23
+ isPreserveClass(className: string): boolean;
24
+ addPreserveClass(className: string): Set<string>;
25
+ isPreserveFunction(calleeName: string): boolean;
26
+ private mergeOptions;
27
+ currentMangleClassFilter(className: string): boolean;
28
+ getClassSet(): Set<string>;
29
+ getReplaceMap(): Map<string, string>;
30
+ addToUsedBy(key: string, file?: string): void;
31
+ loadClassSet(classList: string[]): void;
32
+ initConfig(opts?: InitConfigOptions): Promise<_tailwindcss_mangle_config.UserConfig>;
33
+ dump(): Promise<void>;
34
+ }
35
+
36
+ interface IClassGeneratorContextItem {
37
+ name: string;
38
+ usedBy: string[];
39
+ }
40
+ interface IClassGeneratorOptions {
41
+ reserveClassName?: (string | RegExp)[];
42
+ customGenerate?: (original: string, opts: IClassGeneratorOptions, context: Record<string, any>) => string | undefined;
43
+ log?: boolean;
44
+ exclude?: (string | RegExp)[];
45
+ include?: (string | RegExp)[];
46
+ ignoreClass?: (string | RegExp)[];
47
+ classPrefix?: string;
48
+ }
49
+ interface IHandler {
50
+ (code: string, options: IHandlerOptions): IHandlerTransformResult;
51
+ }
52
+ type IHandlerTransformResult = Exclude<TransformResult, null | undefined | string | void>;
53
+ interface IHandlerOptions {
54
+ ctx: Context;
55
+ id?: string;
56
+ }
57
+ interface IHtmlHandlerOptions extends IHandlerOptions {
58
+ }
59
+ interface IJsHandlerOptions extends IHandlerOptions {
60
+ splitQuote?: boolean;
61
+ }
62
+ interface ICssHandlerOptions extends IHandlerOptions {
63
+ ignoreVueScoped?: boolean;
64
+ }
65
+
66
+ declare function cssHandler(rawSource: string, options: ICssHandlerOptions): Promise<IHandlerTransformResult>;
67
+
68
+ declare function htmlHandler(raw: string | MagicString, options: IHtmlHandlerOptions): IHandlerTransformResult;
69
+
70
+ declare function handleValue(raw: string, node: StringLiteral | TemplateElement, options: IJsHandlerOptions, ms: MagicString, offset: number, escape: boolean): string;
71
+ declare function jsHandler(rawSource: string | MagicString, options: IJsHandlerOptions): IHandlerTransformResult;
72
+
73
+ export { Context, type IClassGeneratorContextItem, type IClassGeneratorOptions, type ICssHandlerOptions, type IHandler, type IHandlerOptions, type IHandlerTransformResult, type IHtmlHandlerOptions, type IJsHandlerOptions, cssHandler, handleValue, htmlHandler, jsHandler };
package/dist/index.js ADDED
@@ -0,0 +1,435 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __copyProps = (to, from, except, desc) => {
6
+ if (from && typeof from === "object" || typeof from === "function") {
7
+ for (let key of __getOwnPropNames(from))
8
+ if (!__hasOwnProp.call(to, key) && key !== except)
9
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
10
+ }
11
+ return to;
12
+ };
13
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
14
+
15
+ // src/css/index.ts
16
+ import postcss from "postcss";
17
+
18
+ // ../../node_modules/.pnpm/defu@6.1.4/node_modules/defu/dist/defu.mjs
19
+ function isPlainObject(value) {
20
+ if (value === null || typeof value !== "object") {
21
+ return false;
22
+ }
23
+ const prototype = Object.getPrototypeOf(value);
24
+ if (prototype !== null && prototype !== Object.prototype && Object.getPrototypeOf(prototype) !== null) {
25
+ return false;
26
+ }
27
+ if (Symbol.iterator in value) {
28
+ return false;
29
+ }
30
+ if (Symbol.toStringTag in value) {
31
+ return Object.prototype.toString.call(value) === "[object Module]";
32
+ }
33
+ return true;
34
+ }
35
+ function _defu(baseObject, defaults, namespace = ".", merger) {
36
+ if (!isPlainObject(defaults)) {
37
+ return _defu(baseObject, {}, namespace, merger);
38
+ }
39
+ const object = Object.assign({}, defaults);
40
+ for (const key in baseObject) {
41
+ if (key === "__proto__" || key === "constructor") {
42
+ continue;
43
+ }
44
+ const value = baseObject[key];
45
+ if (value === null || value === void 0) {
46
+ continue;
47
+ }
48
+ if (merger && merger(object, key, value, namespace)) {
49
+ continue;
50
+ }
51
+ if (Array.isArray(value) && Array.isArray(object[key])) {
52
+ object[key] = [...value, ...object[key]];
53
+ } else if (isPlainObject(value) && isPlainObject(object[key])) {
54
+ object[key] = _defu(
55
+ value,
56
+ object[key],
57
+ (namespace ? `${namespace}.` : "") + key.toString(),
58
+ merger
59
+ );
60
+ } else {
61
+ object[key] = value;
62
+ }
63
+ }
64
+ return object;
65
+ }
66
+ function createDefu(merger) {
67
+ return (...arguments_) => (
68
+ // eslint-disable-next-line unicorn/no-array-reduce
69
+ arguments_.reduce((p, c) => _defu(p, c, "", merger), {})
70
+ );
71
+ }
72
+ var defu = createDefu();
73
+ var defuFn = createDefu((object, key, currentValue) => {
74
+ if (object[key] !== void 0 && typeof currentValue === "function") {
75
+ object[key] = currentValue(object[key]);
76
+ return true;
77
+ }
78
+ });
79
+ var defuArrayFn = createDefu((object, key, currentValue) => {
80
+ if (Array.isArray(object[key]) && typeof currentValue === "function") {
81
+ object[key] = currentValue(object[key]);
82
+ return true;
83
+ }
84
+ });
85
+
86
+ // src/css/plugins.ts
87
+ import parser from "postcss-selector-parser";
88
+ var postcssPlugin = "postcss-mangle-tailwindcss-plugin";
89
+ function isVueScoped(s) {
90
+ if (s.parent) {
91
+ const index = s.parent.nodes.indexOf(s);
92
+ if (index > -1) {
93
+ const nextNode = s.parent.nodes[index + 1];
94
+ if (nextNode && nextNode.type === "attribute" && nextNode.attribute.includes("data-v-")) {
95
+ return true;
96
+ }
97
+ }
98
+ }
99
+ return false;
100
+ }
101
+ var transformSelectorPostcssPlugin = function(options) {
102
+ const { ignoreVueScoped, ctx } = defu(options, {
103
+ ignoreVueScoped: true
104
+ });
105
+ const replaceMap = ctx.replaceMap;
106
+ return {
107
+ postcssPlugin,
108
+ Once(root) {
109
+ root.walkRules((rule) => {
110
+ parser((selectors) => {
111
+ selectors.walkClasses((s) => {
112
+ if (s.value && replaceMap && replaceMap.has(s.value)) {
113
+ if (ignoreVueScoped && isVueScoped(s)) {
114
+ return;
115
+ }
116
+ const v = replaceMap.get(s.value);
117
+ if (v) {
118
+ if (ctx.isPreserveClass(s.value)) {
119
+ rule.cloneBefore();
120
+ }
121
+ s.value = v;
122
+ }
123
+ }
124
+ });
125
+ }).transformSync(rule, {
126
+ lossless: false,
127
+ updateSelector: true
128
+ });
129
+ });
130
+ }
131
+ };
132
+ };
133
+ transformSelectorPostcssPlugin.postcss = true;
134
+
135
+ // src/css/index.ts
136
+ async function cssHandler(rawSource, options) {
137
+ const acceptedPlugins = [transformSelectorPostcssPlugin(options)];
138
+ const { id } = options;
139
+ try {
140
+ const { css: code, map } = await postcss(acceptedPlugins).process(rawSource, {
141
+ from: id,
142
+ to: id
143
+ });
144
+ return {
145
+ code,
146
+ // @ts-ignore
147
+ map
148
+ };
149
+ } catch (_error) {
150
+ return {
151
+ code: rawSource
152
+ };
153
+ }
154
+ }
155
+
156
+ // src/ctx/index.ts
157
+ import process from "node:process";
158
+ import { getConfig } from "@tailwindcss-mangle/config";
159
+ import { sort } from "fast-sort";
160
+ import fs from "fs-extra";
161
+ import { dirname, isAbsolute, resolve } from "pathe";
162
+
163
+ // src/shared.ts
164
+ var shared_exports = {};
165
+ __reExport(shared_exports, shared_star);
166
+ import * as shared_star from "@tailwindcss-mangle/shared";
167
+
168
+ // src/ctx/index.ts
169
+ var Context = class {
170
+ options;
171
+ replaceMap;
172
+ classSet;
173
+ classGenerator;
174
+ preserveFunctionSet;
175
+ preserveClassNamesSet;
176
+ preserveFunctionRegexs;
177
+ constructor() {
178
+ this.options = {};
179
+ this.classSet = /* @__PURE__ */ new Set();
180
+ this.replaceMap = /* @__PURE__ */ new Map();
181
+ this.classGenerator = new shared_exports.ClassGenerator();
182
+ this.preserveFunctionSet = /* @__PURE__ */ new Set();
183
+ this.preserveClassNamesSet = /* @__PURE__ */ new Set();
184
+ this.preserveFunctionRegexs = [];
185
+ }
186
+ isPreserveClass(className) {
187
+ return this.preserveClassNamesSet.has(className);
188
+ }
189
+ addPreserveClass(className) {
190
+ return this.preserveClassNamesSet.add(className);
191
+ }
192
+ isPreserveFunction(calleeName) {
193
+ return this.preserveFunctionSet.has(calleeName);
194
+ }
195
+ mergeOptions(...opts) {
196
+ this.options = defu(this.options, ...opts);
197
+ this.classGenerator = new shared_exports.ClassGenerator(this.options.classGenerator);
198
+ this.preserveFunctionSet = new Set(this.options?.preserveFunction ?? []);
199
+ this.preserveFunctionRegexs = [...this.preserveFunctionSet.values()].map((x) => {
200
+ return new RegExp(`${(0, shared_exports.escapeStringRegexp)(x)}\\(([^)]*)\\)`, "g");
201
+ });
202
+ }
203
+ currentMangleClassFilter(className) {
204
+ return (this.options.mangleClassFilter ?? shared_exports.defaultMangleClassFilter)(className);
205
+ }
206
+ getClassSet() {
207
+ return this.classSet;
208
+ }
209
+ getReplaceMap() {
210
+ return this.replaceMap;
211
+ }
212
+ addToUsedBy(key, file) {
213
+ if (!file) {
214
+ return;
215
+ }
216
+ const hit = this.classGenerator.newClassMap[key];
217
+ if (hit) {
218
+ hit.usedBy.add(file);
219
+ }
220
+ }
221
+ loadClassSet(classList) {
222
+ const list = sort(classList).desc((c) => c.length);
223
+ for (const className of list) {
224
+ if (this.currentMangleClassFilter(className)) {
225
+ this.classSet.add(className);
226
+ }
227
+ }
228
+ }
229
+ async initConfig(opts = {}) {
230
+ const { cwd, classList: _classList, mangleOptions } = opts;
231
+ const { config, cwd: configCwd } = await getConfig(cwd);
232
+ if (mangleOptions?.classMapOutput === true) {
233
+ mangleOptions.classMapOutput = config.mangle?.classMapOutput;
234
+ if (typeof mangleOptions.classMapOutput === "object") {
235
+ mangleOptions.classMapOutput.enable = true;
236
+ }
237
+ }
238
+ this.mergeOptions(mangleOptions, config?.mangle);
239
+ if (_classList) {
240
+ this.loadClassSet(_classList);
241
+ } else {
242
+ let jsonPath = this.options.classListPath ?? resolve(process.cwd(), config?.patch?.output?.filename);
243
+ if (!isAbsolute(jsonPath)) {
244
+ jsonPath = resolve(configCwd ?? process.cwd(), jsonPath);
245
+ }
246
+ if (jsonPath && fs.existsSync(jsonPath)) {
247
+ const rawClassList = fs.readFileSync(jsonPath, "utf8");
248
+ const list = JSON.parse(rawClassList);
249
+ this.loadClassSet(list);
250
+ }
251
+ }
252
+ for (const cls of this.classSet) {
253
+ this.classGenerator.generateClassName(cls);
254
+ }
255
+ for (const x of Object.entries(this.classGenerator.newClassMap)) {
256
+ this.replaceMap.set(x[0], x[1].name);
257
+ }
258
+ return config;
259
+ }
260
+ async dump() {
261
+ try {
262
+ const arr = Object.entries(this.classGenerator.newClassMap).map((x) => {
263
+ return {
264
+ before: x[0],
265
+ after: x[1].name,
266
+ usedBy: Array.from(x[1].usedBy)
267
+ };
268
+ });
269
+ if (typeof this.options.classMapOutput === "function") {
270
+ await this.options.classMapOutput(arr);
271
+ } else if (typeof this.options.classMapOutput === "object" && this.options.classMapOutput.enable && this.options.classMapOutput.filename) {
272
+ fs.mkdirSync(dirname(this.options.classMapOutput.filename), { recursive: true });
273
+ fs.writeFileSync(this.options.classMapOutput.filename, JSON.stringify(arr, null, 2));
274
+ }
275
+ } catch (error) {
276
+ console.error(`[tailwindcss-mangle]: ${error}`);
277
+ }
278
+ }
279
+ };
280
+
281
+ // src/html/index.ts
282
+ import { Parser } from "htmlparser2";
283
+ import MagicString from "magic-string";
284
+ function htmlHandler(raw, options) {
285
+ const { ctx, id } = options;
286
+ const { replaceMap, classGenerator } = ctx;
287
+ const ms = typeof raw === "string" ? new MagicString(raw) : raw;
288
+ const parser2 = new Parser({
289
+ onattribute(name, value) {
290
+ if (name === "class") {
291
+ let needUpdate = false;
292
+ const arr = (0, shared_exports.splitCode)(value, {
293
+ splitQuote: false
294
+ });
295
+ let rawValue = value;
296
+ for (const v of arr) {
297
+ if (replaceMap.has(v)) {
298
+ const gen = classGenerator.generateClassName(v);
299
+ rawValue = rawValue.replace((0, shared_exports.makeRegex)(v), gen.name);
300
+ ctx.addToUsedBy(v, id);
301
+ needUpdate = true;
302
+ }
303
+ }
304
+ needUpdate && ms.update(parser2.startIndex + name.length + 2, parser2.endIndex - 1, rawValue);
305
+ }
306
+ }
307
+ });
308
+ parser2.write(ms.original);
309
+ parser2.end();
310
+ return {
311
+ code: ms.toString()
312
+ };
313
+ }
314
+
315
+ // src/js/index.ts
316
+ import { jsStringEscape } from "@ast-core/escape";
317
+ import { sort as sort2 } from "fast-sort";
318
+ import MagicString2 from "magic-string";
319
+
320
+ // src/babel/index.ts
321
+ import _babelTraverse from "@babel/traverse";
322
+ import { parse, parseExpression } from "@babel/parser";
323
+ function _interopDefaultCompat(e) {
324
+ return e && typeof e === "object" && "default" in e ? e.default : e;
325
+ }
326
+ var traverse = _interopDefaultCompat(_babelTraverse);
327
+
328
+ // src/js/index.ts
329
+ function handleValue(raw, node, options, ms, offset, escape) {
330
+ const { ctx, splitQuote = true, id } = options;
331
+ const { replaceMap, classGenerator: clsGen } = ctx;
332
+ const array = (0, shared_exports.splitCode)(raw, {
333
+ splitQuote
334
+ });
335
+ let rawString = raw;
336
+ let needUpdate = false;
337
+ for (const v of array) {
338
+ if (replaceMap.has(v)) {
339
+ let ignoreFlag = false;
340
+ if (Array.isArray(node.leadingComments)) {
341
+ ignoreFlag = node.leadingComments.findIndex((x) => x.value.includes("tw-mangle") && x.value.includes("ignore")) > -1;
342
+ }
343
+ if (!ignoreFlag) {
344
+ const gen = clsGen.generateClassName(v);
345
+ rawString = rawString.replace((0, shared_exports.makeRegex)(v), gen.name);
346
+ ctx.addToUsedBy(v, id);
347
+ needUpdate = true;
348
+ }
349
+ }
350
+ }
351
+ if (needUpdate && typeof node.start === "number" && typeof node.end === "number") {
352
+ const start = node.start + offset;
353
+ const end = node.end - offset;
354
+ if (start < end && raw !== rawString) {
355
+ ms.update(start, end, escape ? jsStringEscape(rawString) : rawString);
356
+ }
357
+ }
358
+ return rawString;
359
+ }
360
+ function jsHandler(rawSource, options) {
361
+ const ms = typeof rawSource === "string" ? new MagicString2(rawSource) : rawSource;
362
+ let ast;
363
+ try {
364
+ ast = parse(ms.original, {
365
+ sourceType: "unambiguous"
366
+ });
367
+ } catch {
368
+ return {
369
+ code: ms.original
370
+ };
371
+ }
372
+ const { ctx } = options;
373
+ traverse(ast, {
374
+ StringLiteral: {
375
+ enter(p) {
376
+ const n = p.node;
377
+ handleValue(n.value, n, options, ms, 1, true);
378
+ }
379
+ },
380
+ TemplateElement: {
381
+ enter(p) {
382
+ const n = p.node;
383
+ handleValue(n.value.raw, n, options, ms, 0, false);
384
+ }
385
+ },
386
+ CallExpression: {
387
+ enter(p) {
388
+ const callee = p.get("callee");
389
+ if (callee.isIdentifier() && ctx.isPreserveFunction(callee.node.name)) {
390
+ p.traverse({
391
+ StringLiteral: {
392
+ enter(path) {
393
+ const node = path.node;
394
+ const value = node.value;
395
+ const arr = sort2((0, shared_exports.splitCode)(value)).desc((x) => x.length);
396
+ for (const str of arr) {
397
+ if (ctx.replaceMap.has(str)) {
398
+ ctx.addPreserveClass(str);
399
+ }
400
+ }
401
+ }
402
+ },
403
+ TemplateElement: {
404
+ enter(path) {
405
+ const node = path.node;
406
+ const value = node.value.raw;
407
+ const arr = sort2((0, shared_exports.splitCode)(value)).desc((x) => x.length);
408
+ for (const str of arr) {
409
+ if (ctx.replaceMap.has(str)) {
410
+ ctx.addPreserveClass(str);
411
+ }
412
+ }
413
+ }
414
+ }
415
+ });
416
+ }
417
+ }
418
+ }
419
+ });
420
+ return {
421
+ code: ms.toString(),
422
+ get map() {
423
+ return ms.generateMap();
424
+ }
425
+ };
426
+ }
427
+ var export_ClassGenerator = shared_exports.ClassGenerator;
428
+ export {
429
+ export_ClassGenerator as ClassGenerator,
430
+ Context,
431
+ cssHandler,
432
+ handleValue,
433
+ htmlHandler,
434
+ jsHandler
435
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tailwindcss-mangle/core",
3
3
  "type": "module",
4
- "version": "4.0.0",
4
+ "version": "4.0.1",
5
5
  "description": "The core of tailwindcss-mangle",
6
6
  "author": "ice breaker <1324318532@qq.com>",
7
7
  "license": "MIT",
@@ -57,8 +57,8 @@
57
57
  "pathe": "^1.1.2",
58
58
  "postcss": "^8.4.47",
59
59
  "postcss-selector-parser": "^7.0.0",
60
- "@tailwindcss-mangle/config": "^4.0.0",
61
- "@tailwindcss-mangle/shared": "^4.0.0"
60
+ "@tailwindcss-mangle/config": "^4.0.1",
61
+ "@tailwindcss-mangle/shared": "^4.0.1"
62
62
  },
63
63
  "scripts": {
64
64
  "dev": "tsup --watch --sourcemap",