@tbela99/css-parser 0.0.1-rc2 → 0.0.1-rc4
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 +59 -3
- package/dist/index-umd-web.js +253 -129
- package/dist/index.cjs +253 -129
- package/dist/index.d.ts +37 -3
- package/dist/lib/ast/minify.js +11 -0
- package/dist/lib/parser/declaration/map.js +47 -29
- package/dist/lib/parser/parse.js +17 -11
- package/dist/lib/parser/tokenize.js +40 -18
- package/dist/lib/parser/utils/syntax.js +15 -22
- package/dist/lib/parser/utils/type.js +4 -0
- package/dist/lib/renderer/render.js +108 -39
- package/dist/lib/renderer/utils/color.js +2 -2
- package/dist/node/index.js +7 -1
- package/dist/web/index.js +1 -0
- package/package.json +16 -16
- package/.gitattributes +0 -22
- package/dist/index.js +0 -10
package/dist/index.d.ts
CHANGED
|
@@ -91,12 +91,14 @@ interface BlockEndToken {
|
|
|
91
91
|
}
|
|
92
92
|
interface AttrStartToken {
|
|
93
93
|
typ: 'Attr-start';
|
|
94
|
+
chi?: Token[];
|
|
94
95
|
}
|
|
95
96
|
interface AttrEndToken {
|
|
96
97
|
typ: 'Attr-end';
|
|
97
98
|
}
|
|
98
99
|
interface ParensStartToken {
|
|
99
100
|
typ: 'Start-parens';
|
|
101
|
+
chi?: Token[];
|
|
100
102
|
}
|
|
101
103
|
interface ParensEndToken {
|
|
102
104
|
typ: 'End-parens';
|
|
@@ -131,9 +133,15 @@ interface DashMatchToken {
|
|
|
131
133
|
interface LessThanToken {
|
|
132
134
|
typ: 'Lt';
|
|
133
135
|
}
|
|
136
|
+
interface LessThanOrEqualToken {
|
|
137
|
+
typ: 'Lte';
|
|
138
|
+
}
|
|
134
139
|
interface GreaterThanToken {
|
|
135
140
|
typ: 'Gt';
|
|
136
141
|
}
|
|
142
|
+
interface GreaterThanOrEqualToken {
|
|
143
|
+
typ: 'Gte';
|
|
144
|
+
}
|
|
137
145
|
interface PseudoClassToken {
|
|
138
146
|
typ: 'Pseudo-class';
|
|
139
147
|
val: string;
|
|
@@ -171,7 +179,31 @@ interface AttrToken {
|
|
|
171
179
|
typ: 'Attr';
|
|
172
180
|
chi: Token[];
|
|
173
181
|
}
|
|
174
|
-
declare type Token = LiteralToken | IdentToken | CommaToken | ColonToken | SemiColonToken | NumberToken | AtRuleToken | PercentageToken | FunctionURLToken | FunctionToken | DimensionToken | LengthToken | AngleToken | StringToken | TimeToken | FrequencyToken | ResolutionToken | UnclosedStringToken | HashToken | BadStringToken | BlockStartToken | BlockEndToken | AttrStartToken | AttrEndToken | ParensStartToken | ParensEndToken | CDOCommentToken | BadCDOCommentToken | CommentToken | BadCommentToken | WhitespaceToken | IncludesToken | DashMatchToken | LessThanToken | GreaterThanToken | PseudoClassToken | PseudoClassFunctionToken | DelimToken | BadUrlToken | UrlToken | ImportantToken | ColorToken | AttrToken | EOFToken;
|
|
182
|
+
declare type Token = LiteralToken | IdentToken | CommaToken | ColonToken | SemiColonToken | NumberToken | AtRuleToken | PercentageToken | FunctionURLToken | FunctionToken | DimensionToken | LengthToken | AngleToken | StringToken | TimeToken | FrequencyToken | ResolutionToken | UnclosedStringToken | HashToken | BadStringToken | BlockStartToken | BlockEndToken | AttrStartToken | AttrEndToken | ParensStartToken | ParensEndToken | CDOCommentToken | BadCDOCommentToken | CommentToken | BadCommentToken | WhitespaceToken | IncludesToken | DashMatchToken | LessThanToken | LessThanOrEqualToken | GreaterThanToken | GreaterThanOrEqualToken | PseudoClassToken | PseudoClassFunctionToken | DelimToken | BadUrlToken | UrlToken | ImportantToken | ColorToken | AttrToken | EOFToken;
|
|
183
|
+
|
|
184
|
+
interface PropertyMapType {
|
|
185
|
+
default: string[];
|
|
186
|
+
types: string[];
|
|
187
|
+
keywords: string[];
|
|
188
|
+
required?: boolean;
|
|
189
|
+
multiple?: boolean;
|
|
190
|
+
prefix?: {
|
|
191
|
+
typ: 'Literal';
|
|
192
|
+
val: string;
|
|
193
|
+
};
|
|
194
|
+
previous?: string;
|
|
195
|
+
separator?: {
|
|
196
|
+
typ: 'Comma';
|
|
197
|
+
};
|
|
198
|
+
constraints?: {
|
|
199
|
+
[key: string]: {
|
|
200
|
+
[key: string]: any;
|
|
201
|
+
};
|
|
202
|
+
};
|
|
203
|
+
mapping?: {
|
|
204
|
+
[key: string]: any;
|
|
205
|
+
};
|
|
206
|
+
}
|
|
175
207
|
|
|
176
208
|
interface PropertiesConfig {
|
|
177
209
|
properties: PropertiesConfigProperties;
|
|
@@ -629,8 +661,10 @@ declare function isWhiteSpace(codepoint: number): boolean;
|
|
|
629
661
|
|
|
630
662
|
declare const getConfig: () => PropertiesConfig;
|
|
631
663
|
|
|
664
|
+
declare function matchType(val: Token, properties: PropertyMapType): boolean;
|
|
665
|
+
|
|
632
666
|
declare function render(data: AstNode, opt?: RenderOptions): RenderResult;
|
|
633
|
-
declare function renderToken(token: Token, options?: RenderOptions): string;
|
|
667
|
+
declare function renderToken(token: Token, options?: RenderOptions, reducer?: (acc: string, curr: Token) => string): string;
|
|
634
668
|
|
|
635
669
|
declare const combinators: string[];
|
|
636
670
|
declare function minify(ast: AstNode, options?: ParserOptions, recursive?: boolean): AstNode;
|
|
@@ -661,4 +695,4 @@ declare function resolve(url: string, currentDirectory: string, cwd?: string): {
|
|
|
661
695
|
declare function parse(iterator: string, opt?: ParserOptions): Promise<ParseResult>;
|
|
662
696
|
declare function transform(css: string, options?: TransformOptions): Promise<TransformResult>;
|
|
663
697
|
|
|
664
|
-
export { combinators, dirname, getConfig, hasDeclaration, isAngle, isAtKeyword, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor, isHexDigit, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNumber, isPercentage, isPseudo, isResolution, isTime, isWhiteSpace, load, matchUrl, minify, minifyRule, parse, parseDimension, parseString, reduceSelector, render, renderToken, resolve, tokenize, transform, urlTokenMatcher, walk };
|
|
698
|
+
export { combinators, dirname, getConfig, hasDeclaration, isAngle, isAtKeyword, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor, isHexDigit, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNumber, isPercentage, isPseudo, isResolution, isTime, isWhiteSpace, load, matchType, matchUrl, minify, minifyRule, parse, parseDimension, parseString, reduceSelector, render, renderToken, resolve, tokenize, transform, urlTokenMatcher, walk };
|
package/dist/lib/ast/minify.js
CHANGED
|
@@ -344,6 +344,17 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
344
344
|
continue;
|
|
345
345
|
// }
|
|
346
346
|
}
|
|
347
|
+
// @ts-ignore
|
|
348
|
+
if (hasDeclaration(node)) {
|
|
349
|
+
// @ts-ignore
|
|
350
|
+
minifyRule(node);
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
minify(node, options, recursive);
|
|
354
|
+
}
|
|
355
|
+
previous = node;
|
|
356
|
+
nodeIndex = i;
|
|
357
|
+
continue;
|
|
347
358
|
}
|
|
348
359
|
// @ts-ignore
|
|
349
360
|
if (node.typ == 'Rule') {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { eq } from '../utils/eq.js';
|
|
2
2
|
import { getConfig } from '../utils/config.js';
|
|
3
|
-
import { renderToken } from '../../renderer/render.js';
|
|
4
3
|
import { matchType } from '../utils/type.js';
|
|
4
|
+
import { renderToken } from '../../renderer/render.js';
|
|
5
5
|
import { parseString } from '../parse.js';
|
|
6
6
|
import { PropertySet } from './set.js';
|
|
7
7
|
|
|
@@ -19,6 +19,9 @@ class PropertyMap {
|
|
|
19
19
|
this.pattern = config.pattern.split(/\s/);
|
|
20
20
|
}
|
|
21
21
|
add(declaration) {
|
|
22
|
+
for (const val of declaration.val) {
|
|
23
|
+
Object.defineProperty(val, 'propertyName', { enumerable: false, writable: true, value: declaration.nam });
|
|
24
|
+
}
|
|
22
25
|
if (declaration.nam == this.config.shorthand) {
|
|
23
26
|
this.declarations = new Map;
|
|
24
27
|
this.declarations.set(declaration.nam, declaration);
|
|
@@ -52,7 +55,8 @@ class PropertyMap {
|
|
|
52
55
|
i--;
|
|
53
56
|
continue;
|
|
54
57
|
}
|
|
55
|
-
|
|
58
|
+
// @ts-ignore
|
|
59
|
+
if (('propertyName' in acc[i] && acc[i].propertyName == property) || matchType(acc[i], props)) {
|
|
56
60
|
if ('prefix' in props && props.previous != null && !(props.previous in tokens)) {
|
|
57
61
|
return acc;
|
|
58
62
|
}
|
|
@@ -186,10 +190,12 @@ class PropertyMap {
|
|
|
186
190
|
}
|
|
187
191
|
else {
|
|
188
192
|
let count = 0;
|
|
193
|
+
let match;
|
|
189
194
|
const separator = this.config.separator;
|
|
190
195
|
const tokens = {};
|
|
191
196
|
// @ts-ignore
|
|
192
|
-
/* const valid: string[] =*/
|
|
197
|
+
/* const valid: string[] =*/
|
|
198
|
+
Object.entries(this.config.properties).reduce((acc, curr) => {
|
|
193
199
|
if (!this.declarations.has(curr[0])) {
|
|
194
200
|
if (curr[1].required) {
|
|
195
201
|
acc.push(curr[0]);
|
|
@@ -198,33 +204,40 @@ class PropertyMap {
|
|
|
198
204
|
}
|
|
199
205
|
let current = 0;
|
|
200
206
|
const props = this.config.properties[curr[0]];
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
tokens[curr[0]].
|
|
207
|
+
const properties = this.declarations.get(curr[0]);
|
|
208
|
+
for (const declaration of [(properties instanceof PropertySet ? [...properties][0] : properties)]) {
|
|
209
|
+
// @ts-ignore
|
|
210
|
+
for (const val of declaration.val) {
|
|
211
|
+
if (separator != null && separator.typ == val.typ && eq(separator, val)) {
|
|
212
|
+
current++;
|
|
213
|
+
if (tokens[curr[0]].length == current) {
|
|
214
|
+
tokens[curr[0]].push([]);
|
|
215
|
+
}
|
|
216
|
+
continue;
|
|
208
217
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
218
|
+
if (val.typ == 'Whitespace' || val.typ == 'Comment') {
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(props.separator, val)) {
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
// @ts-ignore
|
|
225
|
+
match = val.typ == 'Comment' || matchType(val, curr[1]);
|
|
226
|
+
if (isShorthand) {
|
|
227
|
+
isShorthand = match;
|
|
228
|
+
}
|
|
229
|
+
// @ts-ignore
|
|
230
|
+
if (('propertyName' in val && val.propertyName == property) || match) {
|
|
231
|
+
if (!(curr[0] in tokens)) {
|
|
232
|
+
tokens[curr[0]] = [[]];
|
|
233
|
+
}
|
|
234
|
+
// is default value
|
|
235
|
+
tokens[curr[0]][current].push(val);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
acc.push(curr[0]);
|
|
239
|
+
break;
|
|
220
240
|
}
|
|
221
|
-
// is default value
|
|
222
|
-
tokens[curr[0]][current].push(val);
|
|
223
|
-
// continue;
|
|
224
|
-
}
|
|
225
|
-
else {
|
|
226
|
-
acc.push(curr[0]);
|
|
227
|
-
break;
|
|
228
241
|
}
|
|
229
242
|
}
|
|
230
243
|
if (count == 0) {
|
|
@@ -233,7 +246,12 @@ class PropertyMap {
|
|
|
233
246
|
return acc;
|
|
234
247
|
}, []);
|
|
235
248
|
count++;
|
|
236
|
-
if (!Object.
|
|
249
|
+
if (!isShorthand || Object.entries(this.config.properties).some(entry => {
|
|
250
|
+
// missing required property
|
|
251
|
+
return entry[1].required && !(entry[0] in tokens);
|
|
252
|
+
}) ||
|
|
253
|
+
// @ts-ignore
|
|
254
|
+
!Object.values(tokens).every(v => v.filter(t => t.typ != 'Comment').length == count)) {
|
|
237
255
|
// @ts-ignore
|
|
238
256
|
iterable = this.declarations.values();
|
|
239
257
|
}
|
package/dist/lib/parser/parse.js
CHANGED
|
@@ -5,6 +5,7 @@ import { minify, combinators } from '../ast/minify.js';
|
|
|
5
5
|
import { tokenize } from './tokenize.js';
|
|
6
6
|
|
|
7
7
|
const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
|
|
8
|
+
const trimWhiteSpace = ['Gt', 'Gte', 'Lt', 'Lte'];
|
|
8
9
|
const funcLike = ['Start-parens', 'Func', 'UrlFunc', 'Pseudo-class-func'];
|
|
9
10
|
/**
|
|
10
11
|
*
|
|
@@ -51,6 +52,10 @@ async function parse(iterator, opt = {}) {
|
|
|
51
52
|
let tokens = results.map(mapToken);
|
|
52
53
|
let i;
|
|
53
54
|
let loc;
|
|
55
|
+
// if ((<Token>tokens.at(-1))?.typ == 'EOF') {
|
|
56
|
+
//
|
|
57
|
+
// tokens.pop();
|
|
58
|
+
// }
|
|
54
59
|
for (i = 0; i < tokens.length; i++) {
|
|
55
60
|
if (tokens[i].typ == 'Comment') {
|
|
56
61
|
// @ts-ignore
|
|
@@ -169,7 +174,7 @@ async function parse(iterator, opt = {}) {
|
|
|
169
174
|
// https://www.w3.org/TR/css-nesting-1/#conditionals
|
|
170
175
|
// allowed nesting at-rules
|
|
171
176
|
// there must be a top level rule in the stack
|
|
172
|
-
const raw = tokens.reduce((acc, curr) => {
|
|
177
|
+
const raw = parseTokens(tokens, { minify: options.minify }).reduce((acc, curr) => {
|
|
173
178
|
acc.push(renderToken(curr, { removeComments: true }));
|
|
174
179
|
return acc;
|
|
175
180
|
}, []);
|
|
@@ -200,8 +205,8 @@ async function parse(iterator, opt = {}) {
|
|
|
200
205
|
const uniq = new Map;
|
|
201
206
|
parseTokens(tokens, { minify: options.minify }).reduce((acc, curr, index, array) => {
|
|
202
207
|
if (curr.typ == 'Whitespace') {
|
|
203
|
-
if (array[index - 1]?.typ
|
|
204
|
-
array[index + 1]?.typ
|
|
208
|
+
if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
|
|
209
|
+
trimWhiteSpace.includes(array[index + 1]?.typ) ||
|
|
205
210
|
combinators.includes(array[index - 1]?.val) ||
|
|
206
211
|
combinators.includes(array[index + 1]?.val)) {
|
|
207
212
|
return acc;
|
|
@@ -389,13 +394,13 @@ async function parse(iterator, opt = {}) {
|
|
|
389
394
|
};
|
|
390
395
|
}
|
|
391
396
|
function parseString(src, options = { location: false }) {
|
|
392
|
-
return [...tokenize(src)].map(t => {
|
|
397
|
+
return parseTokens([...tokenize(src)].map(t => {
|
|
393
398
|
const token = getTokenType(t.token, t.hint);
|
|
394
399
|
if (options.location) {
|
|
395
400
|
Object.assign(token, { loc: t.position });
|
|
396
401
|
}
|
|
397
402
|
return token;
|
|
398
|
-
});
|
|
403
|
+
}));
|
|
399
404
|
}
|
|
400
405
|
function getTokenType(val, hint) {
|
|
401
406
|
if (val === '' && hint == null) {
|
|
@@ -405,7 +410,7 @@ function getTokenType(val, hint) {
|
|
|
405
410
|
return ([
|
|
406
411
|
'Whitespace', 'Semi-colon', 'Colon', 'Block-start',
|
|
407
412
|
'Block-start', 'Attr-start', 'Attr-end', 'Start-parens', 'End-parens',
|
|
408
|
-
'Comma', 'Gt', 'Lt'
|
|
413
|
+
'Comma', 'Gt', 'Lt', 'Gte', 'Lte', 'EOF'
|
|
409
414
|
].includes(hint) ? { typ: hint } : { typ: hint, val });
|
|
410
415
|
}
|
|
411
416
|
if (val == ' ') {
|
|
@@ -533,11 +538,12 @@ function parseTokens(tokens, options = {}) {
|
|
|
533
538
|
const t = tokens[i];
|
|
534
539
|
if (t.typ == 'Whitespace' && ((i == 0 ||
|
|
535
540
|
i + 1 == tokens.length ||
|
|
536
|
-
['Comma'].includes(tokens[i + 1].typ) ||
|
|
541
|
+
['Comma', 'Gte', 'Lte'].includes(tokens[i + 1].typ)) ||
|
|
537
542
|
(i > 0 &&
|
|
538
|
-
tokens[i + 1]?.typ != 'Literal'
|
|
539
|
-
funcLike.includes(tokens[i - 1].typ) &&
|
|
540
|
-
!['var', 'calc'].includes(tokens[i - 1].val))))
|
|
543
|
+
// tokens[i + 1]?.typ != 'Literal' ||
|
|
544
|
+
// funcLike.includes(tokens[i - 1].typ) &&
|
|
545
|
+
// !['var', 'calc'].includes((<FunctionToken>tokens[i - 1]).val)))) &&
|
|
546
|
+
trimWhiteSpace.includes(tokens[i - 1].typ)))) {
|
|
541
547
|
tokens.splice(i--, 1);
|
|
542
548
|
continue;
|
|
543
549
|
}
|
|
@@ -654,7 +660,7 @@ function parseTokens(tokens, options = {}) {
|
|
|
654
660
|
let m = t.chi.length;
|
|
655
661
|
while (m-- > 0) {
|
|
656
662
|
// @ts-ignore
|
|
657
|
-
if (t.chi[m].typ
|
|
663
|
+
if (['Literal'].concat(trimWhiteSpace).includes(t.chi[m].typ)) {
|
|
658
664
|
// @ts-ignore
|
|
659
665
|
if (t.chi[m + 1]?.typ == 'Whitespace') {
|
|
660
666
|
// @ts-ignore
|
|
@@ -36,11 +36,6 @@ function* tokenize(iterator) {
|
|
|
36
36
|
}
|
|
37
37
|
buffer += quoteStr;
|
|
38
38
|
while (value = peek()) {
|
|
39
|
-
// if (ind >= iterator.length) {
|
|
40
|
-
//
|
|
41
|
-
// yield pushToken(buffer, hasNewLine ? 'Bad-string' : 'Unclosed-string');
|
|
42
|
-
// break;
|
|
43
|
-
// }
|
|
44
39
|
if (value == '\\') {
|
|
45
40
|
const sequence = peek(6);
|
|
46
41
|
let escapeSequence = '';
|
|
@@ -60,9 +55,23 @@ function* tokenize(iterator) {
|
|
|
60
55
|
}
|
|
61
56
|
break;
|
|
62
57
|
}
|
|
58
|
+
// @ts-ignore
|
|
59
|
+
if (isNewLine(codepoint)) {
|
|
60
|
+
if (i == 1) {
|
|
61
|
+
buffer += value + escapeSequence.slice(0, i);
|
|
62
|
+
next(i + 1);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
// else {
|
|
66
|
+
yield pushToken(buffer + value + escapeSequence.slice(0, i), 'Bad-string');
|
|
67
|
+
buffer = '';
|
|
68
|
+
// }
|
|
69
|
+
next(i + 1);
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
63
72
|
// not hex or new line
|
|
64
73
|
// @ts-ignore
|
|
65
|
-
if (i == 1
|
|
74
|
+
else if (i == 1) {
|
|
66
75
|
buffer += value + sequence[i];
|
|
67
76
|
next(2);
|
|
68
77
|
continue;
|
|
@@ -82,13 +91,6 @@ function* tokenize(iterator) {
|
|
|
82
91
|
next(escapeSequence.length + 1);
|
|
83
92
|
continue;
|
|
84
93
|
}
|
|
85
|
-
// buffer += value;
|
|
86
|
-
// if (ind >= iterator.length) {
|
|
87
|
-
//
|
|
88
|
-
// // drop '\\' at the end
|
|
89
|
-
// yield pushToken(buffer);
|
|
90
|
-
// break;
|
|
91
|
-
// }
|
|
92
94
|
buffer += next(2);
|
|
93
95
|
continue;
|
|
94
96
|
}
|
|
@@ -98,20 +100,28 @@ function* tokenize(iterator) {
|
|
|
98
100
|
next();
|
|
99
101
|
// i += value.length;
|
|
100
102
|
buffer = '';
|
|
101
|
-
|
|
103
|
+
return;
|
|
102
104
|
}
|
|
103
105
|
if (isNewLine(value.charCodeAt(0))) {
|
|
104
106
|
hasNewLine = true;
|
|
105
107
|
}
|
|
106
108
|
if (hasNewLine && value == ';') {
|
|
107
|
-
yield pushToken(buffer, 'Bad-string');
|
|
109
|
+
yield pushToken(buffer + value, 'Bad-string');
|
|
108
110
|
buffer = '';
|
|
111
|
+
next();
|
|
109
112
|
break;
|
|
110
113
|
}
|
|
111
114
|
buffer += value;
|
|
112
|
-
// i += value.length;
|
|
113
115
|
next();
|
|
114
116
|
}
|
|
117
|
+
if (hasNewLine) {
|
|
118
|
+
yield pushToken(buffer, 'Bad-string');
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
// EOF - 'Unclosed-string' fixed
|
|
122
|
+
yield pushToken(buffer + quote, 'String');
|
|
123
|
+
}
|
|
124
|
+
buffer = '';
|
|
115
125
|
}
|
|
116
126
|
function peek(count = 1) {
|
|
117
127
|
if (count == 1) {
|
|
@@ -225,6 +235,11 @@ function* tokenize(iterator) {
|
|
|
225
235
|
yield pushToken(buffer);
|
|
226
236
|
buffer = '';
|
|
227
237
|
}
|
|
238
|
+
if (peek() == '=') {
|
|
239
|
+
yield pushToken('', 'Lte');
|
|
240
|
+
next();
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
228
243
|
buffer += value;
|
|
229
244
|
value = next();
|
|
230
245
|
if (ind >= iterator.length) {
|
|
@@ -293,7 +308,13 @@ function* tokenize(iterator) {
|
|
|
293
308
|
yield pushToken(buffer);
|
|
294
309
|
buffer = '';
|
|
295
310
|
}
|
|
296
|
-
|
|
311
|
+
if (peek() == '=') {
|
|
312
|
+
yield pushToken('', 'Gte');
|
|
313
|
+
next();
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
yield pushToken('', 'Gt');
|
|
317
|
+
}
|
|
297
318
|
consumeWhiteSpace();
|
|
298
319
|
break;
|
|
299
320
|
case '.':
|
|
@@ -335,7 +356,7 @@ function* tokenize(iterator) {
|
|
|
335
356
|
break;
|
|
336
357
|
case '(':
|
|
337
358
|
if (buffer.length == 0) {
|
|
338
|
-
yield pushToken(
|
|
359
|
+
yield pushToken(value);
|
|
339
360
|
break;
|
|
340
361
|
}
|
|
341
362
|
buffer += value;
|
|
@@ -449,6 +470,7 @@ function* tokenize(iterator) {
|
|
|
449
470
|
if (buffer.length > 0) {
|
|
450
471
|
yield pushToken(buffer);
|
|
451
472
|
}
|
|
473
|
+
// yield pushToken('', 'EOF');
|
|
452
474
|
}
|
|
453
475
|
|
|
454
476
|
export { tokenize };
|
|
@@ -159,37 +159,30 @@ function isNumber(name) {
|
|
|
159
159
|
return true;
|
|
160
160
|
}
|
|
161
161
|
function isDimension(name) {
|
|
162
|
-
let index =
|
|
163
|
-
while (index
|
|
164
|
-
if (
|
|
165
|
-
|
|
166
|
-
break;
|
|
167
|
-
}
|
|
168
|
-
if (index == 3) {
|
|
169
|
-
break;
|
|
162
|
+
let index = name.length;
|
|
163
|
+
while (index--) {
|
|
164
|
+
if (isLetter(name.charCodeAt(index))) {
|
|
165
|
+
continue;
|
|
170
166
|
}
|
|
167
|
+
index++;
|
|
168
|
+
break;
|
|
171
169
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
const number = name.slice(0, -index);
|
|
176
|
-
return number.length > 0 && isIdentStart(name.charCodeAt(name.length - index)) && isNumber(number);
|
|
170
|
+
const number = name.slice(0, index);
|
|
171
|
+
return number.length > 0 && isIdentStart(name.charCodeAt(index)) && isNumber(number);
|
|
177
172
|
}
|
|
178
173
|
function isPercentage(name) {
|
|
179
174
|
return name.endsWith('%') && isNumber(name.slice(0, -1));
|
|
180
175
|
}
|
|
181
176
|
function parseDimension(name) {
|
|
182
|
-
let index =
|
|
183
|
-
while (index
|
|
184
|
-
if (
|
|
185
|
-
|
|
186
|
-
break;
|
|
187
|
-
}
|
|
188
|
-
if (index == 3) {
|
|
189
|
-
break;
|
|
177
|
+
let index = name.length;
|
|
178
|
+
while (index--) {
|
|
179
|
+
if (isLetter(name.charCodeAt(index))) {
|
|
180
|
+
continue;
|
|
190
181
|
}
|
|
182
|
+
index++;
|
|
183
|
+
break;
|
|
191
184
|
}
|
|
192
|
-
const dimension = { typ: 'Dimension', val: name.slice(0,
|
|
185
|
+
const dimension = { typ: 'Dimension', val: name.slice(0, index), unit: name.slice(index) };
|
|
193
186
|
if (isAngle(dimension)) {
|
|
194
187
|
// @ts-ignore
|
|
195
188
|
dimension.typ = 'Angle';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const funcList = ['clamp', 'calc'];
|
|
1
2
|
function matchType(val, properties) {
|
|
2
3
|
if (val.typ == 'Iden' && properties.keywords.includes(val.val) ||
|
|
3
4
|
(properties.types.includes(val.typ))) {
|
|
@@ -6,6 +7,9 @@ function matchType(val, properties) {
|
|
|
6
7
|
if (val.typ == 'Number' && val.val == '0') {
|
|
7
8
|
return properties.types.some(type => type == 'Length' || type == 'Angle');
|
|
8
9
|
}
|
|
10
|
+
if (val.typ == 'Func' && funcList.includes(val.val)) {
|
|
11
|
+
return val.chi.every((t => ['Literal', 'Comma', 'Whitespace', 'Start-parens', 'End-parens'].includes(t.typ) || matchType(t, properties)));
|
|
12
|
+
}
|
|
9
13
|
return false;
|
|
10
14
|
}
|
|
11
15
|
|