@fullhuman/postcss-purgecss 7.0.2 → 9.0.0

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.
@@ -34,8 +34,29 @@ export declare type ComplexSafelist = {
34
34
  * in the final CSS, even if `child-of-bg` is not found.
35
35
  *
36
36
  */
37
- deep?: RegExp[];
38
- greedy?: RegExp[];
37
+ deep?: StringRegExpArray;
38
+ /**
39
+ * You can safelist whole selectors if any part of that selector matches a
40
+ * pattern with `safelist.greedy`
41
+ *
42
+ * @example
43
+ *
44
+ * ```ts
45
+ * const purgecss = await new PurgeCSS().purge({
46
+ * content: [],
47
+ * css: [],
48
+ * safelist: {
49
+ * greedy: [/red$/]
50
+ * }
51
+ * })
52
+ * ```
53
+ *
54
+ * In this example, selectors such as `button.bg-red.nonexistent-class`
55
+ * will be left in the final CSS, even if `button` and `nonexistent-class`
56
+ * are not found.
57
+ *
58
+ */
59
+ greedy?: StringRegExpArray;
39
60
  variables?: StringRegExpArray;
40
61
  keyframes?: StringRegExpArray;
41
62
  };
@@ -82,7 +103,6 @@ export declare interface Extractors {
82
103
  */
83
104
  declare const purgeCSSPlugin: postcss.PluginCreator<UserDefinedOptions>;
84
105
  export default purgeCSSPlugin;
85
- export { purgeCSSPlugin }
86
106
 
87
107
  /**
88
108
  * Options used by PurgeCSS to remove unused CSS
@@ -123,7 +143,7 @@ export declare interface PurgeCSSUserDefinedOptions {
123
143
  /** {@inheritDoc purgecss#Options.skippedContentGlobs} */
124
144
  skippedContentGlobs?: Array<string>;
125
145
  /** {@inheritDoc purgecss#Options.dynamicAttributes} */
126
- dynamicAttributes?: string[];
146
+ dynamicAttributes?: StringRegExpArray;
127
147
  }
128
148
 
129
149
  /**
@@ -143,6 +163,12 @@ export declare interface RawCSS {
143
163
  }
144
164
 
145
165
  /**
166
+ * Strings and regular expressions an option is matched against. A string
167
+ * matches a value exactly, except a string written between slashes, like
168
+ * `"/^btn-/"` or `"/^btn-/i"`, which is parsed as a regular expression. This
169
+ * form lets configuration files that cannot contain regular expressions, such
170
+ * as `postcss.config.json`, use patterns.
171
+ *
146
172
  * @public
147
173
  */
148
174
  export declare type StringRegExpArray = Array<RegExp | string>;
@@ -1,5 +1,7 @@
1
+ import * as fs from 'fs';
1
2
  import * as path from 'path';
2
- import { PurgeCSS, defaultOptions, standardizeSafelist, mergeExtractorSelectors } from 'purgecss';
3
+ import { pathToFileURL } from 'url';
4
+ import { PurgeCSS, standardizeSafelist, defaultOptions, mergeExtractorSelectors } from 'purgecss';
3
5
 
4
6
  /**
5
7
  * PostCSS Plugin for PurgeCSS
@@ -20,18 +22,38 @@ const PLUGIN_NAME = "postcss-purgecss";
20
22
  async function purgeCSS(opts, root, { result }) {
21
23
  const purgeCSS = new PurgeCSS();
22
24
  let configFileOptions;
23
- try {
24
- const t = path.resolve(process.cwd(), "purgecss.config.js");
25
- configFileOptions = await import(t);
26
- }
27
- catch {
28
- // no config file present
25
+ const t = path.resolve(process.cwd(), "purgecss.config.js");
26
+ // the config file is optional, but an existing one that fails to load
27
+ // (e.g. a syntax error) is reported instead of being silently ignored
28
+ if (fs.existsSync(t)) {
29
+ try {
30
+ const importedConfig = await import(pathToFileURL(t).href);
31
+ // Handle both ES modules (direct export) and CommonJS (default export)
32
+ configFileOptions =
33
+ importedConfig.default && typeof importedConfig.default === "object"
34
+ ? importedConfig.default
35
+ : importedConfig;
36
+ }
37
+ catch (err) {
38
+ throw new Error(`Error loading the config file ${t}: ${err}`, {
39
+ cause: err,
40
+ });
41
+ }
29
42
  }
43
+ // the safelists of the config file and of the plugin options add up
44
+ const configFileSafelist = standardizeSafelist(configFileOptions === null || configFileOptions === void 0 ? void 0 : configFileOptions.safelist);
45
+ const pluginSafelist = standardizeSafelist(opts === null || opts === void 0 ? void 0 : opts.safelist);
30
46
  const options = {
31
47
  ...defaultOptions,
32
48
  ...configFileOptions,
33
49
  ...opts,
34
- safelist: standardizeSafelist((opts === null || opts === void 0 ? void 0 : opts.safelist) || (configFileOptions === null || configFileOptions === void 0 ? void 0 : configFileOptions.safelist)),
50
+ safelist: {
51
+ standard: [...configFileSafelist.standard, ...pluginSafelist.standard],
52
+ deep: [...configFileSafelist.deep, ...pluginSafelist.deep],
53
+ greedy: [...configFileSafelist.greedy, ...pluginSafelist.greedy],
54
+ keyframes: [...configFileSafelist.keyframes, ...pluginSafelist.keyframes],
55
+ variables: [...configFileSafelist.variables, ...pluginSafelist.variables],
56
+ },
35
57
  };
36
58
  if (opts && typeof opts.contentFunction === "function") {
37
59
  options.content = opts.contentFunction((root.source && root.source.input.file) || "");
@@ -86,4 +108,4 @@ const purgeCSSPlugin = function (opts) {
86
108
  };
87
109
  purgeCSSPlugin.postcss = true;
88
110
 
89
- export { purgeCSSPlugin as default, purgeCSSPlugin };
111
+ export { purgeCSSPlugin as default };
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
3
+ var fs = require('fs');
5
4
  var path = require('path');
5
+ var url = require('url');
6
6
  var purgecss = require('purgecss');
7
7
 
8
8
  function _interopNamespaceDefault(e) {
@@ -22,6 +22,7 @@ function _interopNamespaceDefault(e) {
22
22
  return Object.freeze(n);
23
23
  }
24
24
 
25
+ var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
25
26
  var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
26
27
 
27
28
  /**
@@ -43,18 +44,38 @@ const PLUGIN_NAME = "postcss-purgecss";
43
44
  async function purgeCSS(opts, root, { result }) {
44
45
  const purgeCSS = new purgecss.PurgeCSS();
45
46
  let configFileOptions;
46
- try {
47
- const t = path__namespace.resolve(process.cwd(), "purgecss.config.js");
48
- configFileOptions = await import(t);
49
- }
50
- catch {
51
- // no config file present
47
+ const t = path__namespace.resolve(process.cwd(), "purgecss.config.js");
48
+ // the config file is optional, but an existing one that fails to load
49
+ // (e.g. a syntax error) is reported instead of being silently ignored
50
+ if (fs__namespace.existsSync(t)) {
51
+ try {
52
+ const importedConfig = await import(url.pathToFileURL(t).href);
53
+ // Handle both ES modules (direct export) and CommonJS (default export)
54
+ configFileOptions =
55
+ importedConfig.default && typeof importedConfig.default === "object"
56
+ ? importedConfig.default
57
+ : importedConfig;
58
+ }
59
+ catch (err) {
60
+ throw new Error(`Error loading the config file ${t}: ${err}`, {
61
+ cause: err,
62
+ });
63
+ }
52
64
  }
65
+ // the safelists of the config file and of the plugin options add up
66
+ const configFileSafelist = purgecss.standardizeSafelist(configFileOptions === null || configFileOptions === void 0 ? void 0 : configFileOptions.safelist);
67
+ const pluginSafelist = purgecss.standardizeSafelist(opts === null || opts === void 0 ? void 0 : opts.safelist);
53
68
  const options = {
54
69
  ...purgecss.defaultOptions,
55
70
  ...configFileOptions,
56
71
  ...opts,
57
- safelist: purgecss.standardizeSafelist((opts === null || opts === void 0 ? void 0 : opts.safelist) || (configFileOptions === null || configFileOptions === void 0 ? void 0 : configFileOptions.safelist)),
72
+ safelist: {
73
+ standard: [...configFileSafelist.standard, ...pluginSafelist.standard],
74
+ deep: [...configFileSafelist.deep, ...pluginSafelist.deep],
75
+ greedy: [...configFileSafelist.greedy, ...pluginSafelist.greedy],
76
+ keyframes: [...configFileSafelist.keyframes, ...pluginSafelist.keyframes],
77
+ variables: [...configFileSafelist.variables, ...pluginSafelist.variables],
78
+ },
58
79
  };
59
80
  if (opts && typeof opts.contentFunction === "function") {
60
81
  options.content = opts.contentFunction((root.source && root.source.input.file) || "");
@@ -109,5 +130,4 @@ const purgeCSSPlugin = function (opts) {
109
130
  };
110
131
  purgeCSSPlugin.postcss = true;
111
132
 
112
- exports.default = purgeCSSPlugin;
113
- exports.purgeCSSPlugin = purgeCSSPlugin;
133
+ module.exports = purgeCSSPlugin;
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "@fullhuman/postcss-purgecss",
3
- "version": "7.0.2",
3
+ "version": "9.0.0",
4
4
  "description": "PostCSS plugin for PurgeCSS",
5
5
  "author": "FoundrySH <no-reply@foundry.sh>",
6
6
  "homepage": "https://purgecss.com",
7
7
  "license": "MIT",
8
+ "engines": {
9
+ "node": ">=22.12.0"
10
+ },
8
11
  "main": "lib/postcss-purgecss.js",
9
12
  "module": "lib/postcss-purgecss.esm.js",
10
13
  "types": "lib/postcss-purgecss.d.ts",
@@ -19,18 +22,14 @@
19
22
  "type": "git",
20
23
  "url": "git+https://github.com/FullHuman/purgecss.git"
21
24
  },
22
- "scripts": {
23
- "build": "ts-node build.ts",
24
- "test": "jest"
25
- },
26
25
  "bugs": {
27
26
  "url": "https://github.com/FullHuman/purgecss/issues"
28
27
  },
29
28
  "dependencies": {
30
- "purgecss": "^7.0.2"
29
+ "purgecss": "^9.0.0"
31
30
  },
32
31
  "devDependencies": {
33
- "postcss": "^8.4.47"
32
+ "postcss": "^8.5.29"
34
33
  },
35
34
  "peerDependencies": {
36
35
  "postcss": "^8.0.0"
@@ -39,5 +38,8 @@
39
38
  "access": "public",
40
39
  "registry": "https://registry.npmjs.org/"
41
40
  },
42
- "gitHead": "e95398d961e03a809b5e3da75e3dae1813b46b68"
43
- }
41
+ "scripts": {
42
+ "build": "ts-node build.ts",
43
+ "test": "jest"
44
+ }
45
+ }