@tbela99/css-parser 0.0.1-rc3 → 0.0.1-rc5

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/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';
@@ -117,7 +119,7 @@ interface CDOCommentToken {
117
119
  val: string;
118
120
  }
119
121
  interface BadCDOCommentToken {
120
- typ: 'BADCDO';
122
+ typ: 'Bad-cdo';
121
123
  val: string;
122
124
  }
123
125
  interface IncludesToken {
@@ -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,7 @@ 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;
175
183
 
176
184
  interface PropertyMapType {
177
185
  default: string[];
@@ -634,6 +642,7 @@ declare function isResolution(dimension: DimensionToken): boolean;
634
642
  declare function isAngle(dimension: DimensionToken): boolean;
635
643
  declare function isTime(dimension: DimensionToken): boolean;
636
644
  declare function isFrequency(dimension: DimensionToken): boolean;
645
+ declare function isColor(token: Token): boolean;
637
646
  declare function isIdentStart(codepoint: number): boolean;
638
647
  declare function isDigit(codepoint: number): boolean;
639
648
  declare function isIdentCodepoint(codepoint: number): boolean;
@@ -653,10 +662,12 @@ declare function isWhiteSpace(codepoint: number): boolean;
653
662
 
654
663
  declare const getConfig: () => PropertiesConfig;
655
664
 
665
+ declare const funcList: string[];
656
666
  declare function matchType(val: Token, properties: PropertyMapType): boolean;
657
667
 
668
+ declare const colorsFunc: string[];
658
669
  declare function render(data: AstNode, opt?: RenderOptions): RenderResult;
659
- declare function renderToken(token: Token, options?: RenderOptions): string;
670
+ declare function renderToken(token: Token, options?: RenderOptions, reducer?: (acc: string, curr: Token) => string): string;
660
671
 
661
672
  declare const combinators: string[];
662
673
  declare function minify(ast: AstNode, options?: ParserOptions, recursive?: boolean): AstNode;
@@ -687,4 +698,4 @@ declare function resolve(url: string, currentDirectory: string, cwd?: string): {
687
698
  declare function parse(iterator: string, opt?: ParserOptions): Promise<ParseResult>;
688
699
  declare function transform(css: string, options?: TransformOptions): Promise<TransformResult>;
689
700
 
690
- 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 };
701
+ export { colorsFunc, combinators, dirname, funcList, getConfig, hasDeclaration, isAngle, isAtKeyword, isColor, 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 };
@@ -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,4 +1,5 @@
1
1
  import { PropertySet } from './set.js';
2
+ import '../../renderer/utils/color.js';
2
3
  import { getConfig } from '../utils/config.js';
3
4
  import { PropertyMap } from './map.js';
4
5
  import { parseString } from '../parse.js';
@@ -1,7 +1,8 @@
1
1
  import { eq } from '../utils/eq.js';
2
+ import { renderToken } from '../../renderer/render.js';
3
+ import '../../renderer/utils/color.js';
2
4
  import { getConfig } from '../utils/config.js';
3
5
  import { matchType } from '../utils/type.js';
4
- import { renderToken } from '../../renderer/render.js';
5
6
  import { parseString } from '../parse.js';
6
7
  import { PropertySet } from './set.js';
7
8
 
@@ -55,6 +56,7 @@ class PropertyMap {
55
56
  i--;
56
57
  continue;
57
58
  }
59
+ // @ts-ignore
58
60
  if (('propertyName' in acc[i] && acc[i].propertyName == property) || matchType(acc[i], props)) {
59
61
  if ('prefix' in props && props.previous != null && !(props.previous in tokens)) {
60
62
  return acc;
@@ -220,17 +222,18 @@ class PropertyMap {
220
222
  if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(props.separator, val)) {
221
223
  continue;
222
224
  }
223
- match = matchType(val, curr[1]);
225
+ // @ts-ignore
226
+ match = val.typ == 'Comment' || matchType(val, curr[1]);
224
227
  if (isShorthand) {
225
228
  isShorthand = match;
226
229
  }
230
+ // @ts-ignore
227
231
  if (('propertyName' in val && val.propertyName == property) || match) {
228
232
  if (!(curr[0] in tokens)) {
229
233
  tokens[curr[0]] = [[]];
230
234
  }
231
235
  // is default value
232
236
  tokens[curr[0]][current].push(val);
233
- // continue;
234
237
  }
235
238
  else {
236
239
  acc.push(curr[0]);
@@ -247,7 +250,9 @@ class PropertyMap {
247
250
  if (!isShorthand || Object.entries(this.config.properties).some(entry => {
248
251
  // missing required property
249
252
  return entry[1].required && !(entry[0] in tokens);
250
- }) || !Object.values(tokens).every(v => v.length == count)) {
253
+ }) ||
254
+ // @ts-ignore
255
+ !Object.values(tokens).every(v => v.filter(t => t.typ != 'Comment').length == count)) {
251
256
  // @ts-ignore
252
257
  iterable = this.declarations.values();
253
258
  }
@@ -1,10 +1,11 @@
1
- import { isPseudo, isAtKeyword, isFunction, isNumber, isDimension, parseDimension, isPercentage, isIdent, isHexColor, isHash, isIdentStart } from './utils/syntax.js';
1
+ import { isPseudo, isAtKeyword, isFunction, isNumber, isDimension, parseDimension, isPercentage, isIdent, isHexColor, isHash, isIdentStart, isColor } from './utils/syntax.js';
2
2
  import { renderToken } from '../renderer/render.js';
3
3
  import { COLORS_NAMES } from '../renderer/utils/color.js';
4
4
  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
  *
@@ -169,7 +170,7 @@ async function parse(iterator, opt = {}) {
169
170
  // https://www.w3.org/TR/css-nesting-1/#conditionals
170
171
  // allowed nesting at-rules
171
172
  // there must be a top level rule in the stack
172
- const raw = tokens.reduce((acc, curr) => {
173
+ const raw = parseTokens(tokens, { minify: options.minify }).reduce((acc, curr) => {
173
174
  acc.push(renderToken(curr, { removeComments: true }));
174
175
  return acc;
175
176
  }, []);
@@ -200,8 +201,8 @@ async function parse(iterator, opt = {}) {
200
201
  const uniq = new Map;
201
202
  parseTokens(tokens, { minify: options.minify }).reduce((acc, curr, index, array) => {
202
203
  if (curr.typ == 'Whitespace') {
203
- if (array[index - 1]?.typ == 'Gt' ||
204
- array[index + 1]?.typ == 'Gt' ||
204
+ if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
205
+ trimWhiteSpace.includes(array[index + 1]?.typ) ||
205
206
  combinators.includes(array[index - 1]?.val) ||
206
207
  combinators.includes(array[index + 1]?.val)) {
207
208
  return acc;
@@ -327,6 +328,11 @@ async function parse(iterator, opt = {}) {
327
328
  if (item == null) {
328
329
  break;
329
330
  }
331
+ // console.debug({item});
332
+ if (item.hint != null && item.hint.startsWith('Bad-')) {
333
+ // bad token
334
+ continue;
335
+ }
330
336
  tokens.push(item);
331
337
  bytesIn = item.bytesIn;
332
338
  if (item.token == ';' || item.token == '{') {
@@ -405,7 +411,7 @@ function getTokenType(val, hint) {
405
411
  return ([
406
412
  'Whitespace', 'Semi-colon', 'Colon', 'Block-start',
407
413
  'Block-start', 'Attr-start', 'Attr-end', 'Start-parens', 'End-parens',
408
- 'Comma', 'Gt', 'Lt'
414
+ 'Comma', 'Gt', 'Lt', 'Gte', 'Lte', 'EOF'
409
415
  ].includes(hint) ? { typ: hint } : { typ: hint, val });
410
416
  }
411
417
  if (val == ' ') {
@@ -533,11 +539,12 @@ function parseTokens(tokens, options = {}) {
533
539
  const t = tokens[i];
534
540
  if (t.typ == 'Whitespace' && ((i == 0 ||
535
541
  i + 1 == tokens.length ||
536
- ['Comma'].includes(tokens[i + 1].typ) ||
542
+ ['Comma', 'Gte', 'Lte'].includes(tokens[i + 1].typ)) ||
537
543
  (i > 0 &&
538
- tokens[i + 1]?.typ != 'Literal' &&
539
- funcLike.includes(tokens[i - 1].typ) &&
540
- !['var', 'calc'].includes(tokens[i - 1].val))))) {
544
+ // tokens[i + 1]?.typ != 'Literal' ||
545
+ // funcLike.includes(tokens[i - 1].typ) &&
546
+ // !['var', 'calc'].includes((<FunctionToken>tokens[i - 1]).val)))) &&
547
+ trimWhiteSpace.includes(tokens[i - 1].typ)))) {
541
548
  tokens.splice(i--, 1);
542
549
  continue;
543
550
  }
@@ -635,41 +642,33 @@ function parseTokens(tokens, options = {}) {
635
642
  // @ts-ignore
636
643
  t.chi.pop();
637
644
  }
638
- let isColor = true;
639
645
  // @ts-ignore
640
- if (options.parseColor && ['rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'device-cmyk'].includes(t.val)) {
646
+ if (options.parseColor && t.typ == 'Func' && isColor(t)) {
647
+ // if (isColor) {
641
648
  // @ts-ignore
642
- for (const v of t.chi) {
643
- if (v.typ == 'Func' && v.val == 'var') {
644
- isColor = false;
645
- break;
646
- }
647
- }
648
- if (isColor) {
649
- // @ts-ignore
650
- t.typ = 'Color';
651
- // @ts-ignore
652
- t.kin = t.val;
649
+ t.typ = 'Color';
650
+ // @ts-ignore
651
+ t.kin = t.val;
652
+ // @ts-ignore
653
+ let m = t.chi.length;
654
+ while (m-- > 0) {
653
655
  // @ts-ignore
654
- let m = t.chi.length;
655
- while (m-- > 0) {
656
+ if (['Literal'].concat(trimWhiteSpace).includes(t.chi[m].typ)) {
656
657
  // @ts-ignore
657
- if (t.chi[m].typ == 'Literal') {
658
+ if (t.chi[m + 1]?.typ == 'Whitespace') {
658
659
  // @ts-ignore
659
- if (t.chi[m + 1]?.typ == 'Whitespace') {
660
- // @ts-ignore
661
- t.chi.splice(m + 1, 1);
662
- }
660
+ t.chi.splice(m + 1, 1);
661
+ }
662
+ // @ts-ignore
663
+ if (t.chi[m - 1]?.typ == 'Whitespace') {
663
664
  // @ts-ignore
664
- if (t.chi[m - 1]?.typ == 'Whitespace') {
665
- // @ts-ignore
666
- t.chi.splice(m - 1, 1);
667
- m--;
668
- }
665
+ t.chi.splice(m - 1, 1);
666
+ m--;
669
667
  }
670
668
  }
671
- continue;
672
669
  }
670
+ continue;
671
+ // }
673
672
  }
674
673
  if (t.typ == 'UrlFunc') {
675
674
  // @ts-ignore
@@ -694,7 +693,7 @@ function parseTokens(tokens, options = {}) {
694
693
  // @ts-ignore
695
694
  if (t.chi.length > 0) {
696
695
  // @ts-ignore
697
- parseTokens(t.chi, t.typ);
696
+ parseTokens(t.chi, options);
698
697
  if (t.typ == 'Pseudo-class-func' && t.val == ':is' && options.minify) {
699
698
  //
700
699
  const count = t.chi.filter(t => t.typ != 'Comment').length;
@@ -713,7 +712,7 @@ function parseTokens(tokens, options = {}) {
713
712
  if (t.typ == 'Iden') {
714
713
  // named color
715
714
  const value = t.val.toLowerCase();
716
- if (COLORS_NAMES[value] != null) {
715
+ if (value in COLORS_NAMES) {
717
716
  Object.assign(t, {
718
717
  typ: 'Color',
719
718
  val: COLORS_NAMES[value].length < value.length ? COLORS_NAMES[value] : value,
@@ -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 && !isNewLine(codepoint)) {
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
- break;
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) {
@@ -144,31 +154,18 @@ function* tokenize(iterator) {
144
154
  return char;
145
155
  }
146
156
  while (value = next()) {
147
- if (ind >= iterator.length) {
148
- if (buffer.length > 0) {
149
- yield pushToken(buffer);
150
- buffer = '';
151
- }
152
- break;
153
- }
154
157
  if (isWhiteSpace(value.charCodeAt(0))) {
155
158
  if (buffer.length > 0) {
156
159
  yield pushToken(buffer);
157
160
  buffer = '';
158
161
  }
159
162
  while (value = next()) {
160
- if (ind >= iterator.length) {
161
- break;
162
- }
163
163
  if (!isWhiteSpace(value.charCodeAt(0))) {
164
164
  break;
165
165
  }
166
166
  }
167
167
  yield pushToken('', 'Whitespace');
168
168
  buffer = '';
169
- if (ind >= iterator.length) {
170
- break;
171
- }
172
169
  }
173
170
  switch (value) {
174
171
  case '/':
@@ -182,34 +179,12 @@ function* tokenize(iterator) {
182
179
  }
183
180
  buffer += value;
184
181
  if (peek() == '*') {
185
- buffer += '*';
186
- // i++;
187
- next();
182
+ buffer += next();
188
183
  while (value = next()) {
189
- if (ind >= iterator.length) {
190
- yield pushToken(buffer, 'Bad-comment');
191
- break;
192
- }
193
- if (value == '\\') {
194
- buffer += value;
195
- value = next();
196
- if (ind >= iterator.length) {
197
- yield pushToken(buffer, 'Bad-comment');
198
- break;
199
- }
200
- buffer += value;
201
- continue;
202
- }
203
184
  if (value == '*') {
204
185
  buffer += value;
205
- value = next();
206
- if (ind >= iterator.length) {
207
- yield pushToken(buffer, 'Bad-comment');
208
- break;
209
- }
210
- buffer += value;
211
- if (value == '/') {
212
- yield pushToken(buffer, 'Comment');
186
+ if (peek() == '/') {
187
+ yield pushToken(buffer + next(), 'Comment');
213
188
  buffer = '';
214
189
  break;
215
190
  }
@@ -218,6 +193,8 @@ function* tokenize(iterator) {
218
193
  buffer += value;
219
194
  }
220
195
  }
196
+ yield pushToken(buffer, 'Bad-comment');
197
+ buffer = '';
221
198
  }
222
199
  break;
223
200
  case '<':
@@ -225,16 +202,15 @@ function* tokenize(iterator) {
225
202
  yield pushToken(buffer);
226
203
  buffer = '';
227
204
  }
228
- buffer += value;
229
- value = next();
230
- if (ind >= iterator.length) {
205
+ if (peek() == '=') {
206
+ yield pushToken('', 'Lte');
207
+ next();
231
208
  break;
232
209
  }
210
+ buffer += value;
233
211
  if (peek(3) == '!--') {
212
+ buffer += next(3);
234
213
  while (value = next()) {
235
- if (ind >= iterator.length) {
236
- break;
237
- }
238
214
  buffer += value;
239
215
  if (value == '>' && prev(2) == '--') {
240
216
  yield pushToken(buffer, 'CDOCOMM');
@@ -243,15 +219,14 @@ function* tokenize(iterator) {
243
219
  }
244
220
  }
245
221
  }
246
- if (ind >= iterator.length) {
247
- yield pushToken(buffer, 'BADCDO');
248
- buffer = '';
249
- }
222
+ // if (!peek()) {
223
+ yield pushToken(buffer, 'Bad-cdo');
224
+ buffer = '';
225
+ // }
250
226
  break;
251
227
  case '\\':
252
- value = next();
253
228
  // EOF
254
- if (ind + 1 >= iterator.length) {
229
+ if (!(value = next())) {
255
230
  // end of stream ignore \\
256
231
  yield pushToken(buffer);
257
232
  buffer = '';
@@ -270,8 +245,7 @@ function* tokenize(iterator) {
270
245
  buffer = '';
271
246
  }
272
247
  buffer += value;
273
- value = next();
274
- if (ind >= iterator.length) {
248
+ if (!(value = next())) {
275
249
  yield pushToken(buffer);
276
250
  buffer = '';
277
251
  break;
@@ -293,7 +267,13 @@ function* tokenize(iterator) {
293
267
  yield pushToken(buffer);
294
268
  buffer = '';
295
269
  }
296
- yield pushToken('', 'Gt');
270
+ if (peek() == '=') {
271
+ yield pushToken('', 'Gte');
272
+ next();
273
+ }
274
+ else {
275
+ yield pushToken('', 'Gt');
276
+ }
297
277
  consumeWhiteSpace();
298
278
  break;
299
279
  case '.':
@@ -335,7 +315,7 @@ function* tokenize(iterator) {
335
315
  break;
336
316
  case '(':
337
317
  if (buffer.length == 0) {
338
- yield pushToken('', 'Start-parens');
318
+ yield pushToken(value);
339
319
  break;
340
320
  }
341
321
  buffer += value;
@@ -432,8 +412,7 @@ function* tokenize(iterator) {
432
412
  yield pushToken(buffer);
433
413
  buffer = '';
434
414
  }
435
- const important = peek(9);
436
- if (important == 'important') {
415
+ if (peek(9) == 'important') {
437
416
  yield pushToken('', 'Important');
438
417
  next(9);
439
418
  buffer = '';
@@ -449,6 +428,7 @@ function* tokenize(iterator) {
449
428
  if (buffer.length > 0) {
450
429
  yield pushToken(buffer);
451
430
  }
431
+ // yield pushToken('', 'EOF');
452
432
  }
453
433
 
454
434
  export { tokenize };
@@ -1,3 +1,6 @@
1
+ import { colorsFunc } from '../../renderer/render.js';
2
+ import { COLORS_NAMES } from '../../renderer/utils/color.js';
3
+
1
4
  // https://www.w3.org/TR/CSS21/syndata.html#syntax
2
5
  // https://www.w3.org/TR/2021/CRD-css-syntax-3-20211224/#typedef-ident-token
3
6
  // '\\'
@@ -23,6 +26,25 @@ function isTime(dimension) {
23
26
  function isFrequency(dimension) {
24
27
  return 'unit' in dimension && ['hz', 'khz'].includes(dimension.unit.toLowerCase());
25
28
  }
29
+ function isColor(token) {
30
+ if (token.typ == 'Color') {
31
+ return true;
32
+ }
33
+ if (token.typ == 'Iden') {
34
+ // named color
35
+ return token.val.toLowerCase() in COLORS_NAMES;
36
+ }
37
+ if (token.typ == 'Func' && token.chi.length > 0 && colorsFunc.includes(token.val)) {
38
+ // @ts-ignore
39
+ for (const v of token.chi) {
40
+ if (!['Number', 'Perc', 'Comma', 'Whitespace'].includes(v.typ)) {
41
+ return false;
42
+ }
43
+ }
44
+ return true;
45
+ }
46
+ return false;
47
+ }
26
48
  function isLetter(codepoint) {
27
49
  // lowercase
28
50
  return (codepoint >= 0x61 && codepoint <= 0x7a) ||
@@ -75,19 +97,12 @@ function isIdent(name) {
75
97
  return true;
76
98
  }
77
99
  function isPseudo(name) {
78
- if (name.charAt(0) != ':') {
79
- return false;
80
- }
81
- if (name.endsWith('(')) {
82
- return isIdent(name.charAt(1) == ':' ? name.slice(2, -1) : name.slice(1, -1));
83
- }
84
- return isIdent(name.charAt(1) == ':' ? name.slice(2) : name.slice(1));
100
+ return name.charAt(0) == ':' &&
101
+ ((name.endsWith('(') && isIdent(name.charAt(1) == ':' ? name.slice(2, -1) : name.slice(1, -1))) ||
102
+ isIdent(name.charAt(1) == ':' ? name.slice(2) : name.slice(1)));
85
103
  }
86
104
  function isHash(name) {
87
- if (name.charAt(0) != '#') {
88
- return false;
89
- }
90
- return isIdent(name.charAt(1));
105
+ return name.charAt(0) == '#' && isIdent(name.charAt(1));
91
106
  }
92
107
  function isNumber(name) {
93
108
  if (name.length == 0) {
@@ -159,37 +174,30 @@ function isNumber(name) {
159
174
  return true;
160
175
  }
161
176
  function isDimension(name) {
162
- let index = 0;
163
- while (index++ < name.length) {
164
- if (isDigit(name.charCodeAt(name.length - index))) {
165
- index--;
166
- break;
167
- }
168
- if (index == 3) {
169
- break;
177
+ let index = name.length;
178
+ while (index--) {
179
+ if (isLetter(name.charCodeAt(index))) {
180
+ continue;
170
181
  }
182
+ index++;
183
+ break;
171
184
  }
172
- if (index == 0 || index > 3) {
173
- return false;
174
- }
175
- const number = name.slice(0, -index);
176
- return number.length > 0 && isIdentStart(name.charCodeAt(name.length - index)) && isNumber(number);
185
+ const number = name.slice(0, index);
186
+ return number.length > 0 && isIdentStart(name.charCodeAt(index)) && isNumber(number);
177
187
  }
178
188
  function isPercentage(name) {
179
189
  return name.endsWith('%') && isNumber(name.slice(0, -1));
180
190
  }
181
191
  function parseDimension(name) {
182
- let index = 0;
183
- while (index++ < name.length) {
184
- if (isDigit(name.charCodeAt(name.length - index))) {
185
- index--;
186
- break;
187
- }
188
- if (index == 3) {
189
- break;
192
+ let index = name.length;
193
+ while (index--) {
194
+ if (isLetter(name.charCodeAt(index))) {
195
+ continue;
190
196
  }
197
+ index++;
198
+ break;
191
199
  }
192
- const dimension = { typ: 'Dimension', val: name.slice(0, -index), unit: name.slice(-index) };
200
+ const dimension = { typ: 'Dimension', val: name.slice(0, index), unit: name.slice(index) };
193
201
  if (isAngle(dimension)) {
194
202
  // @ts-ignore
195
203
  dimension.typ = 'Angle';
@@ -263,4 +271,4 @@ function isWhiteSpace(codepoint) {
263
271
  codepoint == 0xa || codepoint == 0xc || codepoint == 0xd;
264
272
  }
265
273
 
266
- export { isAngle, isAtKeyword, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor, isHexDigit, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNumber, isPercentage, isPseudo, isResolution, isTime, isWhiteSpace, parseDimension };
274
+ export { isAngle, isAtKeyword, isColor, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor, isHexDigit, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNumber, isPercentage, isPseudo, isResolution, isTime, isWhiteSpace, parseDimension };