-
-
Notifications
You must be signed in to change notification settings - Fork 247
/
index.ts
131 lines (113 loc) · 3.25 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/**
* PostCSS Plugin for PurgeCSS
*
* Most bundlers and frameworks to build websites are using PostCSS.
* The easiest way to configure PurgeCSS is with its PostCSS plugin.
*
* @packageDocumentation
*/
import * as path from "path";
import * as postcss from "postcss";
import {
PurgeCSS,
defaultOptions,
mergeExtractorSelectors,
standardizeSafelist,
RawContent,
} from "purgecss";
import { UserDefinedOptions } from "./types";
export * from "./types";
const PLUGIN_NAME = "postcss-purgecss";
/**
* Execute PurgeCSS process on the postCSS root node
*
* @param opts - PurgeCSS options
* @param root - root node of postCSS
* @param helpers - postCSS helpers
*/
async function purgeCSS(
opts: UserDefinedOptions,
root: postcss.Root,
{ result }: postcss.Helpers,
): Promise<void> {
const purgeCSS = new PurgeCSS();
let configFileOptions: UserDefinedOptions | undefined;
try {
const t = path.resolve(process.cwd(), "purgecss.config.js");
configFileOptions = await import(t);
} catch {
// no config file present
}
const options = {
...defaultOptions,
...configFileOptions,
...opts,
safelist: standardizeSafelist(
opts?.safelist || configFileOptions?.safelist,
),
};
if (opts && typeof opts.contentFunction === "function") {
options.content = opts.contentFunction(
(root.source && root.source.input.file) || "",
);
}
purgeCSS.options = options;
if (options.variables) {
purgeCSS.variablesStructure.safelist = options.safelist.variables || [];
}
const { content, extractors } = options;
const fileFormatContents = content.filter(
(o) => typeof o === "string",
) as string[];
const rawFormatContents = content.filter(
(o) => typeof o === "object",
) as RawContent[];
const cssFileSelectors = await purgeCSS.extractSelectorsFromFiles(
fileFormatContents,
extractors,
);
const cssRawSelectors = await purgeCSS.extractSelectorsFromString(
rawFormatContents,
extractors,
);
const selectors = mergeExtractorSelectors(cssFileSelectors, cssRawSelectors);
//purge unused selectors
purgeCSS.walkThroughCSS(root, selectors);
if (purgeCSS.options.fontFace) purgeCSS.removeUnusedFontFaces();
if (purgeCSS.options.keyframes) purgeCSS.removeUnusedKeyframes();
if (purgeCSS.options.variables) purgeCSS.removeUnusedCSSVariables();
if (purgeCSS.options.rejected && purgeCSS.selectorsRemoved.size > 0) {
result.messages.push({
type: "purgecss",
plugin: "postcss-purgecss",
text: `purging ${purgeCSS.selectorsRemoved.size} selectors:
${Array.from(purgeCSS.selectorsRemoved)
.map((selector) => selector.trim())
.join("\n ")}`,
});
purgeCSS.selectorsRemoved.clear();
}
}
/**
* PostCSS Plugin for PurgeCSS
*
* @param opts - PurgeCSS Options
* @returns the postCSS plugin
*
* @public
*/
const purgeCSSPlugin: postcss.PluginCreator<UserDefinedOptions> = function (
opts,
) {
if (typeof opts === "undefined")
throw new Error("PurgeCSS plugin does not have the correct options");
return {
postcssPlugin: PLUGIN_NAME,
OnceExit(root, helpers) {
return purgeCSS(opts, root, helpers);
},
};
};
purgeCSSPlugin.postcss = true;
export default purgeCSSPlugin;
export { purgeCSSPlugin };