@tbela99/css-parser 0.0.1-alpha3 → 0.0.1-alpha4
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 +0 -6
- package/dist/index-umd-web.js +352 -146
- package/dist/index.cjs +350 -144
- package/dist/index.d.ts +8 -1
- package/dist/index.js +1 -1
- package/dist/lib/parser/deduplicate.js +250 -30
- package/dist/lib/parser/parse.js +72 -94
- package/dist/lib/parser/utils/syntax.js +7 -2
- package/dist/lib/renderer/render.js +21 -16
- package/dist/node/index.js +2 -4
- package/dist/web/index.js +5 -7
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -191,6 +191,7 @@ interface ParserOptions {
|
|
|
191
191
|
src?: string;
|
|
192
192
|
sourcemap?: boolean;
|
|
193
193
|
compress?: boolean;
|
|
194
|
+
nestingRules?: boolean;
|
|
194
195
|
removeEmpty?: boolean;
|
|
195
196
|
resolveUrls?: boolean;
|
|
196
197
|
resolveImport?: boolean;
|
|
@@ -304,6 +305,12 @@ type AstNode =
|
|
|
304
305
|
declare function deduplicate(ast: AstNode, options?: ParserOptions, recursive?: boolean): AstNode;
|
|
305
306
|
declare function hasDeclaration(node: AstAtRule | AstRule | AstRuleList): boolean;
|
|
306
307
|
declare function deduplicateRule(ast: AstNode, options?: ParserOptions): AstNode;
|
|
308
|
+
declare function reduceSelector(selector: string[][]): null | {
|
|
309
|
+
match: boolean;
|
|
310
|
+
optimized: string[];
|
|
311
|
+
selector: string[][];
|
|
312
|
+
reducible: boolean;
|
|
313
|
+
};
|
|
307
314
|
|
|
308
315
|
declare function render(data: AstNode, opt?: RenderOptions): RenderResult;
|
|
309
316
|
declare function renderToken(token: Token, options?: RenderOptions): string;
|
|
@@ -326,4 +333,4 @@ declare function resolve(url: string, currentDirectory: string, cwd?: string): {
|
|
|
326
333
|
declare function parse(iterator: string, opt?: ParserOptions): Promise<ParseResult>;
|
|
327
334
|
declare function transform(css: string, options?: TransformOptions): Promise<TransformResult>;
|
|
328
335
|
|
|
329
|
-
export { deduplicate, deduplicateRule, dirname, hasDeclaration, load, matchUrl, parse, render, renderToken, resolve, transform, walk };
|
|
336
|
+
export { deduplicate, deduplicateRule, dirname, hasDeclaration, load, matchUrl, parse, reduceSelector, render, renderToken, resolve, transform, walk };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { parse, transform } from './node/index.js';
|
|
2
|
-
export { deduplicate, deduplicateRule, hasDeclaration } from './lib/parser/deduplicate.js';
|
|
2
|
+
export { deduplicate, deduplicateRule, hasDeclaration, reduceSelector } from './lib/parser/deduplicate.js';
|
|
3
3
|
export { render, renderToken } from './lib/renderer/render.js';
|
|
4
4
|
export { walk } from './lib/walker/walk.js';
|
|
5
5
|
export { load } from './node/load.js';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { PropertyList } from './declaration/list.js';
|
|
2
2
|
import { eq } from './utils/eq.js';
|
|
3
|
+
import { isIdentStart } from './utils/syntax.js';
|
|
3
4
|
import { getConfig } from './utils/config.js';
|
|
4
5
|
import { render } from '../renderer/render.js';
|
|
5
6
|
|
|
@@ -29,6 +30,125 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
29
30
|
continue;
|
|
30
31
|
}
|
|
31
32
|
// @ts-ignore
|
|
33
|
+
if (node.typ == 'Rule') {
|
|
34
|
+
reduceRuleSelector(node);
|
|
35
|
+
// @ts-ignore
|
|
36
|
+
if (options.nestingRules && node.raw != null && previous?.raw != null && node.raw.length == 1 && previous.raw.length == 1) {
|
|
37
|
+
const match = [];
|
|
38
|
+
// @ts-ignore
|
|
39
|
+
while (node.raw[0].length > 0 && previous.raw[0].length > 0) {
|
|
40
|
+
// @ts-ignore
|
|
41
|
+
if (node.raw[0][0] != previous.raw[0][0]) {
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
// @ts-ignore
|
|
45
|
+
match.push(node.raw[0].shift());
|
|
46
|
+
// @ts-ignore
|
|
47
|
+
previous.raw[0].shift();
|
|
48
|
+
}
|
|
49
|
+
if (match.length > 0) {
|
|
50
|
+
// @ts-ignore
|
|
51
|
+
const wrapper = { ...previous, chi: [] };
|
|
52
|
+
// @ts-ignore
|
|
53
|
+
if (previous.raw[0].length == 0) {
|
|
54
|
+
// @ts-ignore
|
|
55
|
+
wrapper.chi.push(...previous.chi);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
// @ts-ignore
|
|
59
|
+
previous.sel = previous.raw.reduce((acc, curr) => {
|
|
60
|
+
acc.push(curr.join(''));
|
|
61
|
+
return acc;
|
|
62
|
+
}, []).join(',');
|
|
63
|
+
// @ts-ignore
|
|
64
|
+
wrapper.chi.push(previous);
|
|
65
|
+
}
|
|
66
|
+
// @ts-ignore
|
|
67
|
+
if (node.raw[0].length == 0) {
|
|
68
|
+
// @ts-ignore
|
|
69
|
+
if (previous.raw.length == 0) {
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
wrapper.chi.push(...node.chi);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
if (hasOnlyDeclarations(wrapper)) {
|
|
75
|
+
wrapper.chi.push(...node.chi);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// @ts-ignore
|
|
79
|
+
node.raw[0].push('&');
|
|
80
|
+
// @ts-ignore
|
|
81
|
+
node.sel = node.raw.reduce((acc, curr) => {
|
|
82
|
+
acc.push(curr.join(''));
|
|
83
|
+
return acc;
|
|
84
|
+
}, []).join(',');
|
|
85
|
+
// @ts-ignore
|
|
86
|
+
wrapper.chi.push(node);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// @ts-ignore
|
|
92
|
+
node.sel = node.raw.reduce((acc, curr) => {
|
|
93
|
+
acc.push(curr.join(''));
|
|
94
|
+
return acc;
|
|
95
|
+
}, []).join(',');
|
|
96
|
+
// @ts-ignore
|
|
97
|
+
wrapper.chi.push(node);
|
|
98
|
+
}
|
|
99
|
+
Object.defineProperty(wrapper, 'raw', { enumerable: false, writable: true, value: [match] });
|
|
100
|
+
// @ts-ignore
|
|
101
|
+
ast.chi.splice(i, 1, wrapper);
|
|
102
|
+
// @ts-ignore
|
|
103
|
+
ast.chi.splice(nodeIndex, 1);
|
|
104
|
+
// @ts-ignore
|
|
105
|
+
while (i < ast.chi.length) {
|
|
106
|
+
// @ts-ignore
|
|
107
|
+
const nextNode = ast.chi[i];
|
|
108
|
+
// @ts-ignore
|
|
109
|
+
if (nextNode.typ != 'Rule' || nextNode.raw == null) {
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
reduceRuleSelector(nextNode);
|
|
113
|
+
// @ts-ignore
|
|
114
|
+
if (nextNode.raw.length != 1 || !eq(wrapper.raw[0], nextNode.raw[0].slice(0, wrapper.raw[0].length))) {
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
// @ts-ignore
|
|
118
|
+
nextNode.raw[0].splice(0, wrapper.raw[0].length);
|
|
119
|
+
// @ts-ignore
|
|
120
|
+
if (nextNode.raw[0].length == 0 ||
|
|
121
|
+
// @ts-ignore
|
|
122
|
+
(nextNode.raw.length == 1 && nextNode.raw[0] == '&')) {
|
|
123
|
+
if (hasOnlyDeclarations(wrapper)) {
|
|
124
|
+
wrapper.chi.push(...nextNode.chi);
|
|
125
|
+
// @ts-ignore
|
|
126
|
+
ast.chi.splice(i, 1);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
// @ts-ignore
|
|
131
|
+
nextNode.raw[0].push('&');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// @ts-ignore
|
|
135
|
+
nextNode.sel = nextNode.raw.reduce((acc, curr) => {
|
|
136
|
+
acc.push(curr.join(''));
|
|
137
|
+
return acc;
|
|
138
|
+
}, []).join(',');
|
|
139
|
+
wrapper.chi.push(nextNode);
|
|
140
|
+
// @ts-ignore
|
|
141
|
+
ast.chi.splice(i, 1);
|
|
142
|
+
}
|
|
143
|
+
deduplicateRule(wrapper);
|
|
144
|
+
nodeIndex = --i;
|
|
145
|
+
// @ts-ignore
|
|
146
|
+
previous = ast.chi[i];
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// @ts-ignore
|
|
32
152
|
if (previous != null && 'chi' in previous && ('chi' in node)) {
|
|
33
153
|
// @ts-ignore
|
|
34
154
|
if (previous.typ == node.typ) {
|
|
@@ -48,7 +168,7 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
48
168
|
// @ts-ignore
|
|
49
169
|
if ((node.typ == 'Rule' && node.sel == previous.sel) ||
|
|
50
170
|
// @ts-ignore
|
|
51
|
-
(node.typ == 'AtRule') && node.val == previous.val) {
|
|
171
|
+
(node.typ == 'AtRule') && node.val != 'font-face' && node.val == previous.val) {
|
|
52
172
|
// @ts-ignore
|
|
53
173
|
node.chi.unshift(...previous.chi);
|
|
54
174
|
// @ts-ignore
|
|
@@ -70,19 +190,26 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
70
190
|
if (intersect != null) {
|
|
71
191
|
if (intersect.node1.chi.length == 0) {
|
|
72
192
|
// @ts-ignore
|
|
73
|
-
ast.chi.splice(i
|
|
193
|
+
ast.chi.splice(i--, 1);
|
|
194
|
+
// @ts-ignore
|
|
195
|
+
node = ast.chi[i];
|
|
74
196
|
}
|
|
75
197
|
else {
|
|
76
198
|
// @ts-ignore
|
|
77
199
|
ast.chi.splice(i, 1, intersect.node1);
|
|
200
|
+
node = intersect.node1;
|
|
78
201
|
}
|
|
79
202
|
if (intersect.node2.chi.length == 0) {
|
|
80
203
|
// @ts-ignore
|
|
81
204
|
ast.chi.splice(nodeIndex, 1, intersect.result);
|
|
205
|
+
previous = intersect.result;
|
|
82
206
|
}
|
|
83
207
|
else {
|
|
84
208
|
// @ts-ignore
|
|
85
209
|
ast.chi.splice(nodeIndex, 1, intersect.result, intersect.node2);
|
|
210
|
+
previous = intersect.result;
|
|
211
|
+
// @ts-ignore
|
|
212
|
+
i = nodeIndex;
|
|
86
213
|
}
|
|
87
214
|
}
|
|
88
215
|
}
|
|
@@ -109,12 +236,24 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
109
236
|
deduplicateRule(node);
|
|
110
237
|
}
|
|
111
238
|
else {
|
|
112
|
-
|
|
239
|
+
if (!(node.typ == 'AtRule' && node.nam != 'font-face')) {
|
|
240
|
+
deduplicate(node, options, recursive);
|
|
241
|
+
}
|
|
113
242
|
}
|
|
114
243
|
}
|
|
115
244
|
}
|
|
116
245
|
return ast;
|
|
117
246
|
}
|
|
247
|
+
function hasOnlyDeclarations(node) {
|
|
248
|
+
let k = node.chi.length;
|
|
249
|
+
while (k--) {
|
|
250
|
+
if (node.chi[k].typ == 'Comment') {
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
return node.chi[k].typ == 'Declaration';
|
|
254
|
+
}
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
118
257
|
function hasDeclaration(node) {
|
|
119
258
|
// @ts-ignore
|
|
120
259
|
for (let i = 0; i < node.chi?.length; i++) {
|
|
@@ -174,30 +313,6 @@ function deduplicateRule(ast, options = {}) {
|
|
|
174
313
|
}
|
|
175
314
|
// @ts-ignore
|
|
176
315
|
ast.chi = children.concat(ast.chi?.slice(k));
|
|
177
|
-
/*
|
|
178
|
-
// @ts-ignore
|
|
179
|
-
|
|
180
|
-
const properties: PropertyList = new PropertyList();
|
|
181
|
-
|
|
182
|
-
for (; k < j; k++) {
|
|
183
|
-
|
|
184
|
-
// @ts-ignore
|
|
185
|
-
if ('Comment' == ast.chi[k].typ || 'Declaration' == ast.chi[k].typ) {
|
|
186
|
-
|
|
187
|
-
// @ts-ignore
|
|
188
|
-
properties.add(ast.chi[k]);
|
|
189
|
-
continue;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
break;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// @ts-ignore
|
|
196
|
-
ast.chi = [...properties].concat(ast.chi.slice(k));
|
|
197
|
-
*/
|
|
198
|
-
//
|
|
199
|
-
// @ts-ignore
|
|
200
|
-
// ast.chi.splice(0, k - 1, ...properties);
|
|
201
316
|
return ast;
|
|
202
317
|
}
|
|
203
318
|
function splitRule(buffer) {
|
|
@@ -256,7 +371,6 @@ function splitRule(buffer) {
|
|
|
256
371
|
}
|
|
257
372
|
}
|
|
258
373
|
i = k;
|
|
259
|
-
continue;
|
|
260
374
|
}
|
|
261
375
|
}
|
|
262
376
|
if (str !== '') {
|
|
@@ -264,6 +378,35 @@ function splitRule(buffer) {
|
|
|
264
378
|
}
|
|
265
379
|
return result;
|
|
266
380
|
}
|
|
381
|
+
function reduceRuleSelector(node) {
|
|
382
|
+
// @ts-ignore
|
|
383
|
+
if (node.raw != null) {
|
|
384
|
+
// @ts-ignore
|
|
385
|
+
let optimized = reduceSelector(node.raw);
|
|
386
|
+
if (optimized != null) {
|
|
387
|
+
Object.defineProperty(node, 'optimized', { enumerable: false, writable: true, value: optimized });
|
|
388
|
+
}
|
|
389
|
+
if (optimized != null && optimized.match && optimized.reducible) {
|
|
390
|
+
const raw = [
|
|
391
|
+
[
|
|
392
|
+
optimized.optimized[0], ':is('
|
|
393
|
+
].concat(optimized.selector.reduce((acc, curr) => {
|
|
394
|
+
if (acc.length > 0) {
|
|
395
|
+
acc.push(',');
|
|
396
|
+
}
|
|
397
|
+
acc.push(...curr);
|
|
398
|
+
return acc;
|
|
399
|
+
}, [])).concat(')')
|
|
400
|
+
];
|
|
401
|
+
const sel = raw[0].join('');
|
|
402
|
+
if (sel.length < node.sel.length) {
|
|
403
|
+
node.sel = sel;
|
|
404
|
+
// node.raw = raw;
|
|
405
|
+
Object.defineProperty(node, 'raw', { enumerable: false, writable: true, value: raw });
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
267
410
|
function diff(n1, n2, options = {}) {
|
|
268
411
|
let node1 = n1;
|
|
269
412
|
let node2 = n2;
|
|
@@ -280,8 +423,28 @@ function diff(n1, n2, options = {}) {
|
|
|
280
423
|
// @ts-ignore
|
|
281
424
|
return null;
|
|
282
425
|
}
|
|
426
|
+
// @ts-ignore
|
|
427
|
+
const raw1 = node1.raw;
|
|
428
|
+
// @ts-ignore
|
|
429
|
+
const optimized1 = node1.optimized;
|
|
430
|
+
// @ts-ignore
|
|
431
|
+
const raw2 = node2.raw;
|
|
432
|
+
// @ts-ignore
|
|
433
|
+
const optimized2 = node2.optimized;
|
|
283
434
|
node1 = { ...node1, chi: node1.chi.slice() };
|
|
284
435
|
node2 = { ...node2, chi: node2.chi.slice() };
|
|
436
|
+
if (raw1 != null) {
|
|
437
|
+
Object.defineProperty(node1, 'raw', { enumerable: false, writable: true, value: raw1 });
|
|
438
|
+
}
|
|
439
|
+
if (optimized1 != null) {
|
|
440
|
+
Object.defineProperty(node1, 'optimized', { enumerable: false, writable: true, value: optimized1 });
|
|
441
|
+
}
|
|
442
|
+
if (raw2 != null) {
|
|
443
|
+
Object.defineProperty(node2, 'raw', { enumerable: false, writable: true, value: raw2 });
|
|
444
|
+
}
|
|
445
|
+
if (optimized2 != null) {
|
|
446
|
+
Object.defineProperty(node2, 'optimized', { enumerable: false, writable: true, value: optimized2 });
|
|
447
|
+
}
|
|
285
448
|
const intersect = [];
|
|
286
449
|
while (i--) {
|
|
287
450
|
if (node1.chi[i].typ == 'Comment') {
|
|
@@ -309,7 +472,7 @@ function diff(n1, n2, options = {}) {
|
|
|
309
472
|
const result = (intersect.length == 0 ? null : {
|
|
310
473
|
...node1,
|
|
311
474
|
// @ts-ignore
|
|
312
|
-
sel: [...new Set([...(n1
|
|
475
|
+
sel: [...new Set([...(n1?.raw?.reduce(reducer, []) || splitRule(n1.sel)).concat(n2?.raw?.reduce(reducer, []) || splitRule(n2.sel))])].join(),
|
|
313
476
|
chi: intersect.reverse()
|
|
314
477
|
});
|
|
315
478
|
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)) {
|
|
@@ -318,5 +481,62 @@ function diff(n1, n2, options = {}) {
|
|
|
318
481
|
}
|
|
319
482
|
return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node2 : node2 };
|
|
320
483
|
}
|
|
484
|
+
function reduceSelector(selector) {
|
|
485
|
+
if (selector.length < 2) {
|
|
486
|
+
return null;
|
|
487
|
+
}
|
|
488
|
+
const optimized = [];
|
|
489
|
+
const k = selector.reduce((acc, curr) => acc == 0 ? curr.length : (curr.length == 0 ? acc : Math.min(acc, curr.length)), 0);
|
|
490
|
+
let i = 0;
|
|
491
|
+
let j;
|
|
492
|
+
let match;
|
|
493
|
+
for (; i < k; i++) {
|
|
494
|
+
const item = selector[0][i];
|
|
495
|
+
match = true;
|
|
496
|
+
for (j = 1; j < selector.length; j++) {
|
|
497
|
+
if (item != selector[j][i]) {
|
|
498
|
+
match = false;
|
|
499
|
+
break;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
if (!match) {
|
|
503
|
+
break;
|
|
504
|
+
}
|
|
505
|
+
optimized.push(item);
|
|
506
|
+
}
|
|
507
|
+
if (optimized.at(-1) == ' ') {
|
|
508
|
+
optimized.pop();
|
|
509
|
+
}
|
|
510
|
+
let reducible = optimized.length == 1;
|
|
511
|
+
if (optimized.length == 0) {
|
|
512
|
+
return { match: false, optimized, selector, reducible };
|
|
513
|
+
}
|
|
514
|
+
return {
|
|
515
|
+
match: true,
|
|
516
|
+
optimized,
|
|
517
|
+
selector: selector.reduce((acc, curr) => {
|
|
518
|
+
const slice = curr.slice(optimized.length);
|
|
519
|
+
// @ts-ignore
|
|
520
|
+
if (slice.length > 0 && slice[0] == ' ') {
|
|
521
|
+
slice.shift();
|
|
522
|
+
}
|
|
523
|
+
if (slice.length == 0) {
|
|
524
|
+
slice.push('&');
|
|
525
|
+
}
|
|
526
|
+
if (reducible) {
|
|
527
|
+
const chr = slice[0].charAt(0);
|
|
528
|
+
// @ts-ignore
|
|
529
|
+
reducible = chr == '.' || chr == ':' || isIdentStart(chr.codePointAt(0));
|
|
530
|
+
}
|
|
531
|
+
acc.push(slice);
|
|
532
|
+
return acc;
|
|
533
|
+
}, []),
|
|
534
|
+
reducible
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
function reducer(acc, curr) {
|
|
538
|
+
acc.push(curr.join(''));
|
|
539
|
+
return acc;
|
|
540
|
+
}
|
|
321
541
|
|
|
322
|
-
export { deduplicate, deduplicateRule, hasDeclaration };
|
|
542
|
+
export { deduplicate, deduplicateRule, hasDeclaration, reduceSelector };
|