purgecss 1.2.0 → 1.4.2
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/CHANGELOG.md +11 -0
- package/README.md +7 -7
- package/flow-typed/index.js +2 -1
- package/lib/purgecss.es.js +129 -51
- package/lib/purgecss.js +129 -51
- package/package.json +23 -21
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
# v1.4.0 - 2019-09-01
|
|
4
|
+
|
|
5
|
+
* Merged https://github.com/FullHuman/purgecss/commit/bc9f3b5b9d670832f0d1cca7bc7facfb253fb60b, ensure classes beginning with numbers are properly purged
|
|
6
|
+
* Merged https://github.com/FullHuman/purgecss/pull/214, fix font-face processing
|
|
7
|
+
* update dependencies
|
|
8
|
+
|
|
9
|
+
# v1.3.0 - 2019-04-20
|
|
10
|
+
|
|
11
|
+
* Merged https://github.com/FullHuman/purgecss/pull/183, adding `defaultExtractor` option
|
|
12
|
+
* remove ignore comment once purged, issue https://github.com/FullHuman/purgecss/issues/121
|
|
13
|
+
|
|
3
14
|
# v1.2.0 - 2019-04-05
|
|
4
15
|
|
|
5
16
|
* fix issue https://github.com/FullHuman/purgecss/issues/148, so the default extract is used for any file type that is not specified
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# PurgeCSS
|
|
2
2
|
|
|
3
3
|
[](https://travis-ci.org/FullHuman/purgecss)
|
|
4
4
|
[]()
|
|
@@ -11,23 +11,23 @@
|
|
|
11
11
|
[]() [](https://greenkeeper.io/)
|
|
12
12
|
|
|
13
13
|
<p align="center">
|
|
14
|
-
<img src="./.assets/logo.png" height="200" width="200" alt="
|
|
14
|
+
<img src="./.assets/logo.png" height="200" width="200" alt="PurgeCSS logo"/>
|
|
15
15
|
</p>
|
|
16
16
|
|
|
17
|
-
## What is
|
|
17
|
+
## What is PurgeCSS?
|
|
18
18
|
|
|
19
19
|
When you are building a website, chances are that you are using a css framework
|
|
20
20
|
like Bootstrap, Materializecss, Foundation, etc... But you will only use a small
|
|
21
21
|
set of the framework and a lot of unused css styles will be included.
|
|
22
22
|
|
|
23
|
-
This is where
|
|
23
|
+
This is where PurgeCSS comes into play. PurgeCSS analyzes your content and your
|
|
24
24
|
css files. Then it matches the selectors used in your files with the one in your
|
|
25
25
|
content files. It removes unused selectors from your css, resulting in smaller
|
|
26
26
|
css files.
|
|
27
27
|
|
|
28
28
|
## Documentation
|
|
29
29
|
|
|
30
|
-
You can find the
|
|
30
|
+
You can find the PurgeCSS documentation
|
|
31
31
|
[on this website](https://www.purgecss.com).
|
|
32
32
|
|
|
33
33
|
* [Configuration](https://www.purgecss.com/configuration)
|
|
@@ -112,11 +112,11 @@ conduct, and the process for submitting pull requests to us.
|
|
|
112
112
|
|
|
113
113
|
## Versioning
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
PurgeCSS use [SemVer](http://semver.org/) for versioning.
|
|
116
116
|
|
|
117
117
|
## Acknowledgment
|
|
118
118
|
|
|
119
|
-
|
|
119
|
+
PurgeCSS was originally thought as the v2 of purifycss. And because of it, it is
|
|
120
120
|
greatly inspired by it.\
|
|
121
121
|
Some of the plugins such as purgecss-webpack-plugin are based on the purifycss plugin.\
|
|
122
122
|
Below is the list of the purifycss repositories:
|
package/flow-typed/index.js
CHANGED
|
@@ -8,6 +8,7 @@ type RawContent = {
|
|
|
8
8
|
declare type Options = {
|
|
9
9
|
content: Array<string | RawContent>,
|
|
10
10
|
css: Array<string | RawContent>,
|
|
11
|
+
defaultExtractor?: Object,
|
|
11
12
|
extractors?: Array<ExtractorsObj>,
|
|
12
13
|
whitelist?: Array<string>,
|
|
13
14
|
whitelistPatterns?: Array<RegExp>,
|
|
@@ -36,4 +37,4 @@ declare type AtRules = {
|
|
|
36
37
|
fontFace: Array<Object>
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
declare type IgnoreType = "next" | "start" | "end"
|
|
40
|
+
declare type IgnoreType = "next" | "start" | "end"
|
package/lib/purgecss.es.js
CHANGED
|
@@ -303,10 +303,28 @@ var substr = 'ab'.substr(-1) === 'b' ? function (str, start, len) {
|
|
|
303
303
|
return str.substr(start, len);
|
|
304
304
|
};
|
|
305
305
|
|
|
306
|
+
var DefaultExtractor =
|
|
307
|
+
/*#__PURE__*/
|
|
308
|
+
function () {
|
|
309
|
+
function DefaultExtractor() {
|
|
310
|
+
_classCallCheck(this, DefaultExtractor);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
_createClass(DefaultExtractor, null, [{
|
|
314
|
+
key: "extract",
|
|
315
|
+
value: function extract(content) {
|
|
316
|
+
return content.match(/[A-Za-z0-9_-]+/g) || [];
|
|
317
|
+
}
|
|
318
|
+
}]);
|
|
319
|
+
|
|
320
|
+
return DefaultExtractor;
|
|
321
|
+
}();
|
|
322
|
+
|
|
306
323
|
//
|
|
307
324
|
var defaultOptions = {
|
|
308
325
|
css: [],
|
|
309
326
|
content: [],
|
|
327
|
+
defaultExtractor: DefaultExtractor,
|
|
310
328
|
extractors: [],
|
|
311
329
|
whitelist: [],
|
|
312
330
|
output: undefined,
|
|
@@ -316,6 +334,7 @@ var defaultOptions = {
|
|
|
316
334
|
rejected: false
|
|
317
335
|
};
|
|
318
336
|
|
|
337
|
+
var IGNORE_ANNOTATION_CURRENT = 'purgecss ignore current';
|
|
319
338
|
var IGNORE_ANNOTATION_NEXT = 'purgecss ignore';
|
|
320
339
|
var IGNORE_ANNOTATION_START = 'purgecss start ignore';
|
|
321
340
|
var IGNORE_ANNOTATION_END = 'purgecss end ignore';
|
|
@@ -336,22 +355,7 @@ var CSS_WHITELIST = ['*', '::-webkit-scrollbar', '::selection', ':root', '::befo
|
|
|
336
355
|
|
|
337
356
|
var SELECTOR_STANDARD_TYPES = ['class', 'id', 'universal', 'pseudo'];
|
|
338
357
|
|
|
339
|
-
var
|
|
340
|
-
/*#__PURE__*/
|
|
341
|
-
function () {
|
|
342
|
-
function DefaultExtractor() {
|
|
343
|
-
_classCallCheck(this, DefaultExtractor);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
_createClass(DefaultExtractor, null, [{
|
|
347
|
-
key: "extract",
|
|
348
|
-
value: function extract(content) {
|
|
349
|
-
return content.match(/[A-Za-z0-9_-]+/g) || [];
|
|
350
|
-
}
|
|
351
|
-
}]);
|
|
352
|
-
|
|
353
|
-
return DefaultExtractor;
|
|
354
|
-
}();
|
|
358
|
+
var IS_NTH = /^:nth-/;
|
|
355
359
|
|
|
356
360
|
var Purgecss =
|
|
357
361
|
/*#__PURE__*/
|
|
@@ -374,7 +378,7 @@ function () {
|
|
|
374
378
|
|
|
375
379
|
if (typeof options === 'string' || typeof options === 'undefined') options = this.loadConfigFile(options);
|
|
376
380
|
this.checkOptions(options);
|
|
377
|
-
this.options = Object.assign(defaultOptions, options);
|
|
381
|
+
this.options = Object.assign({}, defaultOptions, options);
|
|
378
382
|
}
|
|
379
383
|
/**
|
|
380
384
|
* Load the configuration file from the path
|
|
@@ -389,7 +393,7 @@ function () {
|
|
|
389
393
|
var options;
|
|
390
394
|
|
|
391
395
|
try {
|
|
392
|
-
var t = path.
|
|
396
|
+
var t = path.join(process.cwd(), pathConfig);
|
|
393
397
|
options = require(t);
|
|
394
398
|
} catch (e) {
|
|
395
399
|
throw new Error(ERROR_CONFIG_FILE_LOADING + e.message);
|
|
@@ -581,6 +585,16 @@ function () {
|
|
|
581
585
|
}
|
|
582
586
|
}
|
|
583
587
|
}
|
|
588
|
+
/**
|
|
589
|
+
* Strips quotes at the end and at the end of a string
|
|
590
|
+
* @param {string} value the string to be stripped
|
|
591
|
+
*/
|
|
592
|
+
|
|
593
|
+
}, {
|
|
594
|
+
key: "stripQuotes",
|
|
595
|
+
value: function stripQuotes(value) {
|
|
596
|
+
return value.replace(/(^["'])|(["']$)/g, '');
|
|
597
|
+
}
|
|
584
598
|
/**
|
|
585
599
|
* Extract the selectors present in the passed string using a purgecss extractor
|
|
586
600
|
* @param {array} content Array of content
|
|
@@ -698,12 +712,14 @@ function () {
|
|
|
698
712
|
key: "getFileExtractor",
|
|
699
713
|
value: function getFileExtractor(filename) {
|
|
700
714
|
var extractors = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
701
|
-
if (!extractors.length) return
|
|
715
|
+
if (!extractors.length) return this.options.defaultExtractor;
|
|
702
716
|
var extractorObj = extractors.find(function (extractor) {
|
|
703
717
|
return extractor.extensions.find(function (ext) {
|
|
704
718
|
return filename.endsWith(ext);
|
|
705
719
|
});
|
|
706
|
-
}) ||
|
|
720
|
+
}) || {
|
|
721
|
+
extractor: this.options.defaultExtractor
|
|
722
|
+
};
|
|
707
723
|
return extractorObj.extractor;
|
|
708
724
|
}
|
|
709
725
|
/**
|
|
@@ -749,7 +765,15 @@ function () {
|
|
|
749
765
|
}
|
|
750
766
|
|
|
751
767
|
if (node.type === 'comment') {
|
|
752
|
-
if (_this.isIgnoreAnnotation(node, 'start'))
|
|
768
|
+
if (_this.isIgnoreAnnotation(node, 'start')) {
|
|
769
|
+
_this.ignore = true; // remove ignore annotation
|
|
770
|
+
|
|
771
|
+
node.remove();
|
|
772
|
+
} else if (_this.isIgnoreAnnotation(node, 'end')) {
|
|
773
|
+
_this.ignore = false; // remove ignore annotation
|
|
774
|
+
|
|
775
|
+
node.remove();
|
|
776
|
+
}
|
|
753
777
|
}
|
|
754
778
|
});
|
|
755
779
|
}
|
|
@@ -765,7 +789,21 @@ function () {
|
|
|
765
789
|
var _this2 = this;
|
|
766
790
|
|
|
767
791
|
var annotation = node.prev();
|
|
768
|
-
if (this.
|
|
792
|
+
if (this.ignore) return;
|
|
793
|
+
|
|
794
|
+
if (typeof annotation !== 'undefined' && annotation.type === 'comment' && this.isIgnoreAnnotation(annotation, 'next')) {
|
|
795
|
+
annotation.remove();
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
if (node.parent && node.parent.type === 'atrule' && node.parent.name === 'keyframes') {
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
if (this.hasIgnoreAnnotation(node)) {
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
|
|
769
807
|
var keepSelector = true;
|
|
770
808
|
node.selector = selectorParser(function (selectorsParsed) {
|
|
771
809
|
selectorsParsed.walk(function (selector) {
|
|
@@ -787,10 +825,10 @@ function () {
|
|
|
787
825
|
type = _step7$value.type,
|
|
788
826
|
value = _step7$value.value;
|
|
789
827
|
|
|
790
|
-
if (SELECTOR_STANDARD_TYPES.includes(type) && typeof value !== 'undefined'
|
|
828
|
+
if (SELECTOR_STANDARD_TYPES.includes(type) && typeof value !== 'undefined') {
|
|
791
829
|
selectorsInRule.push(value);
|
|
792
|
-
} else if (type === 'tag' &&
|
|
793
|
-
|
|
830
|
+
} else if (type === 'tag' && !( // skip everything inside :nth-* pseudo selectors
|
|
831
|
+
selector.parent && selector.parent.type === 'pseudo' && IS_NTH.test(selector.parent.value))) {
|
|
794
832
|
selectorsInRule.push(value);
|
|
795
833
|
}
|
|
796
834
|
}
|
|
@@ -860,7 +898,30 @@ function () {
|
|
|
860
898
|
|
|
861
899
|
if (this.options.fontFace) {
|
|
862
900
|
if (prop === 'font-family') {
|
|
863
|
-
|
|
901
|
+
var _iteratorNormalCompletion10 = true;
|
|
902
|
+
var _didIteratorError10 = false;
|
|
903
|
+
var _iteratorError10 = undefined;
|
|
904
|
+
|
|
905
|
+
try {
|
|
906
|
+
for (var _iterator10 = value.split(',')[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {
|
|
907
|
+
var fontName = _step10.value;
|
|
908
|
+
var cleanedFontFace = this.stripQuotes(fontName.trim());
|
|
909
|
+
this.usedFontFaces.add(cleanedFontFace);
|
|
910
|
+
}
|
|
911
|
+
} catch (err) {
|
|
912
|
+
_didIteratorError10 = true;
|
|
913
|
+
_iteratorError10 = err;
|
|
914
|
+
} finally {
|
|
915
|
+
try {
|
|
916
|
+
if (!_iteratorNormalCompletion10 && _iterator10.return != null) {
|
|
917
|
+
_iterator10.return();
|
|
918
|
+
}
|
|
919
|
+
} finally {
|
|
920
|
+
if (_didIteratorError10) {
|
|
921
|
+
throw _iteratorError10;
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
}
|
|
864
925
|
}
|
|
865
926
|
}
|
|
866
927
|
}
|
|
@@ -899,34 +960,34 @@ function () {
|
|
|
899
960
|
}
|
|
900
961
|
|
|
901
962
|
if (this.options.fontFace && node.name === 'font-face') {
|
|
902
|
-
var
|
|
903
|
-
var
|
|
904
|
-
var
|
|
963
|
+
var _iteratorNormalCompletion11 = true;
|
|
964
|
+
var _didIteratorError11 = false;
|
|
965
|
+
var _iteratorError11 = undefined;
|
|
905
966
|
|
|
906
967
|
try {
|
|
907
|
-
for (var
|
|
908
|
-
var
|
|
909
|
-
prop =
|
|
910
|
-
value =
|
|
968
|
+
for (var _iterator11 = node.nodes[Symbol.iterator](), _step11; !(_iteratorNormalCompletion11 = (_step11 = _iterator11.next()).done); _iteratorNormalCompletion11 = true) {
|
|
969
|
+
var _step11$value = _step11.value,
|
|
970
|
+
prop = _step11$value.prop,
|
|
971
|
+
value = _step11$value.value;
|
|
911
972
|
|
|
912
973
|
if (prop === 'font-family') {
|
|
913
974
|
this.atRules.fontFace.push({
|
|
914
|
-
name: value,
|
|
975
|
+
name: this.stripQuotes(value),
|
|
915
976
|
node: node
|
|
916
977
|
});
|
|
917
978
|
}
|
|
918
979
|
}
|
|
919
980
|
} catch (err) {
|
|
920
|
-
|
|
921
|
-
|
|
981
|
+
_didIteratorError11 = true;
|
|
982
|
+
_iteratorError11 = err;
|
|
922
983
|
} finally {
|
|
923
984
|
try {
|
|
924
|
-
if (!
|
|
925
|
-
|
|
985
|
+
if (!_iteratorNormalCompletion11 && _iterator11.return != null) {
|
|
986
|
+
_iterator11.return();
|
|
926
987
|
}
|
|
927
988
|
} finally {
|
|
928
|
-
if (
|
|
929
|
-
throw
|
|
989
|
+
if (_didIteratorError11) {
|
|
990
|
+
throw _iteratorError11;
|
|
930
991
|
}
|
|
931
992
|
}
|
|
932
993
|
}
|
|
@@ -958,6 +1019,23 @@ function () {
|
|
|
958
1019
|
|
|
959
1020
|
return false;
|
|
960
1021
|
}
|
|
1022
|
+
/**
|
|
1023
|
+
* Check if the node has a css comment to ignore current selector rule
|
|
1024
|
+
* @param {object} rule Node of postcss abstract syntax tree
|
|
1025
|
+
*/
|
|
1026
|
+
|
|
1027
|
+
}, {
|
|
1028
|
+
key: "hasIgnoreAnnotation",
|
|
1029
|
+
value: function hasIgnoreAnnotation(rule) {
|
|
1030
|
+
var found = false;
|
|
1031
|
+
rule.walkComments(function (node) {
|
|
1032
|
+
if (node && node.type === 'comment' && node.text.includes(IGNORE_ANNOTATION_CURRENT)) {
|
|
1033
|
+
found = true;
|
|
1034
|
+
node.remove();
|
|
1035
|
+
}
|
|
1036
|
+
});
|
|
1037
|
+
return found;
|
|
1038
|
+
}
|
|
961
1039
|
/**
|
|
962
1040
|
* Check if the node correspond to an empty css rule
|
|
963
1041
|
* @param {object} node Node of postcss abstract syntax tree
|
|
@@ -981,13 +1059,13 @@ function () {
|
|
|
981
1059
|
}, {
|
|
982
1060
|
key: "shouldKeepSelector",
|
|
983
1061
|
value: function shouldKeepSelector(selectorsInContent, selectorsInRule) {
|
|
984
|
-
var
|
|
985
|
-
var
|
|
986
|
-
var
|
|
1062
|
+
var _iteratorNormalCompletion12 = true;
|
|
1063
|
+
var _didIteratorError12 = false;
|
|
1064
|
+
var _iteratorError12 = undefined;
|
|
987
1065
|
|
|
988
1066
|
try {
|
|
989
|
-
for (var
|
|
990
|
-
var selector =
|
|
1067
|
+
for (var _iterator12 = selectorsInRule[Symbol.iterator](), _step12; !(_iteratorNormalCompletion12 = (_step12 = _iterator12.next()).done); _iteratorNormalCompletion12 = true) {
|
|
1068
|
+
var selector = _step12.value;
|
|
991
1069
|
// pseudo class
|
|
992
1070
|
var unescapedSelector = selector.replace(/\\/g, '');
|
|
993
1071
|
|
|
@@ -1006,16 +1084,16 @@ function () {
|
|
|
1006
1084
|
}
|
|
1007
1085
|
}
|
|
1008
1086
|
} catch (err) {
|
|
1009
|
-
|
|
1010
|
-
|
|
1087
|
+
_didIteratorError12 = true;
|
|
1088
|
+
_iteratorError12 = err;
|
|
1011
1089
|
} finally {
|
|
1012
1090
|
try {
|
|
1013
|
-
if (!
|
|
1014
|
-
|
|
1091
|
+
if (!_iteratorNormalCompletion12 && _iterator12.return != null) {
|
|
1092
|
+
_iterator12.return();
|
|
1015
1093
|
}
|
|
1016
1094
|
} finally {
|
|
1017
|
-
if (
|
|
1018
|
-
throw
|
|
1095
|
+
if (_didIteratorError12) {
|
|
1096
|
+
throw _iteratorError12;
|
|
1019
1097
|
}
|
|
1020
1098
|
}
|
|
1021
1099
|
}
|
package/lib/purgecss.js
CHANGED
|
@@ -307,10 +307,28 @@ var substr = 'ab'.substr(-1) === 'b' ? function (str, start, len) {
|
|
|
307
307
|
return str.substr(start, len);
|
|
308
308
|
};
|
|
309
309
|
|
|
310
|
+
var DefaultExtractor =
|
|
311
|
+
/*#__PURE__*/
|
|
312
|
+
function () {
|
|
313
|
+
function DefaultExtractor() {
|
|
314
|
+
_classCallCheck(this, DefaultExtractor);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
_createClass(DefaultExtractor, null, [{
|
|
318
|
+
key: "extract",
|
|
319
|
+
value: function extract(content) {
|
|
320
|
+
return content.match(/[A-Za-z0-9_-]+/g) || [];
|
|
321
|
+
}
|
|
322
|
+
}]);
|
|
323
|
+
|
|
324
|
+
return DefaultExtractor;
|
|
325
|
+
}();
|
|
326
|
+
|
|
310
327
|
//
|
|
311
328
|
var defaultOptions = {
|
|
312
329
|
css: [],
|
|
313
330
|
content: [],
|
|
331
|
+
defaultExtractor: DefaultExtractor,
|
|
314
332
|
extractors: [],
|
|
315
333
|
whitelist: [],
|
|
316
334
|
output: undefined,
|
|
@@ -320,6 +338,7 @@ var defaultOptions = {
|
|
|
320
338
|
rejected: false
|
|
321
339
|
};
|
|
322
340
|
|
|
341
|
+
var IGNORE_ANNOTATION_CURRENT = 'purgecss ignore current';
|
|
323
342
|
var IGNORE_ANNOTATION_NEXT = 'purgecss ignore';
|
|
324
343
|
var IGNORE_ANNOTATION_START = 'purgecss start ignore';
|
|
325
344
|
var IGNORE_ANNOTATION_END = 'purgecss end ignore';
|
|
@@ -340,22 +359,7 @@ var CSS_WHITELIST = ['*', '::-webkit-scrollbar', '::selection', ':root', '::befo
|
|
|
340
359
|
|
|
341
360
|
var SELECTOR_STANDARD_TYPES = ['class', 'id', 'universal', 'pseudo'];
|
|
342
361
|
|
|
343
|
-
var
|
|
344
|
-
/*#__PURE__*/
|
|
345
|
-
function () {
|
|
346
|
-
function DefaultExtractor() {
|
|
347
|
-
_classCallCheck(this, DefaultExtractor);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
_createClass(DefaultExtractor, null, [{
|
|
351
|
-
key: "extract",
|
|
352
|
-
value: function extract(content) {
|
|
353
|
-
return content.match(/[A-Za-z0-9_-]+/g) || [];
|
|
354
|
-
}
|
|
355
|
-
}]);
|
|
356
|
-
|
|
357
|
-
return DefaultExtractor;
|
|
358
|
-
}();
|
|
362
|
+
var IS_NTH = /^:nth-/;
|
|
359
363
|
|
|
360
364
|
var Purgecss =
|
|
361
365
|
/*#__PURE__*/
|
|
@@ -378,7 +382,7 @@ function () {
|
|
|
378
382
|
|
|
379
383
|
if (typeof options === 'string' || typeof options === 'undefined') options = this.loadConfigFile(options);
|
|
380
384
|
this.checkOptions(options);
|
|
381
|
-
this.options = Object.assign(defaultOptions, options);
|
|
385
|
+
this.options = Object.assign({}, defaultOptions, options);
|
|
382
386
|
}
|
|
383
387
|
/**
|
|
384
388
|
* Load the configuration file from the path
|
|
@@ -393,7 +397,7 @@ function () {
|
|
|
393
397
|
var options;
|
|
394
398
|
|
|
395
399
|
try {
|
|
396
|
-
var t = path.
|
|
400
|
+
var t = path.join(process.cwd(), pathConfig);
|
|
397
401
|
options = require(t);
|
|
398
402
|
} catch (e) {
|
|
399
403
|
throw new Error(ERROR_CONFIG_FILE_LOADING + e.message);
|
|
@@ -585,6 +589,16 @@ function () {
|
|
|
585
589
|
}
|
|
586
590
|
}
|
|
587
591
|
}
|
|
592
|
+
/**
|
|
593
|
+
* Strips quotes at the end and at the end of a string
|
|
594
|
+
* @param {string} value the string to be stripped
|
|
595
|
+
*/
|
|
596
|
+
|
|
597
|
+
}, {
|
|
598
|
+
key: "stripQuotes",
|
|
599
|
+
value: function stripQuotes(value) {
|
|
600
|
+
return value.replace(/(^["'])|(["']$)/g, '');
|
|
601
|
+
}
|
|
588
602
|
/**
|
|
589
603
|
* Extract the selectors present in the passed string using a purgecss extractor
|
|
590
604
|
* @param {array} content Array of content
|
|
@@ -702,12 +716,14 @@ function () {
|
|
|
702
716
|
key: "getFileExtractor",
|
|
703
717
|
value: function getFileExtractor(filename) {
|
|
704
718
|
var extractors = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
705
|
-
if (!extractors.length) return
|
|
719
|
+
if (!extractors.length) return this.options.defaultExtractor;
|
|
706
720
|
var extractorObj = extractors.find(function (extractor) {
|
|
707
721
|
return extractor.extensions.find(function (ext) {
|
|
708
722
|
return filename.endsWith(ext);
|
|
709
723
|
});
|
|
710
|
-
}) ||
|
|
724
|
+
}) || {
|
|
725
|
+
extractor: this.options.defaultExtractor
|
|
726
|
+
};
|
|
711
727
|
return extractorObj.extractor;
|
|
712
728
|
}
|
|
713
729
|
/**
|
|
@@ -753,7 +769,15 @@ function () {
|
|
|
753
769
|
}
|
|
754
770
|
|
|
755
771
|
if (node.type === 'comment') {
|
|
756
|
-
if (_this.isIgnoreAnnotation(node, 'start'))
|
|
772
|
+
if (_this.isIgnoreAnnotation(node, 'start')) {
|
|
773
|
+
_this.ignore = true; // remove ignore annotation
|
|
774
|
+
|
|
775
|
+
node.remove();
|
|
776
|
+
} else if (_this.isIgnoreAnnotation(node, 'end')) {
|
|
777
|
+
_this.ignore = false; // remove ignore annotation
|
|
778
|
+
|
|
779
|
+
node.remove();
|
|
780
|
+
}
|
|
757
781
|
}
|
|
758
782
|
});
|
|
759
783
|
}
|
|
@@ -769,7 +793,21 @@ function () {
|
|
|
769
793
|
var _this2 = this;
|
|
770
794
|
|
|
771
795
|
var annotation = node.prev();
|
|
772
|
-
if (this.
|
|
796
|
+
if (this.ignore) return;
|
|
797
|
+
|
|
798
|
+
if (typeof annotation !== 'undefined' && annotation.type === 'comment' && this.isIgnoreAnnotation(annotation, 'next')) {
|
|
799
|
+
annotation.remove();
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
if (node.parent && node.parent.type === 'atrule' && node.parent.name === 'keyframes') {
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
if (this.hasIgnoreAnnotation(node)) {
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
|
|
773
811
|
var keepSelector = true;
|
|
774
812
|
node.selector = selectorParser(function (selectorsParsed) {
|
|
775
813
|
selectorsParsed.walk(function (selector) {
|
|
@@ -791,10 +829,10 @@ function () {
|
|
|
791
829
|
type = _step7$value.type,
|
|
792
830
|
value = _step7$value.value;
|
|
793
831
|
|
|
794
|
-
if (SELECTOR_STANDARD_TYPES.includes(type) && typeof value !== 'undefined'
|
|
832
|
+
if (SELECTOR_STANDARD_TYPES.includes(type) && typeof value !== 'undefined') {
|
|
795
833
|
selectorsInRule.push(value);
|
|
796
|
-
} else if (type === 'tag' &&
|
|
797
|
-
|
|
834
|
+
} else if (type === 'tag' && !( // skip everything inside :nth-* pseudo selectors
|
|
835
|
+
selector.parent && selector.parent.type === 'pseudo' && IS_NTH.test(selector.parent.value))) {
|
|
798
836
|
selectorsInRule.push(value);
|
|
799
837
|
}
|
|
800
838
|
}
|
|
@@ -864,7 +902,30 @@ function () {
|
|
|
864
902
|
|
|
865
903
|
if (this.options.fontFace) {
|
|
866
904
|
if (prop === 'font-family') {
|
|
867
|
-
|
|
905
|
+
var _iteratorNormalCompletion10 = true;
|
|
906
|
+
var _didIteratorError10 = false;
|
|
907
|
+
var _iteratorError10 = undefined;
|
|
908
|
+
|
|
909
|
+
try {
|
|
910
|
+
for (var _iterator10 = value.split(',')[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {
|
|
911
|
+
var fontName = _step10.value;
|
|
912
|
+
var cleanedFontFace = this.stripQuotes(fontName.trim());
|
|
913
|
+
this.usedFontFaces.add(cleanedFontFace);
|
|
914
|
+
}
|
|
915
|
+
} catch (err) {
|
|
916
|
+
_didIteratorError10 = true;
|
|
917
|
+
_iteratorError10 = err;
|
|
918
|
+
} finally {
|
|
919
|
+
try {
|
|
920
|
+
if (!_iteratorNormalCompletion10 && _iterator10.return != null) {
|
|
921
|
+
_iterator10.return();
|
|
922
|
+
}
|
|
923
|
+
} finally {
|
|
924
|
+
if (_didIteratorError10) {
|
|
925
|
+
throw _iteratorError10;
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
}
|
|
868
929
|
}
|
|
869
930
|
}
|
|
870
931
|
}
|
|
@@ -903,34 +964,34 @@ function () {
|
|
|
903
964
|
}
|
|
904
965
|
|
|
905
966
|
if (this.options.fontFace && node.name === 'font-face') {
|
|
906
|
-
var
|
|
907
|
-
var
|
|
908
|
-
var
|
|
967
|
+
var _iteratorNormalCompletion11 = true;
|
|
968
|
+
var _didIteratorError11 = false;
|
|
969
|
+
var _iteratorError11 = undefined;
|
|
909
970
|
|
|
910
971
|
try {
|
|
911
|
-
for (var
|
|
912
|
-
var
|
|
913
|
-
prop =
|
|
914
|
-
value =
|
|
972
|
+
for (var _iterator11 = node.nodes[Symbol.iterator](), _step11; !(_iteratorNormalCompletion11 = (_step11 = _iterator11.next()).done); _iteratorNormalCompletion11 = true) {
|
|
973
|
+
var _step11$value = _step11.value,
|
|
974
|
+
prop = _step11$value.prop,
|
|
975
|
+
value = _step11$value.value;
|
|
915
976
|
|
|
916
977
|
if (prop === 'font-family') {
|
|
917
978
|
this.atRules.fontFace.push({
|
|
918
|
-
name: value,
|
|
979
|
+
name: this.stripQuotes(value),
|
|
919
980
|
node: node
|
|
920
981
|
});
|
|
921
982
|
}
|
|
922
983
|
}
|
|
923
984
|
} catch (err) {
|
|
924
|
-
|
|
925
|
-
|
|
985
|
+
_didIteratorError11 = true;
|
|
986
|
+
_iteratorError11 = err;
|
|
926
987
|
} finally {
|
|
927
988
|
try {
|
|
928
|
-
if (!
|
|
929
|
-
|
|
989
|
+
if (!_iteratorNormalCompletion11 && _iterator11.return != null) {
|
|
990
|
+
_iterator11.return();
|
|
930
991
|
}
|
|
931
992
|
} finally {
|
|
932
|
-
if (
|
|
933
|
-
throw
|
|
993
|
+
if (_didIteratorError11) {
|
|
994
|
+
throw _iteratorError11;
|
|
934
995
|
}
|
|
935
996
|
}
|
|
936
997
|
}
|
|
@@ -962,6 +1023,23 @@ function () {
|
|
|
962
1023
|
|
|
963
1024
|
return false;
|
|
964
1025
|
}
|
|
1026
|
+
/**
|
|
1027
|
+
* Check if the node has a css comment to ignore current selector rule
|
|
1028
|
+
* @param {object} rule Node of postcss abstract syntax tree
|
|
1029
|
+
*/
|
|
1030
|
+
|
|
1031
|
+
}, {
|
|
1032
|
+
key: "hasIgnoreAnnotation",
|
|
1033
|
+
value: function hasIgnoreAnnotation(rule) {
|
|
1034
|
+
var found = false;
|
|
1035
|
+
rule.walkComments(function (node) {
|
|
1036
|
+
if (node && node.type === 'comment' && node.text.includes(IGNORE_ANNOTATION_CURRENT)) {
|
|
1037
|
+
found = true;
|
|
1038
|
+
node.remove();
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
return found;
|
|
1042
|
+
}
|
|
965
1043
|
/**
|
|
966
1044
|
* Check if the node correspond to an empty css rule
|
|
967
1045
|
* @param {object} node Node of postcss abstract syntax tree
|
|
@@ -985,13 +1063,13 @@ function () {
|
|
|
985
1063
|
}, {
|
|
986
1064
|
key: "shouldKeepSelector",
|
|
987
1065
|
value: function shouldKeepSelector(selectorsInContent, selectorsInRule) {
|
|
988
|
-
var
|
|
989
|
-
var
|
|
990
|
-
var
|
|
1066
|
+
var _iteratorNormalCompletion12 = true;
|
|
1067
|
+
var _didIteratorError12 = false;
|
|
1068
|
+
var _iteratorError12 = undefined;
|
|
991
1069
|
|
|
992
1070
|
try {
|
|
993
|
-
for (var
|
|
994
|
-
var selector =
|
|
1071
|
+
for (var _iterator12 = selectorsInRule[Symbol.iterator](), _step12; !(_iteratorNormalCompletion12 = (_step12 = _iterator12.next()).done); _iteratorNormalCompletion12 = true) {
|
|
1072
|
+
var selector = _step12.value;
|
|
995
1073
|
// pseudo class
|
|
996
1074
|
var unescapedSelector = selector.replace(/\\/g, '');
|
|
997
1075
|
|
|
@@ -1010,16 +1088,16 @@ function () {
|
|
|
1010
1088
|
}
|
|
1011
1089
|
}
|
|
1012
1090
|
} catch (err) {
|
|
1013
|
-
|
|
1014
|
-
|
|
1091
|
+
_didIteratorError12 = true;
|
|
1092
|
+
_iteratorError12 = err;
|
|
1015
1093
|
} finally {
|
|
1016
1094
|
try {
|
|
1017
|
-
if (!
|
|
1018
|
-
|
|
1095
|
+
if (!_iteratorNormalCompletion12 && _iterator12.return != null) {
|
|
1096
|
+
_iterator12.return();
|
|
1019
1097
|
}
|
|
1020
1098
|
} finally {
|
|
1021
|
-
if (
|
|
1022
|
-
throw
|
|
1099
|
+
if (_didIteratorError12) {
|
|
1100
|
+
throw _iteratorError12;
|
|
1023
1101
|
}
|
|
1024
1102
|
}
|
|
1025
1103
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "purgecss",
|
|
3
|
-
"version": "1.2
|
|
3
|
+
"version": "1.4.2",
|
|
4
4
|
"description": "Remove unused css selectors.",
|
|
5
5
|
"main": "./lib/purgecss.js",
|
|
6
6
|
"module": "./lib/purgecss.es.js",
|
|
@@ -18,12 +18,12 @@
|
|
|
18
18
|
],
|
|
19
19
|
"bin": "./bin/purgecss",
|
|
20
20
|
"scripts": {
|
|
21
|
-
"test": "
|
|
21
|
+
"test": "jest __tests__/.+.test.js",
|
|
22
22
|
"dev": "rollup -c rollup.config.js -w",
|
|
23
23
|
"build": "rollup -c rollup.config.js",
|
|
24
|
-
"flow": "
|
|
25
|
-
"lint": "
|
|
26
|
-
"prettier": "
|
|
24
|
+
"flow": "flow",
|
|
25
|
+
"lint": "eslint -c .eslintrc src/",
|
|
26
|
+
"prettier": "prettier --write --print-width 100 --tab-width 4 --no-semi --single-quote '{src,__{tests,mocks}__}/**/*.js'"
|
|
27
27
|
},
|
|
28
28
|
"repository": {
|
|
29
29
|
"type": "git",
|
|
@@ -48,32 +48,34 @@
|
|
|
48
48
|
"glob": "^7.1.3",
|
|
49
49
|
"postcss": "^7.0.14",
|
|
50
50
|
"postcss-selector-parser": "^6.0.0",
|
|
51
|
-
"yargs": "^
|
|
51
|
+
"yargs": "^14.0.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@babel/core": "^7.
|
|
55
|
-
"@babel/plugin-proposal-class-properties": "^7.
|
|
56
|
-
"@babel/preset-env": "^7.
|
|
54
|
+
"@babel/core": "^7.6.4",
|
|
55
|
+
"@babel/plugin-proposal-class-properties": "^7.5.5",
|
|
56
|
+
"@babel/preset-env": "^7.6.3",
|
|
57
57
|
"@babel/preset-flow": "^7.0.0",
|
|
58
58
|
"babel-core": "^7.0.0-bridge.0",
|
|
59
|
-
"babel-eslint": "^10.0.
|
|
60
|
-
"babel-jest": "^24.
|
|
59
|
+
"babel-eslint": "^10.0.3",
|
|
60
|
+
"babel-jest": "^24.9.0",
|
|
61
61
|
"codacy-coverage": "^3.4.0",
|
|
62
|
-
"eslint": "^
|
|
63
|
-
"eslint-plugin-flowtype": "^3.
|
|
64
|
-
"flow-bin": "^0.
|
|
65
|
-
"jest": "^24.
|
|
66
|
-
"prettier": "^1.
|
|
67
|
-
"regenerator-runtime": "^0.13.
|
|
68
|
-
"rollup": "^1.
|
|
69
|
-
"rollup-plugin-babel": "^4.3.
|
|
62
|
+
"eslint": "^6.6.0",
|
|
63
|
+
"eslint-plugin-flowtype": "^4.3.0",
|
|
64
|
+
"flow-bin": "^0.113.0",
|
|
65
|
+
"jest": "^24.9.0",
|
|
66
|
+
"prettier": "^1.18.2",
|
|
67
|
+
"regenerator-runtime": "^0.13.3",
|
|
68
|
+
"rollup": "^1.26.0",
|
|
69
|
+
"rollup-plugin-babel": "^4.3.3",
|
|
70
70
|
"rollup-plugin-flow": "^1.1.1",
|
|
71
71
|
"rollup-plugin-node-builtins": "^2.1.2",
|
|
72
|
-
"rollup-plugin-node-resolve": "^
|
|
73
|
-
"rollup-watch": "^4.3.1"
|
|
72
|
+
"rollup-plugin-node-resolve": "^5.2.0"
|
|
74
73
|
},
|
|
75
74
|
"engines": {
|
|
76
75
|
"npm": ">=5.2.0",
|
|
77
76
|
"node": ">=4.4.0"
|
|
77
|
+
},
|
|
78
|
+
"funding": {
|
|
79
|
+
"url": "https://github.com/sponsors/Ffloriel"
|
|
78
80
|
}
|
|
79
81
|
}
|