@tailwindcss-mangle/core 1.2.7 → 2.0.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/dist/index.cjs +253 -80
- package/dist/index.d.ts +15 -6
- package/dist/index.mjs +250 -67
- package/package.json +6 -3
package/dist/index.cjs
CHANGED
|
@@ -4,26 +4,16 @@ const postcss = require('postcss');
|
|
|
4
4
|
const parser = require('postcss-selector-parser');
|
|
5
5
|
const parse5 = require('parse5');
|
|
6
6
|
const shared = require('@tailwindcss-mangle/shared');
|
|
7
|
-
const
|
|
8
|
-
const
|
|
7
|
+
const babel = require('@babel/core');
|
|
8
|
+
const helperPluginUtils = require('@babel/helper-plugin-utils');
|
|
9
|
+
const MagicString = require('magic-string');
|
|
9
10
|
|
|
10
11
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
11
12
|
|
|
12
|
-
function _interopNamespaceCompat(e) {
|
|
13
|
-
if (e && typeof e === 'object' && 'default' in e) return e;
|
|
14
|
-
const n = Object.create(null);
|
|
15
|
-
if (e) {
|
|
16
|
-
for (const k in e) {
|
|
17
|
-
n[k] = e[k];
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
n.default = e;
|
|
21
|
-
return n;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
13
|
const postcss__default = /*#__PURE__*/_interopDefaultCompat(postcss);
|
|
25
14
|
const parser__default = /*#__PURE__*/_interopDefaultCompat(parser);
|
|
26
|
-
const
|
|
15
|
+
const babel__default = /*#__PURE__*/_interopDefaultCompat(babel);
|
|
16
|
+
const MagicString__default = /*#__PURE__*/_interopDefaultCompat(MagicString);
|
|
27
17
|
|
|
28
18
|
function isObject(value) {
|
|
29
19
|
return value !== null && typeof value === "object";
|
|
@@ -80,64 +70,41 @@ function isVueScoped(s) {
|
|
|
80
70
|
}
|
|
81
71
|
return false;
|
|
82
72
|
}
|
|
83
|
-
const
|
|
84
|
-
const { ignoreVueScoped } = defu(options, {
|
|
73
|
+
const transformSelectorPostcssPlugin = function(options) {
|
|
74
|
+
const { ignoreVueScoped, replaceMap } = defu(options, {
|
|
85
75
|
ignoreVueScoped: true
|
|
86
76
|
});
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
rule.selector = parser__default((selectors) => {
|
|
96
|
-
selectors.walkClasses((s) => {
|
|
97
|
-
if (s.value) {
|
|
98
|
-
const existed = set.has(s.value);
|
|
99
|
-
if (existed) {
|
|
100
|
-
if (ignoreVueScoped && isVueScoped(s)) {
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
s.value = options.classGenerator.generateClassName(s.value).name;
|
|
104
|
-
}
|
|
77
|
+
return {
|
|
78
|
+
postcssPlugin,
|
|
79
|
+
async Rule(rule) {
|
|
80
|
+
await parser__default((selectors) => {
|
|
81
|
+
selectors.walkClasses((s) => {
|
|
82
|
+
if (s.value && replaceMap && replaceMap.has(s.value)) {
|
|
83
|
+
if (ignoreVueScoped && isVueScoped(s)) {
|
|
84
|
+
return;
|
|
105
85
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
};
|
|
110
|
-
} else {
|
|
111
|
-
let newClassMap = {};
|
|
112
|
-
if (options && options.classGenerator) {
|
|
113
|
-
newClassMap = options.classGenerator.newClassMap;
|
|
114
|
-
}
|
|
115
|
-
return {
|
|
116
|
-
postcssPlugin,
|
|
117
|
-
Rule(rule) {
|
|
118
|
-
rule.selector = parser__default((selectors) => {
|
|
119
|
-
selectors.walkClasses((s) => {
|
|
120
|
-
if (s.value) {
|
|
121
|
-
const hit = newClassMap[s.value];
|
|
122
|
-
const existed = Boolean(hit);
|
|
123
|
-
if (existed) {
|
|
124
|
-
if (ignoreVueScoped && isVueScoped(s)) {
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
s.value = hit.name;
|
|
128
|
-
}
|
|
86
|
+
const v = replaceMap.get(s.value);
|
|
87
|
+
if (v) {
|
|
88
|
+
s.value = v;
|
|
129
89
|
}
|
|
130
|
-
}
|
|
131
|
-
})
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}).transform(rule, {
|
|
93
|
+
lossless: false,
|
|
94
|
+
updateSelector: true
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
};
|
|
135
98
|
};
|
|
136
|
-
|
|
99
|
+
transformSelectorPostcssPlugin.postcss = true;
|
|
137
100
|
|
|
138
101
|
function cssHandler(rawSource, options) {
|
|
139
|
-
const acceptedPlugins = [
|
|
140
|
-
|
|
102
|
+
const acceptedPlugins = [transformSelectorPostcssPlugin(options)];
|
|
103
|
+
const { file } = options;
|
|
104
|
+
return postcss__default(acceptedPlugins).process(rawSource, {
|
|
105
|
+
from: file,
|
|
106
|
+
to: file
|
|
107
|
+
});
|
|
141
108
|
}
|
|
142
109
|
|
|
143
110
|
({
|
|
@@ -234,7 +201,7 @@ function traverse(node, visitor, parent) {
|
|
|
234
201
|
}
|
|
235
202
|
|
|
236
203
|
function htmlHandler(rawSource, options) {
|
|
237
|
-
const {
|
|
204
|
+
const { replaceMap, classGenerator } = options;
|
|
238
205
|
const fragment = parse5.parse(rawSource);
|
|
239
206
|
traverse(fragment, {
|
|
240
207
|
element(node) {
|
|
@@ -244,7 +211,7 @@ function htmlHandler(rawSource, options) {
|
|
|
244
211
|
splitQuote: false
|
|
245
212
|
});
|
|
246
213
|
for (const v of array) {
|
|
247
|
-
if (
|
|
214
|
+
if (replaceMap.has(v)) {
|
|
248
215
|
attribute.value = attribute.value.replace(shared.makeRegex(v), classGenerator.generateClassName(v).name);
|
|
249
216
|
}
|
|
250
217
|
}
|
|
@@ -256,14 +223,213 @@ function htmlHandler(rawSource, options) {
|
|
|
256
223
|
|
|
257
224
|
const isProd = () => process.env.NODE_ENV === "production";
|
|
258
225
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
226
|
+
// >>> INTERFACES <<<
|
|
227
|
+
// >>> HELPERS <<<
|
|
228
|
+
var castComparer = function (comparer) { return function (a, b, order) { return comparer(a, b, order) * order; }; };
|
|
229
|
+
var throwInvalidConfigErrorIfTrue = function (condition, context) {
|
|
230
|
+
if (condition)
|
|
231
|
+
throw Error("Invalid sort config: " + context);
|
|
232
|
+
};
|
|
233
|
+
var unpackObjectSorter = function (sortByObj) {
|
|
234
|
+
var _a = sortByObj || {}, asc = _a.asc, desc = _a.desc;
|
|
235
|
+
var order = asc ? 1 : -1;
|
|
236
|
+
var sortBy = (asc || desc);
|
|
237
|
+
// Validate object config
|
|
238
|
+
throwInvalidConfigErrorIfTrue(!sortBy, 'Expected `asc` or `desc` property');
|
|
239
|
+
throwInvalidConfigErrorIfTrue(asc && desc, 'Ambiguous object with `asc` and `desc` config properties');
|
|
240
|
+
var comparer = sortByObj.comparer && castComparer(sortByObj.comparer);
|
|
241
|
+
return { order: order, sortBy: sortBy, comparer: comparer };
|
|
242
|
+
};
|
|
243
|
+
// >>> SORTERS <<<
|
|
244
|
+
var multiPropertySorterProvider = function (defaultComparer) {
|
|
245
|
+
return function multiPropertySorter(sortBy, sortByArr, depth, order, comparer, a, b) {
|
|
246
|
+
var valA;
|
|
247
|
+
var valB;
|
|
248
|
+
if (typeof sortBy === 'string') {
|
|
249
|
+
valA = a[sortBy];
|
|
250
|
+
valB = b[sortBy];
|
|
251
|
+
}
|
|
252
|
+
else if (typeof sortBy === 'function') {
|
|
253
|
+
valA = sortBy(a);
|
|
254
|
+
valB = sortBy(b);
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
var objectSorterConfig = unpackObjectSorter(sortBy);
|
|
258
|
+
return multiPropertySorter(objectSorterConfig.sortBy, sortByArr, depth, objectSorterConfig.order, objectSorterConfig.comparer || defaultComparer, a, b);
|
|
259
|
+
}
|
|
260
|
+
var equality = comparer(valA, valB, order);
|
|
261
|
+
if ((equality === 0 || (valA == null && valB == null)) &&
|
|
262
|
+
sortByArr.length > depth) {
|
|
263
|
+
return multiPropertySorter(sortByArr[depth], sortByArr, depth + 1, order, comparer, a, b);
|
|
264
|
+
}
|
|
265
|
+
return equality;
|
|
266
|
+
};
|
|
267
|
+
};
|
|
268
|
+
function getSortStrategy(sortBy, comparer, order) {
|
|
269
|
+
// Flat array sorter
|
|
270
|
+
if (sortBy === undefined || sortBy === true) {
|
|
271
|
+
return function (a, b) { return comparer(a, b, order); };
|
|
272
|
+
}
|
|
273
|
+
// Sort list of objects by single object key
|
|
274
|
+
if (typeof sortBy === 'string') {
|
|
275
|
+
throwInvalidConfigErrorIfTrue(sortBy.includes('.'), 'String syntax not allowed for nested properties.');
|
|
276
|
+
return function (a, b) { return comparer(a[sortBy], b[sortBy], order); };
|
|
277
|
+
}
|
|
278
|
+
// Sort list of objects by single function sorter
|
|
279
|
+
if (typeof sortBy === 'function') {
|
|
280
|
+
return function (a, b) { return comparer(sortBy(a), sortBy(b), order); };
|
|
281
|
+
}
|
|
282
|
+
// Sort by multiple properties
|
|
283
|
+
if (Array.isArray(sortBy)) {
|
|
284
|
+
var multiPropSorter_1 = multiPropertySorterProvider(comparer);
|
|
285
|
+
return function (a, b) { return multiPropSorter_1(sortBy[0], sortBy, 1, order, comparer, a, b); };
|
|
286
|
+
}
|
|
287
|
+
// Unpack object config to get actual sorter strategy
|
|
288
|
+
var objectSorterConfig = unpackObjectSorter(sortBy);
|
|
289
|
+
return getSortStrategy(objectSorterConfig.sortBy, objectSorterConfig.comparer || comparer, objectSorterConfig.order);
|
|
290
|
+
}
|
|
291
|
+
var sortArray = function (order, ctx, sortBy, comparer) {
|
|
292
|
+
var _a;
|
|
293
|
+
if (!Array.isArray(ctx)) {
|
|
294
|
+
return ctx;
|
|
295
|
+
}
|
|
296
|
+
// Unwrap sortBy if array with only 1 value to get faster sort strategy
|
|
297
|
+
if (Array.isArray(sortBy) && sortBy.length < 2) {
|
|
298
|
+
_a = sortBy, sortBy = _a[0];
|
|
299
|
+
}
|
|
300
|
+
return ctx.sort(getSortStrategy(sortBy, comparer, order));
|
|
301
|
+
};
|
|
302
|
+
function createNewSortInstance(opts) {
|
|
303
|
+
var comparer = castComparer(opts.comparer);
|
|
304
|
+
return function (arrayToSort) {
|
|
305
|
+
var ctx = Array.isArray(arrayToSort) && !opts.inPlaceSorting
|
|
306
|
+
? arrayToSort.slice()
|
|
307
|
+
: arrayToSort;
|
|
308
|
+
return {
|
|
309
|
+
asc: function (sortBy) {
|
|
310
|
+
return sortArray(1, ctx, sortBy, comparer);
|
|
311
|
+
},
|
|
312
|
+
desc: function (sortBy) {
|
|
313
|
+
return sortArray(-1, ctx, sortBy, comparer);
|
|
314
|
+
},
|
|
315
|
+
by: function (sortBy) {
|
|
316
|
+
return sortArray(1, ctx, sortBy, comparer);
|
|
317
|
+
},
|
|
318
|
+
};
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
var defaultComparer = function (a, b, order) {
|
|
322
|
+
if (a == null)
|
|
323
|
+
return order;
|
|
324
|
+
if (b == null)
|
|
325
|
+
return -order;
|
|
326
|
+
if (typeof a !== typeof b) {
|
|
327
|
+
return typeof a < typeof b ? -1 : 1;
|
|
328
|
+
}
|
|
329
|
+
if (a < b)
|
|
330
|
+
return -1;
|
|
331
|
+
if (a > b)
|
|
332
|
+
return 1;
|
|
333
|
+
return 0;
|
|
334
|
+
};
|
|
335
|
+
var sort = createNewSortInstance({
|
|
336
|
+
comparer: defaultComparer,
|
|
337
|
+
});
|
|
338
|
+
createNewSortInstance({
|
|
339
|
+
comparer: defaultComparer,
|
|
340
|
+
inPlaceSorting: true,
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
function handleValue$1(options) {
|
|
344
|
+
const { addToUsedBy, id, magicString, node, raw, replaceMap, offset = 0 } = options;
|
|
345
|
+
let value = raw;
|
|
346
|
+
const arr = sort(shared.splitCode(value)).desc((x) => x.length);
|
|
347
|
+
for (const str of arr) {
|
|
348
|
+
if (replaceMap.has(str)) {
|
|
349
|
+
addToUsedBy(str, id);
|
|
350
|
+
const v = replaceMap.get(str);
|
|
351
|
+
if (v) {
|
|
352
|
+
value = value.replaceAll(str, v);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (typeof node.start === "number" && typeof node.end === "number" && value) {
|
|
357
|
+
magicString.update(node.start + offset, node.end - offset, value);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
const plugin = helperPluginUtils.declare((api, options) => {
|
|
361
|
+
api.assertVersion(7);
|
|
362
|
+
const { magicString, replaceMap, id, addToUsedBy } = options;
|
|
363
|
+
return {
|
|
364
|
+
visitor: {
|
|
365
|
+
StringLiteral: {
|
|
366
|
+
enter(p) {
|
|
367
|
+
const node = p.node;
|
|
368
|
+
handleValue$1({
|
|
369
|
+
addToUsedBy,
|
|
370
|
+
id,
|
|
371
|
+
magicString,
|
|
372
|
+
node,
|
|
373
|
+
raw: node.value,
|
|
374
|
+
replaceMap,
|
|
375
|
+
offset: 1
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
},
|
|
379
|
+
TemplateElement: {
|
|
380
|
+
enter(p) {
|
|
381
|
+
const node = p.node;
|
|
382
|
+
handleValue$1({
|
|
383
|
+
addToUsedBy,
|
|
384
|
+
id,
|
|
385
|
+
magicString,
|
|
386
|
+
node,
|
|
387
|
+
raw: node.value.raw,
|
|
388
|
+
replaceMap,
|
|
389
|
+
offset: 0
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
});
|
|
396
|
+
function preProcessJs(options) {
|
|
397
|
+
const { code, replaceMap, id, addToUsedBy } = options;
|
|
398
|
+
const magicString = new MagicString__default(code);
|
|
399
|
+
babel__default.transformSync(code, {
|
|
400
|
+
presets: [
|
|
401
|
+
// ['@babel/preset-react', {}],
|
|
402
|
+
[
|
|
403
|
+
"@babel/preset-typescript",
|
|
404
|
+
{
|
|
405
|
+
allExtensions: true,
|
|
406
|
+
isTSX: true
|
|
407
|
+
}
|
|
408
|
+
]
|
|
409
|
+
],
|
|
410
|
+
plugins: [
|
|
411
|
+
[
|
|
412
|
+
plugin,
|
|
413
|
+
{
|
|
414
|
+
magicString,
|
|
415
|
+
replaceMap,
|
|
416
|
+
id,
|
|
417
|
+
addToUsedBy
|
|
418
|
+
}
|
|
419
|
+
]
|
|
420
|
+
]
|
|
421
|
+
});
|
|
422
|
+
return magicString.toString();
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function handleValue(raw, node, options) {
|
|
426
|
+
const { replaceMap, classGenerator: clsGen, splitQuote = true } = options;
|
|
427
|
+
const array = shared.splitCode(raw, {
|
|
262
428
|
splitQuote
|
|
263
429
|
});
|
|
264
|
-
let rawString =
|
|
430
|
+
let rawString = raw;
|
|
265
431
|
for (const v of array) {
|
|
266
|
-
if (
|
|
432
|
+
if (replaceMap.has(v)) {
|
|
267
433
|
let ignoreFlag = false;
|
|
268
434
|
if (Array.isArray(node.leadingComments)) {
|
|
269
435
|
ignoreFlag = node.leadingComments.findIndex((x) => x.value.includes("tw-mangle") && x.value.includes("ignore")) > -1;
|
|
@@ -276,7 +442,7 @@ function handleValue(string_, node, options) {
|
|
|
276
442
|
return rawString;
|
|
277
443
|
}
|
|
278
444
|
function jsHandler(rawSource, options) {
|
|
279
|
-
const result =
|
|
445
|
+
const result = babel.transformSync(rawSource, {
|
|
280
446
|
babelrc: false,
|
|
281
447
|
ast: true,
|
|
282
448
|
plugins: [
|
|
@@ -297,12 +463,18 @@ function jsHandler(rawSource, options) {
|
|
|
297
463
|
},
|
|
298
464
|
CallExpression: {
|
|
299
465
|
enter(p) {
|
|
300
|
-
const
|
|
301
|
-
if (
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
466
|
+
const calleePath = p.get("callee");
|
|
467
|
+
if (calleePath.isIdentifier() && calleePath.node.name === "eval") {
|
|
468
|
+
p.traverse({
|
|
469
|
+
StringLiteral: {
|
|
470
|
+
enter(s) {
|
|
471
|
+
const res = jsHandler(s.node.value, options);
|
|
472
|
+
if (res.code) {
|
|
473
|
+
s.node.value = res.code;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
});
|
|
306
478
|
}
|
|
307
479
|
}
|
|
308
480
|
}
|
|
@@ -323,3 +495,4 @@ exports.cssHandler = cssHandler;
|
|
|
323
495
|
exports.handleValue = handleValue;
|
|
324
496
|
exports.htmlHandler = htmlHandler;
|
|
325
497
|
exports.jsHandler = jsHandler;
|
|
498
|
+
exports.preProcessJs = preProcessJs;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as postcss_lib_no_work_result from 'postcss/lib/no-work-result';
|
|
2
|
+
import postcss from 'postcss';
|
|
1
3
|
import { ClassGenerator } from '@tailwindcss-mangle/shared';
|
|
2
4
|
export { ClassGenerator } from '@tailwindcss-mangle/shared';
|
|
3
5
|
import { StringLiteral, TemplateElement } from '@babel/types';
|
|
@@ -5,7 +7,7 @@ import { BabelFileResult } from '@babel/core';
|
|
|
5
7
|
|
|
6
8
|
interface IClassGeneratorContextItem {
|
|
7
9
|
name: string;
|
|
8
|
-
usedBy:
|
|
10
|
+
usedBy: string[];
|
|
9
11
|
}
|
|
10
12
|
interface IClassGeneratorOptions {
|
|
11
13
|
reserveClassName?: (string | RegExp)[];
|
|
@@ -17,8 +19,8 @@ interface IClassGeneratorOptions {
|
|
|
17
19
|
classPrefix?: string;
|
|
18
20
|
}
|
|
19
21
|
interface IHandlerOptions {
|
|
20
|
-
runtimeSet: Set<string>;
|
|
21
22
|
classGenerator: ClassGenerator;
|
|
23
|
+
replaceMap: Map<string, string>;
|
|
22
24
|
}
|
|
23
25
|
interface IHtmlHandlerOptions extends IHandlerOptions {
|
|
24
26
|
}
|
|
@@ -27,8 +29,8 @@ interface IJsHandlerOptions extends IHandlerOptions {
|
|
|
27
29
|
minified?: boolean;
|
|
28
30
|
}
|
|
29
31
|
interface ICssHandlerOptions extends IHandlerOptions {
|
|
30
|
-
scene?: 'loader' | 'process';
|
|
31
32
|
ignoreVueScoped?: boolean;
|
|
33
|
+
file?: string;
|
|
32
34
|
}
|
|
33
35
|
interface ClassSetOutputOptions {
|
|
34
36
|
filename: string;
|
|
@@ -47,11 +49,18 @@ interface Options {
|
|
|
47
49
|
classMapOutput?: boolean | ClassMapOutputOptions;
|
|
48
50
|
}
|
|
49
51
|
|
|
50
|
-
declare function cssHandler(rawSource: string, options: ICssHandlerOptions):
|
|
52
|
+
declare function cssHandler(rawSource: string, options: ICssHandlerOptions): postcss.LazyResult | postcss_lib_no_work_result.default;
|
|
51
53
|
|
|
52
54
|
declare function htmlHandler(rawSource: string, options: IHtmlHandlerOptions): string;
|
|
53
55
|
|
|
54
|
-
declare function
|
|
56
|
+
declare function preProcessJs(options: {
|
|
57
|
+
code: string;
|
|
58
|
+
replaceMap: Map<string, string>;
|
|
59
|
+
id: string;
|
|
60
|
+
addToUsedBy: (key: string, file: string) => void;
|
|
61
|
+
}): string;
|
|
62
|
+
|
|
63
|
+
declare function handleValue(raw: string, node: StringLiteral | TemplateElement, options: IJsHandlerOptions): string;
|
|
55
64
|
declare function jsHandler(rawSource: string, options: IJsHandlerOptions): BabelFileResult;
|
|
56
65
|
|
|
57
|
-
export { ClassMapOutputOptions, ClassSetOutputOptions, IClassGeneratorContextItem, IClassGeneratorOptions, ICssHandlerOptions, IHandlerOptions, IHtmlHandlerOptions, IJsHandlerOptions, Options, cssHandler, handleValue, htmlHandler, jsHandler };
|
|
66
|
+
export { ClassMapOutputOptions, ClassSetOutputOptions, IClassGeneratorContextItem, IClassGeneratorOptions, ICssHandlerOptions, IHandlerOptions, IHtmlHandlerOptions, IJsHandlerOptions, Options, cssHandler, handleValue, htmlHandler, jsHandler, preProcessJs };
|
package/dist/index.mjs
CHANGED
|
@@ -3,8 +3,9 @@ import parser from 'postcss-selector-parser';
|
|
|
3
3
|
import { html, defaultTreeAdapter, parse, serialize } from 'parse5';
|
|
4
4
|
import { splitCode, makeRegex } from '@tailwindcss-mangle/shared';
|
|
5
5
|
export { ClassGenerator } from '@tailwindcss-mangle/shared';
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
6
|
+
import babel, { transformSync } from '@babel/core';
|
|
7
|
+
import { declare } from '@babel/helper-plugin-utils';
|
|
8
|
+
import MagicString from 'magic-string';
|
|
8
9
|
|
|
9
10
|
function isObject(value) {
|
|
10
11
|
return value !== null && typeof value === "object";
|
|
@@ -61,64 +62,41 @@ function isVueScoped(s) {
|
|
|
61
62
|
}
|
|
62
63
|
return false;
|
|
63
64
|
}
|
|
64
|
-
const
|
|
65
|
-
const { ignoreVueScoped } = defu(options, {
|
|
65
|
+
const transformSelectorPostcssPlugin = function(options) {
|
|
66
|
+
const { ignoreVueScoped, replaceMap } = defu(options, {
|
|
66
67
|
ignoreVueScoped: true
|
|
67
68
|
});
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
rule.selector = parser((selectors) => {
|
|
77
|
-
selectors.walkClasses((s) => {
|
|
78
|
-
if (s.value) {
|
|
79
|
-
const existed = set.has(s.value);
|
|
80
|
-
if (existed) {
|
|
81
|
-
if (ignoreVueScoped && isVueScoped(s)) {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
s.value = options.classGenerator.generateClassName(s.value).name;
|
|
85
|
-
}
|
|
69
|
+
return {
|
|
70
|
+
postcssPlugin,
|
|
71
|
+
async Rule(rule) {
|
|
72
|
+
await parser((selectors) => {
|
|
73
|
+
selectors.walkClasses((s) => {
|
|
74
|
+
if (s.value && replaceMap && replaceMap.has(s.value)) {
|
|
75
|
+
if (ignoreVueScoped && isVueScoped(s)) {
|
|
76
|
+
return;
|
|
86
77
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
};
|
|
91
|
-
} else {
|
|
92
|
-
let newClassMap = {};
|
|
93
|
-
if (options && options.classGenerator) {
|
|
94
|
-
newClassMap = options.classGenerator.newClassMap;
|
|
95
|
-
}
|
|
96
|
-
return {
|
|
97
|
-
postcssPlugin,
|
|
98
|
-
Rule(rule) {
|
|
99
|
-
rule.selector = parser((selectors) => {
|
|
100
|
-
selectors.walkClasses((s) => {
|
|
101
|
-
if (s.value) {
|
|
102
|
-
const hit = newClassMap[s.value];
|
|
103
|
-
const existed = Boolean(hit);
|
|
104
|
-
if (existed) {
|
|
105
|
-
if (ignoreVueScoped && isVueScoped(s)) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
s.value = hit.name;
|
|
109
|
-
}
|
|
78
|
+
const v = replaceMap.get(s.value);
|
|
79
|
+
if (v) {
|
|
80
|
+
s.value = v;
|
|
110
81
|
}
|
|
111
|
-
}
|
|
112
|
-
})
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}).transform(rule, {
|
|
85
|
+
lossless: false,
|
|
86
|
+
updateSelector: true
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
};
|
|
116
90
|
};
|
|
117
|
-
|
|
91
|
+
transformSelectorPostcssPlugin.postcss = true;
|
|
118
92
|
|
|
119
93
|
function cssHandler(rawSource, options) {
|
|
120
|
-
const acceptedPlugins = [
|
|
121
|
-
|
|
94
|
+
const acceptedPlugins = [transformSelectorPostcssPlugin(options)];
|
|
95
|
+
const { file } = options;
|
|
96
|
+
return postcss(acceptedPlugins).process(rawSource, {
|
|
97
|
+
from: file,
|
|
98
|
+
to: file
|
|
99
|
+
});
|
|
122
100
|
}
|
|
123
101
|
|
|
124
102
|
({
|
|
@@ -215,7 +193,7 @@ function traverse(node, visitor, parent) {
|
|
|
215
193
|
}
|
|
216
194
|
|
|
217
195
|
function htmlHandler(rawSource, options) {
|
|
218
|
-
const {
|
|
196
|
+
const { replaceMap, classGenerator } = options;
|
|
219
197
|
const fragment = parse(rawSource);
|
|
220
198
|
traverse(fragment, {
|
|
221
199
|
element(node) {
|
|
@@ -225,7 +203,7 @@ function htmlHandler(rawSource, options) {
|
|
|
225
203
|
splitQuote: false
|
|
226
204
|
});
|
|
227
205
|
for (const v of array) {
|
|
228
|
-
if (
|
|
206
|
+
if (replaceMap.has(v)) {
|
|
229
207
|
attribute.value = attribute.value.replace(makeRegex(v), classGenerator.generateClassName(v).name);
|
|
230
208
|
}
|
|
231
209
|
}
|
|
@@ -237,14 +215,213 @@ function htmlHandler(rawSource, options) {
|
|
|
237
215
|
|
|
238
216
|
const isProd = () => process.env.NODE_ENV === "production";
|
|
239
217
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
218
|
+
// >>> INTERFACES <<<
|
|
219
|
+
// >>> HELPERS <<<
|
|
220
|
+
var castComparer = function (comparer) { return function (a, b, order) { return comparer(a, b, order) * order; }; };
|
|
221
|
+
var throwInvalidConfigErrorIfTrue = function (condition, context) {
|
|
222
|
+
if (condition)
|
|
223
|
+
throw Error("Invalid sort config: " + context);
|
|
224
|
+
};
|
|
225
|
+
var unpackObjectSorter = function (sortByObj) {
|
|
226
|
+
var _a = sortByObj || {}, asc = _a.asc, desc = _a.desc;
|
|
227
|
+
var order = asc ? 1 : -1;
|
|
228
|
+
var sortBy = (asc || desc);
|
|
229
|
+
// Validate object config
|
|
230
|
+
throwInvalidConfigErrorIfTrue(!sortBy, 'Expected `asc` or `desc` property');
|
|
231
|
+
throwInvalidConfigErrorIfTrue(asc && desc, 'Ambiguous object with `asc` and `desc` config properties');
|
|
232
|
+
var comparer = sortByObj.comparer && castComparer(sortByObj.comparer);
|
|
233
|
+
return { order: order, sortBy: sortBy, comparer: comparer };
|
|
234
|
+
};
|
|
235
|
+
// >>> SORTERS <<<
|
|
236
|
+
var multiPropertySorterProvider = function (defaultComparer) {
|
|
237
|
+
return function multiPropertySorter(sortBy, sortByArr, depth, order, comparer, a, b) {
|
|
238
|
+
var valA;
|
|
239
|
+
var valB;
|
|
240
|
+
if (typeof sortBy === 'string') {
|
|
241
|
+
valA = a[sortBy];
|
|
242
|
+
valB = b[sortBy];
|
|
243
|
+
}
|
|
244
|
+
else if (typeof sortBy === 'function') {
|
|
245
|
+
valA = sortBy(a);
|
|
246
|
+
valB = sortBy(b);
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
var objectSorterConfig = unpackObjectSorter(sortBy);
|
|
250
|
+
return multiPropertySorter(objectSorterConfig.sortBy, sortByArr, depth, objectSorterConfig.order, objectSorterConfig.comparer || defaultComparer, a, b);
|
|
251
|
+
}
|
|
252
|
+
var equality = comparer(valA, valB, order);
|
|
253
|
+
if ((equality === 0 || (valA == null && valB == null)) &&
|
|
254
|
+
sortByArr.length > depth) {
|
|
255
|
+
return multiPropertySorter(sortByArr[depth], sortByArr, depth + 1, order, comparer, a, b);
|
|
256
|
+
}
|
|
257
|
+
return equality;
|
|
258
|
+
};
|
|
259
|
+
};
|
|
260
|
+
function getSortStrategy(sortBy, comparer, order) {
|
|
261
|
+
// Flat array sorter
|
|
262
|
+
if (sortBy === undefined || sortBy === true) {
|
|
263
|
+
return function (a, b) { return comparer(a, b, order); };
|
|
264
|
+
}
|
|
265
|
+
// Sort list of objects by single object key
|
|
266
|
+
if (typeof sortBy === 'string') {
|
|
267
|
+
throwInvalidConfigErrorIfTrue(sortBy.includes('.'), 'String syntax not allowed for nested properties.');
|
|
268
|
+
return function (a, b) { return comparer(a[sortBy], b[sortBy], order); };
|
|
269
|
+
}
|
|
270
|
+
// Sort list of objects by single function sorter
|
|
271
|
+
if (typeof sortBy === 'function') {
|
|
272
|
+
return function (a, b) { return comparer(sortBy(a), sortBy(b), order); };
|
|
273
|
+
}
|
|
274
|
+
// Sort by multiple properties
|
|
275
|
+
if (Array.isArray(sortBy)) {
|
|
276
|
+
var multiPropSorter_1 = multiPropertySorterProvider(comparer);
|
|
277
|
+
return function (a, b) { return multiPropSorter_1(sortBy[0], sortBy, 1, order, comparer, a, b); };
|
|
278
|
+
}
|
|
279
|
+
// Unpack object config to get actual sorter strategy
|
|
280
|
+
var objectSorterConfig = unpackObjectSorter(sortBy);
|
|
281
|
+
return getSortStrategy(objectSorterConfig.sortBy, objectSorterConfig.comparer || comparer, objectSorterConfig.order);
|
|
282
|
+
}
|
|
283
|
+
var sortArray = function (order, ctx, sortBy, comparer) {
|
|
284
|
+
var _a;
|
|
285
|
+
if (!Array.isArray(ctx)) {
|
|
286
|
+
return ctx;
|
|
287
|
+
}
|
|
288
|
+
// Unwrap sortBy if array with only 1 value to get faster sort strategy
|
|
289
|
+
if (Array.isArray(sortBy) && sortBy.length < 2) {
|
|
290
|
+
_a = sortBy, sortBy = _a[0];
|
|
291
|
+
}
|
|
292
|
+
return ctx.sort(getSortStrategy(sortBy, comparer, order));
|
|
293
|
+
};
|
|
294
|
+
function createNewSortInstance(opts) {
|
|
295
|
+
var comparer = castComparer(opts.comparer);
|
|
296
|
+
return function (arrayToSort) {
|
|
297
|
+
var ctx = Array.isArray(arrayToSort) && !opts.inPlaceSorting
|
|
298
|
+
? arrayToSort.slice()
|
|
299
|
+
: arrayToSort;
|
|
300
|
+
return {
|
|
301
|
+
asc: function (sortBy) {
|
|
302
|
+
return sortArray(1, ctx, sortBy, comparer);
|
|
303
|
+
},
|
|
304
|
+
desc: function (sortBy) {
|
|
305
|
+
return sortArray(-1, ctx, sortBy, comparer);
|
|
306
|
+
},
|
|
307
|
+
by: function (sortBy) {
|
|
308
|
+
return sortArray(1, ctx, sortBy, comparer);
|
|
309
|
+
},
|
|
310
|
+
};
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
var defaultComparer = function (a, b, order) {
|
|
314
|
+
if (a == null)
|
|
315
|
+
return order;
|
|
316
|
+
if (b == null)
|
|
317
|
+
return -order;
|
|
318
|
+
if (typeof a !== typeof b) {
|
|
319
|
+
return typeof a < typeof b ? -1 : 1;
|
|
320
|
+
}
|
|
321
|
+
if (a < b)
|
|
322
|
+
return -1;
|
|
323
|
+
if (a > b)
|
|
324
|
+
return 1;
|
|
325
|
+
return 0;
|
|
326
|
+
};
|
|
327
|
+
var sort = createNewSortInstance({
|
|
328
|
+
comparer: defaultComparer,
|
|
329
|
+
});
|
|
330
|
+
createNewSortInstance({
|
|
331
|
+
comparer: defaultComparer,
|
|
332
|
+
inPlaceSorting: true,
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
function handleValue$1(options) {
|
|
336
|
+
const { addToUsedBy, id, magicString, node, raw, replaceMap, offset = 0 } = options;
|
|
337
|
+
let value = raw;
|
|
338
|
+
const arr = sort(splitCode(value)).desc((x) => x.length);
|
|
339
|
+
for (const str of arr) {
|
|
340
|
+
if (replaceMap.has(str)) {
|
|
341
|
+
addToUsedBy(str, id);
|
|
342
|
+
const v = replaceMap.get(str);
|
|
343
|
+
if (v) {
|
|
344
|
+
value = value.replaceAll(str, v);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (typeof node.start === "number" && typeof node.end === "number" && value) {
|
|
349
|
+
magicString.update(node.start + offset, node.end - offset, value);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
const plugin = declare((api, options) => {
|
|
353
|
+
api.assertVersion(7);
|
|
354
|
+
const { magicString, replaceMap, id, addToUsedBy } = options;
|
|
355
|
+
return {
|
|
356
|
+
visitor: {
|
|
357
|
+
StringLiteral: {
|
|
358
|
+
enter(p) {
|
|
359
|
+
const node = p.node;
|
|
360
|
+
handleValue$1({
|
|
361
|
+
addToUsedBy,
|
|
362
|
+
id,
|
|
363
|
+
magicString,
|
|
364
|
+
node,
|
|
365
|
+
raw: node.value,
|
|
366
|
+
replaceMap,
|
|
367
|
+
offset: 1
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
TemplateElement: {
|
|
372
|
+
enter(p) {
|
|
373
|
+
const node = p.node;
|
|
374
|
+
handleValue$1({
|
|
375
|
+
addToUsedBy,
|
|
376
|
+
id,
|
|
377
|
+
magicString,
|
|
378
|
+
node,
|
|
379
|
+
raw: node.value.raw,
|
|
380
|
+
replaceMap,
|
|
381
|
+
offset: 0
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
});
|
|
388
|
+
function preProcessJs(options) {
|
|
389
|
+
const { code, replaceMap, id, addToUsedBy } = options;
|
|
390
|
+
const magicString = new MagicString(code);
|
|
391
|
+
babel.transformSync(code, {
|
|
392
|
+
presets: [
|
|
393
|
+
// ['@babel/preset-react', {}],
|
|
394
|
+
[
|
|
395
|
+
"@babel/preset-typescript",
|
|
396
|
+
{
|
|
397
|
+
allExtensions: true,
|
|
398
|
+
isTSX: true
|
|
399
|
+
}
|
|
400
|
+
]
|
|
401
|
+
],
|
|
402
|
+
plugins: [
|
|
403
|
+
[
|
|
404
|
+
plugin,
|
|
405
|
+
{
|
|
406
|
+
magicString,
|
|
407
|
+
replaceMap,
|
|
408
|
+
id,
|
|
409
|
+
addToUsedBy
|
|
410
|
+
}
|
|
411
|
+
]
|
|
412
|
+
]
|
|
413
|
+
});
|
|
414
|
+
return magicString.toString();
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function handleValue(raw, node, options) {
|
|
418
|
+
const { replaceMap, classGenerator: clsGen, splitQuote = true } = options;
|
|
419
|
+
const array = splitCode(raw, {
|
|
243
420
|
splitQuote
|
|
244
421
|
});
|
|
245
|
-
let rawString =
|
|
422
|
+
let rawString = raw;
|
|
246
423
|
for (const v of array) {
|
|
247
|
-
if (
|
|
424
|
+
if (replaceMap.has(v)) {
|
|
248
425
|
let ignoreFlag = false;
|
|
249
426
|
if (Array.isArray(node.leadingComments)) {
|
|
250
427
|
ignoreFlag = node.leadingComments.findIndex((x) => x.value.includes("tw-mangle") && x.value.includes("ignore")) > -1;
|
|
@@ -278,12 +455,18 @@ function jsHandler(rawSource, options) {
|
|
|
278
455
|
},
|
|
279
456
|
CallExpression: {
|
|
280
457
|
enter(p) {
|
|
281
|
-
const
|
|
282
|
-
if (
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
458
|
+
const calleePath = p.get("callee");
|
|
459
|
+
if (calleePath.isIdentifier() && calleePath.node.name === "eval") {
|
|
460
|
+
p.traverse({
|
|
461
|
+
StringLiteral: {
|
|
462
|
+
enter(s) {
|
|
463
|
+
const res = jsHandler(s.node.value, options);
|
|
464
|
+
if (res.code) {
|
|
465
|
+
s.node.value = res.code;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
});
|
|
287
470
|
}
|
|
288
471
|
}
|
|
289
472
|
}
|
|
@@ -299,4 +482,4 @@ function jsHandler(rawSource, options) {
|
|
|
299
482
|
return result;
|
|
300
483
|
}
|
|
301
484
|
|
|
302
|
-
export { cssHandler, handleValue, htmlHandler, jsHandler };
|
|
485
|
+
export { cssHandler, handleValue, htmlHandler, jsHandler, preProcessJs };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tailwindcss-mangle/core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "The core of tailwindcss-mangle",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -36,12 +36,15 @@
|
|
|
36
36
|
"registry": "https://registry.npmjs.org/"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
+
"@babel/helper-plugin-utils": "^7.22.5",
|
|
40
|
+
"@babel/preset-typescript": "^7.22.5",
|
|
39
41
|
"@babel/core": "^7.22.10",
|
|
40
42
|
"@babel/types": "^7.22.10",
|
|
41
43
|
"parse5": "^7.1.2",
|
|
42
44
|
"postcss": "^8.4.27",
|
|
43
45
|
"postcss-selector-parser": "^6.0.13",
|
|
44
|
-
"
|
|
46
|
+
"magic-string": "^0.30.2",
|
|
47
|
+
"@tailwindcss-mangle/shared": "^2.0.0"
|
|
45
48
|
},
|
|
46
49
|
"devDependencies": {
|
|
47
50
|
"@parse5/tools": "^0.2.0",
|
|
@@ -54,7 +57,7 @@
|
|
|
54
57
|
},
|
|
55
58
|
"scripts": {
|
|
56
59
|
"build": "unbuild",
|
|
57
|
-
"test": "vitest run",
|
|
60
|
+
"test": "vitest run --coverage.enabled",
|
|
58
61
|
"test:dev": "vitest",
|
|
59
62
|
"coverage": "vitest run --coverage"
|
|
60
63
|
}
|