@tbela99/css-parser 0.0.1-alpha3 → 0.0.1-alpha5
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/.gitattributes +2 -0
- package/README.md +2 -6
- package/dist/index-umd-web.js +649 -161
- package/dist/index.cjs +647 -159
- package/dist/index.d.ts +24 -6
- package/dist/index.js +1 -1
- package/dist/lib/parser/deduplicate.js +530 -35
- package/dist/lib/parser/parse.js +100 -98
- package/dist/lib/parser/utils/syntax.js +7 -2
- package/dist/lib/renderer/render.js +11 -23
- package/dist/lib/walker/walk.js +1 -1
- package/dist/node/index.js +2 -4
- package/dist/web/index.js +5 -7
- package/package.json +5 -4
package/dist/index.cjs
CHANGED
|
@@ -53,7 +53,7 @@ function isIdent(name) {
|
|
|
53
53
|
// -
|
|
54
54
|
if (codepoint == 0x2d) {
|
|
55
55
|
const nextCodepoint = name.charCodeAt(1);
|
|
56
|
-
if (nextCodepoint
|
|
56
|
+
if (Number.isNaN(nextCodepoint)) {
|
|
57
57
|
return false;
|
|
58
58
|
}
|
|
59
59
|
// -
|
|
@@ -102,6 +102,9 @@ function isNumber(name) {
|
|
|
102
102
|
let codepoint = name.charCodeAt(0);
|
|
103
103
|
let i = 0;
|
|
104
104
|
const j = name.length;
|
|
105
|
+
if (j == 1 && !isDigit(codepoint)) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
105
108
|
// '+' '-'
|
|
106
109
|
if ([0x2b, 0x2d].includes(codepoint)) {
|
|
107
110
|
i++;
|
|
@@ -245,7 +248,9 @@ function isNewLine(codepoint) {
|
|
|
245
248
|
return codepoint == 0xa || codepoint == 0xc || codepoint == 0xd;
|
|
246
249
|
}
|
|
247
250
|
function isWhiteSpace(codepoint) {
|
|
248
|
-
return codepoint == 0x9 || codepoint == 0x20 ||
|
|
251
|
+
return codepoint == 0x9 || codepoint == 0x20 ||
|
|
252
|
+
// isNewLine
|
|
253
|
+
codepoint == 0xa || codepoint == 0xc || codepoint == 0xd;
|
|
249
254
|
}
|
|
250
255
|
|
|
251
256
|
var properties = {
|
|
@@ -1450,7 +1455,6 @@ function hsl2rgb(h, s, l, a = null) {
|
|
|
1450
1455
|
return values;
|
|
1451
1456
|
}
|
|
1452
1457
|
|
|
1453
|
-
const indents = [];
|
|
1454
1458
|
function render(data, opt = {}) {
|
|
1455
1459
|
const options = Object.assign(opt.compress ? {
|
|
1456
1460
|
indent: '',
|
|
@@ -1468,24 +1472,12 @@ function render(data, opt = {}) {
|
|
|
1468
1472
|
return acc;
|
|
1469
1473
|
}
|
|
1470
1474
|
}
|
|
1471
|
-
if (options.compress && curr.typ == 'Whitespace') {
|
|
1472
|
-
if (original[index + 1]?.typ == 'Start-parens' ||
|
|
1473
|
-
(index > 0 && (original[index - 1].typ == 'Pseudo-class-func' ||
|
|
1474
|
-
original[index - 1].typ == 'End-parens' ||
|
|
1475
|
-
original[index - 1].typ == 'UrlFunc' ||
|
|
1476
|
-
original[index - 1].typ == 'Func' ||
|
|
1477
|
-
(original[index - 1].typ == 'Color' &&
|
|
1478
|
-
original[index - 1].kin != 'hex' &&
|
|
1479
|
-
original[index - 1].kin != 'lit')))) {
|
|
1480
|
-
return acc;
|
|
1481
|
-
}
|
|
1482
|
-
}
|
|
1483
1475
|
return acc + renderToken(curr, options);
|
|
1484
1476
|
}
|
|
1485
|
-
return { code: doRender(data, options, reducer) };
|
|
1477
|
+
return { code: doRender(data, options, reducer, 0) };
|
|
1486
1478
|
}
|
|
1487
1479
|
// @ts-ignore
|
|
1488
|
-
function doRender(data, options, reducer, level = 0) {
|
|
1480
|
+
function doRender(data, options, reducer, level = 0, indents = []) {
|
|
1489
1481
|
if (indents.length < level + 1) {
|
|
1490
1482
|
indents.push(options.indent.repeat(level));
|
|
1491
1483
|
}
|
|
@@ -1499,7 +1491,7 @@ function doRender(data, options, reducer, level = 0) {
|
|
|
1499
1491
|
return options.removeComments ? '' : data.val;
|
|
1500
1492
|
case 'StyleSheet':
|
|
1501
1493
|
return data.chi.reduce((css, node) => {
|
|
1502
|
-
const str = doRender(node, options, reducer, level);
|
|
1494
|
+
const str = doRender(node, options, reducer, level, indents);
|
|
1503
1495
|
if (str === '') {
|
|
1504
1496
|
return css;
|
|
1505
1497
|
}
|
|
@@ -1526,7 +1518,7 @@ function doRender(data, options, reducer, level = 0) {
|
|
|
1526
1518
|
str = `@${node.nam} ${node.val};`;
|
|
1527
1519
|
}
|
|
1528
1520
|
else {
|
|
1529
|
-
str = doRender(node, options, reducer, level + 1);
|
|
1521
|
+
str = doRender(node, options, reducer, level + 1, indents);
|
|
1530
1522
|
}
|
|
1531
1523
|
if (css === '') {
|
|
1532
1524
|
return str;
|
|
@@ -1534,8 +1526,7 @@ function doRender(data, options, reducer, level = 0) {
|
|
|
1534
1526
|
if (str === '') {
|
|
1535
1527
|
return css;
|
|
1536
1528
|
}
|
|
1537
|
-
|
|
1538
|
-
return `${css}${options.newLine}${indentSub}${str}`;
|
|
1529
|
+
return `${css}${options.newLine}${indentSub}${str}`;
|
|
1539
1530
|
}, '');
|
|
1540
1531
|
if (children.endsWith(';')) {
|
|
1541
1532
|
children = children.slice(0, -1);
|
|
@@ -1587,11 +1578,15 @@ function renderToken(token, options = {}) {
|
|
|
1587
1578
|
if (token.kin == 'hex' || token.kin == 'lit') {
|
|
1588
1579
|
return token.val;
|
|
1589
1580
|
}
|
|
1581
|
+
case 'Start-parens':
|
|
1582
|
+
if (!('chi' in token)) {
|
|
1583
|
+
return '(';
|
|
1584
|
+
}
|
|
1590
1585
|
case 'Func':
|
|
1591
1586
|
case 'UrlFunc':
|
|
1592
1587
|
case 'Pseudo-class-func':
|
|
1593
1588
|
// @ts-ignore
|
|
1594
|
-
return (options.compress && 'Pseudo-class-func' == token.typ && token.val.slice(0, 2) == '::' ? token.val.slice(1)
|
|
1589
|
+
return ( /* options.compress && 'Pseudo-class-func' == token.typ && token.val.slice(0, 2) == '::' ? token.val.slice(1) :*/token.val ?? '') + '(' + token.chi.reduce((acc, curr) => {
|
|
1595
1590
|
if (options.removeComments && curr.typ == 'Comment') {
|
|
1596
1591
|
if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
|
|
1597
1592
|
return acc;
|
|
@@ -1607,8 +1602,6 @@ function renderToken(token, options = {}) {
|
|
|
1607
1602
|
return '<';
|
|
1608
1603
|
case 'Gt':
|
|
1609
1604
|
return '>';
|
|
1610
|
-
case 'Start-parens':
|
|
1611
|
-
return '(';
|
|
1612
1605
|
case 'End-parens':
|
|
1613
1606
|
return ')';
|
|
1614
1607
|
case 'Attr-start':
|
|
@@ -1684,7 +1677,7 @@ function renderToken(token, options = {}) {
|
|
|
1684
1677
|
case 'String':
|
|
1685
1678
|
case 'Iden':
|
|
1686
1679
|
case 'Delim':
|
|
1687
|
-
return options.compress && 'Pseudo-class' == token.typ && '::' == token.val.slice(0, 2) ? token.val.slice(1) : token.val;
|
|
1680
|
+
return /* options.compress && 'Pseudo-class' == token.typ && '::' == token.val.slice(0, 2) ? token.val.slice(1) : */ token.val;
|
|
1688
1681
|
}
|
|
1689
1682
|
throw new Error(`unexpected token ${JSON.stringify(token, null, 1)}`);
|
|
1690
1683
|
}
|
|
@@ -2245,6 +2238,54 @@ class PropertyList {
|
|
|
2245
2238
|
}
|
|
2246
2239
|
|
|
2247
2240
|
const configuration = getConfig();
|
|
2241
|
+
const combinators = ['+', '>', '~'];
|
|
2242
|
+
const notEndingWith = ['(', '['].concat(combinators);
|
|
2243
|
+
function wrapNodes(previous, node, match, ast, i, nodeIndex) {
|
|
2244
|
+
// @ts-ignore
|
|
2245
|
+
let pSel = match.selector1.reduce(reducer, []).join(',');
|
|
2246
|
+
// @ts-ignore
|
|
2247
|
+
let nSel = match.selector2.reduce(reducer, []).join(',');
|
|
2248
|
+
// @ts-ignore
|
|
2249
|
+
const wrapper = { ...previous, chi: [], sel: match.match.reduce(reducer, []).join(',') };
|
|
2250
|
+
// @ts-ignore
|
|
2251
|
+
Object.defineProperty(wrapper, 'raw', {
|
|
2252
|
+
enumerable: false,
|
|
2253
|
+
writable: true,
|
|
2254
|
+
// @ts-ignore
|
|
2255
|
+
value: match.match.map(t => t.slice())
|
|
2256
|
+
});
|
|
2257
|
+
if (pSel == '&' || pSel === '') {
|
|
2258
|
+
// @ts-ignore
|
|
2259
|
+
wrapper.chi.push(...previous.chi);
|
|
2260
|
+
// @ts-ignore
|
|
2261
|
+
if ((nSel == '&' || nSel === '') && hasOnlyDeclarations(previous)) {
|
|
2262
|
+
// @ts-ignore
|
|
2263
|
+
wrapper.chi.push(...node.chi);
|
|
2264
|
+
}
|
|
2265
|
+
else {
|
|
2266
|
+
// @ts-ignore
|
|
2267
|
+
wrapper.chi.push(node);
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
else {
|
|
2271
|
+
// @ts-ignore
|
|
2272
|
+
wrapper.chi.push(previous, node);
|
|
2273
|
+
}
|
|
2274
|
+
// @ts-ignore
|
|
2275
|
+
ast.chi.splice(i, 1, wrapper);
|
|
2276
|
+
// @ts-ignore
|
|
2277
|
+
ast.chi.splice(nodeIndex, 1);
|
|
2278
|
+
// @ts-ignore
|
|
2279
|
+
previous.sel = pSel;
|
|
2280
|
+
// @ts-ignore
|
|
2281
|
+
previous.raw = match.selector1;
|
|
2282
|
+
// @ts-ignore
|
|
2283
|
+
node.sel = nSel;
|
|
2284
|
+
// @ts-ignore
|
|
2285
|
+
node.raw = match.selector2;
|
|
2286
|
+
reduceRuleSelector(wrapper);
|
|
2287
|
+
return wrapper;
|
|
2288
|
+
}
|
|
2248
2289
|
function deduplicate(ast, options = {}, recursive = false) {
|
|
2249
2290
|
// @ts-ignore
|
|
2250
2291
|
if (('chi' in ast) && ast.chi?.length > 0) {
|
|
@@ -2260,6 +2301,14 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
2260
2301
|
}
|
|
2261
2302
|
// @ts-ignore
|
|
2262
2303
|
node = ast.chi[i];
|
|
2304
|
+
// @ts-ignore
|
|
2305
|
+
if (previous == node) {
|
|
2306
|
+
// console.error('idem!');
|
|
2307
|
+
// @ts-ignore
|
|
2308
|
+
ast.chi.splice(i, 1);
|
|
2309
|
+
i--;
|
|
2310
|
+
continue;
|
|
2311
|
+
}
|
|
2263
2312
|
if (node.typ == 'AtRule' && node.nam == 'font-face') {
|
|
2264
2313
|
continue;
|
|
2265
2314
|
}
|
|
@@ -2270,6 +2319,111 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
2270
2319
|
continue;
|
|
2271
2320
|
}
|
|
2272
2321
|
// @ts-ignore
|
|
2322
|
+
if (node.typ == 'Rule') {
|
|
2323
|
+
reduceRuleSelector(node);
|
|
2324
|
+
let wrapper;
|
|
2325
|
+
let match;
|
|
2326
|
+
// @ts-ignore
|
|
2327
|
+
if (options.nestingRules) {
|
|
2328
|
+
// @ts-ignore
|
|
2329
|
+
if (previous != null && previous.typ == 'Rule') {
|
|
2330
|
+
reduceRuleSelector(previous);
|
|
2331
|
+
// @ts-ignore
|
|
2332
|
+
match = matchSelectors(previous.raw, node.raw, ast.typ);
|
|
2333
|
+
// @ts-ignore
|
|
2334
|
+
if (match != null) {
|
|
2335
|
+
// @ts-ignore
|
|
2336
|
+
wrapper = wrapNodes(previous, node, match, ast, i, nodeIndex);
|
|
2337
|
+
nodeIndex = i - 1;
|
|
2338
|
+
// @ts-ignore
|
|
2339
|
+
previous = ast.chi[nodeIndex];
|
|
2340
|
+
}
|
|
2341
|
+
}
|
|
2342
|
+
// @ts-ignore
|
|
2343
|
+
if (wrapper != null) {
|
|
2344
|
+
// @ts-ignore
|
|
2345
|
+
while (i < ast.chi.length) {
|
|
2346
|
+
// @ts-ignore
|
|
2347
|
+
const nextNode = ast.chi[i];
|
|
2348
|
+
// @ts-ignore
|
|
2349
|
+
if (nextNode.typ != 'Rule') {
|
|
2350
|
+
// i--;
|
|
2351
|
+
// previous = wrapper;
|
|
2352
|
+
// nodeIndex = i;
|
|
2353
|
+
break;
|
|
2354
|
+
}
|
|
2355
|
+
reduceRuleSelector(nextNode);
|
|
2356
|
+
// @ts-ignore
|
|
2357
|
+
match = matchSelectors(wrapper.raw, nextNode.raw, ast.typ);
|
|
2358
|
+
// @ts-ignore
|
|
2359
|
+
if (match == null) {
|
|
2360
|
+
break;
|
|
2361
|
+
}
|
|
2362
|
+
// @ts-ignore
|
|
2363
|
+
wrapper = wrapNodes(wrapper, nextNode, match, ast, i, nodeIndex);
|
|
2364
|
+
}
|
|
2365
|
+
nodeIndex = --i;
|
|
2366
|
+
// @ts-ignore
|
|
2367
|
+
previous = ast.chi[nodeIndex];
|
|
2368
|
+
deduplicate(wrapper, options, recursive);
|
|
2369
|
+
continue;
|
|
2370
|
+
}
|
|
2371
|
+
// @ts-ignore
|
|
2372
|
+
else if (node.optimized != null &&
|
|
2373
|
+
// @ts-ignore
|
|
2374
|
+
node.optimized.match &&
|
|
2375
|
+
// @ts-ignore
|
|
2376
|
+
node.optimized.selector.length > 1) {
|
|
2377
|
+
// @ts-ignore
|
|
2378
|
+
wrapper = { ...node, chi: [], sel: node.optimized.optimized[0] };
|
|
2379
|
+
// @ts-ignore
|
|
2380
|
+
Object.defineProperty(wrapper, 'raw', {
|
|
2381
|
+
enumerable: false,
|
|
2382
|
+
writable: true,
|
|
2383
|
+
// @ts-ignore
|
|
2384
|
+
value: [[node.optimized.optimized[0]]]
|
|
2385
|
+
});
|
|
2386
|
+
// @ts-ignore
|
|
2387
|
+
node.sel = node.optimized.selector.reduce(reducer, []).join(',');
|
|
2388
|
+
// @ts-ignore
|
|
2389
|
+
node.raw = node.optimized.selector.slice();
|
|
2390
|
+
// @ts-ignore
|
|
2391
|
+
wrapper.chi.push(node);
|
|
2392
|
+
// @ts-ignore
|
|
2393
|
+
ast.chi.splice(i, 1, wrapper);
|
|
2394
|
+
node = wrapper;
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
// @ts-ignore
|
|
2398
|
+
else if (node.optimized?.match) {
|
|
2399
|
+
let wrap = true;
|
|
2400
|
+
// @ts-ignore
|
|
2401
|
+
const selector = node.optimized.selector.reduce((acc, curr) => {
|
|
2402
|
+
if (curr[0] == '&') {
|
|
2403
|
+
if (curr[1] == ' ') {
|
|
2404
|
+
curr.splice(0, 2);
|
|
2405
|
+
}
|
|
2406
|
+
else {
|
|
2407
|
+
if (ast.typ != 'Rule' && combinators.includes(curr[1])) {
|
|
2408
|
+
wrap = false;
|
|
2409
|
+
}
|
|
2410
|
+
else {
|
|
2411
|
+
curr.splice(0, 1);
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
else if (combinators.includes(curr[0])) {
|
|
2416
|
+
curr.unshift('&');
|
|
2417
|
+
}
|
|
2418
|
+
// @ts-ignore
|
|
2419
|
+
acc.push(curr.map(t => t.replaceAll('&', node.optimized.optimized[0])).join(''));
|
|
2420
|
+
return acc;
|
|
2421
|
+
}, []);
|
|
2422
|
+
// @ts-ignore
|
|
2423
|
+
node.sel = (wrap ? node.optimized.optimized[0] : '') + `:is(${selector.join(',')})`;
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
// @ts-ignore
|
|
2273
2427
|
if (previous != null && 'chi' in previous && ('chi' in node)) {
|
|
2274
2428
|
// @ts-ignore
|
|
2275
2429
|
if (previous.typ == node.typ) {
|
|
@@ -2289,13 +2443,14 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
2289
2443
|
// @ts-ignore
|
|
2290
2444
|
if ((node.typ == 'Rule' && node.sel == previous.sel) ||
|
|
2291
2445
|
// @ts-ignore
|
|
2292
|
-
(node.typ == 'AtRule') && node.val == previous.val) {
|
|
2446
|
+
(node.typ == 'AtRule') && node.val != 'font-face' && node.val == previous.val) {
|
|
2293
2447
|
// @ts-ignore
|
|
2294
2448
|
node.chi.unshift(...previous.chi);
|
|
2295
2449
|
// @ts-ignore
|
|
2296
2450
|
ast.chi.splice(nodeIndex, 1);
|
|
2297
2451
|
// @ts-ignore
|
|
2298
2452
|
if (hasDeclaration(node)) {
|
|
2453
|
+
// @ts-ignore
|
|
2299
2454
|
deduplicateRule(node);
|
|
2300
2455
|
}
|
|
2301
2456
|
else {
|
|
@@ -2311,19 +2466,26 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
2311
2466
|
if (intersect != null) {
|
|
2312
2467
|
if (intersect.node1.chi.length == 0) {
|
|
2313
2468
|
// @ts-ignore
|
|
2314
|
-
ast.chi.splice(i
|
|
2469
|
+
ast.chi.splice(i--, 1);
|
|
2470
|
+
// @ts-ignore
|
|
2471
|
+
node = ast.chi[i];
|
|
2315
2472
|
}
|
|
2316
2473
|
else {
|
|
2317
2474
|
// @ts-ignore
|
|
2318
2475
|
ast.chi.splice(i, 1, intersect.node1);
|
|
2476
|
+
node = intersect.node1;
|
|
2319
2477
|
}
|
|
2320
2478
|
if (intersect.node2.chi.length == 0) {
|
|
2321
2479
|
// @ts-ignore
|
|
2322
2480
|
ast.chi.splice(nodeIndex, 1, intersect.result);
|
|
2481
|
+
previous = intersect.result;
|
|
2323
2482
|
}
|
|
2324
2483
|
else {
|
|
2325
2484
|
// @ts-ignore
|
|
2326
2485
|
ast.chi.splice(nodeIndex, 1, intersect.result, intersect.node2);
|
|
2486
|
+
previous = intersect.result;
|
|
2487
|
+
// @ts-ignore
|
|
2488
|
+
i = nodeIndex;
|
|
2327
2489
|
}
|
|
2328
2490
|
}
|
|
2329
2491
|
}
|
|
@@ -2333,6 +2495,7 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
2333
2495
|
if (recursive && previous != node) {
|
|
2334
2496
|
// @ts-ignore
|
|
2335
2497
|
if (hasDeclaration(previous)) {
|
|
2498
|
+
// @ts-ignore
|
|
2336
2499
|
deduplicateRule(previous);
|
|
2337
2500
|
}
|
|
2338
2501
|
else {
|
|
@@ -2350,12 +2513,25 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
2350
2513
|
deduplicateRule(node);
|
|
2351
2514
|
}
|
|
2352
2515
|
else {
|
|
2353
|
-
|
|
2516
|
+
// @ts-ignore
|
|
2517
|
+
if (!(node.typ == 'AtRule' && node.nam != 'font-face')) {
|
|
2518
|
+
deduplicate(node, options, recursive);
|
|
2519
|
+
}
|
|
2354
2520
|
}
|
|
2355
2521
|
}
|
|
2356
2522
|
}
|
|
2357
2523
|
return ast;
|
|
2358
2524
|
}
|
|
2525
|
+
function hasOnlyDeclarations(node) {
|
|
2526
|
+
let k = node.chi.length;
|
|
2527
|
+
while (k--) {
|
|
2528
|
+
if (node.chi[k].typ == 'Comment') {
|
|
2529
|
+
continue;
|
|
2530
|
+
}
|
|
2531
|
+
return node.chi[k].typ == 'Declaration';
|
|
2532
|
+
}
|
|
2533
|
+
return true;
|
|
2534
|
+
}
|
|
2359
2535
|
function hasDeclaration(node) {
|
|
2360
2536
|
// @ts-ignore
|
|
2361
2537
|
for (let i = 0; i < node.chi?.length; i++) {
|
|
@@ -2368,7 +2544,7 @@ function hasDeclaration(node) {
|
|
|
2368
2544
|
}
|
|
2369
2545
|
return true;
|
|
2370
2546
|
}
|
|
2371
|
-
function deduplicateRule(ast
|
|
2547
|
+
function deduplicateRule(ast) {
|
|
2372
2548
|
// @ts-ignore
|
|
2373
2549
|
if (!('chi' in ast) || ast.chi?.length <= 1) {
|
|
2374
2550
|
return ast;
|
|
@@ -2415,42 +2591,42 @@ function deduplicateRule(ast, options = {}) {
|
|
|
2415
2591
|
}
|
|
2416
2592
|
// @ts-ignore
|
|
2417
2593
|
ast.chi = children.concat(ast.chi?.slice(k));
|
|
2418
|
-
/*
|
|
2419
|
-
// @ts-ignore
|
|
2420
|
-
|
|
2421
|
-
const properties: PropertyList = new PropertyList();
|
|
2422
|
-
|
|
2423
|
-
for (; k < j; k++) {
|
|
2424
|
-
|
|
2425
|
-
// @ts-ignore
|
|
2426
|
-
if ('Comment' == ast.chi[k].typ || 'Declaration' == ast.chi[k].typ) {
|
|
2427
|
-
|
|
2428
|
-
// @ts-ignore
|
|
2429
|
-
properties.add(ast.chi[k]);
|
|
2430
|
-
continue;
|
|
2431
|
-
}
|
|
2432
|
-
|
|
2433
|
-
break;
|
|
2434
|
-
}
|
|
2435
|
-
|
|
2436
|
-
// @ts-ignore
|
|
2437
|
-
ast.chi = [...properties].concat(ast.chi.slice(k));
|
|
2438
|
-
*/
|
|
2439
|
-
//
|
|
2440
|
-
// @ts-ignore
|
|
2441
|
-
// ast.chi.splice(0, k - 1, ...properties);
|
|
2442
2594
|
return ast;
|
|
2443
2595
|
}
|
|
2444
2596
|
function splitRule(buffer) {
|
|
2445
|
-
const result = [];
|
|
2597
|
+
const result = [[]];
|
|
2446
2598
|
let str = '';
|
|
2447
2599
|
for (let i = 0; i < buffer.length; i++) {
|
|
2448
2600
|
let chr = buffer.charAt(i);
|
|
2601
|
+
if (isWhiteSpace(chr.charCodeAt(0))) {
|
|
2602
|
+
let k = i;
|
|
2603
|
+
while (k + 1 < buffer.length) {
|
|
2604
|
+
if (isWhiteSpace(buffer[k + 1].charCodeAt(0))) {
|
|
2605
|
+
k++;
|
|
2606
|
+
continue;
|
|
2607
|
+
}
|
|
2608
|
+
break;
|
|
2609
|
+
}
|
|
2610
|
+
if (str !== '') {
|
|
2611
|
+
// @ts-ignore
|
|
2612
|
+
result.at(-1).push(str);
|
|
2613
|
+
str = '';
|
|
2614
|
+
}
|
|
2615
|
+
// @ts-ignore
|
|
2616
|
+
if (result.at(-1).length > 0) {
|
|
2617
|
+
// @ts-ignore
|
|
2618
|
+
result.at(-1).push(' ');
|
|
2619
|
+
}
|
|
2620
|
+
i = k;
|
|
2621
|
+
continue;
|
|
2622
|
+
}
|
|
2449
2623
|
if (chr == ',') {
|
|
2450
2624
|
if (str !== '') {
|
|
2451
|
-
|
|
2625
|
+
// @ts-ignore
|
|
2626
|
+
result.at(-1).push(str);
|
|
2452
2627
|
str = '';
|
|
2453
2628
|
}
|
|
2629
|
+
result.push([]);
|
|
2454
2630
|
continue;
|
|
2455
2631
|
}
|
|
2456
2632
|
str += chr;
|
|
@@ -2497,14 +2673,49 @@ function splitRule(buffer) {
|
|
|
2497
2673
|
}
|
|
2498
2674
|
}
|
|
2499
2675
|
i = k;
|
|
2500
|
-
continue;
|
|
2501
2676
|
}
|
|
2502
2677
|
}
|
|
2503
2678
|
if (str !== '') {
|
|
2504
|
-
|
|
2679
|
+
// @ts-ignore
|
|
2680
|
+
result.at(-1).push(str);
|
|
2505
2681
|
}
|
|
2506
2682
|
return result;
|
|
2507
2683
|
}
|
|
2684
|
+
function reduceRuleSelector(node) {
|
|
2685
|
+
if (node.raw == null) {
|
|
2686
|
+
Object.defineProperty(node, 'raw', { enumerable: false, writable: true, value: splitRule(node.sel) });
|
|
2687
|
+
}
|
|
2688
|
+
// @ts-ignore
|
|
2689
|
+
// if (node.raw != null) {
|
|
2690
|
+
// @ts-ignore
|
|
2691
|
+
let optimized = reduceSelector(node.raw.reduce((acc, curr) => {
|
|
2692
|
+
acc.push(curr.slice());
|
|
2693
|
+
return acc;
|
|
2694
|
+
}, []));
|
|
2695
|
+
if (optimized != null) {
|
|
2696
|
+
Object.defineProperty(node, 'optimized', { enumerable: false, writable: true, value: optimized });
|
|
2697
|
+
}
|
|
2698
|
+
if (optimized != null && optimized.match && optimized.reducible && optimized.selector.length > 1) {
|
|
2699
|
+
const raw = [
|
|
2700
|
+
[
|
|
2701
|
+
optimized.optimized[0], ':is('
|
|
2702
|
+
].concat(optimized.selector.reduce((acc, curr) => {
|
|
2703
|
+
if (acc.length > 0) {
|
|
2704
|
+
acc.push(',');
|
|
2705
|
+
}
|
|
2706
|
+
acc.push(...curr);
|
|
2707
|
+
return acc;
|
|
2708
|
+
}, [])).concat(')')
|
|
2709
|
+
];
|
|
2710
|
+
const sel = raw[0].join('');
|
|
2711
|
+
if (sel.length < node.sel.length) {
|
|
2712
|
+
node.sel = sel;
|
|
2713
|
+
// node.raw = raw;
|
|
2714
|
+
Object.defineProperty(node, 'raw', { enumerable: false, writable: true, value: raw });
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
// }
|
|
2718
|
+
}
|
|
2508
2719
|
function diff(n1, n2, options = {}) {
|
|
2509
2720
|
let node1 = n1;
|
|
2510
2721
|
let node2 = n2;
|
|
@@ -2521,8 +2732,28 @@ function diff(n1, n2, options = {}) {
|
|
|
2521
2732
|
// @ts-ignore
|
|
2522
2733
|
return null;
|
|
2523
2734
|
}
|
|
2735
|
+
// @ts-ignore
|
|
2736
|
+
const raw1 = node1.raw;
|
|
2737
|
+
// @ts-ignore
|
|
2738
|
+
// const optimized1 = node1.optimized;
|
|
2739
|
+
// @ts-ignore
|
|
2740
|
+
const raw2 = node2.raw;
|
|
2741
|
+
// @ts-ignore
|
|
2742
|
+
// const optimized2 = node2.optimized;
|
|
2524
2743
|
node1 = { ...node1, chi: node1.chi.slice() };
|
|
2525
2744
|
node2 = { ...node2, chi: node2.chi.slice() };
|
|
2745
|
+
if (raw1 != null) {
|
|
2746
|
+
Object.defineProperty(node1, 'raw', { enumerable: false, writable: true, value: raw1 });
|
|
2747
|
+
}
|
|
2748
|
+
// if (optimized1 != null) {
|
|
2749
|
+
// Object.defineProperty(node1, 'optimized', {enumerable: false, writable: true, value: optimized1});
|
|
2750
|
+
// }
|
|
2751
|
+
if (raw2 != null) {
|
|
2752
|
+
Object.defineProperty(node2, 'raw', { enumerable: false, writable: true, value: raw2 });
|
|
2753
|
+
}
|
|
2754
|
+
// if (optimized2 != null) {
|
|
2755
|
+
// Object.defineProperty(node2, 'optimized', {enumerable: false, writable: true, value: optimized2});
|
|
2756
|
+
// }
|
|
2526
2757
|
const intersect = [];
|
|
2527
2758
|
while (i--) {
|
|
2528
2759
|
if (node1.chi[i].typ == 'Comment') {
|
|
@@ -2550,7 +2781,7 @@ function diff(n1, n2, options = {}) {
|
|
|
2550
2781
|
const result = (intersect.length == 0 ? null : {
|
|
2551
2782
|
...node1,
|
|
2552
2783
|
// @ts-ignore
|
|
2553
|
-
sel: [...new Set([...(n1
|
|
2784
|
+
sel: [...new Set([...(n1?.raw?.reduce(reducer, []) || splitRule(n1.sel)).concat(n2?.raw?.reduce(reducer, []) || splitRule(n2.sel))])].join(','),
|
|
2554
2785
|
chi: intersect.reverse()
|
|
2555
2786
|
});
|
|
2556
2787
|
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)) {
|
|
@@ -2559,6 +2790,262 @@ function diff(n1, n2, options = {}) {
|
|
|
2559
2790
|
}
|
|
2560
2791
|
return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node2 : node2 };
|
|
2561
2792
|
}
|
|
2793
|
+
function matchSelectors(selector1, selector2, parentType) {
|
|
2794
|
+
let match = [[]];
|
|
2795
|
+
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));
|
|
2796
|
+
let i = 0;
|
|
2797
|
+
let k;
|
|
2798
|
+
let l;
|
|
2799
|
+
let token;
|
|
2800
|
+
let matching = true;
|
|
2801
|
+
let matchFunction = 0;
|
|
2802
|
+
let inAttr = 0;
|
|
2803
|
+
for (; i < j; i++) {
|
|
2804
|
+
k = 0;
|
|
2805
|
+
token = selector1[0][i];
|
|
2806
|
+
for (; k < selector1.length; k++) {
|
|
2807
|
+
if (selector1[k][i] != token) {
|
|
2808
|
+
matching = false;
|
|
2809
|
+
break;
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2812
|
+
if (matching) {
|
|
2813
|
+
l = 0;
|
|
2814
|
+
for (; l < selector2.length; l++) {
|
|
2815
|
+
if (selector2[l][i] != token) {
|
|
2816
|
+
matching = false;
|
|
2817
|
+
break;
|
|
2818
|
+
}
|
|
2819
|
+
}
|
|
2820
|
+
}
|
|
2821
|
+
if (!matching) {
|
|
2822
|
+
break;
|
|
2823
|
+
}
|
|
2824
|
+
if (token == ',') {
|
|
2825
|
+
match.push([]);
|
|
2826
|
+
}
|
|
2827
|
+
else {
|
|
2828
|
+
if (token.endsWith('(')) {
|
|
2829
|
+
matchFunction++;
|
|
2830
|
+
}
|
|
2831
|
+
if (token.endsWith('[')) {
|
|
2832
|
+
inAttr++;
|
|
2833
|
+
}
|
|
2834
|
+
else if (token == ')') {
|
|
2835
|
+
matchFunction--;
|
|
2836
|
+
}
|
|
2837
|
+
else if (token == ']') {
|
|
2838
|
+
inAttr--;
|
|
2839
|
+
}
|
|
2840
|
+
match.at(-1).push(token);
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
// invalid function
|
|
2844
|
+
if (matchFunction != 0 || inAttr != 0) {
|
|
2845
|
+
return null;
|
|
2846
|
+
}
|
|
2847
|
+
if (parentType != 'Rule') {
|
|
2848
|
+
for (const part of match) {
|
|
2849
|
+
if (part.length > 0 && combinators.includes(part[0].charAt(0))) {
|
|
2850
|
+
return null;
|
|
2851
|
+
}
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2854
|
+
if (match.length > 1) {
|
|
2855
|
+
console.error(`unsupported multilevel matching`);
|
|
2856
|
+
console.error({ match, selector1, selector2 });
|
|
2857
|
+
return null;
|
|
2858
|
+
}
|
|
2859
|
+
for (const part of match) {
|
|
2860
|
+
while (part.length > 0) {
|
|
2861
|
+
const token = part.at(-1);
|
|
2862
|
+
if (token == ' ' || combinators.includes(token) || notEndingWith.includes(token.at(-1))) {
|
|
2863
|
+
part.pop();
|
|
2864
|
+
continue;
|
|
2865
|
+
}
|
|
2866
|
+
break;
|
|
2867
|
+
}
|
|
2868
|
+
}
|
|
2869
|
+
if (match.every(t => t.length == 0)) {
|
|
2870
|
+
return null;
|
|
2871
|
+
}
|
|
2872
|
+
if (eq([['&']], match)) {
|
|
2873
|
+
return null;
|
|
2874
|
+
}
|
|
2875
|
+
function reduce(acc, curr) {
|
|
2876
|
+
if (acc === null) {
|
|
2877
|
+
return null;
|
|
2878
|
+
}
|
|
2879
|
+
let hasCompoundSelector = true;
|
|
2880
|
+
curr = curr.slice(match[0].length);
|
|
2881
|
+
while (curr.length > 0) {
|
|
2882
|
+
if (curr[0] == ' ') {
|
|
2883
|
+
hasCompoundSelector = false;
|
|
2884
|
+
curr.unshift('&');
|
|
2885
|
+
continue;
|
|
2886
|
+
}
|
|
2887
|
+
break;
|
|
2888
|
+
}
|
|
2889
|
+
// invalid function match
|
|
2890
|
+
if (curr.length > 0 && curr[0].endsWith('(') && curr.at(-1) != ')') {
|
|
2891
|
+
return null;
|
|
2892
|
+
}
|
|
2893
|
+
if (curr.length == 1 && combinators.includes(curr[0].charAt(0))) {
|
|
2894
|
+
return null;
|
|
2895
|
+
}
|
|
2896
|
+
if (hasCompoundSelector && curr.length > 0) {
|
|
2897
|
+
hasCompoundSelector = !['&'].concat(combinators).includes(curr[0].charAt(0));
|
|
2898
|
+
}
|
|
2899
|
+
if (curr[0] == ':is(') {
|
|
2900
|
+
let inFunction = 0;
|
|
2901
|
+
let canReduce = true;
|
|
2902
|
+
const isCompound = curr.reduce((acc, token, index) => {
|
|
2903
|
+
if (index == 0) {
|
|
2904
|
+
inFunction++;
|
|
2905
|
+
canReduce = curr[1] == '&';
|
|
2906
|
+
}
|
|
2907
|
+
else if (token.endsWith('(')) {
|
|
2908
|
+
if (inFunction == 0) {
|
|
2909
|
+
canReduce = false;
|
|
2910
|
+
}
|
|
2911
|
+
inFunction++;
|
|
2912
|
+
}
|
|
2913
|
+
else if (token == ')') {
|
|
2914
|
+
inFunction--;
|
|
2915
|
+
}
|
|
2916
|
+
else if (token == ',') {
|
|
2917
|
+
if (!canReduce) {
|
|
2918
|
+
canReduce = curr[index + 1] == '&';
|
|
2919
|
+
}
|
|
2920
|
+
acc.push([]);
|
|
2921
|
+
}
|
|
2922
|
+
else
|
|
2923
|
+
acc.at(-1)?.push(token);
|
|
2924
|
+
return acc;
|
|
2925
|
+
}, [[]]);
|
|
2926
|
+
if (inFunction > 0) {
|
|
2927
|
+
canReduce = false;
|
|
2928
|
+
}
|
|
2929
|
+
if (canReduce) {
|
|
2930
|
+
curr = isCompound.reduce((acc, curr) => {
|
|
2931
|
+
if (acc.length > 0) {
|
|
2932
|
+
acc.push(',');
|
|
2933
|
+
}
|
|
2934
|
+
acc.push(...curr);
|
|
2935
|
+
return acc;
|
|
2936
|
+
}, []);
|
|
2937
|
+
}
|
|
2938
|
+
}
|
|
2939
|
+
// @todo: check hasCompoundSelector && curr[0] == '&' && curr[1] == ' '
|
|
2940
|
+
acc.push(match.length == 0 ? ['&'] : (hasCompoundSelector && curr[0] != '&' && (curr.length == 0 || !combinators.includes(curr[0].charAt(0))) ? ['&'].concat(curr) : curr));
|
|
2941
|
+
return acc;
|
|
2942
|
+
}
|
|
2943
|
+
// @ts-ignore
|
|
2944
|
+
selector1 = selector1.reduce(reduce, []);
|
|
2945
|
+
// @ts-ignore
|
|
2946
|
+
selector2 = selector2.reduce(reduce, []);
|
|
2947
|
+
return selector1 == null || selector2 == null ? null : {
|
|
2948
|
+
eq: eq(selector1, selector2),
|
|
2949
|
+
match,
|
|
2950
|
+
selector1,
|
|
2951
|
+
selector2
|
|
2952
|
+
};
|
|
2953
|
+
}
|
|
2954
|
+
function reduceSelector(selector) {
|
|
2955
|
+
if (selector.length == 0) {
|
|
2956
|
+
return null;
|
|
2957
|
+
}
|
|
2958
|
+
const optimized = [];
|
|
2959
|
+
const k = selector.reduce((acc, curr) => acc == 0 ? curr.length : (curr.length == 0 ? acc : Math.min(acc, curr.length)), 0);
|
|
2960
|
+
let i = 0;
|
|
2961
|
+
let j;
|
|
2962
|
+
let match;
|
|
2963
|
+
for (; i < k; i++) {
|
|
2964
|
+
const item = selector[0][i];
|
|
2965
|
+
match = true;
|
|
2966
|
+
for (j = 1; j < selector.length; j++) {
|
|
2967
|
+
if (item != selector[j][i]) {
|
|
2968
|
+
match = false;
|
|
2969
|
+
break;
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
if (!match) {
|
|
2973
|
+
break;
|
|
2974
|
+
}
|
|
2975
|
+
optimized.push(item);
|
|
2976
|
+
}
|
|
2977
|
+
while (optimized.length > 0) {
|
|
2978
|
+
const last = optimized.at(-1);
|
|
2979
|
+
if ((last == ' ' || combinators.includes(last))) {
|
|
2980
|
+
optimized.pop();
|
|
2981
|
+
continue;
|
|
2982
|
+
}
|
|
2983
|
+
break;
|
|
2984
|
+
}
|
|
2985
|
+
selector.forEach((selector) => selector.splice(0, optimized.length));
|
|
2986
|
+
// combinator
|
|
2987
|
+
if (combinators.includes(optimized.at(-1))) {
|
|
2988
|
+
const combinator = optimized.pop();
|
|
2989
|
+
selector.forEach(selector => selector.unshift(combinator));
|
|
2990
|
+
}
|
|
2991
|
+
let reducible = optimized.length == 1;
|
|
2992
|
+
if (optimized[0] == '&' && optimized[1] == ' ') {
|
|
2993
|
+
optimized.splice(0, 2);
|
|
2994
|
+
}
|
|
2995
|
+
if (optimized.length == 0 ||
|
|
2996
|
+
(optimized[0].charAt(0) == '&' ||
|
|
2997
|
+
selector.length == 1)) {
|
|
2998
|
+
return {
|
|
2999
|
+
match: false,
|
|
3000
|
+
optimized,
|
|
3001
|
+
selector: selector.map(selector => selector[0] == '&' && selector[1] == ' ' ? selector.slice(2) : selector),
|
|
3002
|
+
reducible: selector.length > 1 && selector.every((selector) => !combinators.includes(selector[0]))
|
|
3003
|
+
};
|
|
3004
|
+
}
|
|
3005
|
+
return {
|
|
3006
|
+
match: true,
|
|
3007
|
+
optimized,
|
|
3008
|
+
selector: selector.reduce((acc, curr) => {
|
|
3009
|
+
let hasCompound = true;
|
|
3010
|
+
if (hasCompound && curr.length > 0) {
|
|
3011
|
+
hasCompound = !['&'].concat(combinators).includes(curr[0].charAt(0));
|
|
3012
|
+
}
|
|
3013
|
+
// @ts-ignore
|
|
3014
|
+
if (hasCompound && curr[0] == ' ') {
|
|
3015
|
+
hasCompound = false;
|
|
3016
|
+
curr.unshift('&');
|
|
3017
|
+
}
|
|
3018
|
+
if (curr.length == 0) {
|
|
3019
|
+
curr.push('&');
|
|
3020
|
+
hasCompound = false;
|
|
3021
|
+
}
|
|
3022
|
+
if (reducible) {
|
|
3023
|
+
const chr = curr[0].charAt(0);
|
|
3024
|
+
// @ts-ignore
|
|
3025
|
+
reducible = chr == '.' || chr == ':' || isIdentStart(chr.codePointAt(0));
|
|
3026
|
+
}
|
|
3027
|
+
acc.push(hasCompound ? ['&'].concat(curr) : curr);
|
|
3028
|
+
return acc;
|
|
3029
|
+
}, []),
|
|
3030
|
+
reducible: selector.every((selector) => !['>', '+', '~', '&'].includes(selector[0]))
|
|
3031
|
+
};
|
|
3032
|
+
}
|
|
3033
|
+
function reducer(acc, curr, index, array) {
|
|
3034
|
+
// trim :is()
|
|
3035
|
+
if (array.length == 1 && array[0][0] == ':is(' && array[0].at(-1) == ')') {
|
|
3036
|
+
curr = curr.slice(1, -1);
|
|
3037
|
+
}
|
|
3038
|
+
if (curr[0] == '&') {
|
|
3039
|
+
if (curr[1] == ' ') {
|
|
3040
|
+
curr.splice(0, 2);
|
|
3041
|
+
}
|
|
3042
|
+
else if (combinators.includes(curr[1])) {
|
|
3043
|
+
curr.splice(0, 1);
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3046
|
+
acc.push(curr.join(''));
|
|
3047
|
+
return acc;
|
|
3048
|
+
}
|
|
2562
3049
|
|
|
2563
3050
|
const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
|
|
2564
3051
|
const funcLike = ['Start-parens', 'Func', 'UrlFunc', 'Pseudo-class-func'];
|
|
@@ -2568,6 +3055,7 @@ async function parse$1(iterator, opt = {}) {
|
|
|
2568
3055
|
src: '',
|
|
2569
3056
|
sourcemap: false,
|
|
2570
3057
|
compress: false,
|
|
3058
|
+
nestingRules: false,
|
|
2571
3059
|
resolveImport: false,
|
|
2572
3060
|
resolveUrls: false,
|
|
2573
3061
|
removeEmpty: true,
|
|
@@ -2838,11 +3326,16 @@ async function parse$1(iterator, opt = {}) {
|
|
|
2838
3326
|
try {
|
|
2839
3327
|
// @ts-ignore
|
|
2840
3328
|
const root = await options.load(url, options.src).then((src) => {
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
3329
|
+
return parse$1(src, Object.assign({}, options, {
|
|
3330
|
+
compress: false,
|
|
3331
|
+
// @ts-ignore
|
|
3332
|
+
src: options.resolve(url, options.src).absolute
|
|
3333
|
+
}));
|
|
2844
3334
|
});
|
|
2845
|
-
|
|
3335
|
+
bytesIn += root.bytesIn;
|
|
3336
|
+
if (root.ast.chi.length > 0) {
|
|
3337
|
+
context.chi.push(...root.ast.chi);
|
|
3338
|
+
}
|
|
2846
3339
|
if (root.errors.length > 0) {
|
|
2847
3340
|
errors.push(...root.errors);
|
|
2848
3341
|
}
|
|
@@ -2857,20 +3350,16 @@ async function parse$1(iterator, opt = {}) {
|
|
|
2857
3350
|
// https://www.w3.org/TR/css-nesting-1/#conditionals
|
|
2858
3351
|
// allowed nesting at-rules
|
|
2859
3352
|
// there must be a top level rule in the stack
|
|
3353
|
+
const raw = tokens.reduce((acc, curr) => {
|
|
3354
|
+
acc.push(renderToken(curr, { removeComments: true }));
|
|
3355
|
+
return acc;
|
|
3356
|
+
}, []);
|
|
2860
3357
|
const node = {
|
|
2861
3358
|
typ: 'AtRule',
|
|
2862
3359
|
nam: renderToken(atRule, { removeComments: true }),
|
|
2863
|
-
val:
|
|
2864
|
-
if (curr.typ == 'Whitespace') {
|
|
2865
|
-
if (array[index + 1]?.typ == 'Start-parens' ||
|
|
2866
|
-
array[index - 1]?.typ == 'End-parens' ||
|
|
2867
|
-
array[index - 1]?.typ == 'Func') {
|
|
2868
|
-
return acc;
|
|
2869
|
-
}
|
|
2870
|
-
}
|
|
2871
|
-
return acc + renderToken(curr, { removeComments: true });
|
|
2872
|
-
}, '')
|
|
3360
|
+
val: raw.join('')
|
|
2873
3361
|
};
|
|
3362
|
+
Object.defineProperty(node, 'raw', { enumerable: false, writable: false, value: raw });
|
|
2874
3363
|
if (delim.typ == 'Block-start') {
|
|
2875
3364
|
node.chi = [];
|
|
2876
3365
|
}
|
|
@@ -2895,23 +3384,33 @@ async function parse$1(iterator, opt = {}) {
|
|
|
2895
3384
|
return null;
|
|
2896
3385
|
}
|
|
2897
3386
|
}
|
|
2898
|
-
const
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
else {
|
|
2904
|
-
acc[acc.length - 1] += curr;
|
|
3387
|
+
const uniq = new Map;
|
|
3388
|
+
parseTokens(tokens, 'Rule', { compress: options.compress }).reduce((acc, curr, index, array) => {
|
|
3389
|
+
if (curr.typ == 'Whitespace') {
|
|
3390
|
+
if (array[index - 1]?.val == '+' || array[index + 1]?.val == '+') {
|
|
3391
|
+
return acc;
|
|
2905
3392
|
}
|
|
2906
|
-
|
|
2907
|
-
|
|
3393
|
+
}
|
|
3394
|
+
let t = renderToken(curr, { compress: true });
|
|
3395
|
+
if (t == ',') {
|
|
3396
|
+
acc.push([]);
|
|
3397
|
+
}
|
|
3398
|
+
else {
|
|
3399
|
+
acc[acc.length - 1].push(t);
|
|
3400
|
+
}
|
|
3401
|
+
return acc;
|
|
3402
|
+
}, [[]]).reduce((acc, curr) => {
|
|
3403
|
+
acc.set(curr.join(''), curr);
|
|
3404
|
+
return acc;
|
|
3405
|
+
}, uniq);
|
|
2908
3406
|
const node = {
|
|
2909
3407
|
typ: 'Rule',
|
|
2910
3408
|
// @ts-ignore
|
|
2911
|
-
sel:
|
|
3409
|
+
sel: [...uniq.keys()].join(','),
|
|
2912
3410
|
chi: []
|
|
2913
3411
|
};
|
|
2914
|
-
|
|
3412
|
+
let raw = [...uniq.values()];
|
|
3413
|
+
Object.defineProperty(node, 'raw', { enumerable: false, writable: true, value: raw });
|
|
2915
3414
|
loc = {
|
|
2916
3415
|
sta: position,
|
|
2917
3416
|
src
|
|
@@ -2935,7 +3434,13 @@ async function parse$1(iterator, opt = {}) {
|
|
|
2935
3434
|
}
|
|
2936
3435
|
if (tokens[i].typ == 'Colon') {
|
|
2937
3436
|
name = tokens.slice(0, i);
|
|
2938
|
-
value = parseTokens(tokens.slice(i + 1),
|
|
3437
|
+
value = parseTokens(tokens.slice(i + 1), 'Declaration', {
|
|
3438
|
+
parseColor: true,
|
|
3439
|
+
src: options.src,
|
|
3440
|
+
resolveUrls: options.resolveUrls,
|
|
3441
|
+
resolve: options.resolve,
|
|
3442
|
+
cwd: options.cwd
|
|
3443
|
+
});
|
|
2939
3444
|
}
|
|
2940
3445
|
}
|
|
2941
3446
|
if (name == null) {
|
|
@@ -2954,11 +3459,6 @@ async function parse$1(iterator, opt = {}) {
|
|
|
2954
3459
|
}
|
|
2955
3460
|
}
|
|
2956
3461
|
}
|
|
2957
|
-
// if (name.length == 0) {
|
|
2958
|
-
//
|
|
2959
|
-
// errors.push({action: 'drop', message: 'invalid declaration', location: {src, ...position}});
|
|
2960
|
-
// return null;
|
|
2961
|
-
// }
|
|
2962
3462
|
if (value == null) {
|
|
2963
3463
|
errors.push({ action: 'drop', message: 'invalid declaration', location: { src, ...position } });
|
|
2964
3464
|
return null;
|
|
@@ -2981,16 +3481,6 @@ async function parse$1(iterator, opt = {}) {
|
|
|
2981
3481
|
errors.push({ action: 'drop', message: 'invalid declaration', location: { src, ...position } });
|
|
2982
3482
|
return null;
|
|
2983
3483
|
}
|
|
2984
|
-
// // location not needed for declaration
|
|
2985
|
-
// loc = <Location>{
|
|
2986
|
-
// sta: position,
|
|
2987
|
-
// src
|
|
2988
|
-
// };
|
|
2989
|
-
//
|
|
2990
|
-
// if (options.sourcemap) {
|
|
2991
|
-
//
|
|
2992
|
-
// node.loc = loc
|
|
2993
|
-
// }
|
|
2994
3484
|
// @ts-ignore
|
|
2995
3485
|
context.chi.push(node);
|
|
2996
3486
|
return null;
|
|
@@ -3033,7 +3523,6 @@ async function parse$1(iterator, opt = {}) {
|
|
|
3033
3523
|
position.ind = ind;
|
|
3034
3524
|
position.lin = lin;
|
|
3035
3525
|
position.col = col == 0 ? 1 : col;
|
|
3036
|
-
// }
|
|
3037
3526
|
}
|
|
3038
3527
|
function consumeWhiteSpace() {
|
|
3039
3528
|
let count = 0;
|
|
@@ -3215,11 +3704,6 @@ async function parse$1(iterator, opt = {}) {
|
|
|
3215
3704
|
}
|
|
3216
3705
|
}
|
|
3217
3706
|
}
|
|
3218
|
-
// else {
|
|
3219
|
-
//
|
|
3220
|
-
// pushToken(getType(buffer));
|
|
3221
|
-
// buffer = '';
|
|
3222
|
-
// }
|
|
3223
3707
|
break;
|
|
3224
3708
|
case '<':
|
|
3225
3709
|
if (buffer.length > 0) {
|
|
@@ -3270,6 +3754,9 @@ async function parse$1(iterator, opt = {}) {
|
|
|
3270
3754
|
break;
|
|
3271
3755
|
case '~':
|
|
3272
3756
|
case '|':
|
|
3757
|
+
if (tokens.at(-1)?.typ == 'Whitespace') {
|
|
3758
|
+
tokens.pop();
|
|
3759
|
+
}
|
|
3273
3760
|
if (buffer.length > 0) {
|
|
3274
3761
|
pushToken(getType(buffer));
|
|
3275
3762
|
buffer = '';
|
|
@@ -3291,15 +3778,32 @@ async function parse$1(iterator, opt = {}) {
|
|
|
3291
3778
|
break;
|
|
3292
3779
|
}
|
|
3293
3780
|
pushToken(getType(buffer));
|
|
3781
|
+
while (isWhiteSpace(value.charCodeAt(0))) {
|
|
3782
|
+
value = next();
|
|
3783
|
+
}
|
|
3294
3784
|
buffer = value;
|
|
3295
3785
|
break;
|
|
3296
3786
|
case '>':
|
|
3787
|
+
if (buffer !== '') {
|
|
3788
|
+
pushToken(getType(buffer));
|
|
3789
|
+
buffer = '';
|
|
3790
|
+
}
|
|
3297
3791
|
if (tokens[tokens.length - 1]?.typ == 'Whitespace') {
|
|
3298
3792
|
tokens.pop();
|
|
3299
3793
|
}
|
|
3300
3794
|
pushToken({ typ: 'Gt' });
|
|
3301
3795
|
consumeWhiteSpace();
|
|
3302
3796
|
break;
|
|
3797
|
+
case '.':
|
|
3798
|
+
const codepoint = peek().charCodeAt(0);
|
|
3799
|
+
if (!isDigit(codepoint) && buffer !== '') {
|
|
3800
|
+
pushToken(getType(buffer));
|
|
3801
|
+
buffer = value;
|
|
3802
|
+
break;
|
|
3803
|
+
}
|
|
3804
|
+
buffer += value;
|
|
3805
|
+
break;
|
|
3806
|
+
case '+':
|
|
3303
3807
|
case ':':
|
|
3304
3808
|
case ',':
|
|
3305
3809
|
case '=':
|
|
@@ -3311,12 +3815,11 @@ async function parse$1(iterator, opt = {}) {
|
|
|
3311
3815
|
buffer += value + next();
|
|
3312
3816
|
break;
|
|
3313
3817
|
}
|
|
3314
|
-
// if (value == ',' && tokens[tokens.length - 1]?.typ == 'Whitespace') {
|
|
3315
|
-
//
|
|
3316
|
-
// tokens.pop();
|
|
3317
|
-
// }
|
|
3318
3818
|
pushToken(getType(value));
|
|
3319
3819
|
buffer = '';
|
|
3820
|
+
if (value == '+' && isWhiteSpace(peek().charCodeAt(0))) {
|
|
3821
|
+
pushToken(getType(next()));
|
|
3822
|
+
}
|
|
3320
3823
|
while (isWhiteSpace(peek().charCodeAt(0))) {
|
|
3321
3824
|
next();
|
|
3322
3825
|
}
|
|
@@ -3337,7 +3840,7 @@ async function parse$1(iterator, opt = {}) {
|
|
|
3337
3840
|
pushToken(getType(buffer));
|
|
3338
3841
|
buffer = '';
|
|
3339
3842
|
const token = tokens[tokens.length - 1];
|
|
3340
|
-
if (token.typ == 'UrlFunc'
|
|
3843
|
+
if (token.typ == 'UrlFunc') {
|
|
3341
3844
|
// consume either string or url token
|
|
3342
3845
|
let whitespace = '';
|
|
3343
3846
|
value = peek();
|
|
@@ -3454,15 +3957,6 @@ async function parse$1(iterator, opt = {}) {
|
|
|
3454
3957
|
if (options.removeEmpty && previousNode != null && previousNode.chi.length == 0 && context.chi[context.chi.length - 1] == previousNode) {
|
|
3455
3958
|
context.chi.pop();
|
|
3456
3959
|
}
|
|
3457
|
-
else if (previousNode != null && previousNode != ast && options.compress) {
|
|
3458
|
-
// @ts-ignore
|
|
3459
|
-
if (hasDeclaration(previousNode)) {
|
|
3460
|
-
deduplicateRule(previousNode);
|
|
3461
|
-
}
|
|
3462
|
-
else {
|
|
3463
|
-
deduplicate(previousNode, options);
|
|
3464
|
-
}
|
|
3465
|
-
}
|
|
3466
3960
|
tokens.length = 0;
|
|
3467
3961
|
map.clear();
|
|
3468
3962
|
buffer = '';
|
|
@@ -3497,28 +3991,22 @@ async function parse$1(iterator, opt = {}) {
|
|
|
3497
3991
|
await parseNode(tokens);
|
|
3498
3992
|
}
|
|
3499
3993
|
if (options.compress) {
|
|
3500
|
-
while (stack.length > 0) {
|
|
3501
|
-
const node = stack.pop();
|
|
3502
|
-
if (hasDeclaration(node)) {
|
|
3503
|
-
deduplicateRule(node, options);
|
|
3504
|
-
}
|
|
3505
|
-
else {
|
|
3506
|
-
deduplicate(node, options);
|
|
3507
|
-
}
|
|
3508
|
-
}
|
|
3509
3994
|
if (ast.chi.length > 0) {
|
|
3510
|
-
deduplicate(ast, options);
|
|
3995
|
+
deduplicate(ast, options, true);
|
|
3511
3996
|
}
|
|
3512
3997
|
}
|
|
3513
3998
|
return { ast, errors, bytesIn };
|
|
3514
3999
|
}
|
|
3515
|
-
function parseTokens(tokens, options = {}) {
|
|
4000
|
+
function parseTokens(tokens, nodeType, options = {}) {
|
|
3516
4001
|
for (let i = 0; i < tokens.length; i++) {
|
|
3517
4002
|
const t = tokens[i];
|
|
3518
4003
|
if (t.typ == 'Whitespace' && ((i == 0 ||
|
|
3519
4004
|
i + 1 == tokens.length ||
|
|
3520
|
-
['Comma'
|
|
3521
|
-
(i > 0 &&
|
|
4005
|
+
['Comma'].includes(tokens[i + 1].typ) ||
|
|
4006
|
+
(i > 0 &&
|
|
4007
|
+
tokens[i + 1]?.typ != 'Literal' &&
|
|
4008
|
+
funcLike.includes(tokens[i - 1].typ) &&
|
|
4009
|
+
!['var', 'calc'].includes(tokens[i - 1].val))))) {
|
|
3522
4010
|
tokens.splice(i--, 1);
|
|
3523
4011
|
continue;
|
|
3524
4012
|
}
|
|
@@ -3563,7 +4051,7 @@ function parseTokens(tokens, options = {}) {
|
|
|
3563
4051
|
if (t.chi.length > 1) {
|
|
3564
4052
|
/*(<AttrToken>t).chi =*/
|
|
3565
4053
|
// @ts-ignore
|
|
3566
|
-
parseTokens(t.chi, options);
|
|
4054
|
+
parseTokens(t.chi, t.typ, options);
|
|
3567
4055
|
}
|
|
3568
4056
|
// @ts-ignore
|
|
3569
4057
|
t.chi.forEach(val => {
|
|
@@ -3616,9 +4104,9 @@ function parseTokens(tokens, options = {}) {
|
|
|
3616
4104
|
// @ts-ignore
|
|
3617
4105
|
t.chi.pop();
|
|
3618
4106
|
}
|
|
4107
|
+
let isColor = true;
|
|
3619
4108
|
// @ts-ignore
|
|
3620
4109
|
if (options.parseColor && ['rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'device-cmyk'].includes(t.val)) {
|
|
3621
|
-
let isColor = true;
|
|
3622
4110
|
// @ts-ignore
|
|
3623
4111
|
for (const v of t.chi) {
|
|
3624
4112
|
if (v.typ == 'Func' && v.val == 'var') {
|
|
@@ -3626,37 +4114,38 @@ function parseTokens(tokens, options = {}) {
|
|
|
3626
4114
|
break;
|
|
3627
4115
|
}
|
|
3628
4116
|
}
|
|
3629
|
-
if (
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
// @ts-ignore
|
|
3633
|
-
t.typ = 'Color';
|
|
3634
|
-
// @ts-ignore
|
|
3635
|
-
t.kin = t.val;
|
|
3636
|
-
// @ts-ignore
|
|
3637
|
-
let m = t.chi.length;
|
|
3638
|
-
while (m-- > 0) {
|
|
4117
|
+
if (isColor) {
|
|
4118
|
+
// @ts-ignore
|
|
4119
|
+
t.typ = 'Color';
|
|
3639
4120
|
// @ts-ignore
|
|
3640
|
-
|
|
4121
|
+
t.kin = t.val;
|
|
4122
|
+
// @ts-ignore
|
|
4123
|
+
let m = t.chi.length;
|
|
4124
|
+
while (m-- > 0) {
|
|
3641
4125
|
// @ts-ignore
|
|
3642
|
-
if (t.chi[m
|
|
4126
|
+
if (t.chi[m].typ == 'Literal') {
|
|
3643
4127
|
// @ts-ignore
|
|
3644
|
-
t.chi
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
4128
|
+
if (t.chi[m + 1]?.typ == 'Whitespace') {
|
|
4129
|
+
// @ts-ignore
|
|
4130
|
+
t.chi.splice(m + 1, 1);
|
|
4131
|
+
}
|
|
3648
4132
|
// @ts-ignore
|
|
3649
|
-
t.chi
|
|
3650
|
-
|
|
4133
|
+
if (t.chi[m - 1]?.typ == 'Whitespace') {
|
|
4134
|
+
// @ts-ignore
|
|
4135
|
+
t.chi.splice(m - 1, 1);
|
|
4136
|
+
m--;
|
|
4137
|
+
}
|
|
3651
4138
|
}
|
|
3652
4139
|
}
|
|
4140
|
+
continue;
|
|
3653
4141
|
}
|
|
3654
4142
|
}
|
|
3655
|
-
|
|
4143
|
+
if (t.typ == 'UrlFunc') {
|
|
3656
4144
|
// @ts-ignore
|
|
3657
4145
|
if (t.chi[0]?.typ == 'String') {
|
|
3658
4146
|
// @ts-ignore
|
|
3659
4147
|
const value = t.chi[0].val.slice(1, -1);
|
|
4148
|
+
// @ts-ignore
|
|
3660
4149
|
if (t.chi[0].val.slice(1, 5) != 'data:' && urlTokenMatcher.test(value)) {
|
|
3661
4150
|
// @ts-ignore
|
|
3662
4151
|
t.chi[0].typ = 'Url-token';
|
|
@@ -3674,7 +4163,7 @@ function parseTokens(tokens, options = {}) {
|
|
|
3674
4163
|
// @ts-ignore
|
|
3675
4164
|
if (t.chi.length > 0) {
|
|
3676
4165
|
// @ts-ignore
|
|
3677
|
-
parseTokens(t.chi, options);
|
|
4166
|
+
parseTokens(t.chi, t.typ, options);
|
|
3678
4167
|
if (t.typ == 'Pseudo-class-func' && t.val == ':is' && options.compress) {
|
|
3679
4168
|
//
|
|
3680
4169
|
const count = t.chi.filter(t => t.typ != 'Comment').length;
|
|
@@ -3740,7 +4229,7 @@ function* doWalk(node, parent, root) {
|
|
|
3740
4229
|
yield { node, parent, root };
|
|
3741
4230
|
if ('chi' in node) {
|
|
3742
4231
|
for (const child of node.chi) {
|
|
3743
|
-
yield* doWalk(child, node, (root
|
|
4232
|
+
yield* doWalk(child, node, (root ?? node));
|
|
3744
4233
|
}
|
|
3745
4234
|
}
|
|
3746
4235
|
}
|
|
@@ -3874,12 +4363,10 @@ async function load(url, currentFile) {
|
|
|
3874
4363
|
}
|
|
3875
4364
|
|
|
3876
4365
|
function parse(iterator, opt = {}) {
|
|
3877
|
-
Object.assign(opt, { load, resolve, cwd: opt.cwd ?? process.cwd() });
|
|
3878
|
-
return parse$1(iterator, opt);
|
|
4366
|
+
return parse$1(iterator, Object.assign(opt, { load, resolve, cwd: opt.cwd ?? process.cwd() }));
|
|
3879
4367
|
}
|
|
3880
4368
|
function transform(css, options = {}) {
|
|
3881
|
-
Object.assign(options, { load, resolve, cwd: options.cwd ?? process.cwd() });
|
|
3882
|
-
return transform$1(css, options);
|
|
4369
|
+
return transform$1(css, Object.assign(options, { load, resolve, cwd: options.cwd ?? process.cwd() }));
|
|
3883
4370
|
}
|
|
3884
4371
|
|
|
3885
4372
|
exports.deduplicate = deduplicate;
|
|
@@ -3889,6 +4376,7 @@ exports.hasDeclaration = hasDeclaration;
|
|
|
3889
4376
|
exports.load = load;
|
|
3890
4377
|
exports.matchUrl = matchUrl;
|
|
3891
4378
|
exports.parse = parse;
|
|
4379
|
+
exports.reduceSelector = reduceSelector;
|
|
3892
4380
|
exports.render = render;
|
|
3893
4381
|
exports.renderToken = renderToken;
|
|
3894
4382
|
exports.resolve = resolve;
|