@tailwindcss-mangle/core 3.0.0 → 4.0.0-alpha.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 ice breaker
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@tailwindcss-mangle/core",
3
- "version": "3.0.0",
3
+ "type": "module",
4
+ "version": "4.0.0-alpha.0",
4
5
  "description": "The core of tailwindcss-mangle",
5
6
  "author": "SonOfMagic <qq1324318532@gmail.com>",
6
7
  "license": "MIT",
@@ -21,12 +22,12 @@
21
22
  "exports": {
22
23
  ".": {
23
24
  "types": "./dist/index.d.ts",
24
- "import": "./dist/index.mjs",
25
+ "import": "./dist/index.js",
25
26
  "require": "./dist/index.cjs"
26
27
  }
27
28
  },
28
29
  "main": "./dist/index.cjs",
29
- "module": "./dist/index.mjs",
30
+ "module": "./dist/index.js",
30
31
  "types": "./dist/index.d.ts",
31
32
  "typesVersions": {
32
33
  "*": {
@@ -45,23 +46,22 @@
45
46
  },
46
47
  "dependencies": {
47
48
  "@ast-core/escape": "^1.0.1",
48
- "@babel/parser": "^7.24.7",
49
- "@babel/traverse": "^7.24.7",
50
- "@babel/types": "^7.24.7",
51
- "fast-sort": "^3.4.0",
49
+ "@babel/parser": "^7.26.1",
50
+ "@babel/traverse": "^7.25.9",
51
+ "@babel/types": "^7.26.0",
52
+ "fast-sort": "^3.4.1",
53
+ "fs-extra": "^11.2.0",
52
54
  "htmlparser2": "9.1.0",
53
- "magic-string": "^0.30.10",
54
- "postcss": "^8.4.38",
55
- "postcss-selector-parser": "^6.1.0",
56
- "@tailwindcss-mangle/config": "^3.0.0",
57
- "@tailwindcss-mangle/shared": "^3.0.0"
58
- },
59
- "devDependencies": {
60
- "@types/babel__traverse": "^7.20.6"
55
+ "magic-string": "^0.30.12",
56
+ "pathe": "^1.1.2",
57
+ "postcss": "^8.4.47",
58
+ "postcss-selector-parser": "^7.0.0",
59
+ "@tailwindcss-mangle/config": "^4.0.0-alpha.0",
60
+ "@tailwindcss-mangle/shared": "^4.0.0-alpha.0"
61
61
  },
62
62
  "scripts": {
63
- "dev": "unbuild --sourcemap",
64
- "build": "unbuild",
63
+ "dev": "tsup --watch --sourcemap",
64
+ "build": "tsup",
65
65
  "test": "vitest run --coverage.enabled",
66
66
  "test:dev": "vitest",
67
67
  "coverage": "vitest run --coverage"
package/dist/index.cjs DELETED
@@ -1,408 +0,0 @@
1
- 'use strict';
2
-
3
- const fs = require('node:fs');
4
- const node_path = require('node:path');
5
- const process = require('node:process');
6
- const shared = require('@tailwindcss-mangle/shared');
7
- const config = require('@tailwindcss-mangle/config');
8
- const fastSort = require('fast-sort');
9
- const postcss = require('postcss');
10
- const parser = require('postcss-selector-parser');
11
- const htmlparser2 = require('htmlparser2');
12
- const MagicString = require('magic-string');
13
- const escape = require('@ast-core/escape');
14
- const _babelTraverse = require('@babel/traverse');
15
- const parser$1 = require('@babel/parser');
16
-
17
- function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
18
-
19
- const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
20
- const process__default = /*#__PURE__*/_interopDefaultCompat(process);
21
- const postcss__default = /*#__PURE__*/_interopDefaultCompat(postcss);
22
- const parser__default = /*#__PURE__*/_interopDefaultCompat(parser);
23
- const MagicString__default = /*#__PURE__*/_interopDefaultCompat(MagicString);
24
- const _babelTraverse__default = /*#__PURE__*/_interopDefaultCompat(_babelTraverse);
25
-
26
- function isPlainObject(value) {
27
- if (value === null || typeof value !== "object") {
28
- return false;
29
- }
30
- const prototype = Object.getPrototypeOf(value);
31
- if (prototype !== null && prototype !== Object.prototype && Object.getPrototypeOf(prototype) !== null) {
32
- return false;
33
- }
34
- if (Symbol.iterator in value) {
35
- return false;
36
- }
37
- if (Symbol.toStringTag in value) {
38
- return Object.prototype.toString.call(value) === "[object Module]";
39
- }
40
- return true;
41
- }
42
-
43
- function _defu(baseObject, defaults, namespace = ".", merger) {
44
- if (!isPlainObject(defaults)) {
45
- return _defu(baseObject, {}, namespace, merger);
46
- }
47
- const object = Object.assign({}, defaults);
48
- for (const key in baseObject) {
49
- if (key === "__proto__" || key === "constructor") {
50
- continue;
51
- }
52
- const value = baseObject[key];
53
- if (value === null || value === void 0) {
54
- continue;
55
- }
56
- if (merger && merger(object, key, value, namespace)) {
57
- continue;
58
- }
59
- if (Array.isArray(value) && Array.isArray(object[key])) {
60
- object[key] = [...value, ...object[key]];
61
- } else if (isPlainObject(value) && isPlainObject(object[key])) {
62
- object[key] = _defu(
63
- value,
64
- object[key],
65
- (namespace ? `${namespace}.` : "") + key.toString(),
66
- merger
67
- );
68
- } else {
69
- object[key] = value;
70
- }
71
- }
72
- return object;
73
- }
74
- function createDefu(merger) {
75
- return (...arguments_) => (
76
- // eslint-disable-next-line unicorn/no-array-reduce
77
- arguments_.reduce((p, c) => _defu(p, c, "", merger), {})
78
- );
79
- }
80
- const defu = createDefu();
81
-
82
- function escapeStringRegexp(str) {
83
- if (typeof str !== "string") {
84
- throw new TypeError("Expected a string");
85
- }
86
- return str.replaceAll(/[$()*+.?[\\\]^{|}]/g, "\\$&").replaceAll("-", "\\x2d");
87
- }
88
-
89
- var __defProp = Object.defineProperty;
90
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
91
- var __publicField = (obj, key, value) => {
92
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
93
- return value;
94
- };
95
- class Context {
96
- constructor() {
97
- __publicField(this, "options");
98
- __publicField(this, "replaceMap");
99
- __publicField(this, "classSet");
100
- __publicField(this, "classGenerator");
101
- __publicField(this, "preserveFunctionSet");
102
- __publicField(this, "preserveClassNamesSet");
103
- __publicField(this, "preserveFunctionRegexs");
104
- this.options = {};
105
- this.classSet = /* @__PURE__ */ new Set();
106
- this.replaceMap = /* @__PURE__ */ new Map();
107
- this.classGenerator = new shared.ClassGenerator();
108
- this.preserveFunctionSet = /* @__PURE__ */ new Set();
109
- this.preserveClassNamesSet = /* @__PURE__ */ new Set();
110
- this.preserveFunctionRegexs = [];
111
- }
112
- isPreserveClass(className) {
113
- return this.preserveClassNamesSet.has(className);
114
- }
115
- addPreserveClass(className) {
116
- return this.preserveClassNamesSet.add(className);
117
- }
118
- isPreserveFunction(calleeName) {
119
- return this.preserveFunctionSet.has(calleeName);
120
- }
121
- mergeOptions(...opts) {
122
- this.options = defu(this.options, ...opts);
123
- this.classGenerator = new shared.ClassGenerator(this.options.classGenerator);
124
- this.preserveFunctionSet = new Set(this.options?.preserveFunction ?? []);
125
- this.preserveFunctionRegexs = [...this.preserveFunctionSet.values()].map((x) => {
126
- return new RegExp(`${escapeStringRegexp(x)}\\(([^)]*)\\)`, "g");
127
- });
128
- }
129
- currentMangleClassFilter(className) {
130
- return (this.options.mangleClassFilter ?? shared.defaultMangleClassFilter)(className);
131
- }
132
- getClassSet() {
133
- return this.classSet;
134
- }
135
- getReplaceMap() {
136
- return this.replaceMap;
137
- }
138
- addToUsedBy(key, file) {
139
- if (!file) {
140
- return;
141
- }
142
- const hit = this.classGenerator.newClassMap[key];
143
- if (hit) {
144
- hit.usedBy.add(file);
145
- }
146
- }
147
- loadClassSet(classList) {
148
- const list = fastSort.sort(classList).desc((c) => c.length);
149
- for (const className of list) {
150
- if (this.currentMangleClassFilter(className)) {
151
- this.classSet.add(className);
152
- }
153
- }
154
- }
155
- async initConfig(opts = {}) {
156
- const { cwd, classList: _classList, mangleOptions } = opts;
157
- const { config: config$1, cwd: configCwd } = await config.getConfig(cwd);
158
- if (mangleOptions?.classMapOutput === true) {
159
- mangleOptions.classMapOutput = config$1.mangle?.classMapOutput;
160
- if (typeof mangleOptions.classMapOutput === "object") {
161
- mangleOptions.classMapOutput.enable = true;
162
- }
163
- }
164
- this.mergeOptions(mangleOptions, config$1?.mangle);
165
- if (_classList) {
166
- this.loadClassSet(_classList);
167
- } else {
168
- let jsonPath = this.options.classListPath ?? node_path.resolve(process__default.cwd(), config$1?.patch?.output?.filename);
169
- if (!node_path.isAbsolute(jsonPath)) {
170
- jsonPath = node_path.resolve(configCwd ?? process__default.cwd(), jsonPath);
171
- }
172
- if (jsonPath && fs__default.existsSync(jsonPath)) {
173
- const rawClassList = fs__default.readFileSync(jsonPath, "utf8");
174
- const list = JSON.parse(rawClassList);
175
- this.loadClassSet(list);
176
- }
177
- }
178
- for (const cls of this.classSet) {
179
- this.classGenerator.generateClassName(cls);
180
- }
181
- for (const x of Object.entries(this.classGenerator.newClassMap)) {
182
- this.replaceMap.set(x[0], x[1].name);
183
- }
184
- return config$1;
185
- }
186
- async dump() {
187
- try {
188
- const arr = Object.entries(this.classGenerator.newClassMap).map((x) => {
189
- return {
190
- before: x[0],
191
- after: x[1].name,
192
- usedBy: Array.from(x[1].usedBy)
193
- };
194
- });
195
- if (typeof this.options.classMapOutput === "function") {
196
- await this.options.classMapOutput(arr);
197
- } else if (typeof this.options.classMapOutput === "object" && this.options.classMapOutput.enable && this.options.classMapOutput.filename) {
198
- fs__default.mkdirSync(node_path.dirname(this.options.classMapOutput.filename), { recursive: true });
199
- fs__default.writeFileSync(this.options.classMapOutput.filename, JSON.stringify(arr, null, 2));
200
- }
201
- } catch (error) {
202
- console.error(`[tailwindcss-mangle]: ${error}`);
203
- }
204
- }
205
- }
206
-
207
- const postcssPlugin = "postcss-mangle-tailwindcss-plugin";
208
- function isVueScoped(s) {
209
- if (s.parent) {
210
- const index = s.parent.nodes.indexOf(s);
211
- if (index > -1) {
212
- const nextNode = s.parent.nodes[index + 1];
213
- if (nextNode && nextNode.type === "attribute" && nextNode.attribute.includes("data-v-")) {
214
- return true;
215
- }
216
- }
217
- }
218
- return false;
219
- }
220
- const transformSelectorPostcssPlugin = function(options) {
221
- const { ignoreVueScoped, ctx, id } = defu(options, {
222
- ignoreVueScoped: true
223
- });
224
- const replaceMap = ctx.replaceMap;
225
- return {
226
- postcssPlugin,
227
- Once(root) {
228
- root.walkRules((rule) => {
229
- parser__default((selectors) => {
230
- selectors.walkClasses((s) => {
231
- if (s.value && replaceMap && replaceMap.has(s.value)) {
232
- if (ignoreVueScoped && isVueScoped(s)) {
233
- return;
234
- }
235
- const v = replaceMap.get(s.value);
236
- if (v) {
237
- if (ctx.isPreserveClass(s.value)) {
238
- rule.cloneBefore();
239
- }
240
- s.value = v;
241
- }
242
- }
243
- });
244
- }).transformSync(rule, {
245
- lossless: false,
246
- updateSelector: true
247
- });
248
- });
249
- }
250
- };
251
- };
252
- transformSelectorPostcssPlugin.postcss = true;
253
-
254
- async function cssHandler(rawSource, options) {
255
- const acceptedPlugins = [transformSelectorPostcssPlugin(options)];
256
- const { id } = options;
257
- const { css: code, map } = await postcss__default(acceptedPlugins).process(rawSource, {
258
- from: id,
259
- to: id
260
- });
261
- return {
262
- code,
263
- // @ts-ignore
264
- map
265
- };
266
- }
267
-
268
- function htmlHandler(raw, options) {
269
- const { ctx, id } = options;
270
- const { replaceMap, classGenerator } = ctx;
271
- const ms = typeof raw === "string" ? new MagicString__default(raw) : raw;
272
- const parser = new htmlparser2.Parser({
273
- onattribute(name, value) {
274
- if (name === "class") {
275
- let needUpdate = false;
276
- const arr = shared.splitCode(value, {
277
- splitQuote: false
278
- });
279
- let rawValue = value;
280
- for (const v of arr) {
281
- if (replaceMap.has(v)) {
282
- const gen = classGenerator.generateClassName(v);
283
- rawValue = rawValue.replace(shared.makeRegex(v), gen.name);
284
- ctx.addToUsedBy(v, id);
285
- needUpdate = true;
286
- }
287
- }
288
- needUpdate && ms.update(parser.startIndex + name.length + 2, parser.endIndex - 1, rawValue);
289
- }
290
- }
291
- });
292
- parser.write(ms.original);
293
- parser.end();
294
- return {
295
- code: ms.toString()
296
- };
297
- }
298
-
299
- function _interopDefaultCompat$1(e) {
300
- return e && typeof e === "object" && "default" in e ? e.default : e;
301
- }
302
- const traverse = _interopDefaultCompat$1(_babelTraverse__default);
303
-
304
- function handleValue(raw, node, options, ms, offset, escape$1) {
305
- const { ctx, splitQuote = true, id } = options;
306
- const { replaceMap, classGenerator: clsGen } = ctx;
307
- const array = shared.splitCode(raw, {
308
- splitQuote
309
- });
310
- let rawString = raw;
311
- let needUpdate = false;
312
- for (const v of array) {
313
- if (replaceMap.has(v)) {
314
- let ignoreFlag = false;
315
- if (Array.isArray(node.leadingComments)) {
316
- ignoreFlag = node.leadingComments.findIndex((x) => x.value.includes("tw-mangle") && x.value.includes("ignore")) > -1;
317
- }
318
- if (!ignoreFlag) {
319
- const gen = clsGen.generateClassName(v);
320
- rawString = rawString.replace(shared.makeRegex(v), gen.name);
321
- ctx.addToUsedBy(v, id);
322
- needUpdate = true;
323
- }
324
- }
325
- }
326
- if (needUpdate && typeof node.start === "number" && typeof node.end === "number") {
327
- const start = node.start + offset;
328
- const end = node.end - offset;
329
- if (start < end && raw !== rawString) {
330
- ms.update(start, end, escape$1 ? escape.jsStringEscape(rawString) : rawString);
331
- }
332
- }
333
- return rawString;
334
- }
335
- function jsHandler(rawSource, options) {
336
- const ms = typeof rawSource === "string" ? new MagicString__default(rawSource) : rawSource;
337
- let ast;
338
- try {
339
- ast = parser$1.parse(ms.original, {
340
- sourceType: "unambiguous"
341
- });
342
- } catch (error) {
343
- return {
344
- code: ms.original
345
- };
346
- }
347
- const { ctx } = options;
348
- traverse(ast, {
349
- StringLiteral: {
350
- enter(p) {
351
- const n = p.node;
352
- handleValue(n.value, n, options, ms, 1, true);
353
- }
354
- },
355
- TemplateElement: {
356
- enter(p) {
357
- const n = p.node;
358
- handleValue(n.value.raw, n, options, ms, 0, false);
359
- }
360
- },
361
- CallExpression: {
362
- enter(p) {
363
- const callee = p.get("callee");
364
- if (callee.isIdentifier() && ctx.isPreserveFunction(callee.node.name)) {
365
- p.traverse({
366
- StringLiteral: {
367
- enter(path) {
368
- const node = path.node;
369
- const value = node.value;
370
- const arr = fastSort.sort(shared.splitCode(value)).desc((x) => x.length);
371
- for (const str of arr) {
372
- if (ctx.replaceMap.has(str)) {
373
- ctx.addPreserveClass(str);
374
- }
375
- }
376
- }
377
- },
378
- TemplateElement: {
379
- enter(path) {
380
- const node = path.node;
381
- const value = node.value.raw;
382
- const arr = fastSort.sort(shared.splitCode(value)).desc((x) => x.length);
383
- for (const str of arr) {
384
- if (ctx.replaceMap.has(str)) {
385
- ctx.addPreserveClass(str);
386
- }
387
- }
388
- }
389
- }
390
- });
391
- }
392
- }
393
- }
394
- });
395
- return {
396
- code: ms.toString(),
397
- get map() {
398
- return ms.generateMap();
399
- }
400
- };
401
- }
402
-
403
- exports.ClassGenerator = shared.ClassGenerator;
404
- exports.Context = Context;
405
- exports.cssHandler = cssHandler;
406
- exports.handleValue = handleValue;
407
- exports.htmlHandler = htmlHandler;
408
- exports.jsHandler = jsHandler;
package/dist/index.d.cts DELETED
@@ -1,73 +0,0 @@
1
- import * as _tailwindcss_mangle_config from '@tailwindcss-mangle/config';
2
- import { MangleUserConfig } from '@tailwindcss-mangle/config';
3
- import { ClassGenerator } from '@tailwindcss-mangle/shared';
4
- export { ClassGenerator } from '@tailwindcss-mangle/shared';
5
- import { TransformResult } from 'unplugin';
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>;
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.d.mts DELETED
@@ -1,73 +0,0 @@
1
- import * as _tailwindcss_mangle_config from '@tailwindcss-mangle/config';
2
- import { MangleUserConfig } from '@tailwindcss-mangle/config';
3
- import { ClassGenerator } from '@tailwindcss-mangle/shared';
4
- export { ClassGenerator } from '@tailwindcss-mangle/shared';
5
- import { TransformResult } from 'unplugin';
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>;
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.d.ts DELETED
@@ -1,73 +0,0 @@
1
- import * as _tailwindcss_mangle_config from '@tailwindcss-mangle/config';
2
- import { MangleUserConfig } from '@tailwindcss-mangle/config';
3
- import { ClassGenerator } from '@tailwindcss-mangle/shared';
4
- export { ClassGenerator } from '@tailwindcss-mangle/shared';
5
- import { TransformResult } from 'unplugin';
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>;
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.mjs DELETED
@@ -1,393 +0,0 @@
1
- import fs from 'node:fs';
2
- import { resolve, isAbsolute, dirname } from 'node:path';
3
- import process from 'node:process';
4
- import { ClassGenerator, defaultMangleClassFilter, splitCode, makeRegex } from '@tailwindcss-mangle/shared';
5
- export { ClassGenerator } from '@tailwindcss-mangle/shared';
6
- import { getConfig } from '@tailwindcss-mangle/config';
7
- import { sort } from 'fast-sort';
8
- import postcss from 'postcss';
9
- import parser from 'postcss-selector-parser';
10
- import { Parser } from 'htmlparser2';
11
- import MagicString from 'magic-string';
12
- import { jsStringEscape } from '@ast-core/escape';
13
- import _babelTraverse from '@babel/traverse';
14
- import { parse } from '@babel/parser';
15
-
16
- function isPlainObject(value) {
17
- if (value === null || typeof value !== "object") {
18
- return false;
19
- }
20
- const prototype = Object.getPrototypeOf(value);
21
- if (prototype !== null && prototype !== Object.prototype && Object.getPrototypeOf(prototype) !== null) {
22
- return false;
23
- }
24
- if (Symbol.iterator in value) {
25
- return false;
26
- }
27
- if (Symbol.toStringTag in value) {
28
- return Object.prototype.toString.call(value) === "[object Module]";
29
- }
30
- return true;
31
- }
32
-
33
- function _defu(baseObject, defaults, namespace = ".", merger) {
34
- if (!isPlainObject(defaults)) {
35
- return _defu(baseObject, {}, namespace, merger);
36
- }
37
- const object = Object.assign({}, defaults);
38
- for (const key in baseObject) {
39
- if (key === "__proto__" || key === "constructor") {
40
- continue;
41
- }
42
- const value = baseObject[key];
43
- if (value === null || value === void 0) {
44
- continue;
45
- }
46
- if (merger && merger(object, key, value, namespace)) {
47
- continue;
48
- }
49
- if (Array.isArray(value) && Array.isArray(object[key])) {
50
- object[key] = [...value, ...object[key]];
51
- } else if (isPlainObject(value) && isPlainObject(object[key])) {
52
- object[key] = _defu(
53
- value,
54
- object[key],
55
- (namespace ? `${namespace}.` : "") + key.toString(),
56
- merger
57
- );
58
- } else {
59
- object[key] = value;
60
- }
61
- }
62
- return object;
63
- }
64
- function createDefu(merger) {
65
- return (...arguments_) => (
66
- // eslint-disable-next-line unicorn/no-array-reduce
67
- arguments_.reduce((p, c) => _defu(p, c, "", merger), {})
68
- );
69
- }
70
- const defu = createDefu();
71
-
72
- function escapeStringRegexp(str) {
73
- if (typeof str !== "string") {
74
- throw new TypeError("Expected a string");
75
- }
76
- return str.replaceAll(/[$()*+.?[\\\]^{|}]/g, "\\$&").replaceAll("-", "\\x2d");
77
- }
78
-
79
- var __defProp = Object.defineProperty;
80
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
81
- var __publicField = (obj, key, value) => {
82
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
83
- return value;
84
- };
85
- class Context {
86
- constructor() {
87
- __publicField(this, "options");
88
- __publicField(this, "replaceMap");
89
- __publicField(this, "classSet");
90
- __publicField(this, "classGenerator");
91
- __publicField(this, "preserveFunctionSet");
92
- __publicField(this, "preserveClassNamesSet");
93
- __publicField(this, "preserveFunctionRegexs");
94
- this.options = {};
95
- this.classSet = /* @__PURE__ */ new Set();
96
- this.replaceMap = /* @__PURE__ */ new Map();
97
- this.classGenerator = new ClassGenerator();
98
- this.preserveFunctionSet = /* @__PURE__ */ new Set();
99
- this.preserveClassNamesSet = /* @__PURE__ */ new Set();
100
- this.preserveFunctionRegexs = [];
101
- }
102
- isPreserveClass(className) {
103
- return this.preserveClassNamesSet.has(className);
104
- }
105
- addPreserveClass(className) {
106
- return this.preserveClassNamesSet.add(className);
107
- }
108
- isPreserveFunction(calleeName) {
109
- return this.preserveFunctionSet.has(calleeName);
110
- }
111
- mergeOptions(...opts) {
112
- this.options = defu(this.options, ...opts);
113
- this.classGenerator = new ClassGenerator(this.options.classGenerator);
114
- this.preserveFunctionSet = new Set(this.options?.preserveFunction ?? []);
115
- this.preserveFunctionRegexs = [...this.preserveFunctionSet.values()].map((x) => {
116
- return new RegExp(`${escapeStringRegexp(x)}\\(([^)]*)\\)`, "g");
117
- });
118
- }
119
- currentMangleClassFilter(className) {
120
- return (this.options.mangleClassFilter ?? defaultMangleClassFilter)(className);
121
- }
122
- getClassSet() {
123
- return this.classSet;
124
- }
125
- getReplaceMap() {
126
- return this.replaceMap;
127
- }
128
- addToUsedBy(key, file) {
129
- if (!file) {
130
- return;
131
- }
132
- const hit = this.classGenerator.newClassMap[key];
133
- if (hit) {
134
- hit.usedBy.add(file);
135
- }
136
- }
137
- loadClassSet(classList) {
138
- const list = sort(classList).desc((c) => c.length);
139
- for (const className of list) {
140
- if (this.currentMangleClassFilter(className)) {
141
- this.classSet.add(className);
142
- }
143
- }
144
- }
145
- async initConfig(opts = {}) {
146
- const { cwd, classList: _classList, mangleOptions } = opts;
147
- const { config, cwd: configCwd } = await getConfig(cwd);
148
- if (mangleOptions?.classMapOutput === true) {
149
- mangleOptions.classMapOutput = config.mangle?.classMapOutput;
150
- if (typeof mangleOptions.classMapOutput === "object") {
151
- mangleOptions.classMapOutput.enable = true;
152
- }
153
- }
154
- this.mergeOptions(mangleOptions, config?.mangle);
155
- if (_classList) {
156
- this.loadClassSet(_classList);
157
- } else {
158
- let jsonPath = this.options.classListPath ?? resolve(process.cwd(), config?.patch?.output?.filename);
159
- if (!isAbsolute(jsonPath)) {
160
- jsonPath = resolve(configCwd ?? process.cwd(), jsonPath);
161
- }
162
- if (jsonPath && fs.existsSync(jsonPath)) {
163
- const rawClassList = fs.readFileSync(jsonPath, "utf8");
164
- const list = JSON.parse(rawClassList);
165
- this.loadClassSet(list);
166
- }
167
- }
168
- for (const cls of this.classSet) {
169
- this.classGenerator.generateClassName(cls);
170
- }
171
- for (const x of Object.entries(this.classGenerator.newClassMap)) {
172
- this.replaceMap.set(x[0], x[1].name);
173
- }
174
- return config;
175
- }
176
- async dump() {
177
- try {
178
- const arr = Object.entries(this.classGenerator.newClassMap).map((x) => {
179
- return {
180
- before: x[0],
181
- after: x[1].name,
182
- usedBy: Array.from(x[1].usedBy)
183
- };
184
- });
185
- if (typeof this.options.classMapOutput === "function") {
186
- await this.options.classMapOutput(arr);
187
- } else if (typeof this.options.classMapOutput === "object" && this.options.classMapOutput.enable && this.options.classMapOutput.filename) {
188
- fs.mkdirSync(dirname(this.options.classMapOutput.filename), { recursive: true });
189
- fs.writeFileSync(this.options.classMapOutput.filename, JSON.stringify(arr, null, 2));
190
- }
191
- } catch (error) {
192
- console.error(`[tailwindcss-mangle]: ${error}`);
193
- }
194
- }
195
- }
196
-
197
- const postcssPlugin = "postcss-mangle-tailwindcss-plugin";
198
- function isVueScoped(s) {
199
- if (s.parent) {
200
- const index = s.parent.nodes.indexOf(s);
201
- if (index > -1) {
202
- const nextNode = s.parent.nodes[index + 1];
203
- if (nextNode && nextNode.type === "attribute" && nextNode.attribute.includes("data-v-")) {
204
- return true;
205
- }
206
- }
207
- }
208
- return false;
209
- }
210
- const transformSelectorPostcssPlugin = function(options) {
211
- const { ignoreVueScoped, ctx, id } = defu(options, {
212
- ignoreVueScoped: true
213
- });
214
- const replaceMap = ctx.replaceMap;
215
- return {
216
- postcssPlugin,
217
- Once(root) {
218
- root.walkRules((rule) => {
219
- parser((selectors) => {
220
- selectors.walkClasses((s) => {
221
- if (s.value && replaceMap && replaceMap.has(s.value)) {
222
- if (ignoreVueScoped && isVueScoped(s)) {
223
- return;
224
- }
225
- const v = replaceMap.get(s.value);
226
- if (v) {
227
- if (ctx.isPreserveClass(s.value)) {
228
- rule.cloneBefore();
229
- }
230
- s.value = v;
231
- }
232
- }
233
- });
234
- }).transformSync(rule, {
235
- lossless: false,
236
- updateSelector: true
237
- });
238
- });
239
- }
240
- };
241
- };
242
- transformSelectorPostcssPlugin.postcss = true;
243
-
244
- async function cssHandler(rawSource, options) {
245
- const acceptedPlugins = [transformSelectorPostcssPlugin(options)];
246
- const { id } = options;
247
- const { css: code, map } = await postcss(acceptedPlugins).process(rawSource, {
248
- from: id,
249
- to: id
250
- });
251
- return {
252
- code,
253
- // @ts-ignore
254
- map
255
- };
256
- }
257
-
258
- function htmlHandler(raw, options) {
259
- const { ctx, id } = options;
260
- const { replaceMap, classGenerator } = ctx;
261
- const ms = typeof raw === "string" ? new MagicString(raw) : raw;
262
- const parser = new Parser({
263
- onattribute(name, value) {
264
- if (name === "class") {
265
- let needUpdate = false;
266
- const arr = splitCode(value, {
267
- splitQuote: false
268
- });
269
- let rawValue = value;
270
- for (const v of arr) {
271
- if (replaceMap.has(v)) {
272
- const gen = classGenerator.generateClassName(v);
273
- rawValue = rawValue.replace(makeRegex(v), gen.name);
274
- ctx.addToUsedBy(v, id);
275
- needUpdate = true;
276
- }
277
- }
278
- needUpdate && ms.update(parser.startIndex + name.length + 2, parser.endIndex - 1, rawValue);
279
- }
280
- }
281
- });
282
- parser.write(ms.original);
283
- parser.end();
284
- return {
285
- code: ms.toString()
286
- };
287
- }
288
-
289
- function _interopDefaultCompat(e) {
290
- return e && typeof e === "object" && "default" in e ? e.default : e;
291
- }
292
- const traverse = _interopDefaultCompat(_babelTraverse);
293
-
294
- function handleValue(raw, node, options, ms, offset, escape) {
295
- const { ctx, splitQuote = true, id } = options;
296
- const { replaceMap, classGenerator: clsGen } = ctx;
297
- const array = splitCode(raw, {
298
- splitQuote
299
- });
300
- let rawString = raw;
301
- let needUpdate = false;
302
- for (const v of array) {
303
- if (replaceMap.has(v)) {
304
- let ignoreFlag = false;
305
- if (Array.isArray(node.leadingComments)) {
306
- ignoreFlag = node.leadingComments.findIndex((x) => x.value.includes("tw-mangle") && x.value.includes("ignore")) > -1;
307
- }
308
- if (!ignoreFlag) {
309
- const gen = clsGen.generateClassName(v);
310
- rawString = rawString.replace(makeRegex(v), gen.name);
311
- ctx.addToUsedBy(v, id);
312
- needUpdate = true;
313
- }
314
- }
315
- }
316
- if (needUpdate && typeof node.start === "number" && typeof node.end === "number") {
317
- const start = node.start + offset;
318
- const end = node.end - offset;
319
- if (start < end && raw !== rawString) {
320
- ms.update(start, end, escape ? jsStringEscape(rawString) : rawString);
321
- }
322
- }
323
- return rawString;
324
- }
325
- function jsHandler(rawSource, options) {
326
- const ms = typeof rawSource === "string" ? new MagicString(rawSource) : rawSource;
327
- let ast;
328
- try {
329
- ast = parse(ms.original, {
330
- sourceType: "unambiguous"
331
- });
332
- } catch (error) {
333
- return {
334
- code: ms.original
335
- };
336
- }
337
- const { ctx } = options;
338
- traverse(ast, {
339
- StringLiteral: {
340
- enter(p) {
341
- const n = p.node;
342
- handleValue(n.value, n, options, ms, 1, true);
343
- }
344
- },
345
- TemplateElement: {
346
- enter(p) {
347
- const n = p.node;
348
- handleValue(n.value.raw, n, options, ms, 0, false);
349
- }
350
- },
351
- CallExpression: {
352
- enter(p) {
353
- const callee = p.get("callee");
354
- if (callee.isIdentifier() && ctx.isPreserveFunction(callee.node.name)) {
355
- p.traverse({
356
- StringLiteral: {
357
- enter(path) {
358
- const node = path.node;
359
- const value = node.value;
360
- const arr = sort(splitCode(value)).desc((x) => x.length);
361
- for (const str of arr) {
362
- if (ctx.replaceMap.has(str)) {
363
- ctx.addPreserveClass(str);
364
- }
365
- }
366
- }
367
- },
368
- TemplateElement: {
369
- enter(path) {
370
- const node = path.node;
371
- const value = node.value.raw;
372
- const arr = sort(splitCode(value)).desc((x) => x.length);
373
- for (const str of arr) {
374
- if (ctx.replaceMap.has(str)) {
375
- ctx.addPreserveClass(str);
376
- }
377
- }
378
- }
379
- }
380
- });
381
- }
382
- }
383
- }
384
- });
385
- return {
386
- code: ms.toString(),
387
- get map() {
388
- return ms.generateMap();
389
- }
390
- };
391
- }
392
-
393
- export { Context, cssHandler, handleValue, htmlHandler, jsHandler };