unplugin-tailwindcss-mangle
Advanced tools
Comparing version 0.1.2 to 0.1.3
@@ -6,152 +6,19 @@ 'use strict'; | ||
var unplugin$1 = require('unplugin'); | ||
var micromatch = require('micromatch'); | ||
var index = require('./index-2edd594b.js'); | ||
var parse5 = require('parse5'); | ||
var index$1 = require('./index-c8e1bdc5.js'); | ||
var path = require('path'); | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var parse5 = require('parse5'); | ||
var core = require('@babel/core'); | ||
var postcss = require('postcss'); | ||
var parser = require('postcss-selector-parser'); | ||
var tailwindcssPatch = require('tailwindcss-patch'); | ||
require('@babel/types'); | ||
require('@babel/core'); | ||
require('micromatch'); | ||
require('postcss'); | ||
require('postcss-selector-parser'); | ||
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; } | ||
var micromatch__default = /*#__PURE__*/_interopDefault(micromatch); | ||
var path__default = /*#__PURE__*/_interopDefault(path); | ||
var fs__default = /*#__PURE__*/_interopDefault(fs); | ||
var path__default = /*#__PURE__*/_interopDefault(path); | ||
var postcss__default = /*#__PURE__*/_interopDefault(postcss); | ||
var parser__default = /*#__PURE__*/_interopDefault(parser); | ||
const pluginName = 'unplugin-tailwindcss-mangle'; | ||
const { isMatch } = micromatch__default["default"]; | ||
const isMangleClass = (className) => { | ||
return /[-:]/.test(className); | ||
}; | ||
function groupBy(arr, cb) { | ||
if (!Array.isArray(arr)) { | ||
throw new Error('expected an array for first argument'); | ||
} | ||
if (typeof cb !== 'function') { | ||
throw new Error('expected a function for second argument'); | ||
} | ||
const result = {}; | ||
for (let i = 0; i < arr.length; i++) { | ||
const item = arr[i]; | ||
const bucketCategory = cb(item); | ||
const bucket = result[bucketCategory]; | ||
if (!Array.isArray(bucket)) { | ||
result[bucketCategory] = [item]; | ||
} | ||
else { | ||
result[bucketCategory].push(item); | ||
} | ||
} | ||
return result; | ||
} | ||
function getGroupedEntries(entries, options = { | ||
cssMatcher(file) { | ||
return /\.css$/.test(file); | ||
}, | ||
htmlMatcher(file) { | ||
return /\.html?$/.test(file); | ||
}, | ||
jsMatcher(file) { | ||
return /\.[cm]?js$/.test(file); | ||
} | ||
}) { | ||
const { cssMatcher, htmlMatcher, jsMatcher } = options; | ||
const groupedEntries = groupBy(entries, ([file]) => { | ||
if (cssMatcher(file)) { | ||
return 'css'; | ||
} | ||
else if (htmlMatcher(file)) { | ||
return 'html'; | ||
} | ||
else if (jsMatcher(file)) { | ||
return 'js'; | ||
} | ||
else { | ||
return 'other'; | ||
} | ||
}); | ||
if (!groupedEntries.css) { | ||
groupedEntries.css = []; | ||
} | ||
if (!groupedEntries.html) { | ||
groupedEntries.html = []; | ||
} | ||
if (!groupedEntries.js) { | ||
groupedEntries.js = []; | ||
} | ||
if (!groupedEntries.other) { | ||
groupedEntries.other = []; | ||
} | ||
return groupedEntries; | ||
} | ||
const acceptChars = 'abcdefghijklmnopqrstuvwxyz'.split(''); | ||
function stripEscapeSequence(words) { | ||
return words.replace(/\\/g, ''); | ||
} | ||
function isRegexp(value) { | ||
return Object.prototype.toString.call(value) === '[object RegExp]'; | ||
} | ||
function regExpTest(arr = [], str) { | ||
if (Array.isArray(arr)) { | ||
for (let i = 0; i < arr.length; i++) { | ||
const item = arr[i]; | ||
if (typeof item === 'string') { | ||
if (item === str) { | ||
return true; | ||
} | ||
} | ||
else if (isRegexp(item)) { | ||
item.lastIndex = 0; | ||
if (item.test(str)) { | ||
return true; | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
throw new TypeError("paramater 'arr' should be a Array of Regexp | String !"); | ||
} | ||
function escapeStringRegexp(str) { | ||
if (typeof str !== 'string') { | ||
throw new TypeError('Expected a string'); | ||
} | ||
return str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/-/g, '\\x2d'); | ||
} | ||
function createGlobMatcher(pattern, fallbackValue = false) { | ||
if (typeof pattern === 'undefined') { | ||
return function (file) { | ||
return fallbackValue; | ||
}; | ||
} | ||
return function (file) { | ||
return isMatch(file, pattern); | ||
}; | ||
} | ||
function getCacheDir(basedir = process.cwd()) { | ||
return path__default["default"].resolve(basedir, 'node_modules/.cache', pluginName); | ||
} | ||
function mkCacheDirectory(cwd = process.cwd()) { | ||
const cacheDirectory = getCacheDir(cwd); | ||
const exists = fs__default["default"].existsSync(cacheDirectory); | ||
if (!exists) { | ||
fs__default["default"].mkdirSync(cacheDirectory, { | ||
recursive: true | ||
}); | ||
} | ||
return cacheDirectory; | ||
} | ||
function cacheDump(filename, data, basedir) { | ||
try { | ||
const dir = mkCacheDirectory(basedir); | ||
fs__default["default"].writeFileSync(path__default["default"].resolve(dir, filename), JSON.stringify(Array.from(data), null, 2), 'utf-8'); | ||
} | ||
catch (error) { | ||
console.log(error); | ||
} | ||
} | ||
({ | ||
@@ -272,103 +139,2 @@ HTML: parse5.html.NS.HTML, | ||
const validateFilterRE = /[\w\u00A0-\uFFFF-_:%-?]/; | ||
function isValidSelector(selector = '') { | ||
return validateFilterRE.test(selector); | ||
} | ||
const splitCode = (code) => code.split(/[\s"]+/).filter(isValidSelector); | ||
function makeRegex(str) { | ||
return new RegExp('(?<=^|[\\s"])' + escapeStringRegexp(str), 'g'); | ||
} | ||
function handleValue(str, node, options) { | ||
const set = options.runtimeSet; | ||
const clsGen = options.classGenerator; | ||
const arr = splitCode(str); | ||
let rawStr = str; | ||
for (let i = 0; i < arr.length; i++) { | ||
const v = arr[i]; | ||
if (set.has(v)) { | ||
let ignoreFlag = false; | ||
if (Array.isArray(node.leadingComments)) { | ||
ignoreFlag = node.leadingComments.findIndex((x) => x.value.includes('tw-mangle') && x.value.includes('ignore')) > -1; | ||
} | ||
if (!ignoreFlag) { | ||
rawStr = rawStr.replace(makeRegex(v), clsGen.generateClassName(v).name); | ||
} | ||
} | ||
} | ||
return rawStr; | ||
} | ||
function jsHandler(rawSource, options) { | ||
const result = core.transformSync(rawSource, { | ||
babelrc: false, | ||
ast: true, | ||
plugins: [ | ||
() => { | ||
return { | ||
visitor: { | ||
StringLiteral: { | ||
enter(p) { | ||
const n = p.node; | ||
n.value = handleValue(n.value, n, options); | ||
} | ||
}, | ||
TemplateElement: { | ||
enter(p) { | ||
const n = p.node; | ||
n.value.raw = handleValue(n.value.raw, n, options); | ||
} | ||
} | ||
} | ||
}; | ||
} | ||
], | ||
sourceMaps: false, | ||
configFile: false | ||
}); | ||
return result; | ||
} | ||
const postcssPlugin = 'postcss-mangle-tailwindcss-plugin'; | ||
const postcssMangleTailwindcssPlugin = (options) => { | ||
let newClassMap = {}; | ||
if (options) { | ||
if (options.newClassMap) { | ||
newClassMap = options.newClassMap; | ||
} | ||
} | ||
return { | ||
postcssPlugin, | ||
Rule(rule, helper) { | ||
rule.selector = parser__default["default"]((selectors) => { | ||
selectors.walkClasses((s) => { | ||
if (s.value) { | ||
const hit = newClassMap[s.value]; | ||
if (hit) { | ||
if (s.parent) { | ||
const idx = s.parent.nodes.indexOf(s); | ||
if (idx > -1) { | ||
const nextNode = s.parent.nodes[idx + 1]; | ||
if (nextNode && nextNode.type === 'attribute' && nextNode.attribute.indexOf('data-v-') > -1) { | ||
return; | ||
} | ||
} | ||
} | ||
s.value = hit.name; | ||
} | ||
} | ||
}); | ||
}).processSync(rule.selector); | ||
} | ||
}; | ||
}; | ||
postcssMangleTailwindcssPlugin.postcss = true; | ||
function cssHandler(rawSource, options) { | ||
return postcss__default["default"]([ | ||
postcssMangleTailwindcssPlugin({ | ||
newClassMap: options.classGenerator.newClassMap | ||
}) | ||
]).process(rawSource).css; | ||
} | ||
class ClassGenerator { | ||
@@ -389,8 +155,8 @@ newClassMap; | ||
const chars = []; | ||
let rest = (this.newClassSize - (this.newClassSize % acceptChars.length)) / acceptChars.length; | ||
let rest = (this.newClassSize - (this.newClassSize % index.acceptChars.length)) / index.acceptChars.length; | ||
if (rest > 0) { | ||
while (true) { | ||
rest -= 1; | ||
const m = rest % acceptChars.length; | ||
const c = acceptChars[m]; | ||
const m = rest % index.acceptChars.length; | ||
const c = index.acceptChars[m]; | ||
chars.push(c); | ||
@@ -401,11 +167,11 @@ rest -= m; | ||
} | ||
rest /= acceptChars.length; | ||
rest /= index.acceptChars.length; | ||
} | ||
} | ||
const prefixIndex = this.newClassSize % acceptChars.length; | ||
const newClassName = `${this.classPrefix}${acceptChars[prefixIndex]}${chars.join('')}`; | ||
const prefixIndex = this.newClassSize % index.acceptChars.length; | ||
const newClassName = `${this.classPrefix}${index.acceptChars[prefixIndex]}${chars.join('')}`; | ||
return newClassName; | ||
} | ||
ignoreClassName(className) { | ||
return regExpTest(this.opts.ignoreClass, className); | ||
return index.regExpTest(this.opts.ignoreClass, className); | ||
} | ||
@@ -415,3 +181,3 @@ includeFilePath(filePath) { | ||
if (Array.isArray(include)) { | ||
return regExpTest(include, filePath); | ||
return index.regExpTest(include, filePath); | ||
} | ||
@@ -425,3 +191,3 @@ else { | ||
if (Array.isArray(exclude)) { | ||
return regExpTest(exclude, filePath); | ||
return index.regExpTest(exclude, filePath); | ||
} | ||
@@ -436,3 +202,3 @@ else { | ||
transformCssClass(className) { | ||
const key = stripEscapeSequence(className); | ||
const key = index.stripEscapeSequence(className); | ||
const cn = this.newClassMap[key]; | ||
@@ -445,3 +211,3 @@ if (cn) | ||
const opts = this.opts; | ||
original = stripEscapeSequence(original); | ||
original = index.stripEscapeSequence(original); | ||
const cn = this.newClassMap[original]; | ||
@@ -457,3 +223,3 @@ if (cn) | ||
} | ||
if (opts.reserveClassName && regExpTest(opts.reserveClassName, newClassName)) { | ||
if (opts.reserveClassName && index.regExpTest(opts.reserveClassName, newClassName)) { | ||
if (opts.log) { | ||
@@ -479,4 +245,4 @@ console.log(`The class name has been reserved. ${newClassName}`); | ||
function getOptions(options = {}) { | ||
const includeMatcher = createGlobMatcher(options.include, true); | ||
const excludeMatcher = createGlobMatcher(options.exclude, false); | ||
const includeMatcher = index.createGlobMatcher(options.include, true); | ||
const excludeMatcher = index.createGlobMatcher(options.exclude, false); | ||
function isInclude(file) { | ||
@@ -486,2 +252,3 @@ return includeMatcher(file) && !excludeMatcher(file); | ||
let classSet; | ||
const twPatcher = new tailwindcssPatch.TailwindcssPatcher(); | ||
const classSetOutputOptions = { | ||
@@ -502,9 +269,9 @@ filename: 'classSet.json', | ||
function getCachedClassSet() { | ||
const set = tailwindcssPatch.getClassCacheSet(); | ||
const set = twPatcher.getClassSet(); | ||
const isOutput = set.size && options.classSetOutput; | ||
if (isOutput && classSetOutputOptions.type === 'all') { | ||
cacheDump(classSetOutputOptions.filename, set, classSetOutputOptions.dir); | ||
index.cacheDump(classSetOutputOptions.filename, set, classSetOutputOptions.dir); | ||
} | ||
set.forEach((c) => { | ||
if (!isMangleClass(c)) { | ||
if (!index.isMangleClass(c)) { | ||
set.delete(c); | ||
@@ -514,3 +281,3 @@ } | ||
if (isOutput && classSetOutputOptions.type === 'partial') { | ||
cacheDump(classSetOutputOptions.filename, set, classSetOutputOptions.dir); | ||
index.cacheDump(classSetOutputOptions.filename, set, classSetOutputOptions.dir); | ||
} | ||
@@ -527,3 +294,4 @@ classSet = set; | ||
classSetOutputOptions, | ||
classMapOutputOptions | ||
classMapOutputOptions, | ||
twPatcher | ||
}; | ||
@@ -536,3 +304,3 @@ } | ||
return { | ||
name: pluginName, | ||
name: index.pluginName, | ||
enforce: 'post', | ||
@@ -546,3 +314,3 @@ vite: { | ||
} | ||
const groupedEntries = getGroupedEntries(Object.entries(bundle)); | ||
const groupedEntries = index.getGroupedEntries(Object.entries(bundle)); | ||
if (Array.isArray(groupedEntries.html) && groupedEntries.html.length) { | ||
@@ -563,3 +331,3 @@ for (let i = 0; i < groupedEntries.html.length; i++) { | ||
if (isInclude(file)) { | ||
const code = jsHandler(chunk.code, { | ||
const code = index.jsHandler(chunk.code, { | ||
runtimeSet, | ||
@@ -578,3 +346,3 @@ classGenerator | ||
if (isInclude(file)) { | ||
css.source = cssHandler(css.source.toString(), { | ||
css.source = index$1.cssHandler(css.source.toString(), { | ||
classGenerator, | ||
@@ -590,3 +358,3 @@ runtimeSet | ||
webpack(compiler) { | ||
const Compilation = compiler.webpack.Compilation; | ||
const { NormalModule, Compilation } = compiler.webpack; | ||
const { ConcatSource } = compiler.webpack.sources; | ||
@@ -609,9 +377,24 @@ function getAssetPath(outputPath, file, abs = true) { | ||
} | ||
compiler.hooks.compilation.tap(pluginName, (compilation) => { | ||
const twmCssloader = path__default["default"].resolve(__dirname, 'twm-css.js'); | ||
compiler.hooks.compilation.tap(index.pluginName, (compilation) => { | ||
NormalModule.getCompilationHooks(compilation).loader.tap(index.pluginName, (loaderContext, module) => { | ||
const idx = module.loaders.findIndex((x) => x.loader.includes('css-loader')); | ||
if (idx > -1) { | ||
module.loaders.splice(idx + 1, 0, { | ||
loader: twmCssloader, | ||
options: { | ||
classGenerator, | ||
getCachedClassSet | ||
}, | ||
ident: null, | ||
type: null | ||
}); | ||
} | ||
}); | ||
compilation.hooks.processAssets.tap({ | ||
name: pluginName, | ||
name: index.pluginName, | ||
stage: Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE | ||
}, (assets) => { | ||
const runtimeSet = getCachedClassSet(); | ||
const groupedEntries = getGroupedEntries(Object.entries(assets)); | ||
const groupedEntries = index.getGroupedEntries(Object.entries(assets)); | ||
if (!runtimeSet.size) { | ||
@@ -656,3 +439,3 @@ const css = new Map(); | ||
if (isInclude(file)) { | ||
const code = jsHandler(chunk.source().toString(), { | ||
const code = index.jsHandler(chunk.source().toString(), { | ||
runtimeSet, | ||
@@ -672,3 +455,3 @@ classGenerator | ||
if (isInclude(file)) { | ||
const newCss = cssHandler(css.source().toString(), { | ||
const newCss = index$1.cssHandler(css.source().toString(), { | ||
classGenerator, | ||
@@ -699,3 +482,3 @@ runtimeSet | ||
const rawCode = chunk.source().toString(); | ||
const code = jsHandler(rawCode, { | ||
const code = index.jsHandler(rawCode, { | ||
runtimeSet, | ||
@@ -714,3 +497,3 @@ classGenerator | ||
if (isInclude(file)) { | ||
const newCss = cssHandler(style.source().toString(), { | ||
const newCss = index$1.cssHandler(style.source().toString(), { | ||
classGenerator, | ||
@@ -731,3 +514,3 @@ runtimeSet | ||
if (entries.length && classMapOutputOptions) { | ||
cacheDump(classMapOutputOptions.filename, entries.map((x) => { | ||
index.cacheDump(classMapOutputOptions.filename, entries.map((x) => { | ||
return [x[0], x[1].name]; | ||
@@ -734,0 +517,0 @@ }), classMapOutputOptions.dir); |
@@ -1,2 +0,2 @@ | ||
import { IHandlerOptions } from '@/types'; | ||
export declare function cssHandler(rawSource: string, options: IHandlerOptions): string; | ||
import { ICssHandlerOptions } from '@/types'; | ||
export declare function cssHandler(rawSource: string, options: ICssHandlerOptions): string; |
@@ -1,7 +0,5 @@ | ||
import { IClassGeneratorContextItem } from '@/types'; | ||
import { ICssHandlerOptions } from '@/types'; | ||
import type { PluginCreator } from 'postcss'; | ||
export type PostcssMangleTailwindcssPlugin = PluginCreator<{ | ||
newClassMap: Record<string, IClassGeneratorContextItem>; | ||
}>; | ||
export type PostcssMangleTailwindcssPlugin = PluginCreator<ICssHandlerOptions>; | ||
declare const postcssMangleTailwindcssPlugin: PostcssMangleTailwindcssPlugin; | ||
export { postcssMangleTailwindcssPlugin }; |
@@ -5,2 +5,5 @@ 'use strict'; | ||
require('unplugin'); | ||
require('./index-2edd594b.js'); | ||
require('@babel/types'); | ||
require('@babel/core'); | ||
require('micromatch'); | ||
@@ -10,3 +13,3 @@ require('fs'); | ||
require('parse5'); | ||
require('@babel/core'); | ||
require('./index-c8e1bdc5.js'); | ||
require('postcss'); | ||
@@ -13,0 +16,0 @@ require('postcss-selector-parser'); |
@@ -6,152 +6,19 @@ 'use strict'; | ||
var unplugin$1 = require('unplugin'); | ||
var micromatch = require('micromatch'); | ||
var index = require('./index-2edd594b.js'); | ||
var parse5 = require('parse5'); | ||
var index$1 = require('./index-c8e1bdc5.js'); | ||
var path = require('path'); | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var parse5 = require('parse5'); | ||
var core = require('@babel/core'); | ||
var postcss = require('postcss'); | ||
var parser = require('postcss-selector-parser'); | ||
var tailwindcssPatch = require('tailwindcss-patch'); | ||
require('@babel/types'); | ||
require('@babel/core'); | ||
require('micromatch'); | ||
require('postcss'); | ||
require('postcss-selector-parser'); | ||
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; } | ||
var micromatch__default = /*#__PURE__*/_interopDefault(micromatch); | ||
var path__default = /*#__PURE__*/_interopDefault(path); | ||
var fs__default = /*#__PURE__*/_interopDefault(fs); | ||
var path__default = /*#__PURE__*/_interopDefault(path); | ||
var postcss__default = /*#__PURE__*/_interopDefault(postcss); | ||
var parser__default = /*#__PURE__*/_interopDefault(parser); | ||
const pluginName = 'unplugin-tailwindcss-mangle'; | ||
const { isMatch } = micromatch__default["default"]; | ||
const isMangleClass = (className) => { | ||
return /[-:]/.test(className); | ||
}; | ||
function groupBy(arr, cb) { | ||
if (!Array.isArray(arr)) { | ||
throw new Error('expected an array for first argument'); | ||
} | ||
if (typeof cb !== 'function') { | ||
throw new Error('expected a function for second argument'); | ||
} | ||
const result = {}; | ||
for (let i = 0; i < arr.length; i++) { | ||
const item = arr[i]; | ||
const bucketCategory = cb(item); | ||
const bucket = result[bucketCategory]; | ||
if (!Array.isArray(bucket)) { | ||
result[bucketCategory] = [item]; | ||
} | ||
else { | ||
result[bucketCategory].push(item); | ||
} | ||
} | ||
return result; | ||
} | ||
function getGroupedEntries(entries, options = { | ||
cssMatcher(file) { | ||
return /\.css$/.test(file); | ||
}, | ||
htmlMatcher(file) { | ||
return /\.html?$/.test(file); | ||
}, | ||
jsMatcher(file) { | ||
return /\.[cm]?js$/.test(file); | ||
} | ||
}) { | ||
const { cssMatcher, htmlMatcher, jsMatcher } = options; | ||
const groupedEntries = groupBy(entries, ([file]) => { | ||
if (cssMatcher(file)) { | ||
return 'css'; | ||
} | ||
else if (htmlMatcher(file)) { | ||
return 'html'; | ||
} | ||
else if (jsMatcher(file)) { | ||
return 'js'; | ||
} | ||
else { | ||
return 'other'; | ||
} | ||
}); | ||
if (!groupedEntries.css) { | ||
groupedEntries.css = []; | ||
} | ||
if (!groupedEntries.html) { | ||
groupedEntries.html = []; | ||
} | ||
if (!groupedEntries.js) { | ||
groupedEntries.js = []; | ||
} | ||
if (!groupedEntries.other) { | ||
groupedEntries.other = []; | ||
} | ||
return groupedEntries; | ||
} | ||
const acceptChars = 'abcdefghijklmnopqrstuvwxyz'.split(''); | ||
function stripEscapeSequence(words) { | ||
return words.replace(/\\/g, ''); | ||
} | ||
function isRegexp(value) { | ||
return Object.prototype.toString.call(value) === '[object RegExp]'; | ||
} | ||
function regExpTest(arr = [], str) { | ||
if (Array.isArray(arr)) { | ||
for (let i = 0; i < arr.length; i++) { | ||
const item = arr[i]; | ||
if (typeof item === 'string') { | ||
if (item === str) { | ||
return true; | ||
} | ||
} | ||
else if (isRegexp(item)) { | ||
item.lastIndex = 0; | ||
if (item.test(str)) { | ||
return true; | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
throw new TypeError("paramater 'arr' should be a Array of Regexp | String !"); | ||
} | ||
function escapeStringRegexp(str) { | ||
if (typeof str !== 'string') { | ||
throw new TypeError('Expected a string'); | ||
} | ||
return str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/-/g, '\\x2d'); | ||
} | ||
function createGlobMatcher(pattern, fallbackValue = false) { | ||
if (typeof pattern === 'undefined') { | ||
return function (file) { | ||
return fallbackValue; | ||
}; | ||
} | ||
return function (file) { | ||
return isMatch(file, pattern); | ||
}; | ||
} | ||
function getCacheDir(basedir = process.cwd()) { | ||
return path__default["default"].resolve(basedir, 'node_modules/.cache', pluginName); | ||
} | ||
function mkCacheDirectory(cwd = process.cwd()) { | ||
const cacheDirectory = getCacheDir(cwd); | ||
const exists = fs__default["default"].existsSync(cacheDirectory); | ||
if (!exists) { | ||
fs__default["default"].mkdirSync(cacheDirectory, { | ||
recursive: true | ||
}); | ||
} | ||
return cacheDirectory; | ||
} | ||
function cacheDump(filename, data, basedir) { | ||
try { | ||
const dir = mkCacheDirectory(basedir); | ||
fs__default["default"].writeFileSync(path__default["default"].resolve(dir, filename), JSON.stringify(Array.from(data), null, 2), 'utf-8'); | ||
} | ||
catch (error) { | ||
console.log(error); | ||
} | ||
} | ||
({ | ||
@@ -272,103 +139,2 @@ HTML: parse5.html.NS.HTML, | ||
const validateFilterRE = /[\w\u00A0-\uFFFF-_:%-?]/; | ||
function isValidSelector(selector = '') { | ||
return validateFilterRE.test(selector); | ||
} | ||
const splitCode = (code) => code.split(/[\s"]+/).filter(isValidSelector); | ||
function makeRegex(str) { | ||
return new RegExp('(?<=^|[\\s"])' + escapeStringRegexp(str), 'g'); | ||
} | ||
function handleValue(str, node, options) { | ||
const set = options.runtimeSet; | ||
const clsGen = options.classGenerator; | ||
const arr = splitCode(str); | ||
let rawStr = str; | ||
for (let i = 0; i < arr.length; i++) { | ||
const v = arr[i]; | ||
if (set.has(v)) { | ||
let ignoreFlag = false; | ||
if (Array.isArray(node.leadingComments)) { | ||
ignoreFlag = node.leadingComments.findIndex((x) => x.value.includes('tw-mangle') && x.value.includes('ignore')) > -1; | ||
} | ||
if (!ignoreFlag) { | ||
rawStr = rawStr.replace(makeRegex(v), clsGen.generateClassName(v).name); | ||
} | ||
} | ||
} | ||
return rawStr; | ||
} | ||
function jsHandler(rawSource, options) { | ||
const result = core.transformSync(rawSource, { | ||
babelrc: false, | ||
ast: true, | ||
plugins: [ | ||
() => { | ||
return { | ||
visitor: { | ||
StringLiteral: { | ||
enter(p) { | ||
const n = p.node; | ||
n.value = handleValue(n.value, n, options); | ||
} | ||
}, | ||
TemplateElement: { | ||
enter(p) { | ||
const n = p.node; | ||
n.value.raw = handleValue(n.value.raw, n, options); | ||
} | ||
} | ||
} | ||
}; | ||
} | ||
], | ||
sourceMaps: false, | ||
configFile: false | ||
}); | ||
return result; | ||
} | ||
const postcssPlugin = 'postcss-mangle-tailwindcss-plugin'; | ||
const postcssMangleTailwindcssPlugin = (options) => { | ||
let newClassMap = {}; | ||
if (options) { | ||
if (options.newClassMap) { | ||
newClassMap = options.newClassMap; | ||
} | ||
} | ||
return { | ||
postcssPlugin, | ||
Rule(rule, helper) { | ||
rule.selector = parser__default["default"]((selectors) => { | ||
selectors.walkClasses((s) => { | ||
if (s.value) { | ||
const hit = newClassMap[s.value]; | ||
if (hit) { | ||
if (s.parent) { | ||
const idx = s.parent.nodes.indexOf(s); | ||
if (idx > -1) { | ||
const nextNode = s.parent.nodes[idx + 1]; | ||
if (nextNode && nextNode.type === 'attribute' && nextNode.attribute.indexOf('data-v-') > -1) { | ||
return; | ||
} | ||
} | ||
} | ||
s.value = hit.name; | ||
} | ||
} | ||
}); | ||
}).processSync(rule.selector); | ||
} | ||
}; | ||
}; | ||
postcssMangleTailwindcssPlugin.postcss = true; | ||
function cssHandler(rawSource, options) { | ||
return postcss__default["default"]([ | ||
postcssMangleTailwindcssPlugin({ | ||
newClassMap: options.classGenerator.newClassMap | ||
}) | ||
]).process(rawSource).css; | ||
} | ||
class ClassGenerator { | ||
@@ -389,8 +155,8 @@ newClassMap; | ||
const chars = []; | ||
let rest = (this.newClassSize - (this.newClassSize % acceptChars.length)) / acceptChars.length; | ||
let rest = (this.newClassSize - (this.newClassSize % index.acceptChars.length)) / index.acceptChars.length; | ||
if (rest > 0) { | ||
while (true) { | ||
rest -= 1; | ||
const m = rest % acceptChars.length; | ||
const c = acceptChars[m]; | ||
const m = rest % index.acceptChars.length; | ||
const c = index.acceptChars[m]; | ||
chars.push(c); | ||
@@ -401,11 +167,11 @@ rest -= m; | ||
} | ||
rest /= acceptChars.length; | ||
rest /= index.acceptChars.length; | ||
} | ||
} | ||
const prefixIndex = this.newClassSize % acceptChars.length; | ||
const newClassName = `${this.classPrefix}${acceptChars[prefixIndex]}${chars.join('')}`; | ||
const prefixIndex = this.newClassSize % index.acceptChars.length; | ||
const newClassName = `${this.classPrefix}${index.acceptChars[prefixIndex]}${chars.join('')}`; | ||
return newClassName; | ||
} | ||
ignoreClassName(className) { | ||
return regExpTest(this.opts.ignoreClass, className); | ||
return index.regExpTest(this.opts.ignoreClass, className); | ||
} | ||
@@ -415,3 +181,3 @@ includeFilePath(filePath) { | ||
if (Array.isArray(include)) { | ||
return regExpTest(include, filePath); | ||
return index.regExpTest(include, filePath); | ||
} | ||
@@ -425,3 +191,3 @@ else { | ||
if (Array.isArray(exclude)) { | ||
return regExpTest(exclude, filePath); | ||
return index.regExpTest(exclude, filePath); | ||
} | ||
@@ -436,3 +202,3 @@ else { | ||
transformCssClass(className) { | ||
const key = stripEscapeSequence(className); | ||
const key = index.stripEscapeSequence(className); | ||
const cn = this.newClassMap[key]; | ||
@@ -445,3 +211,3 @@ if (cn) | ||
const opts = this.opts; | ||
original = stripEscapeSequence(original); | ||
original = index.stripEscapeSequence(original); | ||
const cn = this.newClassMap[original]; | ||
@@ -457,3 +223,3 @@ if (cn) | ||
} | ||
if (opts.reserveClassName && regExpTest(opts.reserveClassName, newClassName)) { | ||
if (opts.reserveClassName && index.regExpTest(opts.reserveClassName, newClassName)) { | ||
if (opts.log) { | ||
@@ -479,4 +245,4 @@ console.log(`The class name has been reserved. ${newClassName}`); | ||
function getOptions(options = {}) { | ||
const includeMatcher = createGlobMatcher(options.include, true); | ||
const excludeMatcher = createGlobMatcher(options.exclude, false); | ||
const includeMatcher = index.createGlobMatcher(options.include, true); | ||
const excludeMatcher = index.createGlobMatcher(options.exclude, false); | ||
function isInclude(file) { | ||
@@ -486,2 +252,3 @@ return includeMatcher(file) && !excludeMatcher(file); | ||
let classSet; | ||
const twPatcher = new tailwindcssPatch.TailwindcssPatcher(); | ||
const classSetOutputOptions = { | ||
@@ -502,9 +269,9 @@ filename: 'classSet.json', | ||
function getCachedClassSet() { | ||
const set = tailwindcssPatch.getClassCacheSet(); | ||
const set = twPatcher.getClassSet(); | ||
const isOutput = set.size && options.classSetOutput; | ||
if (isOutput && classSetOutputOptions.type === 'all') { | ||
cacheDump(classSetOutputOptions.filename, set, classSetOutputOptions.dir); | ||
index.cacheDump(classSetOutputOptions.filename, set, classSetOutputOptions.dir); | ||
} | ||
set.forEach((c) => { | ||
if (!isMangleClass(c)) { | ||
if (!index.isMangleClass(c)) { | ||
set.delete(c); | ||
@@ -514,3 +281,3 @@ } | ||
if (isOutput && classSetOutputOptions.type === 'partial') { | ||
cacheDump(classSetOutputOptions.filename, set, classSetOutputOptions.dir); | ||
index.cacheDump(classSetOutputOptions.filename, set, classSetOutputOptions.dir); | ||
} | ||
@@ -527,3 +294,4 @@ classSet = set; | ||
classSetOutputOptions, | ||
classMapOutputOptions | ||
classMapOutputOptions, | ||
twPatcher | ||
}; | ||
@@ -536,3 +304,3 @@ } | ||
return { | ||
name: pluginName, | ||
name: index.pluginName, | ||
enforce: 'post', | ||
@@ -546,3 +314,3 @@ vite: { | ||
} | ||
const groupedEntries = getGroupedEntries(Object.entries(bundle)); | ||
const groupedEntries = index.getGroupedEntries(Object.entries(bundle)); | ||
if (Array.isArray(groupedEntries.html) && groupedEntries.html.length) { | ||
@@ -563,3 +331,3 @@ for (let i = 0; i < groupedEntries.html.length; i++) { | ||
if (isInclude(file)) { | ||
const code = jsHandler(chunk.code, { | ||
const code = index.jsHandler(chunk.code, { | ||
runtimeSet, | ||
@@ -578,3 +346,3 @@ classGenerator | ||
if (isInclude(file)) { | ||
css.source = cssHandler(css.source.toString(), { | ||
css.source = index$1.cssHandler(css.source.toString(), { | ||
classGenerator, | ||
@@ -590,3 +358,3 @@ runtimeSet | ||
webpack(compiler) { | ||
const Compilation = compiler.webpack.Compilation; | ||
const { NormalModule, Compilation } = compiler.webpack; | ||
const { ConcatSource } = compiler.webpack.sources; | ||
@@ -609,9 +377,24 @@ function getAssetPath(outputPath, file, abs = true) { | ||
} | ||
compiler.hooks.compilation.tap(pluginName, (compilation) => { | ||
const twmCssloader = path__default["default"].resolve(__dirname, 'twm-css.js'); | ||
compiler.hooks.compilation.tap(index.pluginName, (compilation) => { | ||
NormalModule.getCompilationHooks(compilation).loader.tap(index.pluginName, (loaderContext, module) => { | ||
const idx = module.loaders.findIndex((x) => x.loader.includes('css-loader')); | ||
if (idx > -1) { | ||
module.loaders.splice(idx + 1, 0, { | ||
loader: twmCssloader, | ||
options: { | ||
classGenerator, | ||
getCachedClassSet | ||
}, | ||
ident: null, | ||
type: null | ||
}); | ||
} | ||
}); | ||
compilation.hooks.processAssets.tap({ | ||
name: pluginName, | ||
name: index.pluginName, | ||
stage: Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE | ||
}, (assets) => { | ||
const runtimeSet = getCachedClassSet(); | ||
const groupedEntries = getGroupedEntries(Object.entries(assets)); | ||
const groupedEntries = index.getGroupedEntries(Object.entries(assets)); | ||
if (!runtimeSet.size) { | ||
@@ -656,3 +439,3 @@ const css = new Map(); | ||
if (isInclude(file)) { | ||
const code = jsHandler(chunk.source().toString(), { | ||
const code = index.jsHandler(chunk.source().toString(), { | ||
runtimeSet, | ||
@@ -672,3 +455,3 @@ classGenerator | ||
if (isInclude(file)) { | ||
const newCss = cssHandler(css.source().toString(), { | ||
const newCss = index$1.cssHandler(css.source().toString(), { | ||
classGenerator, | ||
@@ -699,3 +482,3 @@ runtimeSet | ||
const rawCode = chunk.source().toString(); | ||
const code = jsHandler(rawCode, { | ||
const code = index.jsHandler(rawCode, { | ||
runtimeSet, | ||
@@ -714,3 +497,3 @@ classGenerator | ||
if (isInclude(file)) { | ||
const newCss = cssHandler(style.source().toString(), { | ||
const newCss = index$1.cssHandler(style.source().toString(), { | ||
classGenerator, | ||
@@ -731,3 +514,3 @@ runtimeSet | ||
if (entries.length && classMapOutputOptions) { | ||
cacheDump(classMapOutputOptions.filename, entries.map((x) => { | ||
index.cacheDump(classMapOutputOptions.filename, entries.map((x) => { | ||
return [x[0], x[1].name]; | ||
@@ -734,0 +517,0 @@ }), classMapOutputOptions.dir); |
@@ -5,2 +5,5 @@ 'use strict'; | ||
require('unplugin'); | ||
require('./index-2edd594b.js'); | ||
require('@babel/types'); | ||
require('@babel/core'); | ||
require('micromatch'); | ||
@@ -10,3 +13,3 @@ require('fs'); | ||
require('parse5'); | ||
require('@babel/core'); | ||
require('./index-c8e1bdc5.js'); | ||
require('postcss'); | ||
@@ -13,0 +16,0 @@ require('postcss-selector-parser'); |
import type { Options, ClassSetOutputOptions, ClassMapOutputOptions } from './types'; | ||
import { TailwindcssPatcher } from 'tailwindcss-patch'; | ||
import ClassGenerator from './classGenerator'; | ||
@@ -11,2 +12,3 @@ export declare function getOptions(options?: Options | undefined): { | ||
classMapOutputOptions: ClassMapOutputOptions; | ||
twPatcher: TailwindcssPatcher; | ||
}; |
@@ -5,2 +5,5 @@ 'use strict'; | ||
require('unplugin'); | ||
require('./index-2edd594b.js'); | ||
require('@babel/types'); | ||
require('@babel/core'); | ||
require('micromatch'); | ||
@@ -10,3 +13,3 @@ require('fs'); | ||
require('parse5'); | ||
require('@babel/core'); | ||
require('./index-c8e1bdc5.js'); | ||
require('postcss'); | ||
@@ -13,0 +16,0 @@ require('postcss-selector-parser'); |
@@ -24,2 +24,5 @@ import type ClassGenerator from './classGenerator'; | ||
} | ||
export interface ICssHandlerOptions extends IHandlerOptions { | ||
scene?: 'loader' | 'process'; | ||
} | ||
export interface ClassSetOutputOptions { | ||
@@ -26,0 +29,0 @@ filename: string; |
@@ -5,2 +5,5 @@ 'use strict'; | ||
require('unplugin'); | ||
require('./index-2edd594b.js'); | ||
require('@babel/types'); | ||
require('@babel/core'); | ||
require('micromatch'); | ||
@@ -10,3 +13,3 @@ require('fs'); | ||
require('parse5'); | ||
require('@babel/core'); | ||
require('./index-c8e1bdc5.js'); | ||
require('postcss'); | ||
@@ -13,0 +16,0 @@ require('postcss-selector-parser'); |
@@ -5,2 +5,5 @@ 'use strict'; | ||
require('unplugin'); | ||
require('./index-2edd594b.js'); | ||
require('@babel/types'); | ||
require('@babel/core'); | ||
require('micromatch'); | ||
@@ -10,3 +13,3 @@ require('fs'); | ||
require('parse5'); | ||
require('@babel/core'); | ||
require('./index-c8e1bdc5.js'); | ||
require('postcss'); | ||
@@ -13,0 +16,0 @@ require('postcss-selector-parser'); |
{ | ||
"name": "unplugin-tailwindcss-mangle", | ||
"version": "0.1.2", | ||
"version": "0.1.3", | ||
"description": "mangle tailwindcss utilities class plugin. support vite and webpack!", | ||
@@ -63,11 +63,11 @@ "main": "./dist/index.js", | ||
"dependencies": { | ||
"@babel/core": "^7.21.4", | ||
"@babel/types": "^7.21.4", | ||
"@babel/core": "^7.21.5", | ||
"@babel/types": "^7.21.5", | ||
"micromatch": "^4.0.5", | ||
"parse5": "^7.1.2", | ||
"postcss": "^8.4.23", | ||
"postcss-selector-parser": "^6.0.11", | ||
"postcss-selector-parser": "^6.0.12", | ||
"semver": "^7.5.0", | ||
"unplugin": "^1.3.1", | ||
"tailwindcss-patch": "^1.1.0" | ||
"tailwindcss-patch": "^1.1.1" | ||
}, | ||
@@ -85,2 +85,3 @@ "publishConfig": { | ||
"pkg-types": "^1.0.2", | ||
"simple-functional-loader": "^1.2.1", | ||
"tailwindcss": "^3.3.2", | ||
@@ -87,0 +88,0 @@ "tslib": "^2.5.0", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
99329
41
2449
11
17
Updated@babel/core@^7.21.5
Updated@babel/types@^7.21.5
Updatedtailwindcss-patch@^1.1.1