@tbela99/css-parser 0.5.1 → 0.5.3
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 +12 -6
- package/dist/index-umd-web.js +111 -26
- package/dist/index.cjs +102 -19
- package/dist/index.d.ts +2 -0
- package/dist/lib/ast/expand.js +2 -1
- package/dist/lib/ast/math/expression.js +9 -1
- package/dist/lib/ast/minify.js +83 -14
- package/dist/lib/ast/types.js +1 -0
- package/dist/lib/parser/parse.js +4 -1
- package/dist/lib/renderer/color/rec2020.js +1 -1
- package/dist/lib/renderer/render.js +2 -1
- package/dist/web/load.js +9 -7
- package/package.json +4 -1
- package/syntax.md +62 -0
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
[](https://www.npmjs.com/package/@tbela99/css-parser) [](https://github.com/tbela99/css-parser/actions) [](https://www.npmjs.com/package/@tbela99/css-parser) [](https://github.com/tbela99/css-parser/actions) [](https://www.npmjs.com/package/@tbela99/css-parser)
|
|
2
2
|
|
|
3
3
|
# css-parser
|
|
4
4
|
|
|
@@ -497,30 +497,36 @@ for (const {node, parent, root} of walk(ast)) {
|
|
|
497
497
|
|
|
498
498
|
### Comment
|
|
499
499
|
|
|
500
|
-
- typ:
|
|
500
|
+
- typ: number
|
|
501
501
|
- val: string, the comment
|
|
502
502
|
|
|
503
503
|
### Declaration
|
|
504
504
|
|
|
505
|
-
- typ:
|
|
505
|
+
- typ: number
|
|
506
506
|
- nam: string, declaration name
|
|
507
507
|
- val: array of tokens
|
|
508
508
|
|
|
509
509
|
### Rule
|
|
510
510
|
|
|
511
|
-
- typ:
|
|
511
|
+
- typ: number
|
|
512
512
|
- sel: string, css selector
|
|
513
513
|
- chi: array of children
|
|
514
514
|
|
|
515
515
|
### AtRule
|
|
516
516
|
|
|
517
|
-
- typ:
|
|
517
|
+
- typ: number
|
|
518
518
|
- nam: string. AtRule name
|
|
519
519
|
- val: rule prelude
|
|
520
520
|
|
|
521
521
|
### AtRuleStyleSheet
|
|
522
522
|
|
|
523
|
-
- typ:
|
|
523
|
+
- typ: number
|
|
524
|
+
- chi: array of children
|
|
525
|
+
|
|
526
|
+
### KeyFrameRule
|
|
527
|
+
|
|
528
|
+
- typ: number
|
|
529
|
+
- sel: string, css selector
|
|
524
530
|
- chi: array of children
|
|
525
531
|
|
|
526
532
|
## Sourcemap
|
package/dist/index-umd-web.js
CHANGED
|
@@ -81,6 +81,7 @@
|
|
|
81
81
|
EnumToken[EnumToken["FractionTokenType"] = 69] = "FractionTokenType";
|
|
82
82
|
EnumToken[EnumToken["IdenListTokenType"] = 70] = "IdenListTokenType";
|
|
83
83
|
EnumToken[EnumToken["GridTemplateFuncTokenType"] = 71] = "GridTemplateFuncTokenType";
|
|
84
|
+
EnumToken[EnumToken["KeyFrameRuleNodeType"] = 72] = "KeyFrameRuleNodeType";
|
|
84
85
|
/* aliases */
|
|
85
86
|
EnumToken[EnumToken["Time"] = 25] = "Time";
|
|
86
87
|
EnumToken[EnumToken["Iden"] = 7] = "Iden";
|
|
@@ -1480,7 +1481,7 @@
|
|
|
1480
1481
|
return val / 4.5;
|
|
1481
1482
|
}
|
|
1482
1483
|
return sign * (Math.pow((abs + α - 1) / α, 1 / 0.45));
|
|
1483
|
-
}).concat(
|
|
1484
|
+
}).concat([] );
|
|
1484
1485
|
}
|
|
1485
1486
|
function lrec20202rec2020(r, g, b, a) {
|
|
1486
1487
|
// convert an array of linear-light rec2020 RGB in the range 0.0-1.0
|
|
@@ -2510,7 +2511,15 @@
|
|
|
2510
2511
|
* @param tokens
|
|
2511
2512
|
*/
|
|
2512
2513
|
function evaluate(tokens) {
|
|
2513
|
-
|
|
2514
|
+
let nodes;
|
|
2515
|
+
try {
|
|
2516
|
+
nodes = inlineExpression(evaluateExpression(buildExpression(tokens)));
|
|
2517
|
+
}
|
|
2518
|
+
catch (e) {
|
|
2519
|
+
// console.error({tokens});
|
|
2520
|
+
// console.error(e);
|
|
2521
|
+
return tokens;
|
|
2522
|
+
}
|
|
2514
2523
|
if (nodes.length <= 1) {
|
|
2515
2524
|
return nodes;
|
|
2516
2525
|
}
|
|
@@ -3036,7 +3045,7 @@
|
|
|
3036
3045
|
return result;
|
|
3037
3046
|
}
|
|
3038
3047
|
function updateSourceMap(node, options, cache, sourcemap, position, str) {
|
|
3039
|
-
if ([exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType].includes(node.typ)) {
|
|
3048
|
+
if ([exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType, exports.EnumToken.KeyFrameRuleNodeType].includes(node.typ)) {
|
|
3040
3049
|
let src = node.loc?.src ?? '';
|
|
3041
3050
|
let output = options.output ?? '';
|
|
3042
3051
|
if (!(src in cache)) {
|
|
@@ -3096,6 +3105,7 @@
|
|
|
3096
3105
|
}, '');
|
|
3097
3106
|
case exports.EnumToken.AtRuleNodeType:
|
|
3098
3107
|
case exports.EnumToken.RuleNodeType:
|
|
3108
|
+
case exports.EnumToken.KeyFrameRuleNodeType:
|
|
3099
3109
|
if (data.typ == exports.EnumToken.AtRuleNodeType && !('chi' in data)) {
|
|
3100
3110
|
return `${indent}@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val};`;
|
|
3101
3111
|
}
|
|
@@ -6446,6 +6456,9 @@
|
|
|
6446
6456
|
const position = map.get(tokens[0]);
|
|
6447
6457
|
const uniq = new Map;
|
|
6448
6458
|
parseTokens(tokens, { minify: true }).reduce((acc, curr, index, array) => {
|
|
6459
|
+
if (curr.typ == exports.EnumToken.CommentTokenType) {
|
|
6460
|
+
return acc;
|
|
6461
|
+
}
|
|
6449
6462
|
if (curr.typ == exports.EnumToken.WhitespaceTokenType) {
|
|
6450
6463
|
if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
|
|
6451
6464
|
trimWhiteSpace.includes(array[index + 1]?.typ) ||
|
|
@@ -6467,7 +6480,7 @@
|
|
|
6467
6480
|
return acc;
|
|
6468
6481
|
}, uniq);
|
|
6469
6482
|
const node = {
|
|
6470
|
-
typ: exports.EnumToken.RuleNodeType,
|
|
6483
|
+
typ: context.typ == exports.EnumToken.AtRuleNodeType && context.nam == 'keyframes' ? exports.EnumToken.KeyFrameRuleNodeType : exports.EnumToken.RuleNodeType,
|
|
6471
6484
|
// @ts-ignore
|
|
6472
6485
|
sel: [...uniq.keys()].join(','),
|
|
6473
6486
|
chi: []
|
|
@@ -7251,7 +7264,8 @@
|
|
|
7251
7264
|
for (const t of walkValues(tokens)) {
|
|
7252
7265
|
if (t.value.typ == exports.EnumToken.LiteralTokenType) {
|
|
7253
7266
|
if (t.value.val == '&') {
|
|
7254
|
-
|
|
7267
|
+
const rule = splitRule(replace);
|
|
7268
|
+
t.value.val = rule.length > 1 ? ':is(' + replace + ')' : replace;
|
|
7255
7269
|
}
|
|
7256
7270
|
else if (t.value.val.length > 1 && t.value.val.charAt(0) == '&') {
|
|
7257
7271
|
t.value.val = replaceCompoundLiteral(t.value.val, replace);
|
|
@@ -8406,7 +8420,7 @@
|
|
|
8406
8420
|
const features = Object.values(allFeatures).sort((a, b) => a.ordering - b.ordering);
|
|
8407
8421
|
function minify(ast, options = {}, recursive = false, errors, nestingContent, context = {}) {
|
|
8408
8422
|
if (!('nodes' in context)) {
|
|
8409
|
-
context.nodes = new
|
|
8423
|
+
context.nodes = new Set;
|
|
8410
8424
|
}
|
|
8411
8425
|
if (context.nodes.has(ast)) {
|
|
8412
8426
|
return ast;
|
|
@@ -8435,7 +8449,7 @@
|
|
|
8435
8449
|
curr.splice(0, 2);
|
|
8436
8450
|
}
|
|
8437
8451
|
else if (combinators.includes(curr[1])) {
|
|
8438
|
-
curr.
|
|
8452
|
+
curr.shift();
|
|
8439
8453
|
}
|
|
8440
8454
|
}
|
|
8441
8455
|
else if (ast.typ == exports.EnumToken.RuleNodeType && (isIdent(curr[0]) || isFunction(curr[0]))) {
|
|
@@ -8637,7 +8651,7 @@
|
|
|
8637
8651
|
}
|
|
8638
8652
|
if (shouldMerge) {
|
|
8639
8653
|
// @ts-ignore
|
|
8640
|
-
if ((node.typ == exports.EnumToken.RuleNodeType && node.sel == previous.sel) ||
|
|
8654
|
+
if (((node.typ == exports.EnumToken.RuleNodeType || node.typ == exports.EnumToken.KeyFrameRuleNodeType) && node.sel == previous.sel) ||
|
|
8641
8655
|
// @ts-ignore
|
|
8642
8656
|
(node.typ == exports.EnumToken.AtRuleNodeType) && node.val != 'font-face' && node.val == previous.val) {
|
|
8643
8657
|
// @ts-ignore
|
|
@@ -8656,32 +8670,33 @@
|
|
|
8656
8670
|
nodeIndex = i;
|
|
8657
8671
|
continue;
|
|
8658
8672
|
}
|
|
8659
|
-
else if (node.typ ==
|
|
8673
|
+
else if (node.typ == previous?.typ && [exports.EnumToken.KeyFrameRuleNodeType, exports.EnumToken.RuleNodeType].includes(node.typ)) {
|
|
8660
8674
|
const intersect = diff(previous, node, reducer, options);
|
|
8661
8675
|
if (intersect != null) {
|
|
8662
8676
|
if (intersect.node1.chi.length == 0) {
|
|
8663
8677
|
// @ts-ignore
|
|
8664
8678
|
ast.chi.splice(i--, 1);
|
|
8665
8679
|
// @ts-ignore
|
|
8666
|
-
node = ast.chi[i];
|
|
8680
|
+
// node = ast.chi[i];
|
|
8667
8681
|
}
|
|
8668
8682
|
else {
|
|
8669
8683
|
// @ts-ignore
|
|
8670
8684
|
ast.chi.splice(i, 1, intersect.node1);
|
|
8671
|
-
node = intersect.node1;
|
|
8685
|
+
// node = ast.chi intersect.node1;
|
|
8672
8686
|
}
|
|
8673
8687
|
if (intersect.node2.chi.length == 0) {
|
|
8674
8688
|
// @ts-ignore
|
|
8675
8689
|
ast.chi.splice(nodeIndex, 1, intersect.result);
|
|
8676
|
-
previous = intersect.result;
|
|
8677
8690
|
}
|
|
8678
8691
|
else {
|
|
8679
8692
|
// @ts-ignore
|
|
8680
8693
|
ast.chi.splice(nodeIndex, 1, intersect.result, intersect.node2);
|
|
8681
|
-
previous = intersect.result;
|
|
8682
8694
|
// @ts-ignore
|
|
8683
|
-
i = nodeIndex;
|
|
8695
|
+
i = (nodeIndex ?? 0) + 1;
|
|
8684
8696
|
}
|
|
8697
|
+
reduceRuleSelector(intersect.result);
|
|
8698
|
+
previous = intersect.result;
|
|
8699
|
+
nodeIndex = i;
|
|
8685
8700
|
}
|
|
8686
8701
|
}
|
|
8687
8702
|
}
|
|
@@ -8811,11 +8826,16 @@
|
|
|
8811
8826
|
// combinator
|
|
8812
8827
|
if (combinators.includes(optimized.at(-1))) {
|
|
8813
8828
|
const combinator = optimized.pop();
|
|
8814
|
-
selector.forEach(selector => selector.unshift(combinator));
|
|
8829
|
+
selector.forEach((selector) => selector.unshift(combinator));
|
|
8815
8830
|
}
|
|
8816
8831
|
let reducible = optimized.length == 1;
|
|
8817
|
-
if (optimized[0] == '&'
|
|
8818
|
-
optimized
|
|
8832
|
+
if (optimized[0] == '&') {
|
|
8833
|
+
if (optimized[1] == ' ') {
|
|
8834
|
+
optimized.splice(0, 2);
|
|
8835
|
+
}
|
|
8836
|
+
// else if (combinators.includes(optimized[1])) {
|
|
8837
|
+
//
|
|
8838
|
+
// }
|
|
8819
8839
|
}
|
|
8820
8840
|
if (optimized.length == 0 ||
|
|
8821
8841
|
(optimized[0].charAt(0) == '&' ||
|
|
@@ -8823,7 +8843,7 @@
|
|
|
8823
8843
|
return {
|
|
8824
8844
|
match: false,
|
|
8825
8845
|
optimized,
|
|
8826
|
-
selector: selector.map(selector => selector[0] == '&' && selector[1] == ' ' ? selector.slice(2) : selector),
|
|
8846
|
+
selector: selector.map((selector) => selector[0] == '&' && selector[1] == ' ' ? selector.slice(2) : (selector)),
|
|
8827
8847
|
reducible: selector.length > 1 && selector.every((selector) => !combinators.includes(selector[0]))
|
|
8828
8848
|
};
|
|
8829
8849
|
}
|
|
@@ -8903,6 +8923,18 @@
|
|
|
8903
8923
|
result.push([]);
|
|
8904
8924
|
continue;
|
|
8905
8925
|
}
|
|
8926
|
+
if (chr == ':') {
|
|
8927
|
+
if (str !== '') {
|
|
8928
|
+
// @ts-ignore
|
|
8929
|
+
result.at(-1).push(str);
|
|
8930
|
+
str = '';
|
|
8931
|
+
}
|
|
8932
|
+
if (buffer.charAt(i + 1) == ':') {
|
|
8933
|
+
chr += buffer.charAt(++i);
|
|
8934
|
+
}
|
|
8935
|
+
str += chr;
|
|
8936
|
+
continue;
|
|
8937
|
+
}
|
|
8906
8938
|
str += chr;
|
|
8907
8939
|
if (chr == '\\') {
|
|
8908
8940
|
str += buffer.charAt(++i);
|
|
@@ -9204,6 +9236,52 @@
|
|
|
9204
9236
|
const raw1 = node1.raw;
|
|
9205
9237
|
// @ts-ignore
|
|
9206
9238
|
const raw2 = node2.raw;
|
|
9239
|
+
if (raw1 != null && raw2 != null) {
|
|
9240
|
+
const prefixes1 = new Set;
|
|
9241
|
+
const prefixes2 = new Set;
|
|
9242
|
+
for (const token1 of raw1) {
|
|
9243
|
+
for (const t of token1) {
|
|
9244
|
+
if (t[0] == ':') {
|
|
9245
|
+
const matches = t.match(/::?-([a-z]+)-/);
|
|
9246
|
+
if (matches == null) {
|
|
9247
|
+
continue;
|
|
9248
|
+
}
|
|
9249
|
+
prefixes1.add(matches[1]);
|
|
9250
|
+
if (prefixes1.size > 1) {
|
|
9251
|
+
break;
|
|
9252
|
+
}
|
|
9253
|
+
}
|
|
9254
|
+
}
|
|
9255
|
+
if (prefixes1.size > 1) {
|
|
9256
|
+
break;
|
|
9257
|
+
}
|
|
9258
|
+
}
|
|
9259
|
+
for (const token2 of raw2) {
|
|
9260
|
+
for (const t of token2) {
|
|
9261
|
+
if (t[0] == ':') {
|
|
9262
|
+
const matches = t.match(/::?-([a-z]+)-/);
|
|
9263
|
+
if (matches == null) {
|
|
9264
|
+
continue;
|
|
9265
|
+
}
|
|
9266
|
+
prefixes2.add(matches[1]);
|
|
9267
|
+
if (prefixes2.size > 1) {
|
|
9268
|
+
break;
|
|
9269
|
+
}
|
|
9270
|
+
}
|
|
9271
|
+
}
|
|
9272
|
+
if (prefixes2.size > 1) {
|
|
9273
|
+
break;
|
|
9274
|
+
}
|
|
9275
|
+
}
|
|
9276
|
+
if (prefixes1.size != prefixes2.size) {
|
|
9277
|
+
return null;
|
|
9278
|
+
}
|
|
9279
|
+
for (const prefix of prefixes1) {
|
|
9280
|
+
if (!prefixes2.has(prefix)) {
|
|
9281
|
+
return null;
|
|
9282
|
+
}
|
|
9283
|
+
}
|
|
9284
|
+
}
|
|
9207
9285
|
// @ts-ignore
|
|
9208
9286
|
node1 = { ...node1, chi: node1.chi.slice() };
|
|
9209
9287
|
node2 = { ...node2, chi: node2.chi.slice() };
|
|
@@ -9240,7 +9318,7 @@
|
|
|
9240
9318
|
const result = (intersect.length == 0 ? null : {
|
|
9241
9319
|
...node1,
|
|
9242
9320
|
// @ts-ignore
|
|
9243
|
-
sel: [...new Set([...(n1?.raw?.reduce(reducer, [])
|
|
9321
|
+
sel: [...new Set([...(n1?.raw?.reduce(reducer, []) ?? splitRule(n1.sel)).concat(n2?.raw?.reduce(reducer, []) ?? splitRule(n2.sel))])].join(','),
|
|
9244
9322
|
chi: intersect.reverse()
|
|
9245
9323
|
});
|
|
9246
9324
|
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)) {
|
|
@@ -9264,6 +9342,11 @@
|
|
|
9264
9342
|
Object.defineProperty(node, 'optimized', { ...definedPropertySettings, value: optimized });
|
|
9265
9343
|
}
|
|
9266
9344
|
if (optimized != null && optimized.match && optimized.reducible && optimized.selector.length > 1) {
|
|
9345
|
+
for (const selector of optimized.selector) {
|
|
9346
|
+
if (selector.length > 1 && selector[0] == '&' && combinators.includes(selector[1])) {
|
|
9347
|
+
selector.shift();
|
|
9348
|
+
}
|
|
9349
|
+
}
|
|
9267
9350
|
const raw = [
|
|
9268
9351
|
[
|
|
9269
9352
|
optimized.optimized[0], ':is('
|
|
@@ -9391,16 +9474,18 @@
|
|
|
9391
9474
|
return response.text();
|
|
9392
9475
|
}
|
|
9393
9476
|
async function load(url, currentFile) {
|
|
9477
|
+
let t;
|
|
9394
9478
|
if (matchUrl.test(url)) {
|
|
9395
|
-
|
|
9479
|
+
t = new URL(url);
|
|
9396
9480
|
}
|
|
9397
|
-
if (matchUrl.test(currentFile)) {
|
|
9398
|
-
|
|
9481
|
+
else if (matchUrl.test(currentFile)) {
|
|
9482
|
+
t = new URL(url, currentFile);
|
|
9483
|
+
}
|
|
9484
|
+
else {
|
|
9485
|
+
const path = resolve(url, currentFile).absolute;
|
|
9486
|
+
t = new URL(path, self.origin);
|
|
9399
9487
|
}
|
|
9400
|
-
|
|
9401
|
-
const t = new URL(path, self.origin);
|
|
9402
|
-
// return fetch(new URL(url, new URL(currentFile, self.location.href).href)).then(parseResponse);
|
|
9403
|
-
return fetch(url, t.origin != self.location.origin ? { mode: 'cors' } : {}).then(parseResponse);
|
|
9488
|
+
return fetch(t, t.origin != self.origin ? { mode: 'cors' } : {}).then(parseResponse);
|
|
9404
9489
|
}
|
|
9405
9490
|
|
|
9406
9491
|
function render(data, options = {}) {
|
package/dist/index.cjs
CHANGED
|
@@ -79,6 +79,7 @@ exports.EnumToken = void 0;
|
|
|
79
79
|
EnumToken[EnumToken["FractionTokenType"] = 69] = "FractionTokenType";
|
|
80
80
|
EnumToken[EnumToken["IdenListTokenType"] = 70] = "IdenListTokenType";
|
|
81
81
|
EnumToken[EnumToken["GridTemplateFuncTokenType"] = 71] = "GridTemplateFuncTokenType";
|
|
82
|
+
EnumToken[EnumToken["KeyFrameRuleNodeType"] = 72] = "KeyFrameRuleNodeType";
|
|
82
83
|
/* aliases */
|
|
83
84
|
EnumToken[EnumToken["Time"] = 25] = "Time";
|
|
84
85
|
EnumToken[EnumToken["Iden"] = 7] = "Iden";
|
|
@@ -1478,7 +1479,7 @@ function rec20202lrec2020(r, g, b, a) {
|
|
|
1478
1479
|
return val / 4.5;
|
|
1479
1480
|
}
|
|
1480
1481
|
return sign * (Math.pow((abs + α - 1) / α, 1 / 0.45));
|
|
1481
|
-
}).concat(
|
|
1482
|
+
}).concat([] );
|
|
1482
1483
|
}
|
|
1483
1484
|
function lrec20202rec2020(r, g, b, a) {
|
|
1484
1485
|
// convert an array of linear-light rec2020 RGB in the range 0.0-1.0
|
|
@@ -2508,7 +2509,15 @@ function simplify(a, b) {
|
|
|
2508
2509
|
* @param tokens
|
|
2509
2510
|
*/
|
|
2510
2511
|
function evaluate(tokens) {
|
|
2511
|
-
|
|
2512
|
+
let nodes;
|
|
2513
|
+
try {
|
|
2514
|
+
nodes = inlineExpression(evaluateExpression(buildExpression(tokens)));
|
|
2515
|
+
}
|
|
2516
|
+
catch (e) {
|
|
2517
|
+
// console.error({tokens});
|
|
2518
|
+
// console.error(e);
|
|
2519
|
+
return tokens;
|
|
2520
|
+
}
|
|
2512
2521
|
if (nodes.length <= 1) {
|
|
2513
2522
|
return nodes;
|
|
2514
2523
|
}
|
|
@@ -3034,7 +3043,7 @@ function doRender(data, options = {}) {
|
|
|
3034
3043
|
return result;
|
|
3035
3044
|
}
|
|
3036
3045
|
function updateSourceMap(node, options, cache, sourcemap, position, str) {
|
|
3037
|
-
if ([exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType].includes(node.typ)) {
|
|
3046
|
+
if ([exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType, exports.EnumToken.KeyFrameRuleNodeType].includes(node.typ)) {
|
|
3038
3047
|
let src = node.loc?.src ?? '';
|
|
3039
3048
|
let output = options.output ?? '';
|
|
3040
3049
|
if (!(src in cache)) {
|
|
@@ -3094,6 +3103,7 @@ function renderAstNode(data, options, sourcemap, position, errors, reducer, cach
|
|
|
3094
3103
|
}, '');
|
|
3095
3104
|
case exports.EnumToken.AtRuleNodeType:
|
|
3096
3105
|
case exports.EnumToken.RuleNodeType:
|
|
3106
|
+
case exports.EnumToken.KeyFrameRuleNodeType:
|
|
3097
3107
|
if (data.typ == exports.EnumToken.AtRuleNodeType && !('chi' in data)) {
|
|
3098
3108
|
return `${indent}@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val};`;
|
|
3099
3109
|
}
|
|
@@ -6444,6 +6454,9 @@ async function parseNode(results, context, stats, options, errors, src, map) {
|
|
|
6444
6454
|
const position = map.get(tokens[0]);
|
|
6445
6455
|
const uniq = new Map;
|
|
6446
6456
|
parseTokens(tokens, { minify: true }).reduce((acc, curr, index, array) => {
|
|
6457
|
+
if (curr.typ == exports.EnumToken.CommentTokenType) {
|
|
6458
|
+
return acc;
|
|
6459
|
+
}
|
|
6447
6460
|
if (curr.typ == exports.EnumToken.WhitespaceTokenType) {
|
|
6448
6461
|
if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
|
|
6449
6462
|
trimWhiteSpace.includes(array[index + 1]?.typ) ||
|
|
@@ -6465,7 +6478,7 @@ async function parseNode(results, context, stats, options, errors, src, map) {
|
|
|
6465
6478
|
return acc;
|
|
6466
6479
|
}, uniq);
|
|
6467
6480
|
const node = {
|
|
6468
|
-
typ: exports.EnumToken.RuleNodeType,
|
|
6481
|
+
typ: context.typ == exports.EnumToken.AtRuleNodeType && context.nam == 'keyframes' ? exports.EnumToken.KeyFrameRuleNodeType : exports.EnumToken.RuleNodeType,
|
|
6469
6482
|
// @ts-ignore
|
|
6470
6483
|
sel: [...uniq.keys()].join(','),
|
|
6471
6484
|
chi: []
|
|
@@ -7249,7 +7262,8 @@ function replaceCompound(input, replace) {
|
|
|
7249
7262
|
for (const t of walkValues(tokens)) {
|
|
7250
7263
|
if (t.value.typ == exports.EnumToken.LiteralTokenType) {
|
|
7251
7264
|
if (t.value.val == '&') {
|
|
7252
|
-
|
|
7265
|
+
const rule = splitRule(replace);
|
|
7266
|
+
t.value.val = rule.length > 1 ? ':is(' + replace + ')' : replace;
|
|
7253
7267
|
}
|
|
7254
7268
|
else if (t.value.val.length > 1 && t.value.val.charAt(0) == '&') {
|
|
7255
7269
|
t.value.val = replaceCompoundLiteral(t.value.val, replace);
|
|
@@ -8404,7 +8418,7 @@ const notEndingWith = ['(', '['].concat(combinators);
|
|
|
8404
8418
|
const features = Object.values(allFeatures).sort((a, b) => a.ordering - b.ordering);
|
|
8405
8419
|
function minify(ast, options = {}, recursive = false, errors, nestingContent, context = {}) {
|
|
8406
8420
|
if (!('nodes' in context)) {
|
|
8407
|
-
context.nodes = new
|
|
8421
|
+
context.nodes = new Set;
|
|
8408
8422
|
}
|
|
8409
8423
|
if (context.nodes.has(ast)) {
|
|
8410
8424
|
return ast;
|
|
@@ -8433,7 +8447,7 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
|
|
|
8433
8447
|
curr.splice(0, 2);
|
|
8434
8448
|
}
|
|
8435
8449
|
else if (combinators.includes(curr[1])) {
|
|
8436
|
-
curr.
|
|
8450
|
+
curr.shift();
|
|
8437
8451
|
}
|
|
8438
8452
|
}
|
|
8439
8453
|
else if (ast.typ == exports.EnumToken.RuleNodeType && (isIdent(curr[0]) || isFunction(curr[0]))) {
|
|
@@ -8635,7 +8649,7 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
|
|
|
8635
8649
|
}
|
|
8636
8650
|
if (shouldMerge) {
|
|
8637
8651
|
// @ts-ignore
|
|
8638
|
-
if ((node.typ == exports.EnumToken.RuleNodeType && node.sel == previous.sel) ||
|
|
8652
|
+
if (((node.typ == exports.EnumToken.RuleNodeType || node.typ == exports.EnumToken.KeyFrameRuleNodeType) && node.sel == previous.sel) ||
|
|
8639
8653
|
// @ts-ignore
|
|
8640
8654
|
(node.typ == exports.EnumToken.AtRuleNodeType) && node.val != 'font-face' && node.val == previous.val) {
|
|
8641
8655
|
// @ts-ignore
|
|
@@ -8654,32 +8668,33 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
|
|
|
8654
8668
|
nodeIndex = i;
|
|
8655
8669
|
continue;
|
|
8656
8670
|
}
|
|
8657
|
-
else if (node.typ ==
|
|
8671
|
+
else if (node.typ == previous?.typ && [exports.EnumToken.KeyFrameRuleNodeType, exports.EnumToken.RuleNodeType].includes(node.typ)) {
|
|
8658
8672
|
const intersect = diff(previous, node, reducer, options);
|
|
8659
8673
|
if (intersect != null) {
|
|
8660
8674
|
if (intersect.node1.chi.length == 0) {
|
|
8661
8675
|
// @ts-ignore
|
|
8662
8676
|
ast.chi.splice(i--, 1);
|
|
8663
8677
|
// @ts-ignore
|
|
8664
|
-
node = ast.chi[i];
|
|
8678
|
+
// node = ast.chi[i];
|
|
8665
8679
|
}
|
|
8666
8680
|
else {
|
|
8667
8681
|
// @ts-ignore
|
|
8668
8682
|
ast.chi.splice(i, 1, intersect.node1);
|
|
8669
|
-
node = intersect.node1;
|
|
8683
|
+
// node = ast.chi intersect.node1;
|
|
8670
8684
|
}
|
|
8671
8685
|
if (intersect.node2.chi.length == 0) {
|
|
8672
8686
|
// @ts-ignore
|
|
8673
8687
|
ast.chi.splice(nodeIndex, 1, intersect.result);
|
|
8674
|
-
previous = intersect.result;
|
|
8675
8688
|
}
|
|
8676
8689
|
else {
|
|
8677
8690
|
// @ts-ignore
|
|
8678
8691
|
ast.chi.splice(nodeIndex, 1, intersect.result, intersect.node2);
|
|
8679
|
-
previous = intersect.result;
|
|
8680
8692
|
// @ts-ignore
|
|
8681
|
-
i = nodeIndex;
|
|
8693
|
+
i = (nodeIndex ?? 0) + 1;
|
|
8682
8694
|
}
|
|
8695
|
+
reduceRuleSelector(intersect.result);
|
|
8696
|
+
previous = intersect.result;
|
|
8697
|
+
nodeIndex = i;
|
|
8683
8698
|
}
|
|
8684
8699
|
}
|
|
8685
8700
|
}
|
|
@@ -8809,11 +8824,16 @@ function reduceSelector(selector) {
|
|
|
8809
8824
|
// combinator
|
|
8810
8825
|
if (combinators.includes(optimized.at(-1))) {
|
|
8811
8826
|
const combinator = optimized.pop();
|
|
8812
|
-
selector.forEach(selector => selector.unshift(combinator));
|
|
8827
|
+
selector.forEach((selector) => selector.unshift(combinator));
|
|
8813
8828
|
}
|
|
8814
8829
|
let reducible = optimized.length == 1;
|
|
8815
|
-
if (optimized[0] == '&'
|
|
8816
|
-
optimized
|
|
8830
|
+
if (optimized[0] == '&') {
|
|
8831
|
+
if (optimized[1] == ' ') {
|
|
8832
|
+
optimized.splice(0, 2);
|
|
8833
|
+
}
|
|
8834
|
+
// else if (combinators.includes(optimized[1])) {
|
|
8835
|
+
//
|
|
8836
|
+
// }
|
|
8817
8837
|
}
|
|
8818
8838
|
if (optimized.length == 0 ||
|
|
8819
8839
|
(optimized[0].charAt(0) == '&' ||
|
|
@@ -8821,7 +8841,7 @@ function reduceSelector(selector) {
|
|
|
8821
8841
|
return {
|
|
8822
8842
|
match: false,
|
|
8823
8843
|
optimized,
|
|
8824
|
-
selector: selector.map(selector => selector[0] == '&' && selector[1] == ' ' ? selector.slice(2) : selector),
|
|
8844
|
+
selector: selector.map((selector) => selector[0] == '&' && selector[1] == ' ' ? selector.slice(2) : (selector)),
|
|
8825
8845
|
reducible: selector.length > 1 && selector.every((selector) => !combinators.includes(selector[0]))
|
|
8826
8846
|
};
|
|
8827
8847
|
}
|
|
@@ -8901,6 +8921,18 @@ function splitRule(buffer) {
|
|
|
8901
8921
|
result.push([]);
|
|
8902
8922
|
continue;
|
|
8903
8923
|
}
|
|
8924
|
+
if (chr == ':') {
|
|
8925
|
+
if (str !== '') {
|
|
8926
|
+
// @ts-ignore
|
|
8927
|
+
result.at(-1).push(str);
|
|
8928
|
+
str = '';
|
|
8929
|
+
}
|
|
8930
|
+
if (buffer.charAt(i + 1) == ':') {
|
|
8931
|
+
chr += buffer.charAt(++i);
|
|
8932
|
+
}
|
|
8933
|
+
str += chr;
|
|
8934
|
+
continue;
|
|
8935
|
+
}
|
|
8904
8936
|
str += chr;
|
|
8905
8937
|
if (chr == '\\') {
|
|
8906
8938
|
str += buffer.charAt(++i);
|
|
@@ -9202,6 +9234,52 @@ function diff(n1, n2, reducer, options = {}) {
|
|
|
9202
9234
|
const raw1 = node1.raw;
|
|
9203
9235
|
// @ts-ignore
|
|
9204
9236
|
const raw2 = node2.raw;
|
|
9237
|
+
if (raw1 != null && raw2 != null) {
|
|
9238
|
+
const prefixes1 = new Set;
|
|
9239
|
+
const prefixes2 = new Set;
|
|
9240
|
+
for (const token1 of raw1) {
|
|
9241
|
+
for (const t of token1) {
|
|
9242
|
+
if (t[0] == ':') {
|
|
9243
|
+
const matches = t.match(/::?-([a-z]+)-/);
|
|
9244
|
+
if (matches == null) {
|
|
9245
|
+
continue;
|
|
9246
|
+
}
|
|
9247
|
+
prefixes1.add(matches[1]);
|
|
9248
|
+
if (prefixes1.size > 1) {
|
|
9249
|
+
break;
|
|
9250
|
+
}
|
|
9251
|
+
}
|
|
9252
|
+
}
|
|
9253
|
+
if (prefixes1.size > 1) {
|
|
9254
|
+
break;
|
|
9255
|
+
}
|
|
9256
|
+
}
|
|
9257
|
+
for (const token2 of raw2) {
|
|
9258
|
+
for (const t of token2) {
|
|
9259
|
+
if (t[0] == ':') {
|
|
9260
|
+
const matches = t.match(/::?-([a-z]+)-/);
|
|
9261
|
+
if (matches == null) {
|
|
9262
|
+
continue;
|
|
9263
|
+
}
|
|
9264
|
+
prefixes2.add(matches[1]);
|
|
9265
|
+
if (prefixes2.size > 1) {
|
|
9266
|
+
break;
|
|
9267
|
+
}
|
|
9268
|
+
}
|
|
9269
|
+
}
|
|
9270
|
+
if (prefixes2.size > 1) {
|
|
9271
|
+
break;
|
|
9272
|
+
}
|
|
9273
|
+
}
|
|
9274
|
+
if (prefixes1.size != prefixes2.size) {
|
|
9275
|
+
return null;
|
|
9276
|
+
}
|
|
9277
|
+
for (const prefix of prefixes1) {
|
|
9278
|
+
if (!prefixes2.has(prefix)) {
|
|
9279
|
+
return null;
|
|
9280
|
+
}
|
|
9281
|
+
}
|
|
9282
|
+
}
|
|
9205
9283
|
// @ts-ignore
|
|
9206
9284
|
node1 = { ...node1, chi: node1.chi.slice() };
|
|
9207
9285
|
node2 = { ...node2, chi: node2.chi.slice() };
|
|
@@ -9238,7 +9316,7 @@ function diff(n1, n2, reducer, options = {}) {
|
|
|
9238
9316
|
const result = (intersect.length == 0 ? null : {
|
|
9239
9317
|
...node1,
|
|
9240
9318
|
// @ts-ignore
|
|
9241
|
-
sel: [...new Set([...(n1?.raw?.reduce(reducer, [])
|
|
9319
|
+
sel: [...new Set([...(n1?.raw?.reduce(reducer, []) ?? splitRule(n1.sel)).concat(n2?.raw?.reduce(reducer, []) ?? splitRule(n2.sel))])].join(','),
|
|
9242
9320
|
chi: intersect.reverse()
|
|
9243
9321
|
});
|
|
9244
9322
|
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)) {
|
|
@@ -9262,6 +9340,11 @@ function reduceRuleSelector(node) {
|
|
|
9262
9340
|
Object.defineProperty(node, 'optimized', { ...definedPropertySettings, value: optimized });
|
|
9263
9341
|
}
|
|
9264
9342
|
if (optimized != null && optimized.match && optimized.reducible && optimized.selector.length > 1) {
|
|
9343
|
+
for (const selector of optimized.selector) {
|
|
9344
|
+
if (selector.length > 1 && selector[0] == '&' && combinators.includes(selector[1])) {
|
|
9345
|
+
selector.shift();
|
|
9346
|
+
}
|
|
9347
|
+
}
|
|
9265
9348
|
const raw = [
|
|
9266
9349
|
[
|
|
9267
9350
|
optimized.optimized[0], ':is('
|
package/dist/index.d.ts
CHANGED
|
@@ -71,6 +71,7 @@ declare enum EnumToken {
|
|
|
71
71
|
FractionTokenType = 69,
|
|
72
72
|
IdenListTokenType = 70,
|
|
73
73
|
GridTemplateFuncTokenType = 71,
|
|
74
|
+
KeyFrameRuleNodeType = 72,
|
|
74
75
|
Time = 25,
|
|
75
76
|
Iden = 7,
|
|
76
77
|
EOF = 47,
|
|
@@ -664,6 +665,7 @@ export declare interface AstDeclaration extends Node {
|
|
|
664
665
|
typ: EnumToken.DeclarationNodeType
|
|
665
666
|
}
|
|
666
667
|
|
|
668
|
+
|
|
667
669
|
export declare interface AstRule extends Node {
|
|
668
670
|
|
|
669
671
|
typ: EnumToken.RuleNodeType;
|
package/dist/lib/ast/expand.js
CHANGED
|
@@ -121,7 +121,8 @@ function replaceCompound(input, replace) {
|
|
|
121
121
|
for (const t of walkValues(tokens)) {
|
|
122
122
|
if (t.value.typ == EnumToken.LiteralTokenType) {
|
|
123
123
|
if (t.value.val == '&') {
|
|
124
|
-
|
|
124
|
+
const rule = splitRule(replace);
|
|
125
|
+
t.value.val = rule.length > 1 ? ':is(' + replace + ')' : replace;
|
|
125
126
|
}
|
|
126
127
|
else if (t.value.val.length > 1 && t.value.val.charAt(0) == '&') {
|
|
127
128
|
t.value.val = replaceCompoundLiteral(t.value.val, replace);
|
|
@@ -7,7 +7,15 @@ import { reduceNumber } from '../../renderer/render.js';
|
|
|
7
7
|
* @param tokens
|
|
8
8
|
*/
|
|
9
9
|
function evaluate(tokens) {
|
|
10
|
-
|
|
10
|
+
let nodes;
|
|
11
|
+
try {
|
|
12
|
+
nodes = inlineExpression(evaluateExpression(buildExpression(tokens)));
|
|
13
|
+
}
|
|
14
|
+
catch (e) {
|
|
15
|
+
// console.error({tokens});
|
|
16
|
+
// console.error(e);
|
|
17
|
+
return tokens;
|
|
18
|
+
}
|
|
11
19
|
if (nodes.length <= 1) {
|
|
12
20
|
return nodes;
|
|
13
21
|
}
|
package/dist/lib/ast/minify.js
CHANGED
|
@@ -14,7 +14,7 @@ const notEndingWith = ['(', '['].concat(combinators);
|
|
|
14
14
|
const features = Object.values(index).sort((a, b) => a.ordering - b.ordering);
|
|
15
15
|
function minify(ast, options = {}, recursive = false, errors, nestingContent, context = {}) {
|
|
16
16
|
if (!('nodes' in context)) {
|
|
17
|
-
context.nodes = new
|
|
17
|
+
context.nodes = new Set;
|
|
18
18
|
}
|
|
19
19
|
if (context.nodes.has(ast)) {
|
|
20
20
|
return ast;
|
|
@@ -43,7 +43,7 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
|
|
|
43
43
|
curr.splice(0, 2);
|
|
44
44
|
}
|
|
45
45
|
else if (combinators.includes(curr[1])) {
|
|
46
|
-
curr.
|
|
46
|
+
curr.shift();
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
else if (ast.typ == EnumToken.RuleNodeType && (isIdent(curr[0]) || isFunction(curr[0]))) {
|
|
@@ -245,7 +245,7 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
|
|
|
245
245
|
}
|
|
246
246
|
if (shouldMerge) {
|
|
247
247
|
// @ts-ignore
|
|
248
|
-
if ((node.typ == EnumToken.RuleNodeType && node.sel == previous.sel) ||
|
|
248
|
+
if (((node.typ == EnumToken.RuleNodeType || node.typ == EnumToken.KeyFrameRuleNodeType) && node.sel == previous.sel) ||
|
|
249
249
|
// @ts-ignore
|
|
250
250
|
(node.typ == EnumToken.AtRuleNodeType) && node.val != 'font-face' && node.val == previous.val) {
|
|
251
251
|
// @ts-ignore
|
|
@@ -264,32 +264,33 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
|
|
|
264
264
|
nodeIndex = i;
|
|
265
265
|
continue;
|
|
266
266
|
}
|
|
267
|
-
else if (node.typ ==
|
|
267
|
+
else if (node.typ == previous?.typ && [EnumToken.KeyFrameRuleNodeType, EnumToken.RuleNodeType].includes(node.typ)) {
|
|
268
268
|
const intersect = diff(previous, node, reducer, options);
|
|
269
269
|
if (intersect != null) {
|
|
270
270
|
if (intersect.node1.chi.length == 0) {
|
|
271
271
|
// @ts-ignore
|
|
272
272
|
ast.chi.splice(i--, 1);
|
|
273
273
|
// @ts-ignore
|
|
274
|
-
node = ast.chi[i];
|
|
274
|
+
// node = ast.chi[i];
|
|
275
275
|
}
|
|
276
276
|
else {
|
|
277
277
|
// @ts-ignore
|
|
278
278
|
ast.chi.splice(i, 1, intersect.node1);
|
|
279
|
-
node = intersect.node1;
|
|
279
|
+
// node = ast.chi intersect.node1;
|
|
280
280
|
}
|
|
281
281
|
if (intersect.node2.chi.length == 0) {
|
|
282
282
|
// @ts-ignore
|
|
283
283
|
ast.chi.splice(nodeIndex, 1, intersect.result);
|
|
284
|
-
previous = intersect.result;
|
|
285
284
|
}
|
|
286
285
|
else {
|
|
287
286
|
// @ts-ignore
|
|
288
287
|
ast.chi.splice(nodeIndex, 1, intersect.result, intersect.node2);
|
|
289
|
-
previous = intersect.result;
|
|
290
288
|
// @ts-ignore
|
|
291
|
-
i = nodeIndex;
|
|
289
|
+
i = (nodeIndex ?? 0) + 1;
|
|
292
290
|
}
|
|
291
|
+
reduceRuleSelector(intersect.result);
|
|
292
|
+
previous = intersect.result;
|
|
293
|
+
nodeIndex = i;
|
|
293
294
|
}
|
|
294
295
|
}
|
|
295
296
|
}
|
|
@@ -419,11 +420,16 @@ function reduceSelector(selector) {
|
|
|
419
420
|
// combinator
|
|
420
421
|
if (combinators.includes(optimized.at(-1))) {
|
|
421
422
|
const combinator = optimized.pop();
|
|
422
|
-
selector.forEach(selector => selector.unshift(combinator));
|
|
423
|
+
selector.forEach((selector) => selector.unshift(combinator));
|
|
423
424
|
}
|
|
424
425
|
let reducible = optimized.length == 1;
|
|
425
|
-
if (optimized[0] == '&'
|
|
426
|
-
optimized
|
|
426
|
+
if (optimized[0] == '&') {
|
|
427
|
+
if (optimized[1] == ' ') {
|
|
428
|
+
optimized.splice(0, 2);
|
|
429
|
+
}
|
|
430
|
+
// else if (combinators.includes(optimized[1])) {
|
|
431
|
+
//
|
|
432
|
+
// }
|
|
427
433
|
}
|
|
428
434
|
if (optimized.length == 0 ||
|
|
429
435
|
(optimized[0].charAt(0) == '&' ||
|
|
@@ -431,7 +437,7 @@ function reduceSelector(selector) {
|
|
|
431
437
|
return {
|
|
432
438
|
match: false,
|
|
433
439
|
optimized,
|
|
434
|
-
selector: selector.map(selector => selector[0] == '&' && selector[1] == ' ' ? selector.slice(2) : selector),
|
|
440
|
+
selector: selector.map((selector) => selector[0] == '&' && selector[1] == ' ' ? selector.slice(2) : (selector)),
|
|
435
441
|
reducible: selector.length > 1 && selector.every((selector) => !combinators.includes(selector[0]))
|
|
436
442
|
};
|
|
437
443
|
}
|
|
@@ -511,6 +517,18 @@ function splitRule(buffer) {
|
|
|
511
517
|
result.push([]);
|
|
512
518
|
continue;
|
|
513
519
|
}
|
|
520
|
+
if (chr == ':') {
|
|
521
|
+
if (str !== '') {
|
|
522
|
+
// @ts-ignore
|
|
523
|
+
result.at(-1).push(str);
|
|
524
|
+
str = '';
|
|
525
|
+
}
|
|
526
|
+
if (buffer.charAt(i + 1) == ':') {
|
|
527
|
+
chr += buffer.charAt(++i);
|
|
528
|
+
}
|
|
529
|
+
str += chr;
|
|
530
|
+
continue;
|
|
531
|
+
}
|
|
514
532
|
str += chr;
|
|
515
533
|
if (chr == '\\') {
|
|
516
534
|
str += buffer.charAt(++i);
|
|
@@ -812,6 +830,52 @@ function diff(n1, n2, reducer, options = {}) {
|
|
|
812
830
|
const raw1 = node1.raw;
|
|
813
831
|
// @ts-ignore
|
|
814
832
|
const raw2 = node2.raw;
|
|
833
|
+
if (raw1 != null && raw2 != null) {
|
|
834
|
+
const prefixes1 = new Set;
|
|
835
|
+
const prefixes2 = new Set;
|
|
836
|
+
for (const token1 of raw1) {
|
|
837
|
+
for (const t of token1) {
|
|
838
|
+
if (t[0] == ':') {
|
|
839
|
+
const matches = t.match(/::?-([a-z]+)-/);
|
|
840
|
+
if (matches == null) {
|
|
841
|
+
continue;
|
|
842
|
+
}
|
|
843
|
+
prefixes1.add(matches[1]);
|
|
844
|
+
if (prefixes1.size > 1) {
|
|
845
|
+
break;
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
if (prefixes1.size > 1) {
|
|
850
|
+
break;
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
for (const token2 of raw2) {
|
|
854
|
+
for (const t of token2) {
|
|
855
|
+
if (t[0] == ':') {
|
|
856
|
+
const matches = t.match(/::?-([a-z]+)-/);
|
|
857
|
+
if (matches == null) {
|
|
858
|
+
continue;
|
|
859
|
+
}
|
|
860
|
+
prefixes2.add(matches[1]);
|
|
861
|
+
if (prefixes2.size > 1) {
|
|
862
|
+
break;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
if (prefixes2.size > 1) {
|
|
867
|
+
break;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
if (prefixes1.size != prefixes2.size) {
|
|
871
|
+
return null;
|
|
872
|
+
}
|
|
873
|
+
for (const prefix of prefixes1) {
|
|
874
|
+
if (!prefixes2.has(prefix)) {
|
|
875
|
+
return null;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
}
|
|
815
879
|
// @ts-ignore
|
|
816
880
|
node1 = { ...node1, chi: node1.chi.slice() };
|
|
817
881
|
node2 = { ...node2, chi: node2.chi.slice() };
|
|
@@ -848,7 +912,7 @@ function diff(n1, n2, reducer, options = {}) {
|
|
|
848
912
|
const result = (intersect.length == 0 ? null : {
|
|
849
913
|
...node1,
|
|
850
914
|
// @ts-ignore
|
|
851
|
-
sel: [...new Set([...(n1?.raw?.reduce(reducer, [])
|
|
915
|
+
sel: [...new Set([...(n1?.raw?.reduce(reducer, []) ?? splitRule(n1.sel)).concat(n2?.raw?.reduce(reducer, []) ?? splitRule(n2.sel))])].join(','),
|
|
852
916
|
chi: intersect.reverse()
|
|
853
917
|
});
|
|
854
918
|
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)) {
|
|
@@ -872,6 +936,11 @@ function reduceRuleSelector(node) {
|
|
|
872
936
|
Object.defineProperty(node, 'optimized', { ...definedPropertySettings, value: optimized });
|
|
873
937
|
}
|
|
874
938
|
if (optimized != null && optimized.match && optimized.reducible && optimized.selector.length > 1) {
|
|
939
|
+
for (const selector of optimized.selector) {
|
|
940
|
+
if (selector.length > 1 && selector[0] == '&' && combinators.includes(selector[1])) {
|
|
941
|
+
selector.shift();
|
|
942
|
+
}
|
|
943
|
+
}
|
|
875
944
|
const raw = [
|
|
876
945
|
[
|
|
877
946
|
optimized.optimized[0], ':is('
|
package/dist/lib/ast/types.js
CHANGED
|
@@ -75,6 +75,7 @@ var EnumToken;
|
|
|
75
75
|
EnumToken[EnumToken["FractionTokenType"] = 69] = "FractionTokenType";
|
|
76
76
|
EnumToken[EnumToken["IdenListTokenType"] = 70] = "IdenListTokenType";
|
|
77
77
|
EnumToken[EnumToken["GridTemplateFuncTokenType"] = 71] = "GridTemplateFuncTokenType";
|
|
78
|
+
EnumToken[EnumToken["KeyFrameRuleNodeType"] = 72] = "KeyFrameRuleNodeType";
|
|
78
79
|
/* aliases */
|
|
79
80
|
EnumToken[EnumToken["Time"] = 25] = "Time";
|
|
80
81
|
EnumToken[EnumToken["Iden"] = 7] = "Iden";
|
package/dist/lib/parser/parse.js
CHANGED
|
@@ -421,6 +421,9 @@ async function parseNode(results, context, stats, options, errors, src, map) {
|
|
|
421
421
|
const position = map.get(tokens[0]);
|
|
422
422
|
const uniq = new Map;
|
|
423
423
|
parseTokens(tokens, { minify: true }).reduce((acc, curr, index, array) => {
|
|
424
|
+
if (curr.typ == EnumToken.CommentTokenType) {
|
|
425
|
+
return acc;
|
|
426
|
+
}
|
|
424
427
|
if (curr.typ == EnumToken.WhitespaceTokenType) {
|
|
425
428
|
if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
|
|
426
429
|
trimWhiteSpace.includes(array[index + 1]?.typ) ||
|
|
@@ -442,7 +445,7 @@ async function parseNode(results, context, stats, options, errors, src, map) {
|
|
|
442
445
|
return acc;
|
|
443
446
|
}, uniq);
|
|
444
447
|
const node = {
|
|
445
|
-
typ: EnumToken.RuleNodeType,
|
|
448
|
+
typ: context.typ == EnumToken.AtRuleNodeType && context.nam == 'keyframes' ? EnumToken.KeyFrameRuleNodeType : EnumToken.RuleNodeType,
|
|
446
449
|
// @ts-ignore
|
|
447
450
|
sel: [...uniq.keys()].join(','),
|
|
448
451
|
chi: []
|
|
@@ -28,7 +28,7 @@ function rec20202lrec2020(r, g, b, a) {
|
|
|
28
28
|
return val / 4.5;
|
|
29
29
|
}
|
|
30
30
|
return sign * (Math.pow((abs + α - 1) / α, 1 / 0.45));
|
|
31
|
-
}).concat(
|
|
31
|
+
}).concat([] );
|
|
32
32
|
}
|
|
33
33
|
function lrec20202rec2020(r, g, b, a) {
|
|
34
34
|
// convert an array of linear-light rec2020 RGB in the range 0.0-1.0
|
|
@@ -98,7 +98,7 @@ function doRender(data, options = {}) {
|
|
|
98
98
|
return result;
|
|
99
99
|
}
|
|
100
100
|
function updateSourceMap(node, options, cache, sourcemap, position, str) {
|
|
101
|
-
if ([EnumToken.RuleNodeType, EnumToken.AtRuleNodeType].includes(node.typ)) {
|
|
101
|
+
if ([EnumToken.RuleNodeType, EnumToken.AtRuleNodeType, EnumToken.KeyFrameRuleNodeType].includes(node.typ)) {
|
|
102
102
|
let src = node.loc?.src ?? '';
|
|
103
103
|
let output = options.output ?? '';
|
|
104
104
|
if (!(src in cache)) {
|
|
@@ -158,6 +158,7 @@ function renderAstNode(data, options, sourcemap, position, errors, reducer, cach
|
|
|
158
158
|
}, '');
|
|
159
159
|
case EnumToken.AtRuleNodeType:
|
|
160
160
|
case EnumToken.RuleNodeType:
|
|
161
|
+
case EnumToken.KeyFrameRuleNodeType:
|
|
161
162
|
if (data.typ == EnumToken.AtRuleNodeType && !('chi' in data)) {
|
|
162
163
|
return `${indent}@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val};`;
|
|
163
164
|
}
|
package/dist/web/load.js
CHANGED
|
@@ -7,16 +7,18 @@ function parseResponse(response) {
|
|
|
7
7
|
return response.text();
|
|
8
8
|
}
|
|
9
9
|
async function load(url, currentFile) {
|
|
10
|
+
let t;
|
|
10
11
|
if (matchUrl.test(url)) {
|
|
11
|
-
|
|
12
|
+
t = new URL(url);
|
|
12
13
|
}
|
|
13
|
-
if (matchUrl.test(currentFile)) {
|
|
14
|
-
|
|
14
|
+
else if (matchUrl.test(currentFile)) {
|
|
15
|
+
t = new URL(url, currentFile);
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
else {
|
|
18
|
+
const path = resolve(url, currentFile).absolute;
|
|
19
|
+
t = new URL(path, self.origin);
|
|
20
|
+
}
|
|
21
|
+
return fetch(t, t.origin != self.origin ? { mode: 'cors' } : {}).then(parseResponse);
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export { load };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tbela99/css-parser",
|
|
3
3
|
"description": "CSS parser for node and the browser",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.3",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dist/node/index.js",
|
|
7
7
|
"./umd": "./dist/index-umd-web.js",
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
},
|
|
11
11
|
"type": "module",
|
|
12
12
|
"typings": "dist/index.d.ts",
|
|
13
|
+
"directories": {
|
|
14
|
+
"test": "test"
|
|
15
|
+
},
|
|
13
16
|
"scripts": {
|
|
14
17
|
"build": "rollup -c;./build.sh dist/index.d.ts 'declare interface' 'declare type'",
|
|
15
18
|
"test": "web-test-runner \"test/**/web.spec.js\" --node-resolve --playwright --browsers chromium firefox webkit --root-dir=.; mocha --reporter-options='maxDiffSize=1801920' \"test/**/node.spec.js\"",
|
package/syntax.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
|
|
2
|
+
- postfix (+|?|*)
|
|
3
|
+
|
|
4
|
+
- Expression
|
|
5
|
+
- Statement
|
|
6
|
+
- Literals
|
|
7
|
+
- Unary Expression
|
|
8
|
+
- Binary Expressions
|
|
9
|
+
- Parentheses
|
|
10
|
+
|
|
11
|
+
Grammar
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
expression → literal
|
|
15
|
+
| unary
|
|
16
|
+
| binary
|
|
17
|
+
| grouping ;
|
|
18
|
+
|
|
19
|
+
literal → NUMBER | STRING | "true" | "false" | "nil" ;
|
|
20
|
+
grouping → "(" expression ")" ;
|
|
21
|
+
unary → ( "-" | "!" ) expression ;
|
|
22
|
+
binary → expression operator expression ;
|
|
23
|
+
operator → "==" | "!=" | "<" | "<=" | ">" | ">=" | "+" | "-" | "*" | "/" ;
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Syntax tree
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
// https://developer.mozilla.org/en-US/docs/Web/CSS/Value_definition_syntax#question_mark
|
|
30
|
+
|
|
31
|
+
syntax: "keyword | <'property'> | <function>"
|
|
32
|
+
syntax: "<angle> | [ [ left-side | far-left | left | center-left | center | center-right | right | far-right | right-side ] || behind ] | leftwards | rightwards"
|
|
33
|
+
syntax: "none | [ [<dashed-ident> || <try-tactic>] | inset-area( <'inset-area'> ) ]#"
|
|
34
|
+
syntax: "snapInterval( <percentage>, <percentage> ) | snapList( <percentage># )"
|
|
35
|
+
syntax: "[ center | [ [ left | right | x-start | x-end ]? <length-percentage>? ]! ]#"
|
|
36
|
+
syntax: "<outline-radius>{1,4} [ / <outline-radius>{1,4} ]?
|
|
37
|
+
syntax: "[ [ <url> [ <x> <y> ]? , ]* [ auto | default | none | context-menu | help | pointer | progress | wait | cell | crosshair | text | vertical-text | alias | copy | move | no-drop | not-allowed | e-resize | n-resize | ne-resize | nw-resize | s-resize | se-resize | sw-resize | w-resize | ew-resize | ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | all-scroll | zoom-in | zoom-out | grab | grabbing ] ]"
|
|
38
|
+
syntax: "[ [ <'font-style'> || <font-variant-css21> || <'font-weight'> || <'font-stretch'> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'> ] | caption | icon | menu | message-box | small-caption | status-bar"
|
|
39
|
+
syntax: "false | true"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
||: at least one option must appear in any order each component appears at most once. example border property <'border-width'> || <'border-style'> || <'border-color'>
|
|
43
|
+
|
|
44
|
+
|: exclusive options. at least one must be present
|
|
45
|
+
|
|
46
|
+
&&: tokens appear in any order
|
|
47
|
+
|
|
48
|
+
juxtaposition: space separated and exact order
|
|
49
|
+
|
|
50
|
+
*: postfix. the entity appears 0 or many times
|
|
51
|
+
|
|
52
|
+
+: postfix. apppears at least once.
|
|
53
|
+
|
|
54
|
+
{a,b}: postfix. appears at least A, at most B.
|
|
55
|
+
|
|
56
|
+
#: postfix, repeated one or more times, separated by comma ','
|
|
57
|
+
|
|
58
|
+
!: postfix. the group is required and must produce at least one value.
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
| -> []
|
|
62
|
+
| -> []
|