unplugin-tailwindcss-mangle 0.1.0 → 0.1.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/README.md CHANGED
@@ -116,9 +116,11 @@ export interface IClassGeneratorOptions {
116
116
 
117
117
  ### include / exclude
118
118
 
119
- type: glob string
119
+ Type: `string | string[]`
120
120
 
121
- allow you to control the mangle range of bundles.
121
+ Default: `undefined`
122
+
123
+ `glob string` allow you to control the mangle range of bundles.
122
124
 
123
125
  ## Notice
124
126
 
package/dist/esbuild.js CHANGED
@@ -3,14 +3,12 @@
3
3
  var index = require('./index.js');
4
4
  require('unplugin');
5
5
  require('micromatch');
6
+ require('fs');
7
+ require('path');
6
8
  require('parse5');
7
- require('@babel/generator');
8
- require('@babel/parser');
9
- require('@babel/traverse');
9
+ require('@babel/core');
10
10
  require('postcss');
11
11
  require('postcss-selector-parser');
12
- require('path');
13
- require('fs');
14
12
  require('tailwindcss-patch');
15
13
 
16
14
  var esbuild = index.unplugin.esbuild;
package/dist/esbuild.mjs CHANGED
@@ -1,14 +1,12 @@
1
1
  import { unplugin } from './index.mjs';
2
2
  import 'unplugin';
3
3
  import 'micromatch';
4
+ import 'fs';
5
+ import 'path';
4
6
  import 'parse5';
5
- import '@babel/generator';
6
- import '@babel/parser';
7
- import '@babel/traverse';
7
+ import '@babel/core';
8
8
  import 'postcss';
9
9
  import 'postcss-selector-parser';
10
- import 'path';
11
- import 'fs';
12
10
  import 'tailwindcss-patch';
13
11
 
14
12
  var esbuild = unplugin.esbuild;
package/dist/index.js CHANGED
@@ -4,27 +4,28 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var unplugin$1 = require('unplugin');
6
6
  var micromatch = require('micromatch');
7
+ var fs = require('fs');
8
+ var path = require('path');
7
9
  var parse5 = require('parse5');
8
- var _generate = require('@babel/generator');
9
- var parser = require('@babel/parser');
10
- var _traverse = require('@babel/traverse');
10
+ var core = require('@babel/core');
11
11
  var postcss = require('postcss');
12
- var parser$1 = require('postcss-selector-parser');
13
- var path = require('path');
14
- var fs = require('fs');
12
+ var parser = require('postcss-selector-parser');
15
13
  var tailwindcssPatch = require('tailwindcss-patch');
16
14
 
17
15
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
18
16
 
19
- var _generate__default = /*#__PURE__*/_interopDefault(_generate);
20
- var _traverse__default = /*#__PURE__*/_interopDefault(_traverse);
21
- var postcss__default = /*#__PURE__*/_interopDefault(postcss);
22
- var parser__default = /*#__PURE__*/_interopDefault(parser$1);
23
- var path__default = /*#__PURE__*/_interopDefault(path);
17
+ var micromatch__default = /*#__PURE__*/_interopDefault(micromatch);
24
18
  var fs__default = /*#__PURE__*/_interopDefault(fs);
19
+ var path__default = /*#__PURE__*/_interopDefault(path);
20
+ var postcss__default = /*#__PURE__*/_interopDefault(postcss);
21
+ var parser__default = /*#__PURE__*/_interopDefault(parser);
25
22
 
26
23
  const pluginName = 'unplugin-tailwindcss-mangle';
27
24
 
25
+ const { isMatch } = micromatch__default["default"];
26
+ const isMangleClass = (className) => {
27
+ return /[-:]/.test(className);
28
+ };
28
29
  function groupBy(arr, cb) {
29
30
  if (!Array.isArray(arr)) {
30
31
  throw new Error('expected an array for first argument');
@@ -54,7 +55,7 @@ function getGroupedEntries(entries, options = {
54
55
  return /\.html?$/.test(file);
55
56
  },
56
57
  jsMatcher(file) {
57
- return /\.js$/.test(file);
58
+ return /\.[cm]?js$/.test(file);
58
59
  }
59
60
  }) {
60
61
  const { cssMatcher, htmlMatcher, jsMatcher } = options;
@@ -126,9 +127,31 @@ function createGlobMatcher(pattern, fallbackValue = false) {
126
127
  };
127
128
  }
128
129
  return function (file) {
129
- return micromatch.isMatch(file, pattern);
130
+ return isMatch(file, pattern);
130
131
  };
131
132
  }
133
+ function getCacheDir(basedir = process.cwd()) {
134
+ return path__default["default"].resolve(basedir, 'node_modules/.cache', pluginName);
135
+ }
136
+ function mkCacheDirectory(cwd = process.cwd()) {
137
+ const cacheDirectory = getCacheDir(cwd);
138
+ const exists = fs__default["default"].existsSync(cacheDirectory);
139
+ if (!exists) {
140
+ fs__default["default"].mkdirSync(cacheDirectory, {
141
+ recursive: true
142
+ });
143
+ }
144
+ return cacheDirectory;
145
+ }
146
+ function cacheDump(filename, data, basedir) {
147
+ try {
148
+ const dir = mkCacheDirectory(basedir);
149
+ fs__default["default"].writeFileSync(path__default["default"].resolve(dir, filename), JSON.stringify(Array.from(data), null, 2), 'utf-8');
150
+ }
151
+ catch (error) {
152
+ console.log(error);
153
+ }
154
+ }
132
155
 
133
156
  ({
134
157
  HTML: parse5.html.NS.HTML,
@@ -188,12 +211,12 @@ parse5.defaultTreeAdapter.appendChild;
188
211
  * @param {ParentNode=} parent Parent node of the current node
189
212
  * @return {void}
190
213
  */
191
- function traverse$1(node, visitor, parent) {
214
+ function traverse(node, visitor, parent) {
192
215
  const shouldVisitChildren = typeof visitor['pre:node'] !== 'function' ||
193
216
  visitor['pre:node'](node, parent) !== false;
194
217
  if (shouldVisitChildren && isParentNode(node)) {
195
218
  for (const child of node.childNodes) {
196
- traverse$1(child, visitor, node);
219
+ traverse(child, visitor, node);
197
220
  }
198
221
  }
199
222
  if (typeof visitor.node === 'function') {
@@ -226,7 +249,7 @@ function traverse$1(node, visitor, parent) {
226
249
  function htmlHandler(rawSource, options) {
227
250
  const { runtimeSet, classGenerator } = options;
228
251
  const fragment = parse5.parse(rawSource);
229
- traverse$1(fragment, {
252
+ traverse(fragment, {
230
253
  element(node, parent) {
231
254
  const attr = node.attrs.find((x) => x.name === 'class');
232
255
  if (attr) {
@@ -251,11 +274,6 @@ function isValidSelector(selector = '') {
251
274
  }
252
275
  const splitCode = (code) => code.split(/[\s"]+/).filter(isValidSelector);
253
276
 
254
- function getDefaultExportFromNamespaceIfPresent(n) {
255
- return n && Object.prototype.hasOwnProperty.call(n, 'default') ? n.default : n;
256
- }
257
- const generate = getDefaultExportFromNamespaceIfPresent(_generate__default["default"]);
258
- const traverse = getDefaultExportFromNamespaceIfPresent(_traverse__default["default"]);
259
277
  function makeRegex(str) {
260
278
  return new RegExp('(?<=^|[\\s"])' + escapeStringRegexp(str), 'g');
261
279
  }
@@ -279,24 +297,33 @@ function handleValue(str, node, options) {
279
297
  return rawStr;
280
298
  }
281
299
  function jsHandler(rawSource, options) {
282
- const ast = parser.parse(rawSource);
283
- const topt = {
284
- StringLiteral: {
285
- enter(p) {
286
- const n = p.node;
287
- n.value = handleValue(n.value, n, options);
288
- }
289
- },
290
- TemplateElement: {
291
- enter(p) {
292
- const n = p.node;
293
- n.value.raw = handleValue(n.value.raw, n, options);
300
+ const result = core.transformSync(rawSource, {
301
+ babelrc: false,
302
+ ast: true,
303
+ plugins: [
304
+ () => {
305
+ return {
306
+ visitor: {
307
+ StringLiteral: {
308
+ enter(p) {
309
+ const n = p.node;
310
+ n.value = handleValue(n.value, n, options);
311
+ }
312
+ },
313
+ TemplateElement: {
314
+ enter(p) {
315
+ const n = p.node;
316
+ n.value.raw = handleValue(n.value.raw, n, options);
317
+ }
318
+ }
319
+ }
320
+ };
294
321
  }
295
- },
296
- noScope: true
297
- };
298
- traverse(ast, topt);
299
- return generate(ast);
322
+ ],
323
+ sourceMaps: false,
324
+ configFile: false
325
+ });
326
+ return result;
300
327
  }
301
328
 
302
329
  const postcssPlugin = 'postcss-mangle-tailwindcss-plugin';
@@ -311,10 +338,19 @@ const postcssMangleTailwindcssPlugin = (options) => {
311
338
  postcssPlugin,
312
339
  Rule(rule, helper) {
313
340
  rule.selector = parser__default["default"]((selectors) => {
314
- selectors.walk((s) => {
341
+ selectors.walkClasses((s) => {
315
342
  if (s.value) {
316
343
  const hit = newClassMap[s.value];
317
344
  if (hit) {
345
+ if (s.parent) {
346
+ const idx = s.parent.nodes.indexOf(s);
347
+ if (idx > -1) {
348
+ const nextNode = s.parent.nodes[idx + 1];
349
+ if (nextNode && nextNode.type === 'attribute' && nextNode.attribute.indexOf('data-v-') > -1) {
350
+ return;
351
+ }
352
+ }
353
+ }
318
354
  s.value = hit.name;
319
355
  }
320
356
  }
@@ -334,13 +370,17 @@ function cssHandler(rawSource, options) {
334
370
  }
335
371
 
336
372
  class ClassGenerator {
373
+ newClassMap;
374
+ newClassSize;
375
+ context;
376
+ opts;
377
+ classPrefix;
337
378
  constructor(opts = {}) {
338
- var _a;
339
379
  this.newClassMap = {};
340
380
  this.newClassSize = 0;
341
381
  this.context = {};
342
382
  this.opts = opts;
343
- this.classPrefix = (_a = opts.classPrefix) !== null && _a !== void 0 ? _a : 'tw-';
383
+ this.classPrefix = opts.classPrefix ?? 'tw-';
344
384
  }
345
385
  defaultClassGenerate() {
346
386
  const chars = [];
@@ -432,18 +472,35 @@ function getOptions(options = {}) {
432
472
  function isInclude(file) {
433
473
  return includeMatcher(file) && !excludeMatcher(file);
434
474
  }
435
- const isMangleClass = (className) => {
436
- return /[-:]/.test(className);
437
- };
438
475
  let classSet;
476
+ const classSetOutputOptions = {
477
+ filename: 'classSet.json',
478
+ type: 'partial'
479
+ };
480
+ const classMapOutputOptions = {
481
+ filename: 'classMap.json'
482
+ };
483
+ if (typeof options.classSetOutput === 'object') {
484
+ Object.assign(classSetOutputOptions, options.classSetOutput);
485
+ }
486
+ if (typeof options.classMapOutput === 'object') {
487
+ Object.assign(classMapOutputOptions, options.classMapOutput);
488
+ }
439
489
  const classGenerator = new ClassGenerator(options.classGenerator);
440
490
  function getCachedClassSet() {
441
491
  const set = tailwindcssPatch.getClassCacheSet();
492
+ const isOutput = set.size && options.classSetOutput;
493
+ if (isOutput && classSetOutputOptions.type === 'all') {
494
+ cacheDump(classSetOutputOptions.filename, set, classSetOutputOptions.dir);
495
+ }
442
496
  set.forEach((c) => {
443
497
  if (!isMangleClass(c)) {
444
498
  set.delete(c);
445
499
  }
446
500
  });
501
+ if (isOutput && classSetOutputOptions.type === 'partial') {
502
+ cacheDump(classSetOutputOptions.filename, set, classSetOutputOptions.dir);
503
+ }
447
504
  classSet = set;
448
505
  return classSet;
449
506
  }
@@ -452,13 +509,15 @@ function getOptions(options = {}) {
452
509
  classGenerator,
453
510
  includeMatcher,
454
511
  excludeMatcher,
455
- isInclude
512
+ isInclude,
513
+ classSetOutputOptions,
514
+ classMapOutputOptions
456
515
  };
457
516
  }
458
517
 
459
518
  const outputCachedMap = new Map();
460
519
  const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
461
- const { classGenerator, getCachedClassSet, isInclude } = getOptions(options);
520
+ const { classGenerator, getCachedClassSet, isInclude, classMapOutputOptions } = getOptions(options);
462
521
  return {
463
522
  name: pluginName,
464
523
  enforce: 'post',
@@ -485,10 +544,13 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
485
544
  for (let i = 0; i < groupedEntries.js.length; i++) {
486
545
  const [file, chunk] = groupedEntries.js[i];
487
546
  if (isInclude(file)) {
488
- chunk.code = jsHandler(chunk.code, {
547
+ const code = jsHandler(chunk.code, {
489
548
  runtimeSet,
490
549
  classGenerator
491
550
  }).code;
551
+ if (code) {
552
+ chunk.code = code;
553
+ }
492
554
  }
493
555
  }
494
556
  }
@@ -575,8 +637,10 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
575
637
  runtimeSet,
576
638
  classGenerator
577
639
  }).code;
578
- const source = new ConcatSource(code);
579
- compilation.updateAsset(file, source);
640
+ if (code) {
641
+ const source = new ConcatSource(code);
642
+ compilation.updateAsset(file, source);
643
+ }
580
644
  }
581
645
  }
582
646
  }
@@ -614,7 +678,9 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
614
678
  runtimeSet,
615
679
  classGenerator
616
680
  }).code;
617
- overwriteServerSideAsset(key, file, code);
681
+ if (code) {
682
+ overwriteServerSideAsset(key, file, code);
683
+ }
618
684
  }
619
685
  });
620
686
  js.clear();
@@ -634,6 +700,14 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
634
700
  });
635
701
  });
636
702
  });
703
+ },
704
+ writeBundle() {
705
+ const entries = Object.entries(classGenerator.newClassMap);
706
+ if (entries.length && classMapOutputOptions) {
707
+ cacheDump(classMapOutputOptions.filename, entries.map((x) => {
708
+ return [x[0], x[1].name];
709
+ }), classMapOutputOptions.dir);
710
+ }
637
711
  }
638
712
  };
639
713
  });
package/dist/index.mjs CHANGED
@@ -1,17 +1,19 @@
1
1
  import { createUnplugin } from 'unplugin';
2
- import { isMatch } from 'micromatch';
2
+ import micromatch from 'micromatch';
3
+ import fs from 'fs';
4
+ import path from 'path';
3
5
  import { html, defaultTreeAdapter, parse, serialize } from 'parse5';
4
- import _generate from '@babel/generator';
5
- import { parse as parse$1 } from '@babel/parser';
6
- import _traverse from '@babel/traverse';
6
+ import { transformSync } from '@babel/core';
7
7
  import postcss from 'postcss';
8
8
  import parser from 'postcss-selector-parser';
9
- import path from 'path';
10
- import fs from 'fs';
11
9
  import { getClassCacheSet } from 'tailwindcss-patch';
12
10
 
13
11
  const pluginName = 'unplugin-tailwindcss-mangle';
14
12
 
13
+ const { isMatch } = micromatch;
14
+ const isMangleClass = (className) => {
15
+ return /[-:]/.test(className);
16
+ };
15
17
  function groupBy(arr, cb) {
16
18
  if (!Array.isArray(arr)) {
17
19
  throw new Error('expected an array for first argument');
@@ -41,7 +43,7 @@ function getGroupedEntries(entries, options = {
41
43
  return /\.html?$/.test(file);
42
44
  },
43
45
  jsMatcher(file) {
44
- return /\.js$/.test(file);
46
+ return /\.[cm]?js$/.test(file);
45
47
  }
46
48
  }) {
47
49
  const { cssMatcher, htmlMatcher, jsMatcher } = options;
@@ -116,6 +118,28 @@ function createGlobMatcher(pattern, fallbackValue = false) {
116
118
  return isMatch(file, pattern);
117
119
  };
118
120
  }
121
+ function getCacheDir(basedir = process.cwd()) {
122
+ return path.resolve(basedir, 'node_modules/.cache', pluginName);
123
+ }
124
+ function mkCacheDirectory(cwd = process.cwd()) {
125
+ const cacheDirectory = getCacheDir(cwd);
126
+ const exists = fs.existsSync(cacheDirectory);
127
+ if (!exists) {
128
+ fs.mkdirSync(cacheDirectory, {
129
+ recursive: true
130
+ });
131
+ }
132
+ return cacheDirectory;
133
+ }
134
+ function cacheDump(filename, data, basedir) {
135
+ try {
136
+ const dir = mkCacheDirectory(basedir);
137
+ fs.writeFileSync(path.resolve(dir, filename), JSON.stringify(Array.from(data), null, 2), 'utf-8');
138
+ }
139
+ catch (error) {
140
+ console.log(error);
141
+ }
142
+ }
119
143
 
120
144
  ({
121
145
  HTML: html.NS.HTML,
@@ -175,12 +199,12 @@ defaultTreeAdapter.appendChild;
175
199
  * @param {ParentNode=} parent Parent node of the current node
176
200
  * @return {void}
177
201
  */
178
- function traverse$1(node, visitor, parent) {
202
+ function traverse(node, visitor, parent) {
179
203
  const shouldVisitChildren = typeof visitor['pre:node'] !== 'function' ||
180
204
  visitor['pre:node'](node, parent) !== false;
181
205
  if (shouldVisitChildren && isParentNode(node)) {
182
206
  for (const child of node.childNodes) {
183
- traverse$1(child, visitor, node);
207
+ traverse(child, visitor, node);
184
208
  }
185
209
  }
186
210
  if (typeof visitor.node === 'function') {
@@ -213,7 +237,7 @@ function traverse$1(node, visitor, parent) {
213
237
  function htmlHandler(rawSource, options) {
214
238
  const { runtimeSet, classGenerator } = options;
215
239
  const fragment = parse(rawSource);
216
- traverse$1(fragment, {
240
+ traverse(fragment, {
217
241
  element(node, parent) {
218
242
  const attr = node.attrs.find((x) => x.name === 'class');
219
243
  if (attr) {
@@ -238,11 +262,6 @@ function isValidSelector(selector = '') {
238
262
  }
239
263
  const splitCode = (code) => code.split(/[\s"]+/).filter(isValidSelector);
240
264
 
241
- function getDefaultExportFromNamespaceIfPresent(n) {
242
- return n && Object.prototype.hasOwnProperty.call(n, 'default') ? n.default : n;
243
- }
244
- const generate = getDefaultExportFromNamespaceIfPresent(_generate);
245
- const traverse = getDefaultExportFromNamespaceIfPresent(_traverse);
246
265
  function makeRegex(str) {
247
266
  return new RegExp('(?<=^|[\\s"])' + escapeStringRegexp(str), 'g');
248
267
  }
@@ -266,24 +285,33 @@ function handleValue(str, node, options) {
266
285
  return rawStr;
267
286
  }
268
287
  function jsHandler(rawSource, options) {
269
- const ast = parse$1(rawSource);
270
- const topt = {
271
- StringLiteral: {
272
- enter(p) {
273
- const n = p.node;
274
- n.value = handleValue(n.value, n, options);
275
- }
276
- },
277
- TemplateElement: {
278
- enter(p) {
279
- const n = p.node;
280
- n.value.raw = handleValue(n.value.raw, n, options);
288
+ const result = transformSync(rawSource, {
289
+ babelrc: false,
290
+ ast: true,
291
+ plugins: [
292
+ () => {
293
+ return {
294
+ visitor: {
295
+ StringLiteral: {
296
+ enter(p) {
297
+ const n = p.node;
298
+ n.value = handleValue(n.value, n, options);
299
+ }
300
+ },
301
+ TemplateElement: {
302
+ enter(p) {
303
+ const n = p.node;
304
+ n.value.raw = handleValue(n.value.raw, n, options);
305
+ }
306
+ }
307
+ }
308
+ };
281
309
  }
282
- },
283
- noScope: true
284
- };
285
- traverse(ast, topt);
286
- return generate(ast);
310
+ ],
311
+ sourceMaps: false,
312
+ configFile: false
313
+ });
314
+ return result;
287
315
  }
288
316
 
289
317
  const postcssPlugin = 'postcss-mangle-tailwindcss-plugin';
@@ -298,10 +326,19 @@ const postcssMangleTailwindcssPlugin = (options) => {
298
326
  postcssPlugin,
299
327
  Rule(rule, helper) {
300
328
  rule.selector = parser((selectors) => {
301
- selectors.walk((s) => {
329
+ selectors.walkClasses((s) => {
302
330
  if (s.value) {
303
331
  const hit = newClassMap[s.value];
304
332
  if (hit) {
333
+ if (s.parent) {
334
+ const idx = s.parent.nodes.indexOf(s);
335
+ if (idx > -1) {
336
+ const nextNode = s.parent.nodes[idx + 1];
337
+ if (nextNode && nextNode.type === 'attribute' && nextNode.attribute.indexOf('data-v-') > -1) {
338
+ return;
339
+ }
340
+ }
341
+ }
305
342
  s.value = hit.name;
306
343
  }
307
344
  }
@@ -321,13 +358,17 @@ function cssHandler(rawSource, options) {
321
358
  }
322
359
 
323
360
  class ClassGenerator {
361
+ newClassMap;
362
+ newClassSize;
363
+ context;
364
+ opts;
365
+ classPrefix;
324
366
  constructor(opts = {}) {
325
- var _a;
326
367
  this.newClassMap = {};
327
368
  this.newClassSize = 0;
328
369
  this.context = {};
329
370
  this.opts = opts;
330
- this.classPrefix = (_a = opts.classPrefix) !== null && _a !== void 0 ? _a : 'tw-';
371
+ this.classPrefix = opts.classPrefix ?? 'tw-';
331
372
  }
332
373
  defaultClassGenerate() {
333
374
  const chars = [];
@@ -419,18 +460,35 @@ function getOptions(options = {}) {
419
460
  function isInclude(file) {
420
461
  return includeMatcher(file) && !excludeMatcher(file);
421
462
  }
422
- const isMangleClass = (className) => {
423
- return /[-:]/.test(className);
424
- };
425
463
  let classSet;
464
+ const classSetOutputOptions = {
465
+ filename: 'classSet.json',
466
+ type: 'partial'
467
+ };
468
+ const classMapOutputOptions = {
469
+ filename: 'classMap.json'
470
+ };
471
+ if (typeof options.classSetOutput === 'object') {
472
+ Object.assign(classSetOutputOptions, options.classSetOutput);
473
+ }
474
+ if (typeof options.classMapOutput === 'object') {
475
+ Object.assign(classMapOutputOptions, options.classMapOutput);
476
+ }
426
477
  const classGenerator = new ClassGenerator(options.classGenerator);
427
478
  function getCachedClassSet() {
428
479
  const set = getClassCacheSet();
480
+ const isOutput = set.size && options.classSetOutput;
481
+ if (isOutput && classSetOutputOptions.type === 'all') {
482
+ cacheDump(classSetOutputOptions.filename, set, classSetOutputOptions.dir);
483
+ }
429
484
  set.forEach((c) => {
430
485
  if (!isMangleClass(c)) {
431
486
  set.delete(c);
432
487
  }
433
488
  });
489
+ if (isOutput && classSetOutputOptions.type === 'partial') {
490
+ cacheDump(classSetOutputOptions.filename, set, classSetOutputOptions.dir);
491
+ }
434
492
  classSet = set;
435
493
  return classSet;
436
494
  }
@@ -439,13 +497,15 @@ function getOptions(options = {}) {
439
497
  classGenerator,
440
498
  includeMatcher,
441
499
  excludeMatcher,
442
- isInclude
500
+ isInclude,
501
+ classSetOutputOptions,
502
+ classMapOutputOptions
443
503
  };
444
504
  }
445
505
 
446
506
  const outputCachedMap = new Map();
447
507
  const unplugin = createUnplugin((options = {}, meta) => {
448
- const { classGenerator, getCachedClassSet, isInclude } = getOptions(options);
508
+ const { classGenerator, getCachedClassSet, isInclude, classMapOutputOptions } = getOptions(options);
449
509
  return {
450
510
  name: pluginName,
451
511
  enforce: 'post',
@@ -472,10 +532,13 @@ const unplugin = createUnplugin((options = {}, meta) => {
472
532
  for (let i = 0; i < groupedEntries.js.length; i++) {
473
533
  const [file, chunk] = groupedEntries.js[i];
474
534
  if (isInclude(file)) {
475
- chunk.code = jsHandler(chunk.code, {
535
+ const code = jsHandler(chunk.code, {
476
536
  runtimeSet,
477
537
  classGenerator
478
538
  }).code;
539
+ if (code) {
540
+ chunk.code = code;
541
+ }
479
542
  }
480
543
  }
481
544
  }
@@ -562,8 +625,10 @@ const unplugin = createUnplugin((options = {}, meta) => {
562
625
  runtimeSet,
563
626
  classGenerator
564
627
  }).code;
565
- const source = new ConcatSource(code);
566
- compilation.updateAsset(file, source);
628
+ if (code) {
629
+ const source = new ConcatSource(code);
630
+ compilation.updateAsset(file, source);
631
+ }
567
632
  }
568
633
  }
569
634
  }
@@ -601,7 +666,9 @@ const unplugin = createUnplugin((options = {}, meta) => {
601
666
  runtimeSet,
602
667
  classGenerator
603
668
  }).code;
604
- overwriteServerSideAsset(key, file, code);
669
+ if (code) {
670
+ overwriteServerSideAsset(key, file, code);
671
+ }
605
672
  }
606
673
  });
607
674
  js.clear();
@@ -621,6 +688,14 @@ const unplugin = createUnplugin((options = {}, meta) => {
621
688
  });
622
689
  });
623
690
  });
691
+ },
692
+ writeBundle() {
693
+ const entries = Object.entries(classGenerator.newClassMap);
694
+ if (entries.length && classMapOutputOptions) {
695
+ cacheDump(classMapOutputOptions.filename, entries.map((x) => {
696
+ return [x[0], x[1].name];
697
+ }), classMapOutputOptions.dir);
698
+ }
624
699
  }
625
700
  };
626
701
  });
@@ -1,5 +1,6 @@
1
1
  import type { StringLiteral, TemplateElement } from '@babel/types';
2
+ import { type BabelFileResult } from '@babel/core';
2
3
  import type { IHandlerOptions } from '../types';
3
4
  export declare function makeRegex(str: string): RegExp;
4
5
  export declare function handleValue(str: string, node: StringLiteral | TemplateElement, options: IHandlerOptions): string;
5
- export declare function jsHandler(rawSource: string, options: IHandlerOptions): import("@babel/generator").GeneratorResult;
6
+ export declare function jsHandler(rawSource: string, options: IHandlerOptions): BabelFileResult;
package/dist/nuxt.js CHANGED
@@ -3,50 +3,23 @@
3
3
  var index = require('./index.js');
4
4
  require('unplugin');
5
5
  require('micromatch');
6
+ require('fs');
7
+ require('path');
6
8
  require('parse5');
7
- require('@babel/generator');
8
- require('@babel/parser');
9
- require('@babel/traverse');
9
+ require('@babel/core');
10
10
  require('postcss');
11
11
  require('postcss-selector-parser');
12
- require('path');
13
- require('fs');
14
12
  require('tailwindcss-patch');
15
13
 
16
- /******************************************************************************
17
- Copyright (c) Microsoft Corporation.
18
-
19
- Permission to use, copy, modify, and/or distribute this software for any
20
- purpose with or without fee is hereby granted.
21
-
22
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
23
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
24
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
25
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
26
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
27
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28
- PERFORMANCE OF THIS SOFTWARE.
29
- ***************************************************************************** */
30
-
31
- function __awaiter(thisArg, _arguments, P, generator) {
32
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
33
- return new (P || (P = Promise))(function (resolve, reject) {
34
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
35
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
36
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
37
- step((generator = generator.apply(thisArg, _arguments || [])).next());
38
- });
39
- }
40
-
41
14
  function nuxt (options = {}, nuxt) {
42
- nuxt.hook('webpack:config', (config) => __awaiter(this, void 0, void 0, function* () {
15
+ nuxt.hook('webpack:config', async (config) => {
43
16
  config.plugins = config.plugins || [];
44
17
  config.plugins.unshift(index.unplugin.webpack(options));
45
- }));
46
- nuxt.hook('vite:extendConfig', (config) => __awaiter(this, void 0, void 0, function* () {
18
+ });
19
+ nuxt.hook('vite:extendConfig', async (config) => {
47
20
  config.plugins = config.plugins || [];
48
21
  config.plugins.push(index.unplugin.vite(options));
49
- }));
22
+ });
50
23
  }
51
24
 
52
25
  module.exports = nuxt;
package/dist/nuxt.mjs CHANGED
@@ -1,50 +1,23 @@
1
1
  import { unplugin } from './index.mjs';
2
2
  import 'unplugin';
3
3
  import 'micromatch';
4
+ import 'fs';
5
+ import 'path';
4
6
  import 'parse5';
5
- import '@babel/generator';
6
- import '@babel/parser';
7
- import '@babel/traverse';
7
+ import '@babel/core';
8
8
  import 'postcss';
9
9
  import 'postcss-selector-parser';
10
- import 'path';
11
- import 'fs';
12
10
  import 'tailwindcss-patch';
13
11
 
14
- /******************************************************************************
15
- Copyright (c) Microsoft Corporation.
16
-
17
- Permission to use, copy, modify, and/or distribute this software for any
18
- purpose with or without fee is hereby granted.
19
-
20
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
22
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
23
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
24
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
25
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
26
- PERFORMANCE OF THIS SOFTWARE.
27
- ***************************************************************************** */
28
-
29
- function __awaiter(thisArg, _arguments, P, generator) {
30
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
31
- return new (P || (P = Promise))(function (resolve, reject) {
32
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
33
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
34
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
35
- step((generator = generator.apply(thisArg, _arguments || [])).next());
36
- });
37
- }
38
-
39
12
  function nuxt (options = {}, nuxt) {
40
- nuxt.hook('webpack:config', (config) => __awaiter(this, void 0, void 0, function* () {
13
+ nuxt.hook('webpack:config', async (config) => {
41
14
  config.plugins = config.plugins || [];
42
15
  config.plugins.unshift(unplugin.webpack(options));
43
- }));
44
- nuxt.hook('vite:extendConfig', (config) => __awaiter(this, void 0, void 0, function* () {
16
+ });
17
+ nuxt.hook('vite:extendConfig', async (config) => {
45
18
  config.plugins = config.plugins || [];
46
19
  config.plugins.push(unplugin.vite(options));
47
- }));
20
+ });
48
21
  }
49
22
 
50
23
  export { nuxt as default };
package/dist/options.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Options } from './types';
1
+ import type { Options, ClassSetOutputOptions, ClassMapOutputOptions } from './types';
2
2
  import ClassGenerator from './classGenerator';
3
3
  export declare function getOptions(options?: Options | undefined): {
4
4
  getCachedClassSet: () => Set<string>;
@@ -6,4 +6,6 @@ export declare function getOptions(options?: Options | undefined): {
6
6
  includeMatcher: (file: string) => boolean;
7
7
  excludeMatcher: (file: string) => boolean;
8
8
  isInclude: (file: string) => boolean;
9
+ classSetOutputOptions: ClassSetOutputOptions;
10
+ classMapOutputOptions: ClassMapOutputOptions;
9
11
  };
package/dist/rollup.js CHANGED
@@ -3,14 +3,12 @@
3
3
  var index = require('./index.js');
4
4
  require('unplugin');
5
5
  require('micromatch');
6
+ require('fs');
7
+ require('path');
6
8
  require('parse5');
7
- require('@babel/generator');
8
- require('@babel/parser');
9
- require('@babel/traverse');
9
+ require('@babel/core');
10
10
  require('postcss');
11
11
  require('postcss-selector-parser');
12
- require('path');
13
- require('fs');
14
12
  require('tailwindcss-patch');
15
13
 
16
14
  var rollup = index.unplugin.rollup;
package/dist/rollup.mjs CHANGED
@@ -1,14 +1,12 @@
1
1
  import { unplugin } from './index.mjs';
2
2
  import 'unplugin';
3
3
  import 'micromatch';
4
+ import 'fs';
5
+ import 'path';
4
6
  import 'parse5';
5
- import '@babel/generator';
6
- import '@babel/parser';
7
- import '@babel/traverse';
7
+ import '@babel/core';
8
8
  import 'postcss';
9
9
  import 'postcss-selector-parser';
10
- import 'path';
11
- import 'fs';
12
10
  import 'tailwindcss-patch';
13
11
 
14
12
  var rollup = unplugin.rollup;
package/dist/types.d.ts CHANGED
@@ -17,13 +17,23 @@ export interface IClassGenerator {
17
17
  newClassSize: number;
18
18
  context: Record<string, any>;
19
19
  }
20
- export type { TraverseOptions } from '@babel/traverse';
21
20
  export interface IHandlerOptions {
22
21
  runtimeSet: Set<string>;
23
22
  classGenerator: ClassGenerator;
24
23
  }
24
+ export interface ClassSetOutputOptions {
25
+ filename: string;
26
+ dir?: string;
27
+ type: 'all' | 'partial';
28
+ }
29
+ export interface ClassMapOutputOptions {
30
+ filename: string;
31
+ dir?: string;
32
+ }
25
33
  export interface Options {
26
34
  classGenerator?: IClassGeneratorOptions;
27
35
  exclude?: string[];
28
36
  include?: string[];
37
+ classSetOutput?: boolean | ClassSetOutputOptions;
38
+ classMapOutput?: boolean | ClassMapOutputOptions;
29
39
  }
package/dist/utils.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { IClassGeneratorOptions, IClassGenerator } from './types';
2
+ export declare const isMangleClass: (className: string) => boolean;
2
3
  export declare function groupBy<T>(arr: T[], cb: (arg: T) => string): Record<string, T[]>;
3
4
  export declare function getGroupedEntries<T>(entries: [string, T][], options?: {
4
5
  cssMatcher(file: string): boolean;
@@ -13,3 +14,6 @@ export declare function isMap(value: unknown): boolean;
13
14
  export declare function regExpTest(arr: (string | RegExp)[] | undefined, str: string): boolean;
14
15
  export declare function escapeStringRegexp(str: string): string;
15
16
  export declare function createGlobMatcher(pattern: string | string[] | undefined, fallbackValue?: boolean): (file: string) => boolean;
17
+ export declare function getCacheDir(basedir?: string): string;
18
+ export declare function mkCacheDirectory(cwd?: string): string;
19
+ export declare function cacheDump(filename: string, data: any[] | Set<any>, basedir?: string): void;
package/dist/vite.js CHANGED
@@ -3,14 +3,12 @@
3
3
  var index = require('./index.js');
4
4
  require('unplugin');
5
5
  require('micromatch');
6
+ require('fs');
7
+ require('path');
6
8
  require('parse5');
7
- require('@babel/generator');
8
- require('@babel/parser');
9
- require('@babel/traverse');
9
+ require('@babel/core');
10
10
  require('postcss');
11
11
  require('postcss-selector-parser');
12
- require('path');
13
- require('fs');
14
12
  require('tailwindcss-patch');
15
13
 
16
14
  var vite = index.unplugin.vite;
package/dist/vite.mjs CHANGED
@@ -1,14 +1,12 @@
1
1
  import { unplugin } from './index.mjs';
2
2
  import 'unplugin';
3
3
  import 'micromatch';
4
+ import 'fs';
5
+ import 'path';
4
6
  import 'parse5';
5
- import '@babel/generator';
6
- import '@babel/parser';
7
- import '@babel/traverse';
7
+ import '@babel/core';
8
8
  import 'postcss';
9
9
  import 'postcss-selector-parser';
10
- import 'path';
11
- import 'fs';
12
10
  import 'tailwindcss-patch';
13
11
 
14
12
  var vite = unplugin.vite;
package/dist/webpack.js CHANGED
@@ -3,14 +3,12 @@
3
3
  var index = require('./index.js');
4
4
  require('unplugin');
5
5
  require('micromatch');
6
+ require('fs');
7
+ require('path');
6
8
  require('parse5');
7
- require('@babel/generator');
8
- require('@babel/parser');
9
- require('@babel/traverse');
9
+ require('@babel/core');
10
10
  require('postcss');
11
11
  require('postcss-selector-parser');
12
- require('path');
13
- require('fs');
14
12
  require('tailwindcss-patch');
15
13
 
16
14
  var webpack = index.unplugin.webpack;
package/dist/webpack.mjs CHANGED
@@ -1,14 +1,12 @@
1
1
  import { unplugin } from './index.mjs';
2
2
  import 'unplugin';
3
3
  import 'micromatch';
4
+ import 'fs';
5
+ import 'path';
4
6
  import 'parse5';
5
- import '@babel/generator';
6
- import '@babel/parser';
7
- import '@babel/traverse';
7
+ import '@babel/core';
8
8
  import 'postcss';
9
9
  import 'postcss-selector-parser';
10
- import 'path';
11
- import 'fs';
12
10
  import 'tailwindcss-patch';
13
11
 
14
12
  var webpack = unplugin.webpack;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unplugin-tailwindcss-mangle",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "mangle tailwindcss utilities class plugin. support vite and webpack!",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -60,9 +60,7 @@
60
60
  "author": "SonOfMagic <qq1324318532@gmail.com>",
61
61
  "license": "MIT",
62
62
  "dependencies": {
63
- "@babel/generator": "^7.21.4",
64
- "@babel/parser": "^7.21.4",
65
- "@babel/traverse": "^7.21.4",
63
+ "@babel/core": "^7.21.4",
66
64
  "@babel/types": "^7.21.4",
67
65
  "micromatch": "^4.0.5",
68
66
  "parse5": "^7.1.2",
@@ -70,7 +68,7 @@
70
68
  "postcss-selector-parser": "^6.0.11",
71
69
  "semver": "^7.5.0",
72
70
  "unplugin": "^1.3.1",
73
- "tailwindcss-patch": "1.0.3"
71
+ "tailwindcss-patch": "1.1.0-rc.0"
74
72
  },
75
73
  "publishConfig": {
76
74
  "access": "public",
@@ -78,16 +76,15 @@
78
76
  },
79
77
  "devDependencies": {
80
78
  "@parse5/tools": "^0.1.0",
81
- "@types/babel__generator": "^7.6.4",
82
- "@types/babel__traverse": "^7.18.4",
79
+ "@types/babel__core": "^7.20.0",
83
80
  "@types/escodegen": "^0.0.7",
84
81
  "@types/micromatch": "^4.0.2",
85
82
  "@types/semver": "^7.3.13",
86
83
  "pkg-types": "^1.0.2",
87
84
  "tailwindcss": "^3.3.2",
88
85
  "tslib": "^2.5.0",
89
- "vite": "^4.3.2",
90
- "webpack": "^5.80.0"
86
+ "vite": "^4.3.3",
87
+ "webpack": "^5.81.0"
91
88
  },
92
89
  "homepage": "https://github.com/sonofmagic/tailwindcss-mangle",
93
90
  "repository": {
@@ -100,6 +97,6 @@
100
97
  "dev:tsc": "tsc -p tsconfig.json --sourceMap",
101
98
  "build:tsc": "tsc -p tsconfig.json",
102
99
  "test": "jest",
103
- "preinstall": "npx only-allow pnpm"
100
+ "_prepare": "tw-patch"
104
101
  }
105
102
  }