gulp-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.
- package/lib/gulp-purgecss.d.ts +30 -3
- package/lib/gulp-purgecss.esm.js +67 -48
- package/lib/gulp-purgecss.js +68 -68
- package/package.json +17 -16
package/lib/gulp-purgecss.d.ts
CHANGED
|
@@ -26,8 +26,29 @@ declare type ComplexSafelist = {
|
|
|
26
26
|
* in the final CSS, even if `child-of-bg` is not found.
|
|
27
27
|
*
|
|
28
28
|
*/
|
|
29
|
-
deep?:
|
|
30
|
-
|
|
29
|
+
deep?: StringRegExpArray;
|
|
30
|
+
/**
|
|
31
|
+
* You can safelist whole selectors if any part of that selector matches a
|
|
32
|
+
* pattern with `safelist.greedy`
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
*
|
|
36
|
+
* ```ts
|
|
37
|
+
* const purgecss = await new PurgeCSS().purge({
|
|
38
|
+
* content: [],
|
|
39
|
+
* css: [],
|
|
40
|
+
* safelist: {
|
|
41
|
+
* greedy: [/red$/]
|
|
42
|
+
* }
|
|
43
|
+
* })
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* In this example, selectors such as `button.bg-red.nonexistent-class`
|
|
47
|
+
* will be left in the final CSS, even if `button` and `nonexistent-class`
|
|
48
|
+
* are not found.
|
|
49
|
+
*
|
|
50
|
+
*/
|
|
51
|
+
greedy?: StringRegExpArray;
|
|
31
52
|
variables?: StringRegExpArray;
|
|
32
53
|
keyframes?: StringRegExpArray;
|
|
33
54
|
};
|
|
@@ -91,6 +112,12 @@ declare interface RawCSS {
|
|
|
91
112
|
}
|
|
92
113
|
|
|
93
114
|
/**
|
|
115
|
+
* Strings and regular expressions an option is matched against. A string
|
|
116
|
+
* matches a value exactly, except a string written between slashes, like
|
|
117
|
+
* `"/^btn-/"` or `"/^btn-/i"`, which is parsed as a regular expression. This
|
|
118
|
+
* form lets configuration files that cannot contain regular expressions, such
|
|
119
|
+
* as `postcss.config.json`, use patterns.
|
|
120
|
+
*
|
|
94
121
|
* @public
|
|
95
122
|
*/
|
|
96
123
|
declare type StringRegExpArray = Array<RegExp | string>;
|
|
@@ -141,7 +168,7 @@ declare interface UserDefinedOptions_2 {
|
|
|
141
168
|
/** {@inheritDoc purgecss#Options.skippedContentGlobs} */
|
|
142
169
|
skippedContentGlobs?: Array<string>;
|
|
143
170
|
/** {@inheritDoc purgecss#Options.dynamicAttributes} */
|
|
144
|
-
dynamicAttributes?:
|
|
171
|
+
dynamicAttributes?: StringRegExpArray;
|
|
145
172
|
}
|
|
146
173
|
|
|
147
174
|
/**
|
package/lib/gulp-purgecss.esm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import glob from 'fast-glob';
|
|
2
2
|
import PluginError from 'plugin-error';
|
|
3
3
|
import { PurgeCSS } from 'purgecss';
|
|
4
|
-
import
|
|
4
|
+
import { objectTransform, transform } from 'through2';
|
|
5
5
|
import applySourceMap from 'vinyl-sourcemaps-apply';
|
|
6
6
|
|
|
7
7
|
const PLUGIN_NAME = "gulp-purgecss";
|
|
@@ -10,6 +10,36 @@ function getFiles(contentArray, ignore) {
|
|
|
10
10
|
return [...acc, ...glob.sync(content, { ignore })];
|
|
11
11
|
}, []);
|
|
12
12
|
}
|
|
13
|
+
// generate a separate source map describing only this step, without any
|
|
14
|
+
// annotation in the css, so that it can be chained with gulp-sourcemaps
|
|
15
|
+
function getSourceMapOptions(file) {
|
|
16
|
+
return file.sourceMap
|
|
17
|
+
? { inline: false, annotation: false, prev: false }
|
|
18
|
+
: false;
|
|
19
|
+
}
|
|
20
|
+
function applyPurgedSourceMap(file, sourceMap) {
|
|
21
|
+
if (!file.sourceMap || !sourceMap)
|
|
22
|
+
return;
|
|
23
|
+
const map = JSON.parse(sourceMap);
|
|
24
|
+
// the css is purged as a raw string, so the source map has no file name
|
|
25
|
+
map.file = file.relative;
|
|
26
|
+
map.sources = map.sources.map(() => file.relative);
|
|
27
|
+
applySourceMap(file, map);
|
|
28
|
+
}
|
|
29
|
+
function readStream(stream) {
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
let css = "";
|
|
32
|
+
stream
|
|
33
|
+
.on("data", (buffer) => {
|
|
34
|
+
css += buffer.toString();
|
|
35
|
+
})
|
|
36
|
+
.on("end", () => resolve(css))
|
|
37
|
+
.on("error", reject);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function toPluginError(e) {
|
|
41
|
+
return e instanceof Error ? new PluginError(PLUGIN_NAME, e.message) : e;
|
|
42
|
+
}
|
|
13
43
|
/**
|
|
14
44
|
*
|
|
15
45
|
* @param options - options
|
|
@@ -18,10 +48,13 @@ function getFiles(contentArray, ignore) {
|
|
|
18
48
|
* @public
|
|
19
49
|
*/
|
|
20
50
|
function gulpPurgeCSS(options) {
|
|
21
|
-
|
|
51
|
+
// through2 v5 dispatches on the function kind: an async transform receives
|
|
52
|
+
// no callback, pushes its resolved value and turns a rejection into a
|
|
53
|
+
// stream error
|
|
54
|
+
return objectTransform(async function (file) {
|
|
22
55
|
// empty
|
|
23
56
|
if (file.isNull())
|
|
24
|
-
return
|
|
57
|
+
return file;
|
|
25
58
|
// buffer
|
|
26
59
|
if (file.isBuffer()) {
|
|
27
60
|
try {
|
|
@@ -34,7 +67,7 @@ function gulpPurgeCSS(options) {
|
|
|
34
67
|
},
|
|
35
68
|
],
|
|
36
69
|
stdin: true,
|
|
37
|
-
sourceMap:
|
|
70
|
+
sourceMap: getSourceMapOptions(file),
|
|
38
71
|
};
|
|
39
72
|
const purgedCSSResults = await new PurgeCSS().purge(optionsGulp);
|
|
40
73
|
const purge = purgedCSSResults[0];
|
|
@@ -43,55 +76,41 @@ function gulpPurgeCSS(options) {
|
|
|
43
76
|
: purge.css;
|
|
44
77
|
file.contents = Buffer.from(result, "utf-8");
|
|
45
78
|
// apply source map to the chain
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
callback(null, file);
|
|
79
|
+
applyPurgedSourceMap(file, purge.sourceMap);
|
|
80
|
+
return file;
|
|
50
81
|
}
|
|
51
82
|
catch (e) {
|
|
52
|
-
|
|
53
|
-
this.emit("error", new PluginError(PLUGIN_NAME, e.message));
|
|
54
|
-
}
|
|
83
|
+
throw toPluginError(e);
|
|
55
84
|
}
|
|
56
85
|
}
|
|
57
86
|
// stream
|
|
58
87
|
if (file.isStream()) {
|
|
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
|
-
applySourceMap(file, purge.sourceMap);
|
|
86
|
-
}
|
|
87
|
-
callback(null, file);
|
|
88
|
-
}
|
|
89
|
-
catch (e) {
|
|
90
|
-
if (e instanceof Error) {
|
|
91
|
-
this.emit("error", new PluginError(PLUGIN_NAME, e.message));
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
});
|
|
88
|
+
try {
|
|
89
|
+
const css = await readStream(file.contents);
|
|
90
|
+
const optionsGulp = {
|
|
91
|
+
...options,
|
|
92
|
+
css: [
|
|
93
|
+
{
|
|
94
|
+
raw: css,
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
sourceMap: getSourceMapOptions(file),
|
|
98
|
+
};
|
|
99
|
+
const purgedCSSResults = await new PurgeCSS().purge(optionsGulp);
|
|
100
|
+
const purge = purgedCSSResults[0];
|
|
101
|
+
const result = optionsGulp.rejected && purge.rejected
|
|
102
|
+
? purge.rejected.join(" {}\n") + " {}"
|
|
103
|
+
: purge.css;
|
|
104
|
+
const streamResult = transform();
|
|
105
|
+
streamResult.write(Buffer.from(result, "utf-8"));
|
|
106
|
+
file.contents = file.contents.pipe(streamResult);
|
|
107
|
+
// apply source map to the chain
|
|
108
|
+
applyPurgedSourceMap(file, purge.sourceMap);
|
|
109
|
+
return file;
|
|
110
|
+
}
|
|
111
|
+
catch (e) {
|
|
112
|
+
throw toPluginError(e);
|
|
113
|
+
}
|
|
95
114
|
}
|
|
96
115
|
});
|
|
97
116
|
}
|
package/lib/gulp-purgecss.js
CHANGED
|
@@ -1,36 +1,47 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var glob = require('glob');
|
|
3
|
+
var glob = require('fast-glob');
|
|
4
4
|
var PluginError = require('plugin-error');
|
|
5
5
|
var purgecss = require('purgecss');
|
|
6
|
-
var
|
|
6
|
+
var through2 = require('through2');
|
|
7
7
|
var applySourceMap = require('vinyl-sourcemaps-apply');
|
|
8
8
|
|
|
9
|
-
function _interopNamespaceDefault(e) {
|
|
10
|
-
var n = Object.create(null);
|
|
11
|
-
if (e) {
|
|
12
|
-
Object.keys(e).forEach(function (k) {
|
|
13
|
-
if (k !== 'default') {
|
|
14
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
15
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
16
|
-
enumerable: true,
|
|
17
|
-
get: function () { return e[k]; }
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
n.default = e;
|
|
23
|
-
return Object.freeze(n);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
var glob__namespace = /*#__PURE__*/_interopNamespaceDefault(glob);
|
|
27
|
-
|
|
28
9
|
const PLUGIN_NAME = "gulp-purgecss";
|
|
29
10
|
function getFiles(contentArray, ignore) {
|
|
30
11
|
return contentArray.reduce((acc, content) => {
|
|
31
|
-
return [...acc, ...
|
|
12
|
+
return [...acc, ...glob.sync(content, { ignore })];
|
|
32
13
|
}, []);
|
|
33
14
|
}
|
|
15
|
+
// generate a separate source map describing only this step, without any
|
|
16
|
+
// annotation in the css, so that it can be chained with gulp-sourcemaps
|
|
17
|
+
function getSourceMapOptions(file) {
|
|
18
|
+
return file.sourceMap
|
|
19
|
+
? { inline: false, annotation: false, prev: false }
|
|
20
|
+
: false;
|
|
21
|
+
}
|
|
22
|
+
function applyPurgedSourceMap(file, sourceMap) {
|
|
23
|
+
if (!file.sourceMap || !sourceMap)
|
|
24
|
+
return;
|
|
25
|
+
const map = JSON.parse(sourceMap);
|
|
26
|
+
// the css is purged as a raw string, so the source map has no file name
|
|
27
|
+
map.file = file.relative;
|
|
28
|
+
map.sources = map.sources.map(() => file.relative);
|
|
29
|
+
applySourceMap(file, map);
|
|
30
|
+
}
|
|
31
|
+
function readStream(stream) {
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
let css = "";
|
|
34
|
+
stream
|
|
35
|
+
.on("data", (buffer) => {
|
|
36
|
+
css += buffer.toString();
|
|
37
|
+
})
|
|
38
|
+
.on("end", () => resolve(css))
|
|
39
|
+
.on("error", reject);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function toPluginError(e) {
|
|
43
|
+
return e instanceof Error ? new PluginError(PLUGIN_NAME, e.message) : e;
|
|
44
|
+
}
|
|
34
45
|
/**
|
|
35
46
|
*
|
|
36
47
|
* @param options - options
|
|
@@ -39,10 +50,13 @@ function getFiles(contentArray, ignore) {
|
|
|
39
50
|
* @public
|
|
40
51
|
*/
|
|
41
52
|
function gulpPurgeCSS(options) {
|
|
42
|
-
|
|
53
|
+
// through2 v5 dispatches on the function kind: an async transform receives
|
|
54
|
+
// no callback, pushes its resolved value and turns a rejection into a
|
|
55
|
+
// stream error
|
|
56
|
+
return through2.objectTransform(async function (file) {
|
|
43
57
|
// empty
|
|
44
58
|
if (file.isNull())
|
|
45
|
-
return
|
|
59
|
+
return file;
|
|
46
60
|
// buffer
|
|
47
61
|
if (file.isBuffer()) {
|
|
48
62
|
try {
|
|
@@ -55,7 +69,7 @@ function gulpPurgeCSS(options) {
|
|
|
55
69
|
},
|
|
56
70
|
],
|
|
57
71
|
stdin: true,
|
|
58
|
-
sourceMap:
|
|
72
|
+
sourceMap: getSourceMapOptions(file),
|
|
59
73
|
};
|
|
60
74
|
const purgedCSSResults = await new purgecss.PurgeCSS().purge(optionsGulp);
|
|
61
75
|
const purge = purgedCSSResults[0];
|
|
@@ -64,55 +78,41 @@ function gulpPurgeCSS(options) {
|
|
|
64
78
|
: purge.css;
|
|
65
79
|
file.contents = Buffer.from(result, "utf-8");
|
|
66
80
|
// apply source map to the chain
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
callback(null, file);
|
|
81
|
+
applyPurgedSourceMap(file, purge.sourceMap);
|
|
82
|
+
return file;
|
|
71
83
|
}
|
|
72
84
|
catch (e) {
|
|
73
|
-
|
|
74
|
-
this.emit("error", new PluginError(PLUGIN_NAME, e.message));
|
|
75
|
-
}
|
|
85
|
+
throw toPluginError(e);
|
|
76
86
|
}
|
|
77
87
|
}
|
|
78
88
|
// stream
|
|
79
89
|
if (file.isStream()) {
|
|
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
|
-
applySourceMap(file, purge.sourceMap);
|
|
107
|
-
}
|
|
108
|
-
callback(null, file);
|
|
109
|
-
}
|
|
110
|
-
catch (e) {
|
|
111
|
-
if (e instanceof Error) {
|
|
112
|
-
this.emit("error", new PluginError(PLUGIN_NAME, e.message));
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
});
|
|
90
|
+
try {
|
|
91
|
+
const css = await readStream(file.contents);
|
|
92
|
+
const optionsGulp = {
|
|
93
|
+
...options,
|
|
94
|
+
css: [
|
|
95
|
+
{
|
|
96
|
+
raw: css,
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
sourceMap: getSourceMapOptions(file),
|
|
100
|
+
};
|
|
101
|
+
const purgedCSSResults = await new purgecss.PurgeCSS().purge(optionsGulp);
|
|
102
|
+
const purge = purgedCSSResults[0];
|
|
103
|
+
const result = optionsGulp.rejected && purge.rejected
|
|
104
|
+
? purge.rejected.join(" {}\n") + " {}"
|
|
105
|
+
: purge.css;
|
|
106
|
+
const streamResult = through2.transform();
|
|
107
|
+
streamResult.write(Buffer.from(result, "utf-8"));
|
|
108
|
+
file.contents = file.contents.pipe(streamResult);
|
|
109
|
+
// apply source map to the chain
|
|
110
|
+
applyPurgedSourceMap(file, purge.sourceMap);
|
|
111
|
+
return file;
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
throw toPluginError(e);
|
|
115
|
+
}
|
|
116
116
|
}
|
|
117
117
|
});
|
|
118
118
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gulp-purgecss",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0",
|
|
4
4
|
"description": "Gulp plugin for purgecss",
|
|
5
5
|
"author": "Ffloriel",
|
|
6
6
|
"homepage": "https://purgecss.com",
|
|
@@ -17,6 +17,9 @@
|
|
|
17
17
|
"uncss"
|
|
18
18
|
],
|
|
19
19
|
"license": "MIT",
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=22.12.0"
|
|
22
|
+
},
|
|
20
23
|
"main": "lib/gulp-purgecss.js",
|
|
21
24
|
"module": "./lib/gulp-purgecss.esm.js",
|
|
22
25
|
"types": "./lib/gulp-purgecss.d.ts",
|
|
@@ -31,24 +34,19 @@
|
|
|
31
34
|
"type": "git",
|
|
32
35
|
"url": "git+https://github.com/FullHuman/purgecss.git"
|
|
33
36
|
},
|
|
34
|
-
"scripts": {
|
|
35
|
-
"build": "ts-node build.ts",
|
|
36
|
-
"test": "jest"
|
|
37
|
-
},
|
|
38
37
|
"dependencies": {
|
|
39
|
-
"glob": "^
|
|
40
|
-
"plugin-error": "^2.0.
|
|
41
|
-
"purgecss": "^
|
|
42
|
-
"through2": "^
|
|
38
|
+
"fast-glob": "^3.3.3",
|
|
39
|
+
"plugin-error": "^2.0.1",
|
|
40
|
+
"purgecss": "^9.0.0",
|
|
41
|
+
"through2": "^5.0.12",
|
|
43
42
|
"vinyl-sourcemaps-apply": "^0.2.1"
|
|
44
43
|
},
|
|
45
44
|
"devDependencies": {
|
|
46
|
-
"@types/event-stream": "^4.0.
|
|
47
|
-
"@types/
|
|
48
|
-
"@types/
|
|
49
|
-
"@types/vinyl": "^2.0.4",
|
|
45
|
+
"@types/event-stream": "^4.0.6",
|
|
46
|
+
"@types/readable-stream": "^4.0.25",
|
|
47
|
+
"@types/vinyl": "^2.0.12",
|
|
50
48
|
"event-stream": "^4.0.1",
|
|
51
|
-
"vinyl": "^3.0.
|
|
49
|
+
"vinyl": "^3.0.1"
|
|
52
50
|
},
|
|
53
51
|
"bugs": {
|
|
54
52
|
"url": "https://github.com/FullHuman/purgecss/issues"
|
|
@@ -57,5 +55,8 @@
|
|
|
57
55
|
"access": "public",
|
|
58
56
|
"registry": "https://registry.npmjs.org/"
|
|
59
57
|
},
|
|
60
|
-
"
|
|
61
|
-
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "ts-node build.ts",
|
|
60
|
+
"test": "jest"
|
|
61
|
+
}
|
|
62
|
+
}
|