@tbela99/css-parser 0.9.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +1 -1
- package/README.md +15 -8
- package/dist/index-umd-web.js +1815 -498
- package/dist/index.cjs +1816 -499
- package/dist/index.d.ts +46 -14
- package/dist/lib/ast/features/calc.js +7 -10
- package/dist/lib/ast/features/index.js +1 -0
- package/dist/lib/ast/features/inlinecssvariables.js +0 -5
- package/dist/lib/ast/features/prefix.js +2 -7
- package/dist/lib/ast/features/shorthand.js +6 -9
- package/dist/lib/ast/features/transform.js +60 -0
- package/dist/lib/ast/math/expression.js +14 -10
- package/dist/lib/ast/math/math.js +14 -2
- package/dist/lib/ast/minify.js +46 -5
- package/dist/lib/ast/transform/compute.js +336 -0
- package/dist/lib/ast/transform/convert.js +33 -0
- package/dist/lib/ast/transform/matrix.js +111 -0
- package/dist/lib/ast/transform/minify.js +296 -0
- package/dist/lib/ast/transform/perspective.js +10 -0
- package/dist/lib/ast/transform/rotate.js +40 -0
- package/dist/lib/ast/transform/scale.js +32 -0
- package/dist/lib/ast/transform/skew.js +23 -0
- package/dist/lib/ast/transform/translate.js +32 -0
- package/dist/lib/ast/transform/utils.js +198 -0
- package/dist/lib/ast/types.js +1 -0
- package/dist/lib/ast/walk.js +23 -17
- package/dist/lib/parser/parse.js +109 -88
- package/dist/lib/parser/utils/declaration.js +1 -1
- package/dist/lib/renderer/color/{colormix.js → color-mix.js} +6 -0
- package/dist/lib/renderer/color/color.js +94 -18
- package/dist/lib/renderer/color/hex.js +17 -7
- package/dist/lib/renderer/color/hsl.js +7 -2
- package/dist/lib/renderer/color/lab.js +8 -0
- package/dist/lib/renderer/color/lch.js +8 -0
- package/dist/lib/renderer/color/oklab.js +8 -0
- package/dist/lib/renderer/color/oklch.js +8 -0
- package/dist/lib/renderer/color/relativecolor.js +10 -21
- package/dist/lib/renderer/color/rgb.js +10 -7
- package/dist/lib/renderer/color/srgb.js +30 -6
- package/dist/lib/renderer/color/utils/components.js +13 -2
- package/dist/lib/renderer/render.js +67 -30
- package/dist/lib/syntax/syntax.js +74 -56
- package/dist/lib/validation/at-rules/container.js +6 -6
- package/dist/lib/validation/at-rules/document.js +1 -1
- package/dist/lib/validation/at-rules/keyframes.js +1 -1
- package/dist/lib/validation/at-rules/media.js +0 -1
- package/dist/lib/validation/atrule.js +0 -4
- package/dist/lib/validation/selector.js +5 -2
- package/dist/lib/validation/syntaxes/keyframe-block-list.js +2 -2
- package/dist/lib/validation/syntaxes/keyframe-selector.js +11 -90
- package/dist/lib/validation/syntaxes/relative-selector.js +15 -14
- package/dist/lib/validation/utils/list.js +18 -1
- package/dist/node/load.js +1 -1
- package/package.json +12 -12
- package/dist/lib/renderer/color/prophotoRgb.js +0 -56
- package/dist/lib/validation/declaration.js +0 -94
- package/dist/lib/validation/syntax.js +0 -1509
- package/dist/lib/validation/syntaxes/image.js +0 -29
package/dist/lib/ast/walk.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { EnumToken } from './types.js';
|
|
2
2
|
|
|
3
|
+
var WalkerOptionEnum;
|
|
4
|
+
(function (WalkerOptionEnum) {
|
|
5
|
+
WalkerOptionEnum[WalkerOptionEnum["Ignore"] = 0] = "Ignore";
|
|
6
|
+
WalkerOptionEnum[WalkerOptionEnum["Stop"] = 1] = "Stop";
|
|
7
|
+
WalkerOptionEnum[WalkerOptionEnum["Children"] = 2] = "Children";
|
|
8
|
+
WalkerOptionEnum[WalkerOptionEnum["IgnoreChildren"] = 3] = "IgnoreChildren";
|
|
9
|
+
})(WalkerOptionEnum || (WalkerOptionEnum = {}));
|
|
3
10
|
var WalkerValueEvent;
|
|
4
11
|
(function (WalkerValueEvent) {
|
|
5
12
|
WalkerValueEvent[WalkerValueEvent["Enter"] = 0] = "Enter";
|
|
@@ -18,10 +25,10 @@ function* walk(node, filter) {
|
|
|
18
25
|
let option = null;
|
|
19
26
|
if (filter != null) {
|
|
20
27
|
option = filter(node);
|
|
21
|
-
if (option ===
|
|
28
|
+
if (option === WalkerOptionEnum.Ignore) {
|
|
22
29
|
continue;
|
|
23
30
|
}
|
|
24
|
-
if (option ===
|
|
31
|
+
if (option === WalkerOptionEnum.Stop) {
|
|
25
32
|
break;
|
|
26
33
|
}
|
|
27
34
|
}
|
|
@@ -30,7 +37,7 @@ function* walk(node, filter) {
|
|
|
30
37
|
// @ts-ignore
|
|
31
38
|
yield { node, parent: map.get(node), root };
|
|
32
39
|
}
|
|
33
|
-
if (option !==
|
|
40
|
+
if (option !== WalkerOptionEnum.IgnoreChildren && 'chi' in node) {
|
|
34
41
|
parents.unshift(...node.chi);
|
|
35
42
|
for (const child of node.chi.slice()) {
|
|
36
43
|
map.set(child, node);
|
|
@@ -62,19 +69,20 @@ function* walkValues(values, root = null, filter, reverse) {
|
|
|
62
69
|
event: WalkerValueEvent.Enter
|
|
63
70
|
};
|
|
64
71
|
}
|
|
72
|
+
const eventType = filter.event ?? WalkerValueEvent.Enter;
|
|
65
73
|
while (stack.length > 0) {
|
|
66
74
|
let value = reverse ? stack.pop() : stack.shift();
|
|
67
75
|
let option = null;
|
|
68
|
-
if (filter.fn != null &&
|
|
76
|
+
if (filter.fn != null && eventType == WalkerValueEvent.Enter) {
|
|
69
77
|
const isValid = filter.type == null || value.typ == filter.type ||
|
|
70
78
|
(Array.isArray(filter.type) && filter.type.includes(value.typ)) ||
|
|
71
79
|
(typeof filter.type == 'function' && filter.type(value));
|
|
72
80
|
if (isValid) {
|
|
73
|
-
option = filter.fn(value, map.get(value) ?? root
|
|
74
|
-
if (option ===
|
|
81
|
+
option = filter.fn(value, map.get(value) ?? root);
|
|
82
|
+
if (option === WalkerOptionEnum.Ignore) {
|
|
75
83
|
continue;
|
|
76
84
|
}
|
|
77
|
-
if (option ===
|
|
85
|
+
if (option === WalkerOptionEnum.Stop) {
|
|
78
86
|
break;
|
|
79
87
|
}
|
|
80
88
|
// @ts-ignore
|
|
@@ -83,8 +91,7 @@ function* walkValues(values, root = null, filter, reverse) {
|
|
|
83
91
|
}
|
|
84
92
|
}
|
|
85
93
|
}
|
|
86
|
-
|
|
87
|
-
if (filter.event == WalkerValueEvent.Enter && option !== 'children') {
|
|
94
|
+
if (eventType == WalkerValueEvent.Enter && option !== WalkerOptionEnum.Children) {
|
|
88
95
|
yield {
|
|
89
96
|
value,
|
|
90
97
|
parent: map.get(value) ?? root,
|
|
@@ -94,7 +101,7 @@ function* walkValues(values, root = null, filter, reverse) {
|
|
|
94
101
|
root: root ?? null
|
|
95
102
|
};
|
|
96
103
|
}
|
|
97
|
-
if (option !==
|
|
104
|
+
if (option !== WalkerOptionEnum.IgnoreChildren && 'chi' in value) {
|
|
98
105
|
const sliced = value.chi.slice();
|
|
99
106
|
for (const child of sliced) {
|
|
100
107
|
map.set(child, value);
|
|
@@ -107,24 +114,23 @@ function* walkValues(values, root = null, filter, reverse) {
|
|
|
107
114
|
}
|
|
108
115
|
}
|
|
109
116
|
else if (value.typ == EnumToken.BinaryExpressionTokenType) {
|
|
110
|
-
map.set(value.l,
|
|
111
|
-
map.set(value.r,
|
|
117
|
+
map.set(value.l, value);
|
|
118
|
+
map.set(value.r, value);
|
|
112
119
|
stack.unshift(value.l, value.r);
|
|
113
120
|
}
|
|
114
|
-
if (
|
|
121
|
+
if (eventType == WalkerValueEvent.Leave && filter.fn != null) {
|
|
115
122
|
const isValid = filter.type == null || value.typ == filter.type ||
|
|
116
123
|
(Array.isArray(filter.type) && filter.type.includes(value.typ)) ||
|
|
117
124
|
(typeof filter.type == 'function' && filter.type(value));
|
|
118
125
|
if (isValid) {
|
|
119
|
-
option = filter.fn(value, map.get(value)
|
|
126
|
+
option = filter.fn(value, map.get(value));
|
|
120
127
|
// @ts-ignore
|
|
121
128
|
if (option != null && 'typ' in option) {
|
|
122
129
|
map.set(option, map.get(value) ?? root);
|
|
123
130
|
}
|
|
124
131
|
}
|
|
125
132
|
}
|
|
126
|
-
|
|
127
|
-
if (filter.event == WalkerValueEvent.Leave && option !== 'children') {
|
|
133
|
+
if (eventType == WalkerValueEvent.Leave && option !== WalkerOptionEnum.Children) {
|
|
128
134
|
yield {
|
|
129
135
|
value,
|
|
130
136
|
parent: map.get(value) ?? root,
|
|
@@ -138,4 +144,4 @@ function* walkValues(values, root = null, filter, reverse) {
|
|
|
138
144
|
}
|
|
139
145
|
}
|
|
140
146
|
|
|
141
|
-
export { WalkerValueEvent, walk, walkValues };
|
|
147
|
+
export { WalkerOptionEnum, WalkerValueEvent, walk, walkValues };
|
package/dist/lib/parser/parse.js
CHANGED
|
@@ -2,7 +2,7 @@ import { webkitPseudoAliasMap, isIdentStart, isIdent, mathFuncs, isColor, isHexC
|
|
|
2
2
|
import './utils/config.js';
|
|
3
3
|
import { EnumToken, funcLike, ValidationLevel } from '../ast/types.js';
|
|
4
4
|
import { minify, definedPropertySettings, combinators } from '../ast/minify.js';
|
|
5
|
-
import { walkValues, walk } from '../ast/walk.js';
|
|
5
|
+
import { walkValues, walk, WalkerOptionEnum } from '../ast/walk.js';
|
|
6
6
|
import { expand } from '../ast/expand.js';
|
|
7
7
|
import { parseDeclarationNode } from './utils/declaration.js';
|
|
8
8
|
import { renderToken } from '../renderer/render.js';
|
|
@@ -14,6 +14,8 @@ import '../validation/parser/parse.js';
|
|
|
14
14
|
import { validateSelector } from '../validation/selector.js';
|
|
15
15
|
import { validateAtRule } from '../validation/atrule.js';
|
|
16
16
|
import '../validation/syntaxes/complex-selector.js';
|
|
17
|
+
import { validateKeyframeSelector } from '../validation/syntaxes/keyframe-selector.js';
|
|
18
|
+
import { validateAtRuleKeyframes } from '../validation/at-rules/keyframes.js';
|
|
17
19
|
|
|
18
20
|
const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
|
|
19
21
|
const trimWhiteSpace = [EnumToken.CommentTokenType, EnumToken.GtTokenType, EnumToken.GteTokenType, EnumToken.LtTokenType, EnumToken.LteTokenType, EnumToken.ColumnCombinatorTokenType];
|
|
@@ -48,12 +50,13 @@ async function doParse(iterator, options = {}) {
|
|
|
48
50
|
minify: true,
|
|
49
51
|
pass: 1,
|
|
50
52
|
parseColor: true,
|
|
51
|
-
nestingRules:
|
|
53
|
+
nestingRules: true,
|
|
52
54
|
resolveImport: false,
|
|
53
55
|
resolveUrls: false,
|
|
54
56
|
removeCharset: true,
|
|
55
57
|
removeEmpty: true,
|
|
56
58
|
removeDuplicateDeclarations: true,
|
|
59
|
+
computeTransform: true,
|
|
57
60
|
computeShorthand: true,
|
|
58
61
|
computeCalcExpression: true,
|
|
59
62
|
inlineCssVariables: false,
|
|
@@ -122,11 +125,13 @@ async function doParse(iterator, options = {}) {
|
|
|
122
125
|
}
|
|
123
126
|
else if (item.token == '{') {
|
|
124
127
|
let inBlock = 1;
|
|
128
|
+
tokens = [item];
|
|
125
129
|
do {
|
|
126
130
|
item = iter.next().value;
|
|
127
131
|
if (item == null) {
|
|
128
132
|
break;
|
|
129
133
|
}
|
|
134
|
+
tokens.push(item);
|
|
130
135
|
if (item.token == '{') {
|
|
131
136
|
inBlock++;
|
|
132
137
|
}
|
|
@@ -134,6 +139,13 @@ async function doParse(iterator, options = {}) {
|
|
|
134
139
|
inBlock--;
|
|
135
140
|
}
|
|
136
141
|
} while (inBlock != 0);
|
|
142
|
+
if (tokens.length > 0) {
|
|
143
|
+
errors.push({
|
|
144
|
+
action: 'drop',
|
|
145
|
+
message: 'invalid block',
|
|
146
|
+
rawTokens: tokens.slice()
|
|
147
|
+
});
|
|
148
|
+
}
|
|
137
149
|
}
|
|
138
150
|
tokens = [];
|
|
139
151
|
map = new Map;
|
|
@@ -166,6 +178,7 @@ async function doParse(iterator, options = {}) {
|
|
|
166
178
|
await parseNode(tokens, context, stats, options, errors, src, map, rawTokens);
|
|
167
179
|
rawTokens.length = 0;
|
|
168
180
|
if (context != null && context.typ == EnumToken.InvalidRuleTokenType) {
|
|
181
|
+
// @ts-ignore
|
|
169
182
|
const index = context.chi.findIndex((node) => node == context);
|
|
170
183
|
if (index > -1) {
|
|
171
184
|
context.chi.splice(index, 1);
|
|
@@ -465,9 +478,11 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
465
478
|
acc.push(renderToken(curr, { removeComments: true }));
|
|
466
479
|
return acc;
|
|
467
480
|
}, []);
|
|
481
|
+
const nam = renderToken(atRule, { removeComments: true });
|
|
482
|
+
// @ts-ignore
|
|
468
483
|
const node = {
|
|
469
|
-
typ: EnumToken.AtRuleNodeType,
|
|
470
|
-
nam
|
|
484
|
+
typ: /^(-[a-z]+-)?keyframes$/.test(nam) ? EnumToken.KeyframeAtRuleNodeType : EnumToken.AtRuleNodeType,
|
|
485
|
+
nam,
|
|
471
486
|
// tokens: t,
|
|
472
487
|
val: raw.join('')
|
|
473
488
|
};
|
|
@@ -498,7 +513,7 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
498
513
|
isValid = false;
|
|
499
514
|
}
|
|
500
515
|
}
|
|
501
|
-
const valid = isValid ? validateAtRule(node, options, context) : {
|
|
516
|
+
const valid = isValid ? (node.typ == EnumToken.KeyframeAtRuleNodeType ? validateAtRuleKeyframes(node) : validateAtRule(node, options, context)) : {
|
|
502
517
|
valid: ValidationLevel.Drop,
|
|
503
518
|
node,
|
|
504
519
|
syntax: '@' + node.nam,
|
|
@@ -514,7 +529,10 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
514
529
|
node.typ = EnumToken.InvalidAtRuleTokenType;
|
|
515
530
|
}
|
|
516
531
|
else {
|
|
517
|
-
node.val = node.tokens.reduce((acc, curr) => acc + renderToken(curr, {
|
|
532
|
+
node.val = node.tokens.reduce((acc, curr) => acc + renderToken(curr, {
|
|
533
|
+
minify: false,
|
|
534
|
+
removeComments: true
|
|
535
|
+
}), '');
|
|
518
536
|
}
|
|
519
537
|
}
|
|
520
538
|
// @ts-ignore
|
|
@@ -527,72 +545,79 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
527
545
|
if (delim.typ == EnumToken.BlockStartTokenType) {
|
|
528
546
|
const position = map.get(tokens[0]);
|
|
529
547
|
const uniq = new Map;
|
|
530
|
-
parseTokens(tokens, { minify: true })
|
|
531
|
-
|
|
532
|
-
return acc;
|
|
533
|
-
}
|
|
534
|
-
if (curr.typ == EnumToken.WhitespaceTokenType) {
|
|
535
|
-
if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
|
|
536
|
-
trimWhiteSpace.includes(array[index + 1]?.typ) ||
|
|
537
|
-
combinators.includes(array[index - 1]?.val) ||
|
|
538
|
-
combinators.includes(array[index + 1]?.val)) {
|
|
539
|
-
return acc;
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
let t = renderToken(curr, { minify: false });
|
|
543
|
-
if (t == ',') {
|
|
544
|
-
acc.push([]);
|
|
545
|
-
// uniqTokens.push([]);
|
|
546
|
-
}
|
|
547
|
-
else {
|
|
548
|
-
acc[acc.length - 1].push(t);
|
|
549
|
-
// uniqTokens[uniqTokens.length - 1].push(curr);
|
|
550
|
-
}
|
|
551
|
-
return acc;
|
|
552
|
-
}, [[]]).reduce((acc, curr) => {
|
|
553
|
-
let i = 0;
|
|
554
|
-
for (; i < curr.length; i++) {
|
|
555
|
-
if (i + 1 < curr.length && curr[i] == '*') {
|
|
556
|
-
if (curr[i] == '*') {
|
|
557
|
-
let index = curr[i + 1] == ' ' ? 2 : 1;
|
|
558
|
-
if (!['>', '~', '+'].includes(curr[index])) {
|
|
559
|
-
curr.splice(i, index);
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
acc.set(curr.join(''), curr);
|
|
565
|
-
return acc;
|
|
566
|
-
}, uniq);
|
|
567
|
-
const ruleType = context.typ == EnumToken.AtRuleNodeType && context.nam == 'keyframes' ? EnumToken.KeyFrameRuleNodeType : EnumToken.RuleNodeType;
|
|
548
|
+
parseTokens(tokens, { minify: true });
|
|
549
|
+
const ruleType = context.typ == EnumToken.KeyframeAtRuleNodeType ? EnumToken.KeyFrameRuleNodeType : EnumToken.RuleNodeType;
|
|
568
550
|
if (ruleType == EnumToken.RuleNodeType) {
|
|
569
551
|
parseSelector(tokens);
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
// @ts-ignore
|
|
584
|
-
location: { src, ...(map.get(valid.node) ?? position) }
|
|
585
|
-
});
|
|
552
|
+
}
|
|
553
|
+
if (options.validation) {
|
|
554
|
+
// @ts-ignore
|
|
555
|
+
const valid = ruleType == EnumToken.KeyFrameRuleNodeType ? validateKeyframeSelector(tokens) : validateSelector(tokens, options, context);
|
|
556
|
+
if (valid.valid != ValidationLevel.Valid) {
|
|
557
|
+
const node = {
|
|
558
|
+
typ: EnumToken.InvalidRuleTokenType,
|
|
559
|
+
sel: tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), ''),
|
|
560
|
+
chi: []
|
|
561
|
+
};
|
|
562
|
+
errors.push({
|
|
563
|
+
action: 'drop',
|
|
564
|
+
message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
|
|
586
565
|
// @ts-ignore
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
566
|
+
location: { src, ...(map.get(valid.node) ?? position) }
|
|
567
|
+
});
|
|
568
|
+
// @ts-ignore
|
|
569
|
+
context.chi.push(node);
|
|
570
|
+
Object.defineProperty(node, 'parent', { ...definedPropertySettings, value: context });
|
|
571
|
+
return node;
|
|
591
572
|
}
|
|
592
573
|
}
|
|
593
574
|
const node = {
|
|
594
575
|
typ: ruleType,
|
|
595
|
-
sel: [...
|
|
576
|
+
sel: [...tokens.reduce((acc, curr, index, array) => {
|
|
577
|
+
if (curr.typ == EnumToken.CommentTokenType) {
|
|
578
|
+
return acc;
|
|
579
|
+
}
|
|
580
|
+
if (curr.typ == EnumToken.WhitespaceTokenType) {
|
|
581
|
+
if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
|
|
582
|
+
trimWhiteSpace.includes(array[index + 1]?.typ) ||
|
|
583
|
+
combinators.includes(array[index - 1]?.val) ||
|
|
584
|
+
combinators.includes(array[index + 1]?.val)) {
|
|
585
|
+
return acc;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
if (ruleType == EnumToken.KeyFrameRuleNodeType) {
|
|
589
|
+
if (curr.typ == EnumToken.IdenTokenType && curr.val == 'from') {
|
|
590
|
+
Object.assign(curr, { typ: EnumToken.PercentageTokenType, val: '0' });
|
|
591
|
+
}
|
|
592
|
+
else if (curr.typ == EnumToken.PercentageTokenType && curr.val == '100') {
|
|
593
|
+
Object.assign(curr, { typ: EnumToken.IdenTokenType, val: 'to' });
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
let t = renderToken(curr, { minify: false });
|
|
597
|
+
if (t == ',') {
|
|
598
|
+
acc.push([]);
|
|
599
|
+
// uniqTokens.push([]);
|
|
600
|
+
}
|
|
601
|
+
else {
|
|
602
|
+
acc[acc.length - 1].push(t);
|
|
603
|
+
// uniqTokens[uniqTokens.length - 1].push(curr);
|
|
604
|
+
}
|
|
605
|
+
return acc;
|
|
606
|
+
}, [[]]).reduce((acc, curr) => {
|
|
607
|
+
let i = 0;
|
|
608
|
+
for (; i < curr.length; i++) {
|
|
609
|
+
if (i + 1 < curr.length && curr[i] == '*') {
|
|
610
|
+
if (curr[i] == '*') {
|
|
611
|
+
let index = curr[i + 1] == ' ' ? 2 : 1;
|
|
612
|
+
if (!['>', '~', '+'].includes(curr[index])) {
|
|
613
|
+
curr.splice(i, index);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
acc.set(curr.join(''), curr);
|
|
619
|
+
return acc;
|
|
620
|
+
}, uniq).keys()].join(','),
|
|
596
621
|
chi: []
|
|
597
622
|
};
|
|
598
623
|
Object.defineProperty(node, 'tokens', {
|
|
@@ -677,7 +702,8 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
677
702
|
}
|
|
678
703
|
}
|
|
679
704
|
}
|
|
680
|
-
|
|
705
|
+
const nam = renderToken(name.shift(), { removeComments: true });
|
|
706
|
+
if (value == null || (!nam.startsWith('--') && value.length == 0)) {
|
|
681
707
|
errors.push({
|
|
682
708
|
action: 'drop',
|
|
683
709
|
message: 'doParse: invalid declaration',
|
|
@@ -685,33 +711,30 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
685
711
|
});
|
|
686
712
|
return null;
|
|
687
713
|
}
|
|
714
|
+
for (const { value: token } of walkValues(value, null, {
|
|
715
|
+
fn: (node) => node.typ == EnumToken.FunctionTokenType && node.val == 'calc' ? WalkerOptionEnum.IgnoreChildren : null,
|
|
716
|
+
type: EnumToken.FunctionTokenType
|
|
717
|
+
})) {
|
|
718
|
+
if (token.typ == EnumToken.FunctionTokenType && token.val == 'calc') {
|
|
719
|
+
for (const { value: node, parent } of walkValues(token.chi, token)) {
|
|
720
|
+
// fix expressions starting with '/' or '*' such as '/4' in (1 + 1)/4
|
|
721
|
+
if (node.typ == EnumToken.LiteralTokenType && node.val.length > 0) {
|
|
722
|
+
if (node.val[0] == '/' || node.val[0] == '*') {
|
|
723
|
+
parent.chi.splice(parent.chi.indexOf(node), 1, { typ: node.val[0] == '/' ? EnumToken.Div : EnumToken.Mul }, ...parseString(node.val.slice(1)));
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
}
|
|
688
729
|
const node = {
|
|
689
730
|
typ: EnumToken.DeclarationNodeType,
|
|
690
731
|
// @ts-ignore
|
|
691
|
-
nam
|
|
732
|
+
nam,
|
|
692
733
|
// @ts-ignore
|
|
693
734
|
val: value
|
|
694
735
|
};
|
|
695
736
|
const result = parseDeclarationNode(node, errors, src, position);
|
|
696
737
|
if (result != null) {
|
|
697
|
-
// if (options.validation) {
|
|
698
|
-
//
|
|
699
|
-
// const valid: ValidationResult = validateDeclaration(result, options, context);
|
|
700
|
-
//
|
|
701
|
-
// // console.error({valid});
|
|
702
|
-
//
|
|
703
|
-
// if (valid.valid == ValidationLevel.Drop) {
|
|
704
|
-
//
|
|
705
|
-
// errors.push({
|
|
706
|
-
// action: 'drop',
|
|
707
|
-
// message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, {minify: false}), '') + '"',
|
|
708
|
-
// // @ts-ignore
|
|
709
|
-
// location: {src, ...(map.get(valid.node) ?? position)}
|
|
710
|
-
// });
|
|
711
|
-
//
|
|
712
|
-
// return null;
|
|
713
|
-
// }
|
|
714
|
-
// }
|
|
715
738
|
// @ts-ignore
|
|
716
739
|
context.chi.push(result);
|
|
717
740
|
Object.defineProperty(result, 'parent', { ...definedPropertySettings, value: context });
|
|
@@ -794,8 +817,6 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
794
817
|
}
|
|
795
818
|
}
|
|
796
819
|
if (value.typ == EnumToken.ParensTokenType || (value.typ == EnumToken.FunctionTokenType && ['media', 'supports', 'style', 'scroll-state'].includes(value.val))) {
|
|
797
|
-
// @todo parse range and declarations
|
|
798
|
-
// parseDeclaration(parent.chi);
|
|
799
820
|
let i;
|
|
800
821
|
let nameIndex = -1;
|
|
801
822
|
let valueIndex = -1;
|
|
@@ -1359,7 +1380,7 @@ function parseTokens(tokens, options = {}) {
|
|
|
1359
1380
|
upper++;
|
|
1360
1381
|
}
|
|
1361
1382
|
if (upper < t.chi.length &&
|
|
1362
|
-
t.chi[upper].typ == EnumToken.
|
|
1383
|
+
t.chi[upper].typ == EnumToken.IdenTokenType &&
|
|
1363
1384
|
['i', 's'].includes(t.chi[upper].val.toLowerCase())) {
|
|
1364
1385
|
t.chi[m].attr = t.chi[upper].val;
|
|
1365
1386
|
t.chi.splice(upper, 1);
|
|
@@ -11,7 +11,7 @@ function parseDeclarationNode(node, errors, src, position) {
|
|
|
11
11
|
while (node.val[0]?.typ == EnumToken.WhitespaceTokenType) {
|
|
12
12
|
node.val.shift();
|
|
13
13
|
}
|
|
14
|
-
if (node.val.filter((t) => ![EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType].includes(t.typ)).length == 0) {
|
|
14
|
+
if (!node.nam.startsWith('--') && node.val.filter((t) => ![EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType].includes(t.typ)).length == 0) {
|
|
15
15
|
errors.push({
|
|
16
16
|
action: 'drop',
|
|
17
17
|
message: 'doParse: invalid declaration',
|
|
@@ -57,6 +57,9 @@ function interpolateHue(interpolationMethod, h1, h2) {
|
|
|
57
57
|
return [h1, h2];
|
|
58
58
|
}
|
|
59
59
|
function colorMix(colorSpace, hueInterpolationMethod, color1, percentage1, color2, percentage2) {
|
|
60
|
+
if (color1.val == 'currentcolor' || color2.val == 'currentcolor') {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
60
63
|
if (hueInterpolationMethod != null && isRectangularOrthogonalColorspace(colorSpace)) {
|
|
61
64
|
return null;
|
|
62
65
|
}
|
|
@@ -110,6 +113,9 @@ function colorMix(colorSpace, hueInterpolationMethod, color1, percentage1, color
|
|
|
110
113
|
}
|
|
111
114
|
const components1 = getComponents(color1);
|
|
112
115
|
const components2 = getComponents(color2);
|
|
116
|
+
if (components1 == null || components2 == null) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
113
119
|
if ((components1[3] != null && components1[3].typ == EnumToken.IdenTokenType && components1[3].val == 'none') && values2.length == 4) {
|
|
114
120
|
values1[3] = values2[3];
|
|
115
121
|
}
|
|
@@ -8,7 +8,7 @@ import { lch2hwb, lab2hwb, oklch2hwb, oklab2hwb, hsl2hwb, rgb2hwb } from './hwb.
|
|
|
8
8
|
import { srgb2lab, oklch2lab, oklab2lab, lch2lab, hwb2lab, hsl2lab, rgb2lab, hex2lab } from './lab.js';
|
|
9
9
|
import { srgb2lch, oklch2lch, oklab2lch, lab2lch, hwb2lch, hsl2lch, rgb2lch, hex2lch } from './lch.js';
|
|
10
10
|
import { srgb2oklab, oklch2oklab, lch2oklab, lab2oklab, hwb2oklab, hsl2oklab, rgb2oklab, hex2oklab } from './oklab.js';
|
|
11
|
-
import { lch2oklch, oklab2oklch, lab2oklch, hwb2oklch, hsl2oklch, rgb2oklch, hex2oklch
|
|
11
|
+
import { lch2oklch, oklab2oklch, lab2oklch, hwb2oklch, hsl2oklch, rgb2oklch, hex2oklch } from './oklch.js';
|
|
12
12
|
import { colorFuncColorSpace } from './utils/constants.js';
|
|
13
13
|
import { getComponents } from './utils/components.js';
|
|
14
14
|
import { xyz2srgb, lsrgb2srgbvalues, srgb2lsrgbvalues, lch2srgb, oklab2srgb, lab2srgb, hwb2srgb, hsl2srgb, rgb2srgb, hex2srgb } from './srgb.js';
|
|
@@ -33,10 +33,15 @@ function convert(token, to) {
|
|
|
33
33
|
}
|
|
34
34
|
let values = [];
|
|
35
35
|
if (to == 'hsl') {
|
|
36
|
+
let t;
|
|
36
37
|
switch (token.kin) {
|
|
37
38
|
case 'rgb':
|
|
38
39
|
case 'rgba':
|
|
39
|
-
|
|
40
|
+
t = rgb2hsl(token);
|
|
41
|
+
if (t == null) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
values.push(...t);
|
|
40
45
|
break;
|
|
41
46
|
case 'hex':
|
|
42
47
|
case 'lit':
|
|
@@ -46,10 +51,18 @@ function convert(token, to) {
|
|
|
46
51
|
values.push(...hwb2hsl(token));
|
|
47
52
|
break;
|
|
48
53
|
case 'oklab':
|
|
49
|
-
|
|
54
|
+
t = oklab2hsl(token);
|
|
55
|
+
if (t == null) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
values.push(...t);
|
|
50
59
|
break;
|
|
51
60
|
case 'oklch':
|
|
52
|
-
|
|
61
|
+
t = oklch2hsl(token);
|
|
62
|
+
if (t == null) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
values.push(...t);
|
|
53
66
|
break;
|
|
54
67
|
case 'lab':
|
|
55
68
|
values.push(...lab2hsl(token));
|
|
@@ -98,28 +111,53 @@ function convert(token, to) {
|
|
|
98
111
|
}
|
|
99
112
|
}
|
|
100
113
|
else if (to == 'rgb') {
|
|
114
|
+
let t;
|
|
101
115
|
switch (token.kin) {
|
|
102
116
|
case 'hex':
|
|
103
117
|
case 'lit':
|
|
104
118
|
values.push(...hex2rgb(token));
|
|
105
119
|
break;
|
|
106
120
|
case 'hsl':
|
|
107
|
-
|
|
121
|
+
t = hsl2rgb(token);
|
|
122
|
+
if (t == null) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
values.push(...t);
|
|
108
126
|
break;
|
|
109
127
|
case 'hwb':
|
|
110
|
-
|
|
128
|
+
t = hwb2rgb(token);
|
|
129
|
+
if (t == null) {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
values.push(...t);
|
|
111
133
|
break;
|
|
112
134
|
case 'oklab':
|
|
113
|
-
|
|
135
|
+
t = oklab2rgb(token);
|
|
136
|
+
if (t == null) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
values.push(...t);
|
|
114
140
|
break;
|
|
115
141
|
case 'oklch':
|
|
116
|
-
|
|
142
|
+
t = oklch2rgb(token);
|
|
143
|
+
if (t == null) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
values.push(...t);
|
|
117
147
|
break;
|
|
118
148
|
case 'lab':
|
|
119
|
-
|
|
149
|
+
t = lab2rgb(token);
|
|
150
|
+
if (t == null) {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
values.push(...t);
|
|
120
154
|
break;
|
|
121
155
|
case 'lch':
|
|
122
|
-
|
|
156
|
+
t = lch2rgb(token);
|
|
157
|
+
if (t == null) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
values.push(...t);
|
|
123
161
|
break;
|
|
124
162
|
case 'color':
|
|
125
163
|
// @ts-ignore
|
|
@@ -305,6 +343,7 @@ function convert(token, to) {
|
|
|
305
343
|
}
|
|
306
344
|
}
|
|
307
345
|
else if (colorFuncColorSpace.includes(to)) {
|
|
346
|
+
let t;
|
|
308
347
|
switch (token.kin) {
|
|
309
348
|
case 'hex':
|
|
310
349
|
case 'lit':
|
|
@@ -312,30 +351,60 @@ function convert(token, to) {
|
|
|
312
351
|
break;
|
|
313
352
|
case 'rgb':
|
|
314
353
|
case 'rgba':
|
|
315
|
-
|
|
354
|
+
t = rgb2srgb(token);
|
|
355
|
+
if (t == null) {
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
values.push(...t);
|
|
316
359
|
break;
|
|
317
360
|
case 'hsl':
|
|
318
361
|
case 'hsla':
|
|
319
|
-
|
|
362
|
+
t = hsl2srgb(token);
|
|
363
|
+
if (t == null) {
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
values.push(...t);
|
|
320
367
|
break;
|
|
321
368
|
case 'hwb':
|
|
322
|
-
|
|
369
|
+
t = hwb2srgb(token);
|
|
370
|
+
if (t == null) {
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
values.push(...t);
|
|
323
374
|
break;
|
|
324
375
|
case 'lab':
|
|
325
|
-
|
|
376
|
+
t = lab2srgb(token);
|
|
377
|
+
if (t == null) {
|
|
378
|
+
return null;
|
|
379
|
+
}
|
|
380
|
+
values.push(...t);
|
|
326
381
|
break;
|
|
327
382
|
case 'oklab':
|
|
328
|
-
|
|
383
|
+
t = oklab2srgb(token);
|
|
384
|
+
if (t == null) {
|
|
385
|
+
return null;
|
|
386
|
+
}
|
|
387
|
+
values.push(...t);
|
|
329
388
|
break;
|
|
330
389
|
case 'lch':
|
|
331
|
-
|
|
390
|
+
t = lch2srgb(token);
|
|
391
|
+
if (t == null) {
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
values.push(...t);
|
|
332
395
|
break;
|
|
333
396
|
case 'oklch':
|
|
334
|
-
|
|
335
|
-
|
|
397
|
+
t = color2srgbvalues(token);
|
|
398
|
+
if (t == null) {
|
|
399
|
+
return null;
|
|
400
|
+
}
|
|
401
|
+
values.push(...t);
|
|
336
402
|
break;
|
|
337
403
|
case 'color':
|
|
338
404
|
const val = color2srgbvalues(token);
|
|
405
|
+
if (val == null) {
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
339
408
|
switch (to) {
|
|
340
409
|
case 'srgb':
|
|
341
410
|
values.push(...val);
|
|
@@ -389,6 +458,9 @@ function minmax(value, min, max) {
|
|
|
389
458
|
}
|
|
390
459
|
function color2srgbvalues(token) {
|
|
391
460
|
const components = getComponents(token);
|
|
461
|
+
if (components == null) {
|
|
462
|
+
return null;
|
|
463
|
+
}
|
|
392
464
|
const colorSpace = components.shift();
|
|
393
465
|
let values = components.map((val) => getNumber(val));
|
|
394
466
|
switch (colorSpace.val) {
|
|
@@ -531,6 +603,10 @@ function getNumber(token) {
|
|
|
531
603
|
// @ts-ignore
|
|
532
604
|
return token.typ == EnumToken.PercentageTokenType ? token.val / 100 : +token.val;
|
|
533
605
|
}
|
|
606
|
+
/**
|
|
607
|
+
* convert angle to turn
|
|
608
|
+
* @param token
|
|
609
|
+
*/
|
|
534
610
|
function getAngle(token) {
|
|
535
611
|
if (token.typ == EnumToken.IdenTokenType) {
|
|
536
612
|
if (token.val == 'none') {
|