feat: docker compose maybe
This commit is contained in:
1 parent
180b261e40
commit
b625ccd8d6
8031 files changed
+2182966
No files matched your search
+10
@@ -0,0 +1,10 @@
|
||||
import { Plugin } from 'vite';
|
||||
import { UserDefinedOptions, ComplexSafelist } from 'purgecss';
|
||||
|
||||
type Options = Partial<UserDefinedOptions> & {
|
||||
safelist?: ComplexSafelist;
|
||||
};
|
||||
type PurgeOptions = Omit<Options, 'css'>;
|
||||
declare function purgeCss(purgeOptions?: PurgeOptions): Plugin;
|
||||
|
||||
export { purgeCss as default, purgeCss };
|
||||
+228
@@ -0,0 +1,228 @@
|
||||
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// src/index.ts
|
||||
var _purgecss = require('purgecss');
|
||||
|
||||
// src/extractors/regex.ts
|
||||
var REGEX_SPECIAL = /[\\^$.*+?()[\]{}|]/g;
|
||||
var REGEX_HAS_SPECIAL = RegExp(REGEX_SPECIAL.source);
|
||||
function toSource(source) {
|
||||
source = Array.isArray(source) ? source : [source];
|
||||
source = source.map((item) => item instanceof RegExp ? item.source : item);
|
||||
return source.join("");
|
||||
}
|
||||
function pattern(source) {
|
||||
return new RegExp(toSource(source), "g");
|
||||
}
|
||||
function any(sources) {
|
||||
return `(?:${sources.map(toSource).join("|")})`;
|
||||
}
|
||||
function optional(source) {
|
||||
return `(?:${toSource(source)})?`;
|
||||
}
|
||||
|
||||
// src/extractors/default-extractor.ts
|
||||
function defaultExtractor() {
|
||||
let patterns = Array.from(buildRegExps());
|
||||
return (content) => {
|
||||
let results = [];
|
||||
for (let pattern2 of patterns) {
|
||||
results = [...results, ..._nullishCoalesce(content.match(pattern2), () => ( []))];
|
||||
}
|
||||
return results.filter((v) => v !== void 0).map(clipAtBalancedParens);
|
||||
};
|
||||
}
|
||||
function* buildRegExps() {
|
||||
let separator = ":";
|
||||
let prefix = "";
|
||||
let utility = any([
|
||||
/\[[^\s:'"`]+:[^\s\[\]]+\]/,
|
||||
/\[[^\s:'"`]+:[^\s]+?\[[^\s]+\][^\s]+?\]/,
|
||||
pattern([
|
||||
/-?(?:\w+)/,
|
||||
optional(
|
||||
any([
|
||||
pattern([
|
||||
/-(?:\w+-)*\[[^\s:]+\]/,
|
||||
/(?![{([]])/,
|
||||
/(?:\/[^\s'"`\\><$]*)?/
|
||||
]),
|
||||
pattern([
|
||||
/-(?:\w+-)*\[[^\s]+\]/,
|
||||
/(?![{([]])/,
|
||||
/(?:\/[^\s'"`\\$]*)?/
|
||||
]),
|
||||
/[-\/][^\s'"`\\$={><]*/
|
||||
])
|
||||
)
|
||||
])
|
||||
]);
|
||||
let variantPatterns = [
|
||||
any([
|
||||
pattern([/@\[[^\s"'`]+\](\/[^\s"'`]+)?/, separator]),
|
||||
pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/, separator]),
|
||||
pattern([/[^\s"'`\[\\]+/, separator])
|
||||
]),
|
||||
any([
|
||||
pattern([/([^\s"'`\[\\]+-)?\[[^\s`]+\]/, separator]),
|
||||
pattern([/[^\s`\[\\]+/, separator])
|
||||
])
|
||||
];
|
||||
for (const variantPattern of variantPatterns) {
|
||||
yield pattern([
|
||||
"((?=((",
|
||||
variantPattern,
|
||||
")+))\\2)?",
|
||||
/!?/,
|
||||
prefix,
|
||||
utility
|
||||
]);
|
||||
}
|
||||
yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g;
|
||||
}
|
||||
var SPECIALS = /([\[\]'"`])([^\[\]'"`])?/g;
|
||||
var ALLOWED_CLASS_CHARACTERS = /[^"'`\s<>\]]+/;
|
||||
function clipAtBalancedParens(input) {
|
||||
if (!input.includes("-[")) {
|
||||
return input;
|
||||
}
|
||||
let depth = 0;
|
||||
let openStringTypes = [];
|
||||
let matches = input.matchAll(SPECIALS);
|
||||
const matched = Array.from(matches).flatMap((match) => {
|
||||
const [, ...groups] = match;
|
||||
return groups.map(
|
||||
(group, idx) => Object.assign([], match, {
|
||||
index: match.index + idx,
|
||||
0: group
|
||||
})
|
||||
);
|
||||
});
|
||||
for (let match of matched) {
|
||||
let char = match[0];
|
||||
let inStringType = openStringTypes.at(-1);
|
||||
if (char === inStringType) {
|
||||
openStringTypes.pop();
|
||||
} else if (char === "'" || char === '"' || char === "`") {
|
||||
openStringTypes.push(char);
|
||||
}
|
||||
if (inStringType) {
|
||||
continue;
|
||||
} else if (char === "[") {
|
||||
depth++;
|
||||
continue;
|
||||
} else if (char === "]") {
|
||||
depth--;
|
||||
continue;
|
||||
}
|
||||
if (depth < 0) {
|
||||
return input.substring(0, match.index - 1);
|
||||
}
|
||||
if (depth === 0 && !ALLOWED_CLASS_CHARACTERS.test(char)) {
|
||||
return input.substring(0, match.index);
|
||||
}
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
// src/index.ts
|
||||
var _estreewalker = require('estree-walker');
|
||||
var _path = require('path');
|
||||
var EXT_CSS = /\.(css)$/;
|
||||
var MAX_STRING_LITERAL_LENGTH = 5e4;
|
||||
function purgeCss(purgeOptions) {
|
||||
var _a;
|
||||
let viteConfig;
|
||||
const selectors = /* @__PURE__ */ new Set();
|
||||
const standard = [
|
||||
"*",
|
||||
"html",
|
||||
"body",
|
||||
/aria-current/,
|
||||
/^\:[-a-z]+$/,
|
||||
..._nullishCoalesce(((_a = purgeOptions == null ? void 0 : purgeOptions.safelist) == null ? void 0 : _a.standard), () => ( []))
|
||||
];
|
||||
const extractor = _nullishCoalesce((purgeOptions == null ? void 0 : purgeOptions.defaultExtractor), () => ( defaultExtractor()));
|
||||
const moduleIds = /* @__PURE__ */ new Set();
|
||||
return {
|
||||
name: "vite-plugin-tailwind-purgecss",
|
||||
apply: "build",
|
||||
enforce: "post",
|
||||
load(id) {
|
||||
if (EXT_CSS.test(id))
|
||||
return;
|
||||
moduleIds.add(id);
|
||||
},
|
||||
configResolved(config) {
|
||||
viteConfig = config;
|
||||
},
|
||||
async generateBundle(options, bundle) {
|
||||
var _a2;
|
||||
const assets = {};
|
||||
for (const id of moduleIds) {
|
||||
const info = this.getModuleInfo(id);
|
||||
if ((info == null ? void 0 : info.isIncluded) !== true || info.code === null)
|
||||
continue;
|
||||
const ast = this.parse(info.code);
|
||||
_estreewalker.walk.call(void 0, ast, {
|
||||
enter(node, parent, key, index) {
|
||||
if (node.type === "Literal" && typeof node.value === "string") {
|
||||
node.value.split(/\s+/).forEach((word) => {
|
||||
if (word.length < MAX_STRING_LITERAL_LENGTH) {
|
||||
extractor(word).forEach((selector) => selectors.add(selector));
|
||||
} else
|
||||
selectors.add(word);
|
||||
});
|
||||
}
|
||||
if (node.type === "Identifier") {
|
||||
selectors.add(node.name);
|
||||
}
|
||||
if (node.type === "TemplateElement") {
|
||||
const value = _nullishCoalesce(node.value.cooked, () => ( node.value.raw));
|
||||
value.split(/\s+/).forEach((word) => {
|
||||
if (word.length < MAX_STRING_LITERAL_LENGTH) {
|
||||
extractor(word).forEach((selector) => selectors.add(selector));
|
||||
} else
|
||||
selectors.add(word);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
for (const [fileName, chunkOrAsset] of Object.entries(bundle)) {
|
||||
if (chunkOrAsset.type === "asset" && EXT_CSS.test(fileName)) {
|
||||
assets[fileName] = chunkOrAsset;
|
||||
}
|
||||
}
|
||||
for (const selector of selectors) {
|
||||
standard.push(selector);
|
||||
}
|
||||
for (const [fileName, asset] of Object.entries(assets)) {
|
||||
const purgeCSSResult = await new (0, _purgecss.PurgeCSS)().purge({
|
||||
...purgeOptions,
|
||||
content: [_path.join.call(void 0, viteConfig.root, "**/*.html"), ..._nullishCoalesce((purgeOptions == null ? void 0 : purgeOptions.content), () => ( []))],
|
||||
css: [{ raw: asset.source.trim(), name: fileName }],
|
||||
rejected: true,
|
||||
rejectedCss: true,
|
||||
safelist: {
|
||||
...purgeOptions == null ? void 0 : purgeOptions.safelist,
|
||||
standard,
|
||||
greedy: [/svelte-/, /data-theme/, ..._nullishCoalesce(((_a2 = purgeOptions == null ? void 0 : purgeOptions.safelist) == null ? void 0 : _a2.greedy), () => ( []))]
|
||||
}
|
||||
});
|
||||
if (purgeCSSResult[0]) {
|
||||
delete bundle[asset.fileName];
|
||||
this.emitFile({
|
||||
...asset,
|
||||
type: "asset",
|
||||
source: purgeCSSResult[0].css
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
var src_default = purgeCss;
|
||||
|
||||
|
||||
|
||||
exports.default = src_default; exports.purgeCss = purgeCss;
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../src/index.ts","../src/extractors/regex.ts","../src/extractors/default-extractor.ts"],"names":["pattern","_a"],"mappings":"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","sourcesContent":["import { PurgeCSS } from 'purgecss';\nimport { defaultExtractor } from './extractors/default-extractor';\nimport { walk } from 'estree-walker';\nimport { join } from 'path';\nimport type { ResolvedConfig, Plugin } from 'vite';\nimport type { ComplexSafelist, StringRegExpArray, UserDefinedOptions } from 'purgecss';\n\ntype Extractor = (content: stLine truncated
|
||||
+228
@@ -0,0 +1,228 @@
|
||||
// src/index.ts
|
||||
import { PurgeCSS } from "purgecss";
|
||||
|
||||
// src/extractors/regex.ts
|
||||
var REGEX_SPECIAL = /[\\^$.*+?()[\]{}|]/g;
|
||||
var REGEX_HAS_SPECIAL = RegExp(REGEX_SPECIAL.source);
|
||||
function toSource(source) {
|
||||
source = Array.isArray(source) ? source : [source];
|
||||
source = source.map((item) => item instanceof RegExp ? item.source : item);
|
||||
return source.join("");
|
||||
}
|
||||
function pattern(source) {
|
||||
return new RegExp(toSource(source), "g");
|
||||
}
|
||||
function any(sources) {
|
||||
return `(?:${sources.map(toSource).join("|")})`;
|
||||
}
|
||||
function optional(source) {
|
||||
return `(?:${toSource(source)})?`;
|
||||
}
|
||||
|
||||
// src/extractors/default-extractor.ts
|
||||
function defaultExtractor() {
|
||||
let patterns = Array.from(buildRegExps());
|
||||
return (content) => {
|
||||
let results = [];
|
||||
for (let pattern2 of patterns) {
|
||||
results = [...results, ...content.match(pattern2) ?? []];
|
||||
}
|
||||
return results.filter((v) => v !== void 0).map(clipAtBalancedParens);
|
||||
};
|
||||
}
|
||||
function* buildRegExps() {
|
||||
let separator = ":";
|
||||
let prefix = "";
|
||||
let utility = any([
|
||||
/\[[^\s:'"`]+:[^\s\[\]]+\]/,
|
||||
/\[[^\s:'"`]+:[^\s]+?\[[^\s]+\][^\s]+?\]/,
|
||||
pattern([
|
||||
/-?(?:\w+)/,
|
||||
optional(
|
||||
any([
|
||||
pattern([
|
||||
/-(?:\w+-)*\[[^\s:]+\]/,
|
||||
/(?![{([]])/,
|
||||
/(?:\/[^\s'"`\\><$]*)?/
|
||||
]),
|
||||
pattern([
|
||||
/-(?:\w+-)*\[[^\s]+\]/,
|
||||
/(?![{([]])/,
|
||||
/(?:\/[^\s'"`\\$]*)?/
|
||||
]),
|
||||
/[-\/][^\s'"`\\$={><]*/
|
||||
])
|
||||
)
|
||||
])
|
||||
]);
|
||||
let variantPatterns = [
|
||||
any([
|
||||
pattern([/@\[[^\s"'`]+\](\/[^\s"'`]+)?/, separator]),
|
||||
pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/, separator]),
|
||||
pattern([/[^\s"'`\[\\]+/, separator])
|
||||
]),
|
||||
any([
|
||||
pattern([/([^\s"'`\[\\]+-)?\[[^\s`]+\]/, separator]),
|
||||
pattern([/[^\s`\[\\]+/, separator])
|
||||
])
|
||||
];
|
||||
for (const variantPattern of variantPatterns) {
|
||||
yield pattern([
|
||||
"((?=((",
|
||||
variantPattern,
|
||||
")+))\\2)?",
|
||||
/!?/,
|
||||
prefix,
|
||||
utility
|
||||
]);
|
||||
}
|
||||
yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g;
|
||||
}
|
||||
var SPECIALS = /([\[\]'"`])([^\[\]'"`])?/g;
|
||||
var ALLOWED_CLASS_CHARACTERS = /[^"'`\s<>\]]+/;
|
||||
function clipAtBalancedParens(input) {
|
||||
if (!input.includes("-[")) {
|
||||
return input;
|
||||
}
|
||||
let depth = 0;
|
||||
let openStringTypes = [];
|
||||
let matches = input.matchAll(SPECIALS);
|
||||
const matched = Array.from(matches).flatMap((match) => {
|
||||
const [, ...groups] = match;
|
||||
return groups.map(
|
||||
(group, idx) => Object.assign([], match, {
|
||||
index: match.index + idx,
|
||||
0: group
|
||||
})
|
||||
);
|
||||
});
|
||||
for (let match of matched) {
|
||||
let char = match[0];
|
||||
let inStringType = openStringTypes.at(-1);
|
||||
if (char === inStringType) {
|
||||
openStringTypes.pop();
|
||||
} else if (char === "'" || char === '"' || char === "`") {
|
||||
openStringTypes.push(char);
|
||||
}
|
||||
if (inStringType) {
|
||||
continue;
|
||||
} else if (char === "[") {
|
||||
depth++;
|
||||
continue;
|
||||
} else if (char === "]") {
|
||||
depth--;
|
||||
continue;
|
||||
}
|
||||
if (depth < 0) {
|
||||
return input.substring(0, match.index - 1);
|
||||
}
|
||||
if (depth === 0 && !ALLOWED_CLASS_CHARACTERS.test(char)) {
|
||||
return input.substring(0, match.index);
|
||||
}
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
// src/index.ts
|
||||
import { walk } from "estree-walker";
|
||||
import { join } from "path";
|
||||
var EXT_CSS = /\.(css)$/;
|
||||
var MAX_STRING_LITERAL_LENGTH = 5e4;
|
||||
function purgeCss(purgeOptions) {
|
||||
var _a;
|
||||
let viteConfig;
|
||||
const selectors = /* @__PURE__ */ new Set();
|
||||
const standard = [
|
||||
"*",
|
||||
"html",
|
||||
"body",
|
||||
/aria-current/,
|
||||
/^\:[-a-z]+$/,
|
||||
...((_a = purgeOptions == null ? void 0 : purgeOptions.safelist) == null ? void 0 : _a.standard) ?? []
|
||||
];
|
||||
const extractor = (purgeOptions == null ? void 0 : purgeOptions.defaultExtractor) ?? defaultExtractor();
|
||||
const moduleIds = /* @__PURE__ */ new Set();
|
||||
return {
|
||||
name: "vite-plugin-tailwind-purgecss",
|
||||
apply: "build",
|
||||
enforce: "post",
|
||||
load(id) {
|
||||
if (EXT_CSS.test(id))
|
||||
return;
|
||||
moduleIds.add(id);
|
||||
},
|
||||
configResolved(config) {
|
||||
viteConfig = config;
|
||||
},
|
||||
async generateBundle(options, bundle) {
|
||||
var _a2;
|
||||
const assets = {};
|
||||
for (const id of moduleIds) {
|
||||
const info = this.getModuleInfo(id);
|
||||
if ((info == null ? void 0 : info.isIncluded) !== true || info.code === null)
|
||||
continue;
|
||||
const ast = this.parse(info.code);
|
||||
walk(ast, {
|
||||
enter(node, parent, key, index) {
|
||||
if (node.type === "Literal" && typeof node.value === "string") {
|
||||
node.value.split(/\s+/).forEach((word) => {
|
||||
if (word.length < MAX_STRING_LITERAL_LENGTH) {
|
||||
extractor(word).forEach((selector) => selectors.add(selector));
|
||||
} else
|
||||
selectors.add(word);
|
||||
});
|
||||
}
|
||||
if (node.type === "Identifier") {
|
||||
selectors.add(node.name);
|
||||
}
|
||||
if (node.type === "TemplateElement") {
|
||||
const value = node.value.cooked ?? node.value.raw;
|
||||
value.split(/\s+/).forEach((word) => {
|
||||
if (word.length < MAX_STRING_LITERAL_LENGTH) {
|
||||
extractor(word).forEach((selector) => selectors.add(selector));
|
||||
} else
|
||||
selectors.add(word);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
for (const [fileName, chunkOrAsset] of Object.entries(bundle)) {
|
||||
if (chunkOrAsset.type === "asset" && EXT_CSS.test(fileName)) {
|
||||
assets[fileName] = chunkOrAsset;
|
||||
}
|
||||
}
|
||||
for (const selector of selectors) {
|
||||
standard.push(selector);
|
||||
}
|
||||
for (const [fileName, asset] of Object.entries(assets)) {
|
||||
const purgeCSSResult = await new PurgeCSS().purge({
|
||||
...purgeOptions,
|
||||
content: [join(viteConfig.root, "**/*.html"), ...(purgeOptions == null ? void 0 : purgeOptions.content) ?? []],
|
||||
css: [{ raw: asset.source.trim(), name: fileName }],
|
||||
rejected: true,
|
||||
rejectedCss: true,
|
||||
safelist: {
|
||||
...purgeOptions == null ? void 0 : purgeOptions.safelist,
|
||||
standard,
|
||||
greedy: [/svelte-/, /data-theme/, ...((_a2 = purgeOptions == null ? void 0 : purgeOptions.safelist) == null ? void 0 : _a2.greedy) ?? []]
|
||||
}
|
||||
});
|
||||
if (purgeCSSResult[0]) {
|
||||
delete bundle[asset.fileName];
|
||||
this.emitFile({
|
||||
...asset,
|
||||
type: "asset",
|
||||
source: purgeCSSResult[0].css
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
var src_default = purgeCss;
|
||||
export {
|
||||
src_default as default,
|
||||
purgeCss
|
||||
};
|
||||
//# sourceMappingURL=index.mjs.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../src/index.ts","../src/extractors/regex.ts","../src/extractors/default-extractor.ts"],"sourcesContent":["import { PurgeCSS } from 'purgecss';\nimport { defaultExtractor } from './extractors/default-extractor';\nimport { walk } from 'estree-walker';\nimport { join } from 'path';\nimport type { ResolvedConfig, Plugin } from 'vite';\nimport type { ComplexSafelist, StringRegExpArray, UserDefinedOptions } from 'purgecss';\n\ntype Extractor = (content: string) => string[];\n\ntype Options = Partial<UserDefinedOptions> & {\n\tsafelist?: ComplexSafelist;\n};\ntype PurgeOptions = Omit<Options, 'css'>;\n\nconst EXT_CSS = /\\.(css)$/;\nconst MAX_STRING_LITERAL_LENGTH = 50_000;\n\nexport function purgeCss(purgeOptions?: PurgeOptions): Plugin {\n\tlet viteConfig: ResolvedConfig;\n\tconst selectors = new Set<string>();\n\tconst standard: StringRegExpArray = [\n\t\t'*',\n\t\t'html',\n\t\t'body',\n\t\t/aria-current/,\n\t\t// fix for pseudo-class functions that begin with `:` getting purged (e.g. `:is`)\n\t\t// see: https://github.com/FullHuman/purgecss/issues/978\n\t\t/^\\:[-a-z]+$/,\n\t\t...(purgeOptions?.safelist?.standard ?? []),\n\t];\n\tconst extractor = (purgeOptions?.defaultExtractor as Extractor) ?? defaultExtractor();\n\tconst moduleIds = new Set<string>();\n\n\treturn {\n\t\tname: 'vite-plugin-tailwind-purgecss',\n\t\tapply: 'build',\n\t\tenforce: 'post',\n\n\t\tload(id) {\n\t\t\tif (EXT_CSS.test(id)) return;\n\t\t\tmoduleIds.add(id);\n\t\t},\n\n\t\tconfigResolved(config) {\n\t\t\tviteConfig = config;\n\t\t},\n\n\t\tasync generateBundle(options, bundle) {\n\t\t\ttype ChunkOrAsset = (typeof bundle)[string];\n\t\t\ttype Asset = Extract<ChunkOrAsset, { type: 'asset' }>;\n\t\t\tconst assets: Record<string, Asset> = {};\n\n\t\t\tfor (const id of moduleIds) {\n\t\t\t\tconst info = this.getModuleInfo(id);\n\t\t\t\tif (info?.isIncluded !== true || info.code === null) continue;\n\n\t\t\t\tconst ast = this.parse(info.code);\n\n\t\t\t\t// @ts-expect-error mismatched node types\n\t\t\t\twalk(ast, {\n\t\t\t\t\tenter(node, parent, key, index) {\n\t\t\t\t\t\tif (node.type === 'Literal' && typeof node.value === 'string') {\n\t\t\t\t\t\t\tnode.value.split(/\\s+/).forEach((word) => {\n\t\t\t\t\t\t\t\tif (word.length < MAX_STRING_LITERAL_LENGTH) {\n\t\t\t\t\t\t\t\t\textractor(word).forEach((selector) => selectors.add(selector));\n\t\t\t\t\t\t\t\t} else selectors.add(word);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (node.type === 'Identifier') {\n\t\t\t\t\t\t\tselectors.add(node.name);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (node.type === 'TemplateElement') {\n\t\t\t\t\t\t\tconst value = node.value.cooked ?? node.value.raw;\n\t\t\t\t\t\t\tvalue.split(/\\s+/).forEach((word) => {\n\t\t\t\t\t\t\t\tif (word.length < MAX_STRING_LITERAL_LENGTH) {\n\t\t\t\t\t\t\t\t\textractor(word).forEach((selector) => selectors.add(selector));\n\t\t\t\t\t\t\t\t} else selectors.add(word);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tfor (const [fileName, chunkOrAsset] of Object.entries(bundle)) {\n\t\t\t\tif (chunkOrAsset.type === 'asset' && EXT_CSS.test(fileName)) {\n\t\t\t\t\tassets[fileName] = chunkOrAsset;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const selector of selectors) {\n\t\t\t\tstandard.push(selector);\n\t\t\t}\n\n\t\t\tfor (const [fileName, asset] of Object.entries(assets)) {\n\t\t\t\tconst purgeCSSResult = await new PurgeCSS().purge({\n\t\t\t\t\t...purgeOptions,\n\t\t\t\t\tcontent: [join(viteConfig.root, '**/*.html'), ...(purgeOptions?.content ?? [])],\n\t\t\t\t\tcss: [{ raw: (asset.source as string).trim(), name: fileName }],\n\t\t\t\t\trejected: true,\n\t\t\t\t\trejectedCss: true,\n\t\t\t\t\tsafelist: {\n\t\t\t\t\t\t...purgeOptions?.safelist,\n\t\t\t\t\t\tstandard,\n\t\t\t\t\t\tgreedy: [/svelte-/, /data-theme/, ...(purgeOptions?.safelist?.greedy ?? [])],\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\tif (purgeCSSResult[0]) {\n\t\t\t\t\t// prevent the original from being written\n\t\t\t\t\tdelete bundle[asset.fileName];\n\n\t\t\t\t\t// emit the newly purged css file\n\t\t\t\t\tthis.emitFile({\n\t\t\t\t\t\t...asset,\n\t\t\t\t\t\ttype: 'asset',\n\t\t\t\t\t\tsource: purgeCSSResult[0].css,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport default purgeCss;\n","const REGEX_SPECIAL = /[\\\\^$.*+?()[\\]{}|]/g;\nconst REGEX_HAS_SPECIAL = RegExp(REGEX_SPECIAL.source);\n\nfunction toSource(source: string | RegExp | Array<string | RegExp>) {\n\tsource = Array.isArray(source) ? source : [source];\n\n\tsource = source.map((item) => (item instanceof RegExp ? item.source : item));\n\n\treturn source.join('');\n}\n\nexport function pattern(source: string | RegExp | Array<string | RegExp>) {\n\treturn new RegExp(toSource(source), 'g');\n}\n\nexport function withoutCapturing(source: string | RegExp | Array<string | RegExp>) {\n\treturn new RegExp(`(?:${toSource(source)})`, 'g');\n}\n\nexport function any(sources: Array<string | RegExp>) {\n\treturn `(?:${sources.map(toSource).join('|')})`;\n}\n\nexporLine truncated
|
||||
Reference in new issue
Block a user