@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 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 t = require('@babel/types');
8
- const core = require('@babel/core');
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 t__namespace = /*#__PURE__*/_interopNamespaceCompat(t);
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 postcssMangleTailwindcssPlugin = (options) => {
84
- const { ignoreVueScoped } = defu(options, {
73
+ const transformSelectorPostcssPlugin = function(options) {
74
+ const { ignoreVueScoped, replaceMap } = defu(options, {
85
75
  ignoreVueScoped: true
86
76
  });
87
- if (options?.scene === "loader") {
88
- let set = /* @__PURE__ */ new Set();
89
- if (options && options.runtimeSet) {
90
- set = options.runtimeSet;
91
- }
92
- return {
93
- postcssPlugin,
94
- Rule(rule) {
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
- }).processSync(rule.selector);
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
- }).processSync(rule.selector);
132
- }
133
- };
134
- }
90
+ }
91
+ });
92
+ }).transform(rule, {
93
+ lossless: false,
94
+ updateSelector: true
95
+ });
96
+ }
97
+ };
135
98
  };
136
- postcssMangleTailwindcssPlugin.postcss = true;
99
+ transformSelectorPostcssPlugin.postcss = true;
137
100
 
138
101
  function cssHandler(rawSource, options) {
139
- const acceptedPlugins = [postcssMangleTailwindcssPlugin(options)];
140
- return postcss__default(acceptedPlugins).process(rawSource).css;
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 { runtimeSet, classGenerator } = options;
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 (runtimeSet.has(v)) {
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
- function handleValue(string_, node, options) {
260
- const { runtimeSet: set, classGenerator: clsGen, splitQuote = true } = options;
261
- const array = shared.splitCode(string_, {
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 = string_;
430
+ let rawString = raw;
265
431
  for (const v of array) {
266
- if (set.has(v)) {
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 = core.transformSync(rawSource, {
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 n = p.node;
301
- if (t__namespace.isIdentifier(n.callee) && n.callee.name === "eval" && t__namespace.isStringLiteral(n.arguments[0])) {
302
- const res = jsHandler(n.arguments[0].value, options);
303
- if (res.code) {
304
- n.arguments[0].value = res.code;
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: any[];
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): string;
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 handleValue(string_: string, node: StringLiteral | TemplateElement, options: IJsHandlerOptions): string;
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 * as t from '@babel/types';
7
- import { transformSync } from '@babel/core';
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 postcssMangleTailwindcssPlugin = (options) => {
65
- const { ignoreVueScoped } = defu(options, {
65
+ const transformSelectorPostcssPlugin = function(options) {
66
+ const { ignoreVueScoped, replaceMap } = defu(options, {
66
67
  ignoreVueScoped: true
67
68
  });
68
- if (options?.scene === "loader") {
69
- let set = /* @__PURE__ */ new Set();
70
- if (options && options.runtimeSet) {
71
- set = options.runtimeSet;
72
- }
73
- return {
74
- postcssPlugin,
75
- Rule(rule) {
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
- }).processSync(rule.selector);
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
- }).processSync(rule.selector);
113
- }
114
- };
115
- }
82
+ }
83
+ });
84
+ }).transform(rule, {
85
+ lossless: false,
86
+ updateSelector: true
87
+ });
88
+ }
89
+ };
116
90
  };
117
- postcssMangleTailwindcssPlugin.postcss = true;
91
+ transformSelectorPostcssPlugin.postcss = true;
118
92
 
119
93
  function cssHandler(rawSource, options) {
120
- const acceptedPlugins = [postcssMangleTailwindcssPlugin(options)];
121
- return postcss(acceptedPlugins).process(rawSource).css;
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 { runtimeSet, classGenerator } = options;
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 (runtimeSet.has(v)) {
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
- function handleValue(string_, node, options) {
241
- const { runtimeSet: set, classGenerator: clsGen, splitQuote = true } = options;
242
- const array = splitCode(string_, {
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 = string_;
422
+ let rawString = raw;
246
423
  for (const v of array) {
247
- if (set.has(v)) {
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 n = p.node;
282
- if (t.isIdentifier(n.callee) && n.callee.name === "eval" && t.isStringLiteral(n.arguments[0])) {
283
- const res = jsHandler(n.arguments[0].value, options);
284
- if (res.code) {
285
- n.arguments[0].value = res.code;
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": "1.2.7",
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
- "@tailwindcss-mangle/shared": "^1.2.7"
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
  }