@tailwindcss-mangle/core 2.1.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,9 +1,14 @@
1
+ import fs from 'node:fs';
2
+ import { resolve, isAbsolute } from 'node:path';
3
+ import { ClassGenerator, defaultMangleClassFilter, splitCode, makeRegex } from '@tailwindcss-mangle/shared';
4
+ export { ClassGenerator } from '@tailwindcss-mangle/shared';
5
+ import { getConfig } from '@tailwindcss-mangle/config';
6
+ import { sort } from 'fast-sort';
7
+ import micromatch from 'micromatch';
1
8
  import postcss from 'postcss';
2
9
  import parser from 'postcss-selector-parser';
3
10
  import { html, defaultTreeAdapter, parse, serialize } from 'parse5';
4
- import { splitCode, makeRegex } from '@tailwindcss-mangle/shared';
5
- export { ClassGenerator } from '@tailwindcss-mangle/shared';
6
- import babel, { transformSync } from '@babel/core';
11
+ import babel, { transformSync as transformSync$1 } from '@babel/core';
7
12
  import { declare } from '@babel/helper-plugin-utils';
8
13
  import MagicString from 'magic-string';
9
14
  import { jsStringEscape } from '@ast-core/escape';
@@ -59,7 +64,126 @@ function createDefu(merger) {
59
64
  }
60
65
  const defu = createDefu();
61
66
 
67
+ const { isMatch } = micromatch;
68
+ function escapeStringRegexp(str) {
69
+ if (typeof str !== "string") {
70
+ throw new TypeError("Expected a string");
71
+ }
72
+ return str.replaceAll(/[$()*+.?[\\\]^{|}]/g, "\\$&").replaceAll("-", "\\x2d");
73
+ }
74
+ function createGlobMatcher(pattern, fallbackValue = false) {
75
+ if (pattern === void 0) {
76
+ return function() {
77
+ return fallbackValue;
78
+ };
79
+ }
80
+ return function(file) {
81
+ return isMatch(file, pattern);
82
+ };
83
+ }
84
+
85
+ var __defProp = Object.defineProperty;
86
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
87
+ var __publicField = (obj, key, value) => {
88
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
89
+ return value;
90
+ };
91
+ class Context {
92
+ constructor() {
93
+ __publicField(this, "options");
94
+ __publicField(this, "includeMatcher");
95
+ __publicField(this, "excludeMatcher");
96
+ __publicField(this, "replaceMap");
97
+ __publicField(this, "classSet");
98
+ __publicField(this, "classGenerator");
99
+ __publicField(this, "preserveFunctionSet");
100
+ __publicField(this, "preserveClassNamesSet");
101
+ __publicField(this, "preserveFunctionRegexs");
102
+ this.options = {};
103
+ this.classSet = /* @__PURE__ */ new Set();
104
+ this.replaceMap = /* @__PURE__ */ new Map();
105
+ this.includeMatcher = () => true;
106
+ this.excludeMatcher = () => false;
107
+ this.classGenerator = new 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.includeMatcher = createGlobMatcher(this.options.include, true);
124
+ this.excludeMatcher = createGlobMatcher(this.options.exclude, false);
125
+ this.classGenerator = new ClassGenerator(this.options.classGenerator);
126
+ this.preserveFunctionSet = new Set(this.options?.preserveFunction ?? []);
127
+ this.preserveFunctionRegexs = [...this.preserveFunctionSet.values()].map((x) => {
128
+ return new RegExp(escapeStringRegexp(x) + "\\(([^)]*)\\)", "g");
129
+ });
130
+ }
131
+ isInclude(file) {
132
+ return this.includeMatcher(file) && !this.excludeMatcher(file);
133
+ }
134
+ currentMangleClassFilter(className) {
135
+ return (this.options.mangleClassFilter ?? defaultMangleClassFilter)(className);
136
+ }
137
+ getClassSet() {
138
+ return this.classSet;
139
+ }
140
+ getReplaceMap() {
141
+ return this.replaceMap;
142
+ }
143
+ addToUsedBy(key, file) {
144
+ const hit = this.classGenerator.newClassMap[key];
145
+ if (hit) {
146
+ hit.usedBy.add(file);
147
+ }
148
+ }
149
+ loadClassSet(classList) {
150
+ const list = sort(classList).desc((c) => c.length);
151
+ for (const className of list) {
152
+ if (this.currentMangleClassFilter(className)) {
153
+ this.classSet.add(className);
154
+ }
155
+ }
156
+ }
157
+ async initConfig(opts = {}) {
158
+ const { cwd, classList: _classList, mangleOptions } = opts;
159
+ const { config, cwd: configCwd } = await getConfig(cwd);
160
+ this.mergeOptions(mangleOptions, config?.mangle);
161
+ if (_classList) {
162
+ this.loadClassSet(_classList);
163
+ } else {
164
+ let jsonPath = this.options.classListPath ?? resolve(process.cwd(), config?.patch?.output?.filename);
165
+ if (!isAbsolute(jsonPath)) {
166
+ jsonPath = resolve(configCwd ?? process.cwd(), jsonPath);
167
+ }
168
+ if (jsonPath && fs.existsSync(jsonPath)) {
169
+ const rawClassList = fs.readFileSync(jsonPath, "utf8");
170
+ const list = JSON.parse(rawClassList);
171
+ this.loadClassSet(list);
172
+ }
173
+ }
174
+ for (const cls of this.classSet) {
175
+ this.classGenerator.generateClassName(cls);
176
+ }
177
+ for (const x of Object.entries(this.classGenerator.newClassMap)) {
178
+ this.replaceMap.set(x[0], x[1].name);
179
+ }
180
+ return config;
181
+ }
182
+ // ["clsx\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"]
183
+ }
184
+
62
185
  const postcssPlugin = "postcss-mangle-tailwindcss-plugin";
186
+ const clonedKey = "__tw_mangle_cloned__";
63
187
  function isVueScoped(s) {
64
188
  if (s.parent) {
65
189
  const index = s.parent.nodes.indexOf(s);
@@ -73,12 +197,15 @@ function isVueScoped(s) {
73
197
  return false;
74
198
  }
75
199
  const transformSelectorPostcssPlugin = function(options) {
76
- const { ignoreVueScoped, replaceMap } = defu(options, {
200
+ const { ignoreVueScoped, replaceMap, ctx } = defu(options, {
77
201
  ignoreVueScoped: true
78
202
  });
79
203
  return {
80
204
  postcssPlugin,
81
205
  async Rule(rule) {
206
+ if (rule[clonedKey]) {
207
+ return;
208
+ }
82
209
  await parser((selectors) => {
83
210
  selectors.walkClasses((s) => {
84
211
  if (s.value && replaceMap && replaceMap.has(s.value)) {
@@ -87,6 +214,10 @@ const transformSelectorPostcssPlugin = function(options) {
87
214
  }
88
215
  const v = replaceMap.get(s.value);
89
216
  if (v) {
217
+ if (ctx.isPreserveClass(s.value)) {
218
+ const r = rule.cloneBefore();
219
+ r[clonedKey] = true;
220
+ }
90
221
  s.value = v;
91
222
  }
92
223
  }
@@ -203,7 +334,7 @@ function traverse(node, visitor, parent) {
203
334
  }
204
335
 
205
336
  function htmlHandler(rawSource, options) {
206
- const { replaceMap, classGenerator } = options;
337
+ const { replaceMap, ctx } = options;
207
338
  const fragment = parse(rawSource);
208
339
  traverse(fragment, {
209
340
  element(node) {
@@ -214,7 +345,7 @@ function htmlHandler(rawSource, options) {
214
345
  });
215
346
  for (const v of array) {
216
347
  if (replaceMap.has(v)) {
217
- attribute.value = attribute.value.replace(makeRegex(v), classGenerator.generateClassName(v).name);
348
+ attribute.value = attribute.value.replace(makeRegex(v), ctx.classGenerator.generateClassName(v).name);
218
349
  }
219
350
  }
220
351
  }
@@ -225,130 +356,26 @@ function htmlHandler(rawSource, options) {
225
356
 
226
357
  const isProd = () => process.env.NODE_ENV === "production";
227
358
 
228
- // >>> INTERFACES <<<
229
- // >>> HELPERS <<<
230
- var castComparer = function (comparer) { return function (a, b, order) { return comparer(a, b, order) * order; }; };
231
- var throwInvalidConfigErrorIfTrue = function (condition, context) {
232
- if (condition)
233
- throw Error("Invalid sort config: " + context);
234
- };
235
- var unpackObjectSorter = function (sortByObj) {
236
- var _a = sortByObj || {}, asc = _a.asc, desc = _a.desc;
237
- var order = asc ? 1 : -1;
238
- var sortBy = (asc || desc);
239
- // Validate object config
240
- throwInvalidConfigErrorIfTrue(!sortBy, 'Expected `asc` or `desc` property');
241
- throwInvalidConfigErrorIfTrue(asc && desc, 'Ambiguous object with `asc` and `desc` config properties');
242
- var comparer = sortByObj.comparer && castComparer(sortByObj.comparer);
243
- return { order: order, sortBy: sortBy, comparer: comparer };
244
- };
245
- // >>> SORTERS <<<
246
- var multiPropertySorterProvider = function (defaultComparer) {
247
- return function multiPropertySorter(sortBy, sortByArr, depth, order, comparer, a, b) {
248
- var valA;
249
- var valB;
250
- if (typeof sortBy === 'string') {
251
- valA = a[sortBy];
252
- valB = b[sortBy];
253
- }
254
- else if (typeof sortBy === 'function') {
255
- valA = sortBy(a);
256
- valB = sortBy(b);
257
- }
258
- else {
259
- var objectSorterConfig = unpackObjectSorter(sortBy);
260
- return multiPropertySorter(objectSorterConfig.sortBy, sortByArr, depth, objectSorterConfig.order, objectSorterConfig.comparer || defaultComparer, a, b);
261
- }
262
- var equality = comparer(valA, valB, order);
263
- if ((equality === 0 || (valA == null && valB == null)) &&
264
- sortByArr.length > depth) {
265
- return multiPropertySorter(sortByArr[depth], sortByArr, depth + 1, order, comparer, a, b);
266
- }
267
- return equality;
268
- };
269
- };
270
- function getSortStrategy(sortBy, comparer, order) {
271
- // Flat array sorter
272
- if (sortBy === undefined || sortBy === true) {
273
- return function (a, b) { return comparer(a, b, order); };
274
- }
275
- // Sort list of objects by single object key
276
- if (typeof sortBy === 'string') {
277
- throwInvalidConfigErrorIfTrue(sortBy.includes('.'), 'String syntax not allowed for nested properties.');
278
- return function (a, b) { return comparer(a[sortBy], b[sortBy], order); };
279
- }
280
- // Sort list of objects by single function sorter
281
- if (typeof sortBy === 'function') {
282
- return function (a, b) { return comparer(sortBy(a), sortBy(b), order); };
283
- }
284
- // Sort by multiple properties
285
- if (Array.isArray(sortBy)) {
286
- var multiPropSorter_1 = multiPropertySorterProvider(comparer);
287
- return function (a, b) { return multiPropSorter_1(sortBy[0], sortBy, 1, order, comparer, a, b); };
288
- }
289
- // Unpack object config to get actual sorter strategy
290
- var objectSorterConfig = unpackObjectSorter(sortBy);
291
- return getSortStrategy(objectSorterConfig.sortBy, objectSorterConfig.comparer || comparer, objectSorterConfig.order);
292
- }
293
- var sortArray = function (order, ctx, sortBy, comparer) {
294
- var _a;
295
- if (!Array.isArray(ctx)) {
296
- return ctx;
297
- }
298
- // Unwrap sortBy if array with only 1 value to get faster sort strategy
299
- if (Array.isArray(sortBy) && sortBy.length < 2) {
300
- _a = sortBy, sortBy = _a[0];
301
- }
302
- return ctx.sort(getSortStrategy(sortBy, comparer, order));
303
- };
304
- function createNewSortInstance(opts) {
305
- var comparer = castComparer(opts.comparer);
306
- return function (arrayToSort) {
307
- var ctx = Array.isArray(arrayToSort) && !opts.inPlaceSorting
308
- ? arrayToSort.slice()
309
- : arrayToSort;
310
- return {
311
- asc: function (sortBy) {
312
- return sortArray(1, ctx, sortBy, comparer);
313
- },
314
- desc: function (sortBy) {
315
- return sortArray(-1, ctx, sortBy, comparer);
316
- },
317
- by: function (sortBy) {
318
- return sortArray(1, ctx, sortBy, comparer);
319
- },
320
- };
321
- };
322
- }
323
- var defaultComparer = function (a, b, order) {
324
- if (a == null)
325
- return order;
326
- if (b == null)
327
- return -order;
328
- if (typeof a !== typeof b) {
329
- return typeof a < typeof b ? -1 : 1;
330
- }
331
- if (a < b)
332
- return -1;
333
- if (a > b)
334
- return 1;
335
- return 0;
336
- };
337
- var sort = createNewSortInstance({
338
- comparer: defaultComparer,
339
- });
340
- createNewSortInstance({
341
- comparer: defaultComparer,
342
- inPlaceSorting: true,
343
- });
359
+ function between(x, min, max, included = false) {
360
+ if (typeof x !== "number") {
361
+ return false;
362
+ }
363
+ return included ? x >= min && x <= max : x > min && x < max;
364
+ }
344
365
 
345
366
  function handleValue$1(options) {
346
- const { addToUsedBy, id, magicString, node, raw, replaceMap, offset = 0, escape = false } = options;
367
+ const { ctx, id, path, magicString, raw, replaceMap, offset = 0, escape = false, markedArray } = options;
368
+ const node = path.node;
347
369
  let value = raw;
370
+ for (const [s, e] of markedArray) {
371
+ if (between(node.start, s, e) || between(node.end, s, e)) {
372
+ return;
373
+ }
374
+ }
348
375
  const arr = sort(splitCode(value)).desc((x) => x.length);
349
376
  for (const str of arr) {
350
377
  if (replaceMap.has(str)) {
351
- addToUsedBy(str, id);
378
+ ctx.addToUsedBy(str, id);
352
379
  const v = replaceMap.get(str);
353
380
  if (v) {
354
381
  value = value.replaceAll(str, v);
@@ -363,76 +390,208 @@ function handleValue$1(options) {
363
390
  }
364
391
  }
365
392
  }
366
- const plugin = declare((api, options) => {
393
+ const JsPlugin = declare((api, options) => {
367
394
  api.assertVersion(7);
368
- const { magicString, replaceMap, id, addToUsedBy } = options;
395
+ const { magicString, replaceMap, id, ctx, markedArray } = options;
369
396
  return {
370
397
  visitor: {
371
398
  StringLiteral: {
372
- enter(p) {
373
- const node = p.node;
374
- handleValue$1({
375
- addToUsedBy,
399
+ exit(p) {
400
+ const opts = {
401
+ ctx,
376
402
  id,
377
403
  magicString,
378
- node,
379
- raw: node.value,
404
+ path: p,
405
+ raw: p.node.value,
380
406
  replaceMap,
381
407
  offset: 1,
382
- escape: true
383
- });
408
+ escape: true,
409
+ markedArray
410
+ };
411
+ handleValue$1(opts);
384
412
  }
385
413
  },
386
414
  TemplateElement: {
387
- enter(p) {
388
- const node = p.node;
389
- handleValue$1({
390
- addToUsedBy,
415
+ exit(p) {
416
+ const opts = {
417
+ ctx,
391
418
  id,
392
419
  magicString,
393
- node,
394
- raw: node.value.raw,
420
+ path: p,
421
+ raw: p.node.value.raw,
395
422
  replaceMap,
396
423
  offset: 0,
397
- escape: false
398
- });
424
+ escape: false,
425
+ markedArray
426
+ };
427
+ handleValue$1(opts);
399
428
  }
400
429
  }
401
430
  }
402
431
  };
403
432
  });
433
+ function transformSync(ast, code, plugins, filename) {
434
+ babel.transformFromAstSync(ast, code, {
435
+ presets: loadPresets(),
436
+ plugins,
437
+ filename
438
+ });
439
+ }
440
+ function loadPresets() {
441
+ return [
442
+ [
443
+ require("@babel/preset-typescript"),
444
+ {
445
+ allExtensions: true,
446
+ isTSX: true
447
+ }
448
+ ]
449
+ ];
450
+ }
404
451
  function preProcessJs(options) {
405
- const { code, replaceMap, id, addToUsedBy } = options;
452
+ const { code, replaceMap, id, ctx } = options;
406
453
  const magicString = typeof code === "string" ? new MagicString(code) : code;
407
- babel.transformSync(magicString.original, {
408
- presets: [
409
- // ['@babel/preset-react', {}],
410
- [
411
- require("@babel/preset-typescript"),
412
- {
413
- allExtensions: true,
414
- isTSX: true
454
+ let ast;
455
+ try {
456
+ const file = babel.parseSync(magicString.original, {
457
+ sourceType: "unambiguous",
458
+ presets: loadPresets()
459
+ });
460
+ if (file) {
461
+ ast = file;
462
+ } else {
463
+ return code.toString();
464
+ }
465
+ } catch {
466
+ return code.toString();
467
+ }
468
+ const markedArray = [];
469
+ babel.traverse(ast, {
470
+ CallExpression: {
471
+ enter(p) {
472
+ const callee = p.get("callee");
473
+ if (callee.isIdentifier() && ctx.isPreserveFunction(callee.node.name)) {
474
+ if (p.node.start && p.node.end) {
475
+ markedArray.push([p.node.start, p.node.end]);
476
+ }
477
+ p.traverse({
478
+ StringLiteral: {
479
+ enter(path) {
480
+ const node = path.node;
481
+ const value = node.value;
482
+ const arr = sort(splitCode(value)).desc((x) => x.length);
483
+ for (const str of arr) {
484
+ if (replaceMap.has(str)) {
485
+ ctx.addPreserveClass(str);
486
+ }
487
+ }
488
+ }
489
+ },
490
+ TemplateElement: {
491
+ enter(path) {
492
+ const node = path.node;
493
+ const value = node.value.raw;
494
+ const arr = sort(splitCode(value)).desc((x) => x.length);
495
+ for (const str of arr) {
496
+ if (replaceMap.has(str)) {
497
+ ctx.addPreserveClass(str);
498
+ }
499
+ }
500
+ }
501
+ }
502
+ });
415
503
  }
416
- ]
417
- ],
418
- plugins: [
504
+ }
505
+ }
506
+ });
507
+ transformSync(
508
+ ast,
509
+ magicString.original,
510
+ [
419
511
  [
420
- plugin,
512
+ JsPlugin,
421
513
  {
422
514
  magicString,
423
515
  replaceMap,
424
516
  id,
425
- addToUsedBy
517
+ ctx,
518
+ markedArray
426
519
  }
427
520
  ]
428
521
  ],
429
- filename: id
430
- });
522
+ id
523
+ );
524
+ return magicString.toString();
525
+ }
526
+ function preProcessRawCode(options) {
527
+ const { code, replaceMap, ctx } = options;
528
+ const magicString = typeof code === "string" ? new MagicString(code) : code;
529
+ const markArr = [];
530
+ for (const regex of ctx.preserveFunctionRegexs) {
531
+ const allArr = [];
532
+ let arr = null;
533
+ while ((arr = regex.exec(magicString.original)) !== null) {
534
+ allArr.push(arr);
535
+ markArr.push([arr.index, arr.index + arr[0].length]);
536
+ }
537
+ for (const regExpMatch of allArr) {
538
+ let ast;
539
+ try {
540
+ ast = babel.parseSync(regExpMatch[0], {
541
+ sourceType: "unambiguous"
542
+ });
543
+ ast && babel.traverse(ast, {
544
+ StringLiteral: {
545
+ enter(p) {
546
+ const arr2 = sort(splitCode(p.node.value)).desc((x) => x.length);
547
+ for (const v of arr2) {
548
+ if (replaceMap.has(v)) {
549
+ ctx.addPreserveClass(v);
550
+ }
551
+ }
552
+ }
553
+ },
554
+ TemplateElement: {
555
+ enter(p) {
556
+ const arr2 = sort(splitCode(p.node.value.raw)).desc((x) => x.length);
557
+ for (const v of arr2) {
558
+ if (replaceMap.has(v)) {
559
+ ctx.addPreserveClass(v);
560
+ }
561
+ }
562
+ }
563
+ }
564
+ });
565
+ } catch {
566
+ continue;
567
+ }
568
+ }
569
+ }
570
+ for (const [key, value] of replaceMap) {
571
+ const regex = new RegExp(escapeStringRegexp(key), "g");
572
+ let arr = null;
573
+ while ((arr = regex.exec(magicString.original)) !== null) {
574
+ const start = arr.index;
575
+ const end = arr.index + arr[0].length;
576
+ let shouldUpdate = true;
577
+ for (const [ps, pe] of markArr) {
578
+ if (between(start, ps, pe) || between(end, ps, pe)) {
579
+ shouldUpdate = false;
580
+ break;
581
+ }
582
+ }
583
+ if (shouldUpdate) {
584
+ magicString.update(start, end, value);
585
+ markArr.push([start, end]);
586
+ }
587
+ }
588
+ }
431
589
  return magicString.toString();
432
590
  }
433
591
 
434
592
  function handleValue(raw, node, options) {
435
- const { replaceMap, classGenerator: clsGen, splitQuote = true } = options;
593
+ const { replaceMap, ctx, splitQuote = true } = options;
594
+ const clsGen = ctx.classGenerator;
436
595
  const array = splitCode(raw, {
437
596
  splitQuote
438
597
  });
@@ -451,7 +610,7 @@ function handleValue(raw, node, options) {
451
610
  return rawString;
452
611
  }
453
612
  function jsHandler(rawSource, options) {
454
- const result = transformSync(rawSource, {
613
+ const result = transformSync$1(rawSource, {
455
614
  babelrc: false,
456
615
  ast: true,
457
616
  plugins: [
@@ -499,4 +658,4 @@ function jsHandler(rawSource, options) {
499
658
  return result;
500
659
  }
501
660
 
502
- export { cssHandler, handleValue, htmlHandler, jsHandler, preProcessJs };
661
+ export { Context, cssHandler, handleValue, htmlHandler, jsHandler, preProcessJs, preProcessRawCode };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tailwindcss-mangle/core",
3
- "version": "2.1.0",
3
+ "version": "2.2.1",
4
4
  "description": "The core of tailwindcss-mangle",
5
5
  "exports": {
6
6
  ".": {
@@ -36,27 +36,40 @@
36
36
  "registry": "https://registry.npmjs.org/"
37
37
  },
38
38
  "dependencies": {
39
- "@ast-core/escape": "^1.0.0",
40
- "@babel/core": "^7.22.10",
39
+ "@ast-core/escape": "^1.0.1",
40
+ "@babel/core": "^7.22.19",
41
41
  "@babel/helper-plugin-utils": "^7.22.5",
42
- "@babel/preset-typescript": "^7.22.5",
43
- "@babel/types": "^7.22.10",
44
- "magic-string": "^0.30.2",
42
+ "@babel/preset-typescript": "^7.22.15",
43
+ "@babel/types": "^7.22.19",
44
+ "fast-sort": "^3.4.0",
45
+ "magic-string": "^0.30.3",
46
+ "micromatch": "^4.0.5",
45
47
  "parse5": "^7.1.2",
46
- "postcss": "^8.4.27",
48
+ "postcss": "^8.4.29",
47
49
  "postcss-selector-parser": "^6.0.13",
48
- "@tailwindcss-mangle/shared": "^2.1.0"
50
+ "@tailwindcss-mangle/config": "^2.2.1",
51
+ "@tailwindcss-mangle/shared": "^2.2.1"
49
52
  },
50
53
  "devDependencies": {
51
- "@parse5/tools": "^0.2.0",
52
- "@types/babel__core": "^7.20.1"
54
+ "@parse5/tools": "^0.3.0",
55
+ "@types/babel__core": "^7.20.1",
56
+ "@types/micromatch": "^4.0.2",
57
+ "@vue/compiler-core": "^3.3.4",
58
+ "@vue/compiler-sfc": "^3.3.4"
53
59
  },
54
60
  "homepage": "https://github.com/sonofmagic/tailwindcss-mangle",
55
61
  "repository": {
56
62
  "type": "git",
57
63
  "url": "git+https://github.com/sonofmagic/tailwindcss-mangle.git"
58
64
  },
65
+ "bugs": {
66
+ "url": "https://github.com/sonofmagic/tailwindcss-mangle/issues"
67
+ },
68
+ "directories": {
69
+ "test": "test"
70
+ },
59
71
  "scripts": {
72
+ "dev": "unbuild --sourcemap",
60
73
  "build": "unbuild",
61
74
  "test": "vitest run --coverage.enabled",
62
75
  "test:dev": "vitest",