postcss-discard-comments 7.0.4 → 7.0.5
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/package.json +2 -2
- package/src/index.js +53 -11
- package/src/lib/commentParser.js +80 -16
- package/types/index.d.ts.map +1 -1
- package/types/lib/commentParser.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "postcss-discard-comments",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.5",
|
|
4
4
|
"description": "Discard comments in your CSS files with PostCSS.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "types/index.d.ts",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"node": "^18.12.0 || ^20.9.0 || >=22.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"postcss": "^8.5.
|
|
36
|
+
"postcss": "^8.5.6",
|
|
37
37
|
"postcss-scss": "^4.0.9",
|
|
38
38
|
"postcss-simple-vars": "^7.0.1"
|
|
39
39
|
},
|
package/src/index.js
CHANGED
|
@@ -16,8 +16,25 @@ const selectorParser = require('postcss-selector-parser');
|
|
|
16
16
|
function pluginCreator(opts = {}) {
|
|
17
17
|
const remover = new CommentRemover(opts);
|
|
18
18
|
const matcherCache = new Map();
|
|
19
|
+
const parserCache = new Map();
|
|
19
20
|
const replacerCache = new Map();
|
|
20
21
|
|
|
22
|
+
/**
|
|
23
|
+
* @param {string} source
|
|
24
|
+
* @return {[number, number, number][]}
|
|
25
|
+
*/
|
|
26
|
+
function getTokens(source) {
|
|
27
|
+
if (parserCache.has(source)) {
|
|
28
|
+
return parserCache.get(source);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const tokens = commentParser(source);
|
|
32
|
+
|
|
33
|
+
parserCache.set(source, tokens);
|
|
34
|
+
|
|
35
|
+
return tokens;
|
|
36
|
+
}
|
|
37
|
+
|
|
21
38
|
/**
|
|
22
39
|
* @param {string} source
|
|
23
40
|
* @return {[number, number, number][]}
|
|
@@ -27,7 +44,7 @@ function pluginCreator(opts = {}) {
|
|
|
27
44
|
return matcherCache.get(source);
|
|
28
45
|
}
|
|
29
46
|
|
|
30
|
-
const result =
|
|
47
|
+
const result = getTokens(source).filter(([type]) => type);
|
|
31
48
|
|
|
32
49
|
matcherCache.set(source, result);
|
|
33
50
|
|
|
@@ -35,29 +52,46 @@ function pluginCreator(opts = {}) {
|
|
|
35
52
|
}
|
|
36
53
|
|
|
37
54
|
/**
|
|
38
|
-
* @param {string}
|
|
55
|
+
* @param {string | undefined} rawSource
|
|
39
56
|
* @param {(s: string) => string[]} space
|
|
57
|
+
* @param {string=} separator
|
|
40
58
|
* @return {string}
|
|
41
59
|
*/
|
|
42
|
-
function replaceComments(
|
|
60
|
+
function replaceComments(rawSource, space, separator = ' ') {
|
|
61
|
+
const source = rawSource || '';
|
|
43
62
|
const key = source + '@|@' + separator;
|
|
44
63
|
|
|
45
64
|
if (replacerCache.has(key)) {
|
|
46
65
|
return replacerCache.get(key);
|
|
47
66
|
}
|
|
48
|
-
const parsed = commentParser(source).reduce((value, [type, start, end]) => {
|
|
49
|
-
const contents = source.slice(start, end);
|
|
50
67
|
|
|
68
|
+
if (source.indexOf('/*') === -1) {
|
|
69
|
+
const normalized = space(source).join(' ');
|
|
70
|
+
|
|
71
|
+
replacerCache.set(key, normalized);
|
|
72
|
+
|
|
73
|
+
return normalized;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const parts = [];
|
|
77
|
+
|
|
78
|
+
for (const [type, start, end] of getTokens(source)) {
|
|
51
79
|
if (!type) {
|
|
52
|
-
|
|
80
|
+
parts.push(source.slice(start, end));
|
|
81
|
+
continue;
|
|
53
82
|
}
|
|
54
83
|
|
|
84
|
+
const contents = source.slice(start, end);
|
|
85
|
+
|
|
55
86
|
if (remover.canRemove(contents)) {
|
|
56
|
-
|
|
87
|
+
parts.push(separator);
|
|
88
|
+
continue;
|
|
57
89
|
}
|
|
58
90
|
|
|
59
|
-
|
|
60
|
-
}
|
|
91
|
+
parts.push('/*' + contents + '*/');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const parsed = parts.join('');
|
|
61
95
|
|
|
62
96
|
const result = space(parsed).join(' ');
|
|
63
97
|
|
|
@@ -67,16 +101,24 @@ function pluginCreator(opts = {}) {
|
|
|
67
101
|
}
|
|
68
102
|
|
|
69
103
|
/**
|
|
70
|
-
* @param {string}
|
|
104
|
+
* @param {string | undefined} rawSource
|
|
71
105
|
* @param {(s: string) => string[]} space
|
|
72
106
|
* @return {string}
|
|
73
107
|
*/
|
|
74
|
-
function replaceCommentsInSelector(
|
|
108
|
+
function replaceCommentsInSelector(rawSource, space) {
|
|
109
|
+
const source = rawSource || '';
|
|
75
110
|
const key = source + '@|@';
|
|
76
111
|
|
|
77
112
|
if (replacerCache.has(key)) {
|
|
78
113
|
return replacerCache.get(key);
|
|
79
114
|
}
|
|
115
|
+
if (source.indexOf('/*') === -1) {
|
|
116
|
+
const normalized = space(source).join(' ');
|
|
117
|
+
|
|
118
|
+
replacerCache.set(key, normalized);
|
|
119
|
+
|
|
120
|
+
return normalized;
|
|
121
|
+
}
|
|
80
122
|
const processed = selectorParser((ast) => {
|
|
81
123
|
ast.walk((node) => {
|
|
82
124
|
if (node.type === 'comment') {
|
package/src/lib/commentParser.js
CHANGED
|
@@ -1,31 +1,95 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
// State machine states reused between parses for better perf
|
|
4
|
+
const STATES = {
|
|
5
|
+
NORMAL: 0,
|
|
6
|
+
IN_SINGLE_QUOTE: 1,
|
|
7
|
+
IN_DOUBLE_QUOTE: 2,
|
|
8
|
+
IN_COMMENT: 3,
|
|
9
|
+
};
|
|
10
|
+
|
|
3
11
|
/**
|
|
12
|
+
* CSS Comment Parser with context awareness
|
|
13
|
+
* Properly handles comments inside strings, URLs, and escaped characters
|
|
14
|
+
*
|
|
4
15
|
* @param {string} input
|
|
5
16
|
* @return {[number, number, number][]}
|
|
6
17
|
*/
|
|
7
18
|
module.exports = function commentParser(input) {
|
|
8
|
-
/** @type [number, number, number][] */
|
|
19
|
+
/** @type {[number, number, number][]} */
|
|
9
20
|
const tokens = [];
|
|
10
21
|
const length = input.length;
|
|
11
22
|
let pos = 0;
|
|
12
|
-
|
|
13
|
-
|
|
23
|
+
|
|
24
|
+
let state = STATES.NORMAL;
|
|
25
|
+
let tokenStart = 0;
|
|
26
|
+
let commentStart = 0;
|
|
27
|
+
|
|
14
28
|
while (pos < length) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
const char = input[pos];
|
|
30
|
+
const nextChar = pos + 1 < length ? input[pos + 1] : '';
|
|
31
|
+
|
|
32
|
+
switch (state) {
|
|
33
|
+
case STATES.NORMAL:
|
|
34
|
+
if (char === '/' && nextChar === '*') {
|
|
35
|
+
// Found comment start - add non-comment token if needed
|
|
36
|
+
if (pos > tokenStart) {
|
|
37
|
+
tokens.push([0, tokenStart, pos]);
|
|
38
|
+
}
|
|
39
|
+
commentStart = pos;
|
|
40
|
+
state = STATES.IN_COMMENT;
|
|
41
|
+
pos += 2; // Skip /*
|
|
42
|
+
continue;
|
|
43
|
+
} else if (char === '"') {
|
|
44
|
+
state = STATES.IN_DOUBLE_QUOTE;
|
|
45
|
+
} else if (char === "'") {
|
|
46
|
+
state = STATES.IN_SINGLE_QUOTE;
|
|
47
|
+
}
|
|
48
|
+
break;
|
|
49
|
+
|
|
50
|
+
case STATES.IN_SINGLE_QUOTE:
|
|
51
|
+
if (char === '\\' && nextChar) {
|
|
52
|
+
// Skip escaped character
|
|
53
|
+
pos += 2;
|
|
54
|
+
continue;
|
|
55
|
+
} else if (char === "'") {
|
|
56
|
+
state = STATES.NORMAL;
|
|
57
|
+
}
|
|
58
|
+
break;
|
|
59
|
+
|
|
60
|
+
case STATES.IN_DOUBLE_QUOTE:
|
|
61
|
+
if (char === '\\' && nextChar) {
|
|
62
|
+
// Skip escaped character
|
|
63
|
+
pos += 2;
|
|
64
|
+
continue;
|
|
65
|
+
} else if (char === '"') {
|
|
66
|
+
state = STATES.NORMAL;
|
|
67
|
+
}
|
|
68
|
+
break;
|
|
69
|
+
|
|
70
|
+
case STATES.IN_COMMENT:
|
|
71
|
+
if (char === '*' && nextChar === '/') {
|
|
72
|
+
// Found comment end
|
|
73
|
+
tokens.push([1, commentStart + 2, pos]);
|
|
74
|
+
tokenStart = pos + 2;
|
|
75
|
+
state = STATES.NORMAL;
|
|
76
|
+
pos += 2; // Skip */
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
break;
|
|
27
80
|
}
|
|
81
|
+
|
|
82
|
+
pos++;
|
|
28
83
|
}
|
|
29
|
-
|
|
84
|
+
|
|
85
|
+
// Handle remaining content
|
|
86
|
+
if (state === STATES.IN_COMMENT) {
|
|
87
|
+
// Unclosed comment - treat as comment to end
|
|
88
|
+
tokens.push([1, commentStart + 2, length]);
|
|
89
|
+
} else if (tokenStart < length) {
|
|
90
|
+
// Add final non-comment token
|
|
91
|
+
tokens.push([0, tokenStart, length]);
|
|
92
|
+
}
|
|
93
|
+
|
|
30
94
|
return tokens;
|
|
31
95
|
};
|
package/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":";AAKA;;;;GAIG;AACH;;;;GAIG;AACH,sCAHW,OAAO,GACN,OAAO,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":";AAKA;;;;GAIG;AACH;;;;GAIG;AACH,sCAHW,OAAO,GACN,OAAO,SAAS,EAAE,MAAM,CA8NnC;;;;;;gBArOc,OAAO,YAAC;wBACR,OAAO,YAAC;aACR,CAAA,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,aAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commentParser.d.ts","sourceRoot":"","sources":["../../src/lib/commentParser.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"commentParser.d.ts","sourceRoot":"","sources":["../../src/lib/commentParser.js"],"names":[],"mappings":"AAiBiB,iCAHN,MAAM,GACL,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CA+ErC"}
|