@tbela99/css-parser 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -0
- package/dist/config.json.js +225 -0
- package/dist/index-umd-web.js +1404 -604
- package/dist/index.cjs +1404 -604
- package/dist/lib/ast/features/calc.js +30 -190
- package/dist/lib/ast/features/index.js +3 -3
- package/dist/lib/ast/features/inlinecssvariables.js +5 -5
- package/dist/lib/ast/features/shorthand.js +4 -5
- package/dist/lib/ast/math/expression.js +185 -0
- package/dist/lib/ast/math/math.js +95 -0
- package/dist/lib/ast/types.js +30 -13
- package/dist/lib/ast/walk.js +24 -4
- package/dist/lib/fs/resolve.js +4 -3
- package/dist/lib/iterable/weakset.js +48 -0
- package/dist/lib/parser/declaration/list.js +5 -1
- package/dist/lib/parser/declaration/map.js +44 -13
- package/dist/lib/parser/declaration/set.js +41 -21
- package/dist/lib/parser/parse.js +30 -56
- package/dist/lib/parser/utils/declaration.js +67 -0
- package/dist/lib/parser/utils/syntax.js +32 -2
- package/dist/lib/renderer/render.js +77 -8
- package/dist/lib/renderer/utils/calccolor.js +238 -0
- package/dist/lib/renderer/utils/color.js +36 -164
- package/dist/lib/renderer/utils/hex.js +124 -0
- package/dist/lib/renderer/utils/hsl.js +49 -0
- package/dist/lib/renderer/utils/hsv.js +15 -0
- package/dist/lib/renderer/utils/hwb.js +50 -0
- package/dist/lib/renderer/utils/rgb.js +66 -0
- package/package.json +5 -5
- package/dist/index.d.ts +0 -862
package/dist/lib/ast/walk.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { EnumToken } from './types.js';
|
|
2
|
+
|
|
1
3
|
function* walk(node, filter) {
|
|
2
4
|
const parents = [node];
|
|
3
5
|
const root = node;
|
|
@@ -27,20 +29,38 @@ function* walk(node, filter) {
|
|
|
27
29
|
}
|
|
28
30
|
}
|
|
29
31
|
}
|
|
30
|
-
function* walkValues(values) {
|
|
32
|
+
function* walkValues(values, root = null, filter) {
|
|
31
33
|
const stack = values.slice();
|
|
32
34
|
const weakMap = new WeakMap;
|
|
33
35
|
let value;
|
|
34
36
|
while (stack.length > 0) {
|
|
35
37
|
value = stack.shift();
|
|
38
|
+
let option = null;
|
|
39
|
+
if (filter != null) {
|
|
40
|
+
option = filter(value);
|
|
41
|
+
if (option === 'ignore') {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (option === 'stop') {
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
36
48
|
// @ts-ignore
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
49
|
+
if (option !== 'children') {
|
|
50
|
+
// @ts-ignore
|
|
51
|
+
yield { value, parent: weakMap.get(value), root };
|
|
52
|
+
}
|
|
53
|
+
if (option !== 'ignore-children' && 'chi' in value) {
|
|
54
|
+
for (const child of value.chi.slice()) {
|
|
40
55
|
weakMap.set(child, value);
|
|
41
56
|
}
|
|
42
57
|
stack.unshift(...value.chi);
|
|
43
58
|
}
|
|
59
|
+
else if (value.typ == EnumToken.BinaryExpressionTokenType) {
|
|
60
|
+
weakMap.set(value.l, value);
|
|
61
|
+
weakMap.set(value.r, value);
|
|
62
|
+
stack.unshift(value.l, value.r);
|
|
63
|
+
}
|
|
44
64
|
}
|
|
45
65
|
}
|
|
46
66
|
|
package/dist/lib/fs/resolve.js
CHANGED
|
@@ -35,13 +35,14 @@ function splitPath(result) {
|
|
|
35
35
|
parts[parts.length - 1] += chr;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
-
let k =
|
|
39
|
-
while (k
|
|
38
|
+
let k = -1;
|
|
39
|
+
while (++k < parts.length) {
|
|
40
40
|
if (parts[k] == '.') {
|
|
41
|
-
parts.splice(k
|
|
41
|
+
parts.splice(k--, 1);
|
|
42
42
|
}
|
|
43
43
|
else if (parts[k] == '..') {
|
|
44
44
|
parts.splice(k - 1, 2);
|
|
45
|
+
k -= 2;
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
return { parts, i };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
class IterableWeakSet {
|
|
2
|
+
#weakset = new WeakSet;
|
|
3
|
+
#set = new Set;
|
|
4
|
+
constructor(iterable) {
|
|
5
|
+
if (iterable) {
|
|
6
|
+
for (const value of iterable) {
|
|
7
|
+
const ref = new WeakRef(value);
|
|
8
|
+
this.#weakset.add(value);
|
|
9
|
+
this.#set.add(ref);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
has(value) {
|
|
14
|
+
return this.#weakset.has(value);
|
|
15
|
+
}
|
|
16
|
+
delete(value) {
|
|
17
|
+
if (this.#weakset.has(value)) {
|
|
18
|
+
for (const ref of this.#set) {
|
|
19
|
+
if (ref.deref() === value) {
|
|
20
|
+
this.#set.delete(ref);
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return this.#weakset.delete(value);
|
|
25
|
+
}
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
add(value) {
|
|
29
|
+
if (!this.#weakset.has(value)) {
|
|
30
|
+
this.#weakset.add(value);
|
|
31
|
+
this.#set.add(new WeakRef(value));
|
|
32
|
+
}
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
*[Symbol.iterator]() {
|
|
36
|
+
for (const ref of new Set(this.#set)) {
|
|
37
|
+
const key = ref.deref();
|
|
38
|
+
if (key != null) {
|
|
39
|
+
yield key;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
this.#set.delete(ref);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { IterableWeakSet };
|
|
@@ -21,7 +21,11 @@ class PropertyList {
|
|
|
21
21
|
this.declarations = new Map;
|
|
22
22
|
}
|
|
23
23
|
set(nam, value) {
|
|
24
|
-
return this.add({
|
|
24
|
+
return this.add({
|
|
25
|
+
typ: EnumToken.DeclarationNodeType,
|
|
26
|
+
nam,
|
|
27
|
+
val: Array.isArray(value) ? value : parseString(String(value))
|
|
28
|
+
});
|
|
25
29
|
}
|
|
26
30
|
add(declaration) {
|
|
27
31
|
if (declaration.typ != EnumToken.DeclarationNodeType || !this.options.removeDuplicateDeclarations) {
|
|
@@ -7,9 +7,7 @@ import { parseString } from '../parse.js';
|
|
|
7
7
|
import { getConfig } from '../utils/config.js';
|
|
8
8
|
import { matchType } from '../utils/type.js';
|
|
9
9
|
import { PropertySet } from './set.js';
|
|
10
|
-
import { IterableWeakMap } from '../../iterable/weakmap.js';
|
|
11
10
|
|
|
12
|
-
const cache = new IterableWeakMap();
|
|
13
11
|
const propertiesConfig = getConfig();
|
|
14
12
|
class PropertyMap {
|
|
15
13
|
config;
|
|
@@ -195,15 +193,29 @@ class PropertyMap {
|
|
|
195
193
|
}
|
|
196
194
|
if (!isShorthand || requiredCount < this.requiredCount) {
|
|
197
195
|
if (isShorthand && this.declarations.has(this.config.shorthand)) {
|
|
198
|
-
|
|
196
|
+
const cache = new Map();
|
|
199
197
|
const removeDefaults = (declaration) => {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
198
|
+
let config = this.config.shorthand == declaration.nam ? this.config : this.config.properties[declaration.nam];
|
|
199
|
+
if (config == null && declaration.nam in propertiesConfig.properties) {
|
|
200
|
+
// @ts-ignore
|
|
201
|
+
const shorthand = propertiesConfig.properties[declaration.nam].shorthand;
|
|
202
|
+
// @ts-ignore
|
|
203
|
+
config = propertiesConfig.properties[shorthand];
|
|
204
|
+
}
|
|
205
|
+
declaration.val = declaration.val.map((t) => {
|
|
206
|
+
if (!cache.has(t)) {
|
|
207
|
+
cache.set(t, renderToken(t, { minify: true }));
|
|
205
208
|
}
|
|
206
|
-
|
|
209
|
+
const value = cache.get(t);
|
|
210
|
+
// @ts-ignore
|
|
211
|
+
if (config?.mapping?.[value] != null) {
|
|
212
|
+
// @ts-ignore
|
|
213
|
+
t = parseString(config.mapping[value])[0];
|
|
214
|
+
cache.set(t, renderToken(t, { minify: true }));
|
|
215
|
+
}
|
|
216
|
+
return t;
|
|
217
|
+
}).filter((val) => {
|
|
218
|
+
return !config?.default?.includes(cache.get(val));
|
|
207
219
|
})
|
|
208
220
|
.filter((val, index, array) => !(index > 0 &&
|
|
209
221
|
val.typ == EnumToken.WhitespaceTokenType &&
|
|
@@ -222,13 +234,24 @@ class PropertyMap {
|
|
|
222
234
|
}
|
|
223
235
|
return acc;
|
|
224
236
|
}, []);
|
|
225
|
-
|
|
237
|
+
let isImportant = false;
|
|
238
|
+
const filtered = values.map(removeDefaults).filter((x) => x.val.filter((t) => {
|
|
239
|
+
if (t.typ == EnumToken.ImportantTokenType) {
|
|
240
|
+
isImportant = true;
|
|
241
|
+
}
|
|
242
|
+
return ![EnumToken.WhitespaceTokenType, EnumToken.ImportantTokenType].includes(t.typ);
|
|
243
|
+
}).length > 0);
|
|
226
244
|
if (filtered.length == 0 && this.config.default.length > 0) {
|
|
227
245
|
filtered.push({
|
|
228
246
|
typ: EnumToken.DeclarationNodeType,
|
|
229
247
|
nam: this.config.shorthand,
|
|
230
248
|
val: parseString(this.config.default[0])
|
|
231
249
|
});
|
|
250
|
+
if (isImportant) {
|
|
251
|
+
filtered[0].val.push({
|
|
252
|
+
typ: EnumToken.ImportantTokenType
|
|
253
|
+
});
|
|
254
|
+
}
|
|
232
255
|
}
|
|
233
256
|
return (filtered.length > 0 ? filtered : values)[Symbol.iterator]();
|
|
234
257
|
}
|
|
@@ -324,7 +347,9 @@ class PropertyMap {
|
|
|
324
347
|
}, []);
|
|
325
348
|
// @todo remove renderToken call
|
|
326
349
|
if (props.default.includes(curr[1][i].reduce((acc, curr) => acc + renderToken(curr) + ' ', '').trimEnd())) {
|
|
327
|
-
|
|
350
|
+
if (!this.config.properties[curr[0]].required) {
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
328
353
|
}
|
|
329
354
|
// remove default values
|
|
330
355
|
let doFilterDefault = true;
|
|
@@ -338,12 +363,15 @@ class PropertyMap {
|
|
|
338
363
|
}
|
|
339
364
|
}
|
|
340
365
|
// remove default values
|
|
341
|
-
|
|
366
|
+
const filtered = values.filter((val) => {
|
|
342
367
|
if (val.typ == EnumToken.WhitespaceTokenType || val.typ == EnumToken.CommentTokenType) {
|
|
343
368
|
return false;
|
|
344
369
|
}
|
|
345
370
|
return !doFilterDefault || !(val.typ == EnumToken.IdenTokenType && props.default.includes(val.val));
|
|
346
371
|
});
|
|
372
|
+
if (filtered.length > 0 || !(this.requiredCount == requiredCount && this.config.properties[curr[0]].required)) {
|
|
373
|
+
values = filtered;
|
|
374
|
+
}
|
|
347
375
|
if (values.length > 0) {
|
|
348
376
|
if ('mapping' in props) {
|
|
349
377
|
// @ts-ignore
|
|
@@ -399,7 +427,10 @@ class PropertyMap {
|
|
|
399
427
|
return acc;
|
|
400
428
|
}, []);
|
|
401
429
|
if (this.config.mapping != null) {
|
|
402
|
-
const val = values.reduce((acc, curr) => acc + renderToken(curr, {
|
|
430
|
+
const val = values.reduce((acc, curr) => acc + renderToken(curr, {
|
|
431
|
+
removeComments: true,
|
|
432
|
+
minify: true
|
|
433
|
+
}), '');
|
|
403
434
|
if (val in this.config.mapping) {
|
|
404
435
|
values.length = 0;
|
|
405
436
|
values.push({
|
|
@@ -6,6 +6,29 @@ import '../parse.js';
|
|
|
6
6
|
import '../../renderer/utils/color.js';
|
|
7
7
|
import '../../renderer/sourcemap/lib/encode.js';
|
|
8
8
|
|
|
9
|
+
function dedup(values) {
|
|
10
|
+
for (const value of values) {
|
|
11
|
+
let i = value.length;
|
|
12
|
+
while (i-- > 1) {
|
|
13
|
+
const t = value[i];
|
|
14
|
+
const k = value[i == 1 ? 0 : i % 2];
|
|
15
|
+
if (t.val == k.val && t.val == '0') {
|
|
16
|
+
if ((t.typ == EnumToken.NumberTokenType && isLength(k)) ||
|
|
17
|
+
(k.typ == EnumToken.NumberTokenType && isLength(t)) ||
|
|
18
|
+
(isLength(k) || isLength(t))) {
|
|
19
|
+
value.splice(i, 1);
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (eq(t, k)) {
|
|
24
|
+
value.splice(i, 1);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return values;
|
|
31
|
+
}
|
|
9
32
|
class PropertySet {
|
|
10
33
|
config;
|
|
11
34
|
declarations;
|
|
@@ -100,7 +123,23 @@ class PropertySet {
|
|
|
100
123
|
let iterator;
|
|
101
124
|
const declarations = this.declarations;
|
|
102
125
|
if (declarations.size < this.config.properties.length) {
|
|
103
|
-
|
|
126
|
+
const values = [...declarations.values()];
|
|
127
|
+
if (this.isShortHand()) {
|
|
128
|
+
const val = values[0].val.reduce((acc, curr) => {
|
|
129
|
+
if (![EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType].includes(curr.typ)) {
|
|
130
|
+
acc.push(curr);
|
|
131
|
+
}
|
|
132
|
+
return acc;
|
|
133
|
+
}, []);
|
|
134
|
+
values[0].val = val.reduce((acc, curr) => {
|
|
135
|
+
if (acc.length > 0) {
|
|
136
|
+
acc.push({ typ: EnumToken.WhitespaceTokenType });
|
|
137
|
+
}
|
|
138
|
+
acc.push(curr);
|
|
139
|
+
return acc;
|
|
140
|
+
}, []);
|
|
141
|
+
}
|
|
142
|
+
return values[Symbol.iterator]();
|
|
104
143
|
}
|
|
105
144
|
else {
|
|
106
145
|
const values = [];
|
|
@@ -118,26 +157,7 @@ class PropertySet {
|
|
|
118
157
|
index++;
|
|
119
158
|
}
|
|
120
159
|
});
|
|
121
|
-
|
|
122
|
-
let i = value.length;
|
|
123
|
-
while (i-- > 1) {
|
|
124
|
-
const t = value[i];
|
|
125
|
-
const k = value[i == 1 ? 0 : i % 2];
|
|
126
|
-
if (t.val == k.val && t.val == '0') {
|
|
127
|
-
if ((t.typ == EnumToken.NumberTokenType && isLength(k)) ||
|
|
128
|
-
(k.typ == EnumToken.NumberTokenType && isLength(t)) ||
|
|
129
|
-
(isLength(k) || isLength(t))) {
|
|
130
|
-
value.splice(i, 1);
|
|
131
|
-
continue;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
if (eq(t, k)) {
|
|
135
|
-
value.splice(i, 1);
|
|
136
|
-
continue;
|
|
137
|
-
}
|
|
138
|
-
break;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
160
|
+
dedup(values);
|
|
141
161
|
iterator = [{
|
|
142
162
|
typ: EnumToken.DeclarationNodeType,
|
|
143
163
|
nam: this.config.shorthand,
|
package/dist/lib/parser/parse.js
CHANGED
|
@@ -1,24 +1,15 @@
|
|
|
1
|
-
import { isPseudo, isAtKeyword, isFunction, isNumber, isDimension, parseDimension,
|
|
2
|
-
import { EnumToken } from '../ast/types.js';
|
|
1
|
+
import { isPseudo, isAtKeyword, isFunction, isNumber, isPercentage, isFlex, isDimension, parseDimension, isIdent, isHexColor, isHash, isIdentStart, isColor } from './utils/syntax.js';
|
|
2
|
+
import { EnumToken, funcLike } from '../ast/types.js';
|
|
3
3
|
import { minify, combinators } from '../ast/minify.js';
|
|
4
4
|
import { walkValues, walk } from '../ast/walk.js';
|
|
5
5
|
import { expand } from '../ast/expand.js';
|
|
6
|
+
import { parseDeclaration } from './utils/declaration.js';
|
|
6
7
|
import { renderToken } from '../renderer/render.js';
|
|
7
8
|
import { COLORS_NAMES } from '../renderer/utils/color.js';
|
|
8
9
|
import { tokenize } from './tokenize.js';
|
|
9
10
|
|
|
10
11
|
const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
|
|
11
12
|
const trimWhiteSpace = [EnumToken.CommentTokenType, EnumToken.GtTokenType, EnumToken.GteTokenType, EnumToken.LtTokenType, EnumToken.LteTokenType, EnumToken.ColumnCombinatorTokenType];
|
|
12
|
-
const funcLike = [
|
|
13
|
-
EnumToken.ParensTokenType,
|
|
14
|
-
EnumToken.FunctionTokenType,
|
|
15
|
-
EnumToken.UrlFunctionTokenType,
|
|
16
|
-
EnumToken.StartParensTokenType,
|
|
17
|
-
EnumToken.ImageFunctionTokenType,
|
|
18
|
-
EnumToken.PseudoClassFuncTokenType,
|
|
19
|
-
EnumToken.TimingFunctionTokenType,
|
|
20
|
-
EnumToken.TimingFunctionTokenType
|
|
21
|
-
];
|
|
22
13
|
const BadTokensTypes = [
|
|
23
14
|
EnumToken.BadCommentTokenType,
|
|
24
15
|
EnumToken.BadCdoTokenType,
|
|
@@ -37,6 +28,7 @@ async function doParse(iterator, options = {}) {
|
|
|
37
28
|
src: '',
|
|
38
29
|
sourcemap: false,
|
|
39
30
|
minify: true,
|
|
31
|
+
parseColor: true,
|
|
40
32
|
nestingRules: false,
|
|
41
33
|
resolveImport: false,
|
|
42
34
|
resolveUrls: false,
|
|
@@ -312,7 +304,7 @@ async function doParse(iterator, options = {}) {
|
|
|
312
304
|
if (tokens[i].typ == EnumToken.ColonTokenType) {
|
|
313
305
|
name = tokens.slice(0, i);
|
|
314
306
|
value = parseTokens(tokens.slice(i + 1), {
|
|
315
|
-
parseColor:
|
|
307
|
+
parseColor: options.parseColor,
|
|
316
308
|
src: options.src,
|
|
317
309
|
resolveUrls: options.resolveUrls,
|
|
318
310
|
resolve: options.resolve,
|
|
@@ -351,19 +343,11 @@ async function doParse(iterator, options = {}) {
|
|
|
351
343
|
// @ts-ignore
|
|
352
344
|
val: value
|
|
353
345
|
};
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
errors.push({
|
|
359
|
-
action: 'drop',
|
|
360
|
-
message: 'doParse: invalid declaration',
|
|
361
|
-
location: { src, ...position }
|
|
362
|
-
});
|
|
363
|
-
return null;
|
|
346
|
+
const result = parseDeclaration(node, errors, src, position);
|
|
347
|
+
if (result != null) {
|
|
348
|
+
// @ts-ignore
|
|
349
|
+
context.chi.push(node);
|
|
364
350
|
}
|
|
365
|
-
// @ts-ignore
|
|
366
|
-
context.chi.push(node);
|
|
367
351
|
return null;
|
|
368
352
|
}
|
|
369
353
|
}
|
|
@@ -620,15 +604,21 @@ function getTokenType(val, hint) {
|
|
|
620
604
|
val
|
|
621
605
|
};
|
|
622
606
|
}
|
|
623
|
-
if (isDimension(val)) {
|
|
624
|
-
return parseDimension(val);
|
|
625
|
-
}
|
|
626
607
|
if (isPercentage(val)) {
|
|
627
608
|
return {
|
|
628
609
|
typ: EnumToken.PercentageTokenType,
|
|
629
610
|
val: val.slice(0, -1)
|
|
630
611
|
};
|
|
631
612
|
}
|
|
613
|
+
if (isFlex(val)) {
|
|
614
|
+
return {
|
|
615
|
+
typ: EnumToken.FlexTokenType,
|
|
616
|
+
val: val.slice(0, -2)
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
if (isDimension(val)) {
|
|
620
|
+
return parseDimension(val);
|
|
621
|
+
}
|
|
632
622
|
const v = val.toLowerCase();
|
|
633
623
|
if (v == 'currentcolor' || val == 'transparent' || v in COLORS_NAMES) {
|
|
634
624
|
return {
|
|
@@ -728,15 +718,6 @@ function parseTokens(tokens, options = {}) {
|
|
|
728
718
|
// @ts-ignore
|
|
729
719
|
parseTokens(t.chi, t.typ);
|
|
730
720
|
}
|
|
731
|
-
// @ts-ignore
|
|
732
|
-
// t.chi.forEach(val => {
|
|
733
|
-
// if (val.typ == EnumToken.StringTokenType) {
|
|
734
|
-
// const slice = val.val.slice(1, -1);
|
|
735
|
-
// if ((slice.charAt(0) != '-' || (slice.charAt(0) == '-' && isIdentStart(slice.charCodeAt(1)))) && isIdent(slice)) {
|
|
736
|
-
// Object.assign(val, {typ: EnumToken.IdenTokenType, val: slice});
|
|
737
|
-
// }
|
|
738
|
-
// }
|
|
739
|
-
// });
|
|
740
721
|
let m = t.chi.length;
|
|
741
722
|
let val;
|
|
742
723
|
for (m = 0; m < t.chi.length; m++) {
|
|
@@ -871,6 +852,11 @@ function parseTokens(tokens, options = {}) {
|
|
|
871
852
|
// @ts-ignore
|
|
872
853
|
t.chi.pop();
|
|
873
854
|
}
|
|
855
|
+
// @ts-ignore
|
|
856
|
+
if (t.chi.length > 0) {
|
|
857
|
+
// @ts-ignore
|
|
858
|
+
parseTokens(t.chi, options);
|
|
859
|
+
}
|
|
874
860
|
if (t.typ == EnumToken.FunctionTokenType && t.val == 'calc') {
|
|
875
861
|
for (const { value, parent } of walkValues(t.chi)) {
|
|
876
862
|
if (value.typ == EnumToken.WhitespaceTokenType) {
|
|
@@ -893,35 +879,25 @@ function parseTokens(tokens, options = {}) {
|
|
|
893
879
|
}
|
|
894
880
|
}
|
|
895
881
|
}
|
|
882
|
+
else if (t.typ == EnumToken.FunctionTokenType && ['minmax', 'fit-content', 'repeat'].includes(t.val)) {
|
|
883
|
+
// @ts-ignore
|
|
884
|
+
t.typ = EnumToken.GridTemplateFuncTokenType;
|
|
885
|
+
}
|
|
896
886
|
else if (t.typ == EnumToken.StartParensTokenType) {
|
|
897
887
|
// @ts-ignore
|
|
898
888
|
t.typ = EnumToken.ParensTokenType;
|
|
899
889
|
}
|
|
900
890
|
// @ts-ignore
|
|
901
891
|
if (options.parseColor && t.typ == EnumToken.FunctionTokenType && isColor(t)) {
|
|
902
|
-
// if (isColor) {
|
|
903
892
|
// @ts-ignore
|
|
904
893
|
t.typ = EnumToken.ColorTokenType;
|
|
905
894
|
// @ts-ignore
|
|
906
895
|
t.kin = t.val;
|
|
907
|
-
|
|
908
|
-
let m = t.chi.length;
|
|
909
|
-
while (m-- > 0) {
|
|
896
|
+
if (t.chi[0].typ == EnumToken.IdenTokenType && t.chi[0].val == 'from') {
|
|
910
897
|
// @ts-ignore
|
|
911
|
-
|
|
912
|
-
// @ts-ignore
|
|
913
|
-
if (t.chi[m + 1]?.typ == EnumToken.WhitespaceTokenType) {
|
|
914
|
-
// @ts-ignore
|
|
915
|
-
t.chi.splice(m + 1, 1);
|
|
916
|
-
}
|
|
917
|
-
// @ts-ignore
|
|
918
|
-
if (t.chi[m - 1]?.typ == EnumToken.WhitespaceTokenType) {
|
|
919
|
-
// @ts-ignore
|
|
920
|
-
t.chi.splice(m - 1, 1);
|
|
921
|
-
m--;
|
|
922
|
-
}
|
|
923
|
-
}
|
|
898
|
+
t.cal = 'rel';
|
|
924
899
|
}
|
|
900
|
+
t.chi = t.chi.filter((t) => ![EnumToken.WhitespaceTokenType, EnumToken.CommaTokenType, EnumToken.CommentTokenType].includes(t.typ));
|
|
925
901
|
continue;
|
|
926
902
|
}
|
|
927
903
|
if (t.typ == EnumToken.UrlFunctionTokenType) {
|
|
@@ -946,8 +922,6 @@ function parseTokens(tokens, options = {}) {
|
|
|
946
922
|
}
|
|
947
923
|
// @ts-ignore
|
|
948
924
|
if (t.chi.length > 0) {
|
|
949
|
-
// @ts-ignore
|
|
950
|
-
parseTokens(t.chi, options);
|
|
951
925
|
if (t.typ == EnumToken.PseudoClassFuncTokenType && t.val == ':is' && options.minify) {
|
|
952
926
|
//
|
|
953
927
|
const count = t.chi.filter(t => t.typ != EnumToken.CommentTokenType).length;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { EnumToken } from '../../ast/types.js';
|
|
2
|
+
import '../../ast/minify.js';
|
|
3
|
+
import { walkValues } from '../../ast/walk.js';
|
|
4
|
+
import '../parse.js';
|
|
5
|
+
import { isWhiteSpace } from './syntax.js';
|
|
6
|
+
import '../../renderer/utils/color.js';
|
|
7
|
+
import '../../renderer/sourcemap/lib/encode.js';
|
|
8
|
+
|
|
9
|
+
function parseDeclaration(node, errors, src, position) {
|
|
10
|
+
while (node.val[0]?.typ == EnumToken.WhitespaceTokenType) {
|
|
11
|
+
node.val.shift();
|
|
12
|
+
}
|
|
13
|
+
if (node.val.filter((t) => ![EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType].includes(t.typ)).length == 0) {
|
|
14
|
+
errors.push({
|
|
15
|
+
action: 'drop',
|
|
16
|
+
message: 'doParse: invalid declaration',
|
|
17
|
+
location: { src, ...position }
|
|
18
|
+
});
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
for (const { value: val, parent } of walkValues(node.val, node)) {
|
|
22
|
+
if (val.typ == EnumToken.AttrTokenType && val.chi.every((t) => [EnumToken.IdenTokenType, EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType].includes(t.typ))) {
|
|
23
|
+
// @ts-ignore
|
|
24
|
+
val.typ = EnumToken.IdenListTokenType;
|
|
25
|
+
}
|
|
26
|
+
else if (val.typ == EnumToken.StringTokenType && (node.nam == 'grid' || node.nam == 'grid-template-areas' || node.nam == 'grid-template-rows' || node.nam == 'grid-template-columns')) {
|
|
27
|
+
val.val = val.val.at(0) + parseGridTemplate(val.val.slice(1, -1)) + val.val.at(-1);
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
const array = parent?.chi ?? node.val;
|
|
30
|
+
const index = array.indexOf(val);
|
|
31
|
+
if (index > 0 && array[index - 1].typ == EnumToken.WhitespaceTokenType) {
|
|
32
|
+
array.splice(index - 1, 1);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return node;
|
|
37
|
+
}
|
|
38
|
+
function parseGridTemplate(template) {
|
|
39
|
+
let result = '';
|
|
40
|
+
let buffer = '';
|
|
41
|
+
for (let i = 0; i < template.length; i++) {
|
|
42
|
+
const char = template[i];
|
|
43
|
+
if (isWhiteSpace(char.codePointAt(0))) {
|
|
44
|
+
while (i + 1 < template.length && isWhiteSpace(template[i + 1].codePointAt(0))) {
|
|
45
|
+
i++;
|
|
46
|
+
}
|
|
47
|
+
result += buffer + ' ';
|
|
48
|
+
buffer = '';
|
|
49
|
+
}
|
|
50
|
+
else if (char == '.') {
|
|
51
|
+
while (i + 1 < template.length && template[i + 1] == '.') {
|
|
52
|
+
i++;
|
|
53
|
+
}
|
|
54
|
+
if (isWhiteSpace((result.at(-1)?.codePointAt(0)))) {
|
|
55
|
+
result = result.slice(0, -1);
|
|
56
|
+
}
|
|
57
|
+
result += buffer + char;
|
|
58
|
+
buffer = '';
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
buffer += char;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return buffer.length > 0 ? result + buffer : result;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export { parseDeclaration };
|
|
@@ -37,10 +37,37 @@ function isColor(token) {
|
|
|
37
37
|
// named color
|
|
38
38
|
return token.val.toLowerCase() in COLORS_NAMES;
|
|
39
39
|
}
|
|
40
|
+
let isLegacySyntax = false;
|
|
40
41
|
if (token.typ == EnumToken.FunctionTokenType && token.chi.length > 0 && colorsFunc.includes(token.val)) {
|
|
42
|
+
const keywords = ['from', 'none'];
|
|
43
|
+
if (['rgb', 'hsl', 'hwb'].includes(token.val)) {
|
|
44
|
+
keywords.push('a', ...token.val.split(''));
|
|
45
|
+
}
|
|
46
|
+
// console.debug(JSON.stringify({token}, null, 1));
|
|
41
47
|
// @ts-ignore
|
|
42
48
|
for (const v of token.chi) {
|
|
43
|
-
|
|
49
|
+
// console.debug(JSON.stringify({v}, null, 1));
|
|
50
|
+
if (v.typ == EnumToken.CommaTokenType) {
|
|
51
|
+
isLegacySyntax = true;
|
|
52
|
+
}
|
|
53
|
+
if (v.typ == EnumToken.IdenTokenType) {
|
|
54
|
+
if (!(keywords.includes(v.val) || v.val.toLowerCase() in COLORS_NAMES)) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
if (keywords.includes(v.val)) {
|
|
58
|
+
if (isLegacySyntax) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
if (v.val == 'from' && ['rgba', 'hsla'].includes(token.val)) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (v.typ == EnumToken.FunctionTokenType && (v.val == 'calc' || colorsFunc.includes(v.val))) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (![EnumToken.ColorTokenType, EnumToken.IdenTokenType, EnumToken.NumberTokenType, EnumToken.AngleTokenType, EnumToken.PercentageTokenType, EnumToken.CommaTokenType, EnumToken.WhitespaceTokenType, EnumToken.LiteralTokenType].includes(v.typ)) {
|
|
44
71
|
return false;
|
|
45
72
|
}
|
|
46
73
|
}
|
|
@@ -200,6 +227,9 @@ function isDimension(name) {
|
|
|
200
227
|
function isPercentage(name) {
|
|
201
228
|
return name.endsWith('%') && isNumber(name.slice(0, -1));
|
|
202
229
|
}
|
|
230
|
+
function isFlex(name) {
|
|
231
|
+
return name.endsWith('fr') && isNumber(name.slice(0, -2));
|
|
232
|
+
}
|
|
203
233
|
function parseDimension(name) {
|
|
204
234
|
let index = name.length;
|
|
205
235
|
while (index--) {
|
|
@@ -267,4 +297,4 @@ function isWhiteSpace(codepoint) {
|
|
|
267
297
|
codepoint == 0xa || codepoint == 0xc || codepoint == 0xd;
|
|
268
298
|
}
|
|
269
299
|
|
|
270
|
-
export { isAngle, isAtKeyword, isColor, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNonPrintable, isNumber, isPercentage, isPseudo, isResolution, isTime, isWhiteSpace, parseDimension };
|
|
300
|
+
export { isAngle, isAtKeyword, isColor, isDigit, isDimension, isFlex, isFrequency, isFunction, isHash, isHexColor, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNonPrintable, isNumber, isPercentage, isPseudo, isResolution, isTime, isWhiteSpace, parseDimension };
|