@tbela99/css-parser 0.0.1 → 0.1.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/README.md +117 -36
- package/dist/index-umd-web.js +2057 -1235
- package/dist/index.cjs +2051 -1231
- package/dist/index.d.ts +677 -332
- package/dist/lib/ast/expand.js +14 -14
- package/dist/lib/ast/features/calc.js +256 -0
- package/dist/lib/ast/features/index.js +3 -0
- package/dist/lib/ast/features/inlinecssvariables.js +115 -0
- package/dist/lib/ast/features/shorthand.js +45 -0
- package/dist/lib/ast/minify.js +395 -371
- package/dist/lib/ast/types.js +88 -0
- package/dist/lib/ast/utiles/minifyfeature.js +8 -0
- package/dist/lib/ast/walk.js +24 -9
- package/dist/lib/parser/declaration/list.js +18 -4
- package/dist/lib/parser/declaration/map.js +51 -30
- package/dist/lib/parser/declaration/set.js +18 -12
- package/dist/lib/parser/parse.js +176 -136
- package/dist/lib/parser/tokenize.js +42 -35
- package/dist/lib/parser/utils/syntax.js +13 -10
- package/dist/lib/parser/utils/type.js +18 -6
- package/dist/lib/renderer/render.js +201 -79
- package/dist/lib/renderer/sourcemap/lib/encode.js +37 -0
- package/dist/lib/renderer/sourcemap/sourcemap.js +58 -0
- package/dist/lib/renderer/utils/color.js +25 -20
- package/dist/node/index.js +29 -10
- package/dist/web/index.js +33 -12
- package/package.json +5 -4
- package/dist/lib/transform.js +0 -24
package/dist/lib/ast/minify.js
CHANGED
|
@@ -1,58 +1,33 @@
|
|
|
1
|
-
import { isIdentStart, isWhiteSpace, isIdent, isFunction } from '../parser/utils/syntax.js';
|
|
2
|
-
import { PropertyList } from '../parser/declaration/list.js';
|
|
3
|
-
import { eq } from '../parser/utils/eq.js';
|
|
4
|
-
import { render, renderToken } from '../renderer/render.js';
|
|
5
1
|
import { parseString } from '../parser/parse.js';
|
|
6
|
-
import {
|
|
2
|
+
import { isIdentStart, isWhiteSpace, isIdent, isFunction } from '../parser/utils/syntax.js';
|
|
3
|
+
import { EnumToken } from './types.js';
|
|
7
4
|
import { walkValues } from './walk.js';
|
|
5
|
+
import { replaceCompound } from './expand.js';
|
|
6
|
+
import { eq } from '../parser/utils/eq.js';
|
|
7
|
+
import { renderToken, doRender } from '../renderer/render.js';
|
|
8
|
+
import * as index from './features/index.js';
|
|
8
9
|
|
|
9
10
|
const combinators = ['+', '>', '~'];
|
|
10
11
|
const notEndingWith = ['(', '['].concat(combinators);
|
|
11
12
|
const definedPropertySettings = { configurable: true, enumerable: false, writable: true };
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
// @ts-ignore
|
|
14
|
+
const features = Object.values(index).sort((a, b) => a.ordering - b.ordering);
|
|
15
|
+
function minify(ast, options = {}, recursive = false, errors, nestingContent, context = {}) {
|
|
16
|
+
if (!('nodes' in context)) {
|
|
17
|
+
context.nodes = new WeakSet;
|
|
18
|
+
}
|
|
19
|
+
if (context.nodes.has(ast)) {
|
|
20
|
+
// console.error('skipped', ast.typ);
|
|
21
|
+
return ast;
|
|
22
|
+
}
|
|
23
|
+
context.nodes.add(ast);
|
|
24
|
+
if (!('features' in options)) {
|
|
18
25
|
// @ts-ignore
|
|
19
|
-
|
|
26
|
+
options = { removeDuplicateDeclarations: true, computeShorthand: true, computeCalcExpression: true, features: [], ...options };
|
|
20
27
|
// @ts-ignore
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
value: match.match.map(t => t.slice())
|
|
24
|
-
});
|
|
25
|
-
if (pSel == '&' || pSel === '') {
|
|
26
|
-
// @ts-ignore
|
|
27
|
-
wrapper.chi.push(...previous.chi);
|
|
28
|
-
// @ts-ignore
|
|
29
|
-
if ((nSel == '&' || nSel === '')) {
|
|
30
|
-
// @ts-ignore
|
|
31
|
-
wrapper.chi.push(...node.chi);
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
// @ts-ignore
|
|
35
|
-
wrapper.chi.push(node);
|
|
36
|
-
}
|
|
28
|
+
for (const feature of features) {
|
|
29
|
+
feature.register(options);
|
|
37
30
|
}
|
|
38
|
-
else {
|
|
39
|
-
// @ts-ignore
|
|
40
|
-
wrapper.chi.push(previous, node);
|
|
41
|
-
}
|
|
42
|
-
// @ts-ignore
|
|
43
|
-
ast.chi.splice(i, 1, wrapper);
|
|
44
|
-
// @ts-ignore
|
|
45
|
-
ast.chi.splice(nodeIndex, 1);
|
|
46
|
-
// @ts-ignore
|
|
47
|
-
previous.sel = pSel;
|
|
48
|
-
// @ts-ignore
|
|
49
|
-
previous.raw = match.selector1;
|
|
50
|
-
// @ts-ignore
|
|
51
|
-
node.sel = nSel;
|
|
52
|
-
// @ts-ignore
|
|
53
|
-
node.raw = match.selector2;
|
|
54
|
-
reduceRuleSelector(wrapper);
|
|
55
|
-
return wrapper;
|
|
56
31
|
}
|
|
57
32
|
function reducer(acc, curr, index, array) {
|
|
58
33
|
// trim :is()
|
|
@@ -67,258 +42,16 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
|
|
|
67
42
|
curr.splice(0, 1);
|
|
68
43
|
}
|
|
69
44
|
}
|
|
70
|
-
else if (ast.typ ==
|
|
45
|
+
else if (ast.typ == 4 /* NodeType.RuleNodeType */ && (isIdent(curr[0]) || isFunction(curr[0]))) {
|
|
71
46
|
curr.unshift('&', ' ');
|
|
72
47
|
}
|
|
73
48
|
acc.push(curr.join(''));
|
|
74
49
|
return acc;
|
|
75
50
|
}
|
|
76
|
-
function diff(n1, n2, options = {}) {
|
|
77
|
-
let node1 = n1;
|
|
78
|
-
let node2 = n2;
|
|
79
|
-
let exchanged = false;
|
|
80
|
-
if (node1.chi.length > node2.chi.length) {
|
|
81
|
-
const t = node1;
|
|
82
|
-
node1 = node2;
|
|
83
|
-
node2 = t;
|
|
84
|
-
exchanged = true;
|
|
85
|
-
}
|
|
86
|
-
let i = node1.chi.length;
|
|
87
|
-
let j = node2.chi.length;
|
|
88
|
-
if (i == 0 || j == 0) {
|
|
89
|
-
// @ts-ignore
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
92
|
-
// @ts-ignore
|
|
93
|
-
const raw1 = node1.raw;
|
|
94
|
-
// @ts-ignore
|
|
95
|
-
const raw2 = node2.raw;
|
|
96
|
-
// @ts-ignore
|
|
97
|
-
node1 = { ...node1, chi: node1.chi.slice() };
|
|
98
|
-
node2 = { ...node2, chi: node2.chi.slice() };
|
|
99
|
-
if (raw1 != null) {
|
|
100
|
-
Object.defineProperty(node1, 'raw', { ...definedPropertySettings, value: raw1 });
|
|
101
|
-
}
|
|
102
|
-
if (raw2 != null) {
|
|
103
|
-
Object.defineProperty(node2, 'raw', { ...definedPropertySettings, value: raw2 });
|
|
104
|
-
}
|
|
105
|
-
const intersect = [];
|
|
106
|
-
while (i--) {
|
|
107
|
-
if (node1.chi[i].typ == 'Comment') {
|
|
108
|
-
continue;
|
|
109
|
-
}
|
|
110
|
-
j = node2.chi.length;
|
|
111
|
-
if (j == 0) {
|
|
112
|
-
break;
|
|
113
|
-
}
|
|
114
|
-
while (j--) {
|
|
115
|
-
if (node2.chi[j].typ == 'Comment') {
|
|
116
|
-
continue;
|
|
117
|
-
}
|
|
118
|
-
if (node1.chi[i].nam == node2.chi[j].nam) {
|
|
119
|
-
if (eq(node1.chi[i], node2.chi[j])) {
|
|
120
|
-
intersect.push(node1.chi[i]);
|
|
121
|
-
node1.chi.splice(i, 1);
|
|
122
|
-
node2.chi.splice(j, 1);
|
|
123
|
-
break;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
// @ts-ignore
|
|
129
|
-
const result = (intersect.length == 0 ? null : {
|
|
130
|
-
...node1,
|
|
131
|
-
// @ts-ignore
|
|
132
|
-
sel: [...new Set([...(n1?.raw?.reduce(reducer, []) || splitRule(n1.sel)).concat(n2?.raw?.reduce(reducer, []) || splitRule(n2.sel))])].join(','),
|
|
133
|
-
chi: intersect.reverse()
|
|
134
|
-
});
|
|
135
|
-
if (result == null || [n1, n2].reduce((acc, curr) => curr.chi.length == 0 ? acc : acc + render(curr, options).code.length, 0) <= [node1, node2, result].reduce((acc, curr) => curr.chi.length == 0 ? acc : acc + render(curr, options).code.length, 0)) {
|
|
136
|
-
// @ts-ignore
|
|
137
|
-
return null;
|
|
138
|
-
}
|
|
139
|
-
return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node1 : node2 };
|
|
140
|
-
}
|
|
141
|
-
function matchSelectors(selector1, selector2, parentType) {
|
|
142
|
-
let match = [[]];
|
|
143
|
-
const j = Math.min(selector1.reduce((acc, curr) => Math.min(acc, curr.length), selector1.length > 0 ? selector1[0].length : 0), selector2.reduce((acc, curr) => Math.min(acc, curr.length), selector2.length > 0 ? selector2[0].length : 0));
|
|
144
|
-
let i = 0;
|
|
145
|
-
let k;
|
|
146
|
-
let l;
|
|
147
|
-
let token;
|
|
148
|
-
let matching = true;
|
|
149
|
-
let matchFunction = 0;
|
|
150
|
-
let inAttr = 0;
|
|
151
|
-
for (; i < j; i++) {
|
|
152
|
-
k = 0;
|
|
153
|
-
token = selector1[0][i];
|
|
154
|
-
for (; k < selector1.length; k++) {
|
|
155
|
-
if (selector1[k][i] != token) {
|
|
156
|
-
matching = false;
|
|
157
|
-
break;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
if (matching) {
|
|
161
|
-
l = 0;
|
|
162
|
-
for (; l < selector2.length; l++) {
|
|
163
|
-
if (selector2[l][i] != token) {
|
|
164
|
-
matching = false;
|
|
165
|
-
break;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
if (!matching) {
|
|
170
|
-
break;
|
|
171
|
-
}
|
|
172
|
-
if (token == ',') {
|
|
173
|
-
match.push([]);
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
if (token.endsWith('(')) {
|
|
177
|
-
matchFunction++;
|
|
178
|
-
}
|
|
179
|
-
if (token.endsWith('[')) {
|
|
180
|
-
inAttr++;
|
|
181
|
-
}
|
|
182
|
-
else if (token == ')') {
|
|
183
|
-
matchFunction--;
|
|
184
|
-
}
|
|
185
|
-
else if (token == ']') {
|
|
186
|
-
inAttr--;
|
|
187
|
-
}
|
|
188
|
-
match.at(-1).push(token);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
// invalid function
|
|
192
|
-
if (matchFunction != 0 || inAttr != 0) {
|
|
193
|
-
return null;
|
|
194
|
-
}
|
|
195
|
-
if (parentType != 'Rule') {
|
|
196
|
-
for (const part of match) {
|
|
197
|
-
if (part.length > 0 && combinators.includes(part[0].charAt(0))) {
|
|
198
|
-
return null;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
if (match.length > 1) {
|
|
203
|
-
errors?.push({ action: 'ignore', message: `minify: unsupported multilevel matching\n${JSON.stringify({ match, selector1, selector2 }, null, 1)}` });
|
|
204
|
-
return null;
|
|
205
|
-
}
|
|
206
|
-
for (const part of match) {
|
|
207
|
-
while (part.length > 0) {
|
|
208
|
-
const token = part.at(-1);
|
|
209
|
-
if (token == ' ' || combinators.includes(token) || notEndingWith.includes(token.at(-1))) {
|
|
210
|
-
part.pop();
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
213
|
-
break;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
if (match.every(t => t.length == 0)) {
|
|
217
|
-
return null;
|
|
218
|
-
}
|
|
219
|
-
if (eq([['&']], match)) {
|
|
220
|
-
return null;
|
|
221
|
-
}
|
|
222
|
-
function reduce(acc, curr) {
|
|
223
|
-
if (acc === null) {
|
|
224
|
-
return null;
|
|
225
|
-
}
|
|
226
|
-
let hasCompoundSelector = true;
|
|
227
|
-
curr = curr.slice(match[0].length);
|
|
228
|
-
while (curr.length > 0) {
|
|
229
|
-
if (curr[0] == ' ') {
|
|
230
|
-
hasCompoundSelector = false;
|
|
231
|
-
curr.unshift('&');
|
|
232
|
-
continue;
|
|
233
|
-
}
|
|
234
|
-
break;
|
|
235
|
-
}
|
|
236
|
-
// invalid function match
|
|
237
|
-
if (curr.length > 0 && curr[0].endsWith('(') && curr.at(-1) != ')') {
|
|
238
|
-
return null;
|
|
239
|
-
}
|
|
240
|
-
if (curr.length == 1 && combinators.includes(curr[0].charAt(0))) {
|
|
241
|
-
return null;
|
|
242
|
-
}
|
|
243
|
-
if (hasCompoundSelector && curr.length > 0) {
|
|
244
|
-
hasCompoundSelector = !['&'].concat(combinators).includes(curr[0].charAt(0));
|
|
245
|
-
}
|
|
246
|
-
if (curr[0] == ':is(') {
|
|
247
|
-
let inFunction = 0;
|
|
248
|
-
let canReduce = true;
|
|
249
|
-
const isCompound = curr.reduce((acc, token, index) => {
|
|
250
|
-
if (index == 0) {
|
|
251
|
-
inFunction++;
|
|
252
|
-
canReduce = curr[1] == '&';
|
|
253
|
-
}
|
|
254
|
-
else if (token.endsWith('(')) {
|
|
255
|
-
if (inFunction == 0) {
|
|
256
|
-
canReduce = false;
|
|
257
|
-
}
|
|
258
|
-
inFunction++;
|
|
259
|
-
}
|
|
260
|
-
else if (token == ')') {
|
|
261
|
-
inFunction--;
|
|
262
|
-
}
|
|
263
|
-
else if (token == ',') {
|
|
264
|
-
if (!canReduce) {
|
|
265
|
-
canReduce = curr[index + 1] == '&';
|
|
266
|
-
}
|
|
267
|
-
acc.push([]);
|
|
268
|
-
}
|
|
269
|
-
else
|
|
270
|
-
acc.at(-1)?.push(token);
|
|
271
|
-
return acc;
|
|
272
|
-
}, [[]]);
|
|
273
|
-
if (inFunction > 0) {
|
|
274
|
-
canReduce = false;
|
|
275
|
-
}
|
|
276
|
-
if (canReduce) {
|
|
277
|
-
curr = isCompound.reduce((acc, curr) => {
|
|
278
|
-
if (acc.length > 0) {
|
|
279
|
-
acc.push(',');
|
|
280
|
-
}
|
|
281
|
-
acc.push(...curr);
|
|
282
|
-
return acc;
|
|
283
|
-
}, []);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
// @todo: check hasCompoundSelector && curr[0] == '&' && curr[1] == ' '
|
|
287
|
-
acc.push(match.length == 0 ? ['&'] : (hasCompoundSelector && curr[0] != '&' && (curr.length == 0 || !combinators.includes(curr[0].charAt(0))) ? ['&'].concat(curr) : curr));
|
|
288
|
-
return acc;
|
|
289
|
-
}
|
|
290
|
-
// @ts-ignore
|
|
291
|
-
selector1 = selector1.reduce(reduce, []);
|
|
292
|
-
// @ts-ignore
|
|
293
|
-
selector2 = selector2.reduce(reduce, []);
|
|
294
|
-
return selector1 == null || selector2 == null ? null : {
|
|
295
|
-
eq: eq(selector1, selector2),
|
|
296
|
-
match,
|
|
297
|
-
selector1,
|
|
298
|
-
selector2
|
|
299
|
-
};
|
|
300
|
-
}
|
|
301
|
-
function fixSelector(node) {
|
|
302
|
-
// @ts-ignore
|
|
303
|
-
if (node.sel.includes('&')) {
|
|
304
|
-
const attributes = parseString(node.sel);
|
|
305
|
-
for (const attr of walkValues(attributes)) {
|
|
306
|
-
if (attr.value.typ == 'Pseudo-class-func' && attr.value.val == ':is') {
|
|
307
|
-
let i = attr.value.chi.length;
|
|
308
|
-
while (i--) {
|
|
309
|
-
if (attr.value.chi[i].typ == 'Literal' && attr.value.chi[i].val == '&') {
|
|
310
|
-
attr.value.chi.splice(i, 1);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
node.sel = attributes.reduce((acc, curr) => acc + renderToken(curr), '');
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
51
|
// @ts-ignore
|
|
319
|
-
if (
|
|
52
|
+
if ('chi' in ast && ast.chi.length > 0) {
|
|
320
53
|
if (!nestingContent) {
|
|
321
|
-
nestingContent = options.nestingRules && ast.typ ==
|
|
54
|
+
nestingContent = options.nestingRules && ast.typ == 4 /* NodeType.RuleNodeType */;
|
|
322
55
|
}
|
|
323
56
|
let i = 0;
|
|
324
57
|
let previous;
|
|
@@ -327,7 +60,7 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
|
|
|
327
60
|
// @ts-ignore
|
|
328
61
|
for (; i < ast.chi.length; i++) {
|
|
329
62
|
// @ts-ignore
|
|
330
|
-
if (ast.chi[i].typ ==
|
|
63
|
+
if (ast.chi[i].typ == 0 /* NodeType.CommentNodeType */) {
|
|
331
64
|
continue;
|
|
332
65
|
}
|
|
333
66
|
// @ts-ignore
|
|
@@ -339,10 +72,10 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
|
|
|
339
72
|
i--;
|
|
340
73
|
continue;
|
|
341
74
|
}
|
|
342
|
-
if (node.typ ==
|
|
75
|
+
if (node.typ == 3 /* NodeType.AtRuleNodeType */ && node.nam == 'font-face') {
|
|
343
76
|
continue;
|
|
344
77
|
}
|
|
345
|
-
if (node.typ ==
|
|
78
|
+
if (node.typ == 3 /* NodeType.AtRuleNodeType */) {
|
|
346
79
|
if (node.nam == 'media' && node.val == 'all') {
|
|
347
80
|
// @ts-ignore
|
|
348
81
|
ast.chi?.splice(i, 1, ...node.chi);
|
|
@@ -350,47 +83,41 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
|
|
|
350
83
|
continue;
|
|
351
84
|
}
|
|
352
85
|
// @ts-ignore
|
|
353
|
-
if (previous?.typ ==
|
|
86
|
+
if (previous?.typ == 3 /* NodeType.AtRuleNodeType */ &&
|
|
354
87
|
previous.nam == node.nam &&
|
|
355
88
|
previous.val == node.val) {
|
|
356
89
|
if ('chi' in node) {
|
|
357
90
|
// @ts-ignore
|
|
358
91
|
previous.chi.push(...node.chi);
|
|
359
92
|
}
|
|
360
|
-
// else {
|
|
361
93
|
ast?.chi?.splice(i--, 1);
|
|
362
94
|
continue;
|
|
363
|
-
// }
|
|
364
95
|
}
|
|
365
96
|
// @ts-ignore
|
|
366
|
-
if (hasDeclaration(node)) {
|
|
367
|
-
|
|
368
|
-
minifyRule(node);
|
|
369
|
-
}
|
|
370
|
-
else {
|
|
371
|
-
minify(node, options, recursive, errors, nestingContent);
|
|
97
|
+
if (!hasDeclaration(node)) {
|
|
98
|
+
minify(node, options, recursive, errors, nestingContent, context);
|
|
372
99
|
}
|
|
373
100
|
previous = node;
|
|
374
101
|
nodeIndex = i;
|
|
375
102
|
continue;
|
|
376
103
|
}
|
|
377
104
|
// @ts-ignore
|
|
378
|
-
if (node.typ ==
|
|
105
|
+
if (node.typ == 4 /* NodeType.RuleNodeType */) {
|
|
379
106
|
reduceRuleSelector(node);
|
|
380
107
|
let wrapper;
|
|
381
108
|
let match;
|
|
382
109
|
// @ts-ignore
|
|
383
110
|
if (options.nestingRules) {
|
|
384
111
|
// @ts-ignore
|
|
385
|
-
if (previous?.typ ==
|
|
112
|
+
if (previous?.typ == 4 /* NodeType.RuleNodeType */) {
|
|
386
113
|
// @ts-ignore
|
|
387
114
|
reduceRuleSelector(previous);
|
|
388
115
|
// @ts-ignore
|
|
389
|
-
match = matchSelectors(previous.raw, node.raw, ast.typ);
|
|
116
|
+
match = matchSelectors(previous.raw, node.raw, ast.typ, errors);
|
|
390
117
|
// @ts-ignore
|
|
391
118
|
if (match != null) {
|
|
392
119
|
// @ts-ignore
|
|
393
|
-
wrapper = wrapNodes(previous, node, match, ast, i, nodeIndex);
|
|
120
|
+
wrapper = wrapNodes(previous, node, match, ast, reducer, i, nodeIndex);
|
|
394
121
|
nodeIndex = i - 1;
|
|
395
122
|
// @ts-ignore
|
|
396
123
|
previous = ast.chi[nodeIndex];
|
|
@@ -403,26 +130,23 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
|
|
|
403
130
|
// @ts-ignore
|
|
404
131
|
const nextNode = ast.chi[i];
|
|
405
132
|
// @ts-ignore
|
|
406
|
-
if (nextNode.typ !=
|
|
407
|
-
// i--;
|
|
408
|
-
// previous = wrapper;
|
|
409
|
-
// nodeIndex = i;
|
|
133
|
+
if (nextNode.typ != 4 /* NodeType.RuleNodeType */) {
|
|
410
134
|
break;
|
|
411
135
|
}
|
|
412
136
|
reduceRuleSelector(nextNode);
|
|
413
137
|
// @ts-ignore
|
|
414
|
-
match = matchSelectors(wrapper.raw, nextNode.raw, ast.typ);
|
|
138
|
+
match = matchSelectors(wrapper.raw, nextNode.raw, ast.typ, errors);
|
|
415
139
|
// @ts-ignore
|
|
416
140
|
if (match == null) {
|
|
417
141
|
break;
|
|
418
142
|
}
|
|
419
143
|
// @ts-ignore
|
|
420
|
-
wrapper = wrapNodes(wrapper, nextNode, match, ast, i, nodeIndex);
|
|
144
|
+
wrapper = wrapNodes(wrapper, nextNode, match, ast, reducer, i, nodeIndex);
|
|
421
145
|
}
|
|
422
146
|
nodeIndex = --i;
|
|
423
147
|
// @ts-ignore
|
|
424
148
|
previous = ast.chi[nodeIndex];
|
|
425
|
-
minify(wrapper, options, recursive, errors, nestingContent);
|
|
149
|
+
minify(wrapper, options, recursive, errors, nestingContent, context);
|
|
426
150
|
continue;
|
|
427
151
|
}
|
|
428
152
|
// @ts-ignore
|
|
@@ -460,7 +184,7 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
|
|
|
460
184
|
curr.splice(0, 2);
|
|
461
185
|
}
|
|
462
186
|
else {
|
|
463
|
-
if (ast.typ !=
|
|
187
|
+
if (ast.typ != 4 /* NodeType.RuleNodeType */ && combinators.includes(curr[1])) {
|
|
464
188
|
wrap = false;
|
|
465
189
|
}
|
|
466
190
|
else {
|
|
@@ -477,7 +201,7 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
|
|
|
477
201
|
return acc;
|
|
478
202
|
}, []);
|
|
479
203
|
if (!wrap) {
|
|
480
|
-
wrap = selector.some(s => s[0] != '&');
|
|
204
|
+
wrap = selector.some((s) => s[0] != '&');
|
|
481
205
|
}
|
|
482
206
|
let rule = selector.map(s => {
|
|
483
207
|
if (s[0] == '&') {
|
|
@@ -508,37 +232,36 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
|
|
|
508
232
|
let k = previous.chi.length;
|
|
509
233
|
while (k-- > 0) {
|
|
510
234
|
// @ts-ignore
|
|
511
|
-
if (previous.chi[k].typ ==
|
|
235
|
+
if (previous.chi[k].typ == 0 /* NodeType.CommentNodeType */) {
|
|
512
236
|
continue;
|
|
513
237
|
}
|
|
514
238
|
// @ts-ignore
|
|
515
|
-
shouldMerge = previous.chi[k].typ ==
|
|
239
|
+
shouldMerge = previous.chi[k].typ == 5 /* NodeType.DeclarationNodeType */;
|
|
516
240
|
break;
|
|
517
241
|
}
|
|
518
242
|
if (shouldMerge) {
|
|
519
243
|
// @ts-ignore
|
|
520
|
-
if ((node.typ ==
|
|
244
|
+
if ((node.typ == 4 /* NodeType.RuleNodeType */ && node.sel == previous.sel) ||
|
|
521
245
|
// @ts-ignore
|
|
522
|
-
(node.typ ==
|
|
246
|
+
(node.typ == 3 /* NodeType.AtRuleNodeType */) && node.val != 'font-face' && node.val == previous.val) {
|
|
523
247
|
// @ts-ignore
|
|
524
248
|
node.chi.unshift(...previous.chi);
|
|
525
249
|
// @ts-ignore
|
|
526
250
|
ast.chi.splice(nodeIndex, 1);
|
|
527
251
|
// @ts-ignore
|
|
528
|
-
if (hasDeclaration(node)) {
|
|
252
|
+
if (!hasDeclaration(node)) {
|
|
529
253
|
// @ts-ignore
|
|
530
|
-
minifyRule(node);
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
minify(node, options, recursive, errors, nestingContent);
|
|
254
|
+
// minifyRule(node, <MinifyOptions>options, ast, context);
|
|
255
|
+
// } else {
|
|
256
|
+
minify(node, options, recursive, errors, nestingContent, context);
|
|
534
257
|
}
|
|
535
258
|
i--;
|
|
536
259
|
previous = node;
|
|
537
260
|
nodeIndex = i;
|
|
538
261
|
continue;
|
|
539
262
|
}
|
|
540
|
-
else if (node.typ ==
|
|
541
|
-
const intersect = diff(previous, node, options);
|
|
263
|
+
else if (node.typ == 4 /* NodeType.RuleNodeType */ && previous?.typ == 4 /* NodeType.RuleNodeType */) {
|
|
264
|
+
const intersect = diff(previous, node, reducer, options);
|
|
542
265
|
if (intersect != null) {
|
|
543
266
|
if (intersect.node1.chi.length == 0) {
|
|
544
267
|
// @ts-ignore
|
|
@@ -570,24 +293,22 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
|
|
|
570
293
|
// @ts-ignore
|
|
571
294
|
if (recursive && previous != node) {
|
|
572
295
|
// @ts-ignore
|
|
573
|
-
if (hasDeclaration(previous)) {
|
|
296
|
+
if (!hasDeclaration(previous)) {
|
|
574
297
|
// @ts-ignore
|
|
575
|
-
minifyRule(previous);
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
minify(previous, options, recursive, errors, nestingContent);
|
|
298
|
+
// minifyRule(previous, <MinifyOptions>options, ast, context);
|
|
299
|
+
// } else {
|
|
300
|
+
minify(previous, options, recursive, errors, nestingContent, context);
|
|
579
301
|
}
|
|
580
302
|
}
|
|
581
303
|
}
|
|
582
304
|
else {
|
|
583
305
|
if ('chi' in previous) {
|
|
584
306
|
// @ts-ignore
|
|
585
|
-
if (hasDeclaration(previous)) {
|
|
307
|
+
if (!hasDeclaration(previous)) {
|
|
586
308
|
// @ts-ignore
|
|
587
|
-
minifyRule(previous);
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
minify(previous, options, recursive, errors, nestingContent);
|
|
309
|
+
// minifyRule(previous, <MinifyOptions>options, ast, context);
|
|
310
|
+
// } else {
|
|
311
|
+
minify(previous, options, recursive, errors, nestingContent, context);
|
|
591
312
|
}
|
|
592
313
|
}
|
|
593
314
|
}
|
|
@@ -596,7 +317,7 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
|
|
|
596
317
|
// @ts-ignore
|
|
597
318
|
previous != null &&
|
|
598
319
|
// previous.optimized != null &&
|
|
599
|
-
previous.typ ==
|
|
320
|
+
previous.typ == 4 /* NodeType.RuleNodeType */ &&
|
|
600
321
|
previous.sel.includes('&')) {
|
|
601
322
|
fixSelector(previous);
|
|
602
323
|
}
|
|
@@ -606,13 +327,10 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
|
|
|
606
327
|
// @ts-ignore
|
|
607
328
|
if (recursive && node != null && ('chi' in node)) {
|
|
608
329
|
// @ts-ignore
|
|
609
|
-
if (node.chi.some(n => n.typ ==
|
|
610
|
-
minifyRule(node);
|
|
611
|
-
}
|
|
612
|
-
else {
|
|
330
|
+
if (!node.chi.some(n => n.typ == 5 /* NodeType.DeclarationNodeType */)) {
|
|
613
331
|
// @ts-ignore
|
|
614
|
-
if (!(node.typ ==
|
|
615
|
-
minify(node, options, recursive, errors, nestingContent);
|
|
332
|
+
if (!(node.typ == 3 /* NodeType.AtRuleNodeType */ && node.nam != 'font-face')) {
|
|
333
|
+
minify(node, options, recursive, errors, nestingContent, context);
|
|
616
334
|
}
|
|
617
335
|
}
|
|
618
336
|
}
|
|
@@ -620,11 +338,46 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
|
|
|
620
338
|
// @ts-ignore
|
|
621
339
|
node != null &&
|
|
622
340
|
// previous.optimized != null &&
|
|
623
|
-
node.typ ==
|
|
341
|
+
node.typ == 4 /* NodeType.RuleNodeType */ &&
|
|
624
342
|
node.sel.includes('&')) {
|
|
625
343
|
fixSelector(node);
|
|
626
344
|
}
|
|
627
345
|
}
|
|
346
|
+
if (ast.typ == 2 /* NodeType.StyleSheetNodeType */) {
|
|
347
|
+
let parent;
|
|
348
|
+
let parents = [ast];
|
|
349
|
+
while (parents.length > 0) {
|
|
350
|
+
parent = parents.shift();
|
|
351
|
+
// @ts-ignore
|
|
352
|
+
for (let k = 0; k < parent.chi.length; k++) {
|
|
353
|
+
// @ts-ignore
|
|
354
|
+
const node = parent.chi[k];
|
|
355
|
+
if (!('chi' in node) || node.typ == 2 /* NodeType.StyleSheetNodeType */ || (node.typ == 3 /* NodeType.AtRuleNodeType */ && node.nam == 'font-face')) {
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
// @ts-ignore
|
|
359
|
+
if (node.chi.length > 0) {
|
|
360
|
+
parents.push(node);
|
|
361
|
+
Object.defineProperty(node, 'parent', { ...definedPropertySettings, value: parent });
|
|
362
|
+
for (const feature of options.features) {
|
|
363
|
+
feature.run(node, options, parent, context);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
// @ts-ignore
|
|
367
|
+
if (options.removeEmpty && node.chi.length == 0) {
|
|
368
|
+
// @ts-ignore
|
|
369
|
+
parent.chi.splice(k, 1);
|
|
370
|
+
k--;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
for (const feature of options.features) {
|
|
375
|
+
if ('cleanup' in feature) {
|
|
376
|
+
// @ts-ignore
|
|
377
|
+
feature.cleanup(ast, options, context);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
628
381
|
return ast;
|
|
629
382
|
}
|
|
630
383
|
function reduceSelector(selector) {
|
|
@@ -710,37 +463,14 @@ function hasDeclaration(node) {
|
|
|
710
463
|
// @ts-ignore
|
|
711
464
|
for (let i = 0; i < node.chi?.length; i++) {
|
|
712
465
|
// @ts-ignore
|
|
713
|
-
if (node.chi[i].typ ==
|
|
466
|
+
if (node.chi[i].typ == 0 /* NodeType.CommentNodeType */) {
|
|
714
467
|
continue;
|
|
715
468
|
}
|
|
716
469
|
// @ts-ignore
|
|
717
|
-
return node.chi[i].typ ==
|
|
470
|
+
return node.chi[i].typ == 5 /* NodeType.DeclarationNodeType */;
|
|
718
471
|
}
|
|
719
472
|
return true;
|
|
720
473
|
}
|
|
721
|
-
function minifyRule(ast) {
|
|
722
|
-
// @ts-ignore
|
|
723
|
-
if (!('chi' in ast) || ast.chi?.length <= 1) {
|
|
724
|
-
return ast;
|
|
725
|
-
}
|
|
726
|
-
// @ts-ignore
|
|
727
|
-
const j = ast.chi.length;
|
|
728
|
-
let k = 0;
|
|
729
|
-
let properties = new PropertyList();
|
|
730
|
-
// @ts-ignore
|
|
731
|
-
for (; k < j; k++) {
|
|
732
|
-
// @ts-ignore
|
|
733
|
-
const node = ast.chi[k];
|
|
734
|
-
if (node.typ == 'Comment' || node.typ == 'Declaration') {
|
|
735
|
-
properties.add(node);
|
|
736
|
-
continue;
|
|
737
|
-
}
|
|
738
|
-
break;
|
|
739
|
-
}
|
|
740
|
-
// @ts-ignore
|
|
741
|
-
ast.chi = [...properties].concat(ast.chi.slice(k));
|
|
742
|
-
return ast;
|
|
743
|
-
}
|
|
744
474
|
function splitRule(buffer) {
|
|
745
475
|
const result = [[]];
|
|
746
476
|
let str = '';
|
|
@@ -829,6 +559,300 @@ function splitRule(buffer) {
|
|
|
829
559
|
}
|
|
830
560
|
return result;
|
|
831
561
|
}
|
|
562
|
+
function matchSelectors(selector1, selector2, parentType, errors) {
|
|
563
|
+
let match = [[]];
|
|
564
|
+
const j = Math.min(selector1.reduce((acc, curr) => Math.min(acc, curr.length), selector1.length > 0 ? selector1[0].length : 0), selector2.reduce((acc, curr) => Math.min(acc, curr.length), selector2.length > 0 ? selector2[0].length : 0));
|
|
565
|
+
let i = 0;
|
|
566
|
+
let k;
|
|
567
|
+
let l;
|
|
568
|
+
let token;
|
|
569
|
+
let matching = true;
|
|
570
|
+
let matchFunction = 0;
|
|
571
|
+
let inAttr = 0;
|
|
572
|
+
for (; i < j; i++) {
|
|
573
|
+
k = 0;
|
|
574
|
+
token = selector1[0][i];
|
|
575
|
+
for (; k < selector1.length; k++) {
|
|
576
|
+
if (selector1[k][i] != token) {
|
|
577
|
+
matching = false;
|
|
578
|
+
break;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
if (matching) {
|
|
582
|
+
l = 0;
|
|
583
|
+
for (; l < selector2.length; l++) {
|
|
584
|
+
if (selector2[l][i] != token) {
|
|
585
|
+
matching = false;
|
|
586
|
+
break;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
if (!matching) {
|
|
591
|
+
break;
|
|
592
|
+
}
|
|
593
|
+
if (token == ',') {
|
|
594
|
+
match.push([]);
|
|
595
|
+
}
|
|
596
|
+
else {
|
|
597
|
+
if (token.endsWith('(')) {
|
|
598
|
+
matchFunction++;
|
|
599
|
+
}
|
|
600
|
+
if (token.endsWith('[')) {
|
|
601
|
+
inAttr++;
|
|
602
|
+
}
|
|
603
|
+
else if (token == ')') {
|
|
604
|
+
matchFunction--;
|
|
605
|
+
}
|
|
606
|
+
else if (token == ']') {
|
|
607
|
+
inAttr--;
|
|
608
|
+
}
|
|
609
|
+
match.at(-1).push(token);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
// invalid function
|
|
613
|
+
if (matchFunction != 0 || inAttr != 0) {
|
|
614
|
+
return null;
|
|
615
|
+
}
|
|
616
|
+
if (parentType != 4 /* NodeType.RuleNodeType */) {
|
|
617
|
+
for (const part of match) {
|
|
618
|
+
if (part.length > 0 && combinators.includes(part[0].charAt(0))) {
|
|
619
|
+
return null;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
if (match.length > 1) {
|
|
624
|
+
errors?.push({
|
|
625
|
+
action: 'ignore',
|
|
626
|
+
message: `minify: unsupported multilevel matching\n${JSON.stringify({
|
|
627
|
+
match,
|
|
628
|
+
selector1,
|
|
629
|
+
selector2
|
|
630
|
+
}, null, 1)}`
|
|
631
|
+
});
|
|
632
|
+
return null;
|
|
633
|
+
}
|
|
634
|
+
for (const part of match) {
|
|
635
|
+
while (part.length > 0) {
|
|
636
|
+
const token = part.at(-1);
|
|
637
|
+
if (token == ' ' || combinators.includes(token) || notEndingWith.includes(token.at(-1))) {
|
|
638
|
+
part.pop();
|
|
639
|
+
continue;
|
|
640
|
+
}
|
|
641
|
+
break;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
if (match.every(t => t.length == 0)) {
|
|
645
|
+
return null;
|
|
646
|
+
}
|
|
647
|
+
if (eq([['&']], match)) {
|
|
648
|
+
return null;
|
|
649
|
+
}
|
|
650
|
+
function reduce(acc, curr) {
|
|
651
|
+
if (acc === null) {
|
|
652
|
+
return null;
|
|
653
|
+
}
|
|
654
|
+
let hasCompoundSelector = true;
|
|
655
|
+
curr = curr.slice(match[0].length);
|
|
656
|
+
while (curr.length > 0) {
|
|
657
|
+
if (curr[0] == ' ') {
|
|
658
|
+
hasCompoundSelector = false;
|
|
659
|
+
curr.unshift('&');
|
|
660
|
+
continue;
|
|
661
|
+
}
|
|
662
|
+
break;
|
|
663
|
+
}
|
|
664
|
+
// invalid function match
|
|
665
|
+
if (curr.length > 0 && curr[0].endsWith('(') && curr.at(-1) != ')') {
|
|
666
|
+
return null;
|
|
667
|
+
}
|
|
668
|
+
if (curr.length == 1 && combinators.includes(curr[0].charAt(0))) {
|
|
669
|
+
return null;
|
|
670
|
+
}
|
|
671
|
+
if (hasCompoundSelector && curr.length > 0) {
|
|
672
|
+
hasCompoundSelector = !['&'].concat(combinators).includes(curr[0].charAt(0));
|
|
673
|
+
}
|
|
674
|
+
if (curr[0] == ':is(') {
|
|
675
|
+
let inFunction = 0;
|
|
676
|
+
let canReduce = true;
|
|
677
|
+
const isCompound = curr.reduce((acc, token, index) => {
|
|
678
|
+
if (index == 0) {
|
|
679
|
+
inFunction++;
|
|
680
|
+
canReduce = curr[1] == '&';
|
|
681
|
+
}
|
|
682
|
+
else if (token.endsWith('(')) {
|
|
683
|
+
if (inFunction == 0) {
|
|
684
|
+
canReduce = false;
|
|
685
|
+
}
|
|
686
|
+
inFunction++;
|
|
687
|
+
}
|
|
688
|
+
else if (token == ')') {
|
|
689
|
+
inFunction--;
|
|
690
|
+
}
|
|
691
|
+
else if (token == ',') {
|
|
692
|
+
if (!canReduce) {
|
|
693
|
+
canReduce = curr[index + 1] == '&';
|
|
694
|
+
}
|
|
695
|
+
acc.push([]);
|
|
696
|
+
}
|
|
697
|
+
else
|
|
698
|
+
acc.at(-1)?.push(token);
|
|
699
|
+
return acc;
|
|
700
|
+
}, [[]]);
|
|
701
|
+
if (inFunction > 0) {
|
|
702
|
+
canReduce = false;
|
|
703
|
+
}
|
|
704
|
+
if (canReduce) {
|
|
705
|
+
curr = isCompound.reduce((acc, curr) => {
|
|
706
|
+
if (acc.length > 0) {
|
|
707
|
+
acc.push(',');
|
|
708
|
+
}
|
|
709
|
+
acc.push(...curr);
|
|
710
|
+
return acc;
|
|
711
|
+
}, []);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
// @todo: check hasCompoundSelector && curr[0] == '&' && curr[1] == ' '
|
|
715
|
+
acc.push(match.length == 0 ? ['&'] : (hasCompoundSelector && curr[0] != '&' && (curr.length == 0 || !combinators.includes(curr[0].charAt(0))) ? ['&'].concat(curr) : curr));
|
|
716
|
+
return acc;
|
|
717
|
+
}
|
|
718
|
+
// @ts-ignore
|
|
719
|
+
selector1 = selector1.reduce(reduce, []);
|
|
720
|
+
// @ts-ignore
|
|
721
|
+
selector2 = selector2.reduce(reduce, []);
|
|
722
|
+
return selector1 == null || selector2 == null ? null : {
|
|
723
|
+
eq: eq(selector1, selector2),
|
|
724
|
+
match,
|
|
725
|
+
selector1,
|
|
726
|
+
selector2
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
function fixSelector(node) {
|
|
730
|
+
// @ts-ignore
|
|
731
|
+
if (node.sel.includes('&')) {
|
|
732
|
+
const attributes = parseString(node.sel);
|
|
733
|
+
for (const attr of walkValues(attributes)) {
|
|
734
|
+
if (attr.value.typ == EnumToken.PseudoClassFuncTokenType && attr.value.val == ':is') {
|
|
735
|
+
let i = attr.value.chi.length;
|
|
736
|
+
while (i--) {
|
|
737
|
+
if (attr.value.chi[i].typ == EnumToken.LiteralTokenType && attr.value.chi[i].val == '&') {
|
|
738
|
+
attr.value.chi.splice(i, 1);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
node.sel = attributes.reduce((acc, curr) => acc + renderToken(curr), '');
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
function wrapNodes(previous, node, match, ast, reducer, i, nodeIndex) {
|
|
747
|
+
// @ts-ignore
|
|
748
|
+
let pSel = match.selector1.reduce(reducer, []).join(',');
|
|
749
|
+
// @ts-ignore
|
|
750
|
+
let nSel = match.selector2.reduce(reducer, []).join(',');
|
|
751
|
+
// @ts-ignore
|
|
752
|
+
const wrapper = { ...previous, chi: [], sel: match.match.reduce(reducer, []).join(',') };
|
|
753
|
+
// @ts-ignore
|
|
754
|
+
Object.defineProperty(wrapper, 'raw', {
|
|
755
|
+
...definedPropertySettings,
|
|
756
|
+
// @ts-ignore
|
|
757
|
+
value: match.match.map(t => t.slice())
|
|
758
|
+
});
|
|
759
|
+
if (pSel == '&' || pSel === '') {
|
|
760
|
+
// @ts-ignore
|
|
761
|
+
wrapper.chi.push(...previous.chi);
|
|
762
|
+
// @ts-ignore
|
|
763
|
+
if ((nSel == '&' || nSel === '')) {
|
|
764
|
+
// @ts-ignore
|
|
765
|
+
wrapper.chi.push(...node.chi);
|
|
766
|
+
}
|
|
767
|
+
else {
|
|
768
|
+
// @ts-ignore
|
|
769
|
+
wrapper.chi.push(node);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
else {
|
|
773
|
+
// @ts-ignore
|
|
774
|
+
wrapper.chi.push(previous, node);
|
|
775
|
+
}
|
|
776
|
+
// @ts-ignore
|
|
777
|
+
ast.chi.splice(i, 1, wrapper);
|
|
778
|
+
// @ts-ignore
|
|
779
|
+
ast.chi.splice(nodeIndex, 1);
|
|
780
|
+
// @ts-ignore
|
|
781
|
+
previous.sel = pSel;
|
|
782
|
+
// @ts-ignore
|
|
783
|
+
previous.raw = match.selector1;
|
|
784
|
+
// @ts-ignore
|
|
785
|
+
node.sel = nSel;
|
|
786
|
+
// @ts-ignore
|
|
787
|
+
node.raw = match.selector2;
|
|
788
|
+
reduceRuleSelector(wrapper);
|
|
789
|
+
return wrapper;
|
|
790
|
+
}
|
|
791
|
+
function diff(n1, n2, reducer, options = {}) {
|
|
792
|
+
let node1 = n1;
|
|
793
|
+
let node2 = n2;
|
|
794
|
+
let exchanged = false;
|
|
795
|
+
if (node1.chi.length > node2.chi.length) {
|
|
796
|
+
const t = node1;
|
|
797
|
+
node1 = node2;
|
|
798
|
+
node2 = t;
|
|
799
|
+
exchanged = true;
|
|
800
|
+
}
|
|
801
|
+
let i = node1.chi.length;
|
|
802
|
+
let j = node2.chi.length;
|
|
803
|
+
if (i == 0 || j == 0) {
|
|
804
|
+
// @ts-ignore
|
|
805
|
+
return null;
|
|
806
|
+
}
|
|
807
|
+
// @ts-ignore
|
|
808
|
+
const raw1 = node1.raw;
|
|
809
|
+
// @ts-ignore
|
|
810
|
+
const raw2 = node2.raw;
|
|
811
|
+
// @ts-ignore
|
|
812
|
+
node1 = { ...node1, chi: node1.chi.slice() };
|
|
813
|
+
node2 = { ...node2, chi: node2.chi.slice() };
|
|
814
|
+
if (raw1 != null) {
|
|
815
|
+
Object.defineProperty(node1, 'raw', { ...definedPropertySettings, value: raw1 });
|
|
816
|
+
}
|
|
817
|
+
if (raw2 != null) {
|
|
818
|
+
Object.defineProperty(node2, 'raw', { ...definedPropertySettings, value: raw2 });
|
|
819
|
+
}
|
|
820
|
+
const intersect = [];
|
|
821
|
+
while (i--) {
|
|
822
|
+
if (node1.chi[i].typ == 0 /* NodeType.CommentNodeType */) {
|
|
823
|
+
continue;
|
|
824
|
+
}
|
|
825
|
+
j = node2.chi.length;
|
|
826
|
+
if (j == 0) {
|
|
827
|
+
break;
|
|
828
|
+
}
|
|
829
|
+
while (j--) {
|
|
830
|
+
if (node2.chi[j].typ == 0 /* NodeType.CommentNodeType */) {
|
|
831
|
+
continue;
|
|
832
|
+
}
|
|
833
|
+
if (node1.chi[i].nam == node2.chi[j].nam) {
|
|
834
|
+
if (eq(node1.chi[i], node2.chi[j])) {
|
|
835
|
+
intersect.push(node1.chi[i]);
|
|
836
|
+
node1.chi.splice(i, 1);
|
|
837
|
+
node2.chi.splice(j, 1);
|
|
838
|
+
break;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
// @ts-ignore
|
|
844
|
+
const result = (intersect.length == 0 ? null : {
|
|
845
|
+
...node1,
|
|
846
|
+
// @ts-ignore
|
|
847
|
+
sel: [...new Set([...(n1?.raw?.reduce(reducer, []) || splitRule(n1.sel)).concat(n2?.raw?.reduce(reducer, []) || splitRule(n2.sel))])].join(','),
|
|
848
|
+
chi: intersect.reverse()
|
|
849
|
+
});
|
|
850
|
+
if (result == null || [n1, n2].reduce((acc, curr) => curr.chi.length == 0 ? acc : acc + doRender(curr, options).code.length, 0) <= [node1, node2, result].reduce((acc, curr) => curr.chi.length == 0 ? acc : acc + doRender(curr, options).code.length, 0)) {
|
|
851
|
+
// @ts-ignore
|
|
852
|
+
return null;
|
|
853
|
+
}
|
|
854
|
+
return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node1 : node2 };
|
|
855
|
+
}
|
|
832
856
|
function reduceRuleSelector(node) {
|
|
833
857
|
if (node.raw == null) {
|
|
834
858
|
Object.defineProperty(node, 'raw', { ...definedPropertySettings, value: splitRule(node.sel) });
|
|
@@ -864,4 +888,4 @@ function reduceRuleSelector(node) {
|
|
|
864
888
|
}
|
|
865
889
|
}
|
|
866
890
|
|
|
867
|
-
export { combinators, hasDeclaration, minify,
|
|
891
|
+
export { combinators, hasDeclaration, minify, reduceSelector, splitRule };
|