@tbela99/css-parser 0.8.0 → 0.9.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.
Files changed (59) hide show
  1. package/.editorconfig +484 -0
  2. package/README.md +5 -3
  3. package/dist/index-umd-web.js +3272 -1898
  4. package/dist/index.cjs +3272 -1898
  5. package/dist/index.d.ts +48 -11
  6. package/dist/lib/ast/expand.js +14 -2
  7. package/dist/lib/ast/math/expression.js +1 -1
  8. package/dist/lib/ast/minify.js +30 -16
  9. package/dist/lib/ast/types.js +1 -0
  10. package/dist/lib/ast/walk.js +12 -0
  11. package/dist/lib/parser/declaration/map.js +59 -52
  12. package/dist/lib/parser/declaration/set.js +0 -12
  13. package/dist/lib/parser/parse.js +140 -101
  14. package/dist/lib/parser/tokenize.js +15 -3
  15. package/dist/lib/renderer/color/hex.js +1 -1
  16. package/dist/lib/renderer/color/hsl.js +1 -1
  17. package/dist/lib/renderer/color/hwb.js +2 -2
  18. package/dist/lib/renderer/color/lab.js +1 -1
  19. package/dist/lib/renderer/color/lch.js +1 -1
  20. package/dist/lib/renderer/color/oklab.js +2 -2
  21. package/dist/lib/renderer/color/oklch.js +1 -1
  22. package/dist/lib/renderer/color/p3.js +1 -1
  23. package/dist/lib/renderer/color/prophotoRgb.js +1 -1
  24. package/dist/lib/renderer/color/prophotorgb.js +1 -1
  25. package/dist/lib/renderer/color/rgb.js +1 -1
  26. package/dist/lib/renderer/color/srgb.js +2 -2
  27. package/dist/lib/renderer/color/utils/constants.js +1 -1
  28. package/dist/lib/renderer/color/xyz.js +1 -1
  29. package/dist/lib/renderer/render.js +34 -6
  30. package/dist/lib/syntax/syntax.js +336 -1
  31. package/dist/lib/validation/at-rules/container.js +353 -0
  32. package/dist/lib/validation/at-rules/counter-style.js +2 -2
  33. package/dist/lib/validation/at-rules/custom-media.js +52 -0
  34. package/dist/lib/validation/at-rules/else.js +5 -0
  35. package/dist/lib/validation/at-rules/font-feature-values.js +3 -0
  36. package/dist/lib/validation/at-rules/import.js +3 -0
  37. package/dist/lib/validation/at-rules/layer.js +3 -0
  38. package/dist/lib/validation/at-rules/media.js +117 -29
  39. package/dist/lib/validation/at-rules/supports.js +11 -11
  40. package/dist/lib/validation/at-rules/when.js +178 -0
  41. package/dist/lib/validation/atrule.js +25 -10
  42. package/dist/lib/validation/config.js +20 -15
  43. package/dist/lib/validation/config.json.js +162 -42
  44. package/dist/lib/validation/declaration.js +39 -9
  45. package/dist/lib/validation/parser/parse.js +91 -13
  46. package/dist/lib/validation/parser/types.js +1 -0
  47. package/dist/lib/validation/selector.js +6 -3
  48. package/dist/lib/validation/syntax.js +50 -4
  49. package/dist/lib/validation/syntaxes/complex-selector-list.js +16 -12
  50. package/dist/lib/validation/syntaxes/complex-selector.js +17 -247
  51. package/dist/lib/validation/syntaxes/compound-selector.js +226 -0
  52. package/dist/lib/validation/syntaxes/image.js +29 -0
  53. package/dist/lib/validation/syntaxes/keyframe-block-list.js +1 -1
  54. package/dist/lib/validation/syntaxes/keyframe-selector.js +1 -1
  55. package/dist/lib/validation/syntaxes/relative-selector-list.js +43 -13
  56. package/dist/lib/validation/utils/list.js +2 -2
  57. package/dist/node/index.js +1 -1
  58. package/dist/web/index.js +1 -1
  59. package/package.json +7 -7
@@ -1,4 +1,4 @@
1
- import { isPseudo, isAtKeyword, isFunction, isNumber, isPercentage, isFlex, isDimension, parseDimension, isIdent, isHexColor, isHash, isIdentStart, mathFuncs, isColor, mediaTypes } from '../syntax/syntax.js';
1
+ import { webkitPseudoAliasMap, isIdentStart, isIdent, mathFuncs, isColor, isHexColor, isPseudo, isAtKeyword, isFunction, isNumber, isPercentage, isFlex, isDimension, parseDimension, isHash, mediaTypes } from '../syntax/syntax.js';
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';
@@ -13,6 +13,7 @@ import '../validation/parser/types.js';
13
13
  import '../validation/parser/parse.js';
14
14
  import { validateSelector } from '../validation/selector.js';
15
15
  import { validateAtRule } from '../validation/atrule.js';
16
+ import '../validation/syntaxes/complex-selector.js';
16
17
 
17
18
  const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
18
19
  const trimWhiteSpace = [EnumToken.CommentTokenType, EnumToken.GtTokenType, EnumToken.GteTokenType, EnumToken.LtTokenType, EnumToken.LteTokenType, EnumToken.ColumnCombinatorTokenType];
@@ -29,51 +30,14 @@ const enumTokenHints = new Set([
29
30
  EnumToken.StartMatchTokenType, EnumToken.EndMatchTokenType, EnumToken.IncludeMatchTokenType, EnumToken.DashMatchTokenType, EnumToken.ContainMatchTokenType,
30
31
  EnumToken.EOFTokenType
31
32
  ]);
32
- const webkitPseudoAliasMap = {
33
- '-webkit-autofill': 'autofill',
34
- '-webkit-any': 'is',
35
- '-moz-any': 'is',
36
- '-webkit-border-after': 'border-block-end',
37
- '-webkit-border-after-color': 'border-block-end-color',
38
- '-webkit-border-after-style': 'border-block-end-style',
39
- '-webkit-border-after-width': 'border-block-end-width',
40
- '-webkit-border-before': 'border-block-start',
41
- '-webkit-border-before-color': 'border-block-start-color',
42
- '-webkit-border-before-style': 'border-block-start-style',
43
- '-webkit-border-before-width': 'border-block-start-width',
44
- '-webkit-border-end': 'border-inline-end',
45
- '-webkit-border-end-color': 'border-inline-end-color',
46
- '-webkit-border-end-style': 'border-inline-end-style',
47
- '-webkit-border-end-width': 'border-inline-end-width',
48
- '-webkit-border-start': 'border-inline-start',
49
- '-webkit-border-start-color': 'border-inline-start-color',
50
- '-webkit-border-start-style': 'border-inline-start-style',
51
- '-webkit-border-start-width': 'border-inline-start-width',
52
- '-webkit-box-align': 'align-items',
53
- '-webkit-box-direction': 'flex-direction',
54
- '-webkit-box-flex': 'flex-grow',
55
- '-webkit-box-lines': 'flex-flow',
56
- '-webkit-box-ordinal-group': 'order',
57
- '-webkit-box-orient': 'flex-direction',
58
- '-webkit-box-pack': 'justify-content',
59
- '-webkit-column-break-after': 'break-after',
60
- '-webkit-column-break-before': 'break-before',
61
- '-webkit-column-break-inside': 'break-inside',
62
- '-webkit-font-feature-settings': 'font-feature-settings',
63
- '-webkit-hyphenate-character': 'hyphenate-character',
64
- '-webkit-initial-letter': 'initial-letter',
65
- '-webkit-margin-end': 'margin-block-end',
66
- '-webkit-margin-start': 'margin-block-start',
67
- '-webkit-padding-after': 'padding-block-end',
68
- '-webkit-padding-before': 'padding-block-start',
69
- '-webkit-padding-end': 'padding-inline-end',
70
- '-webkit-padding-start': 'padding-inline-start',
71
- '-webkit-min-device-pixel-ratio': 'min-resolution',
72
- '-webkit-max-device-pixel-ratio': 'max-resolution'
73
- };
74
33
  function reject(reason) {
75
34
  throw new Error(reason ?? 'Parsing aborted');
76
35
  }
36
+ /**
37
+ * parse css string
38
+ * @param iterator
39
+ * @param options
40
+ */
77
41
  async function doParse(iterator, options = {}) {
78
42
  if (options.signal != null) {
79
43
  options.signal.addEventListener('abort', reject);
@@ -95,6 +59,7 @@ async function doParse(iterator, options = {}) {
95
59
  setParent: true,
96
60
  removePrefix: false,
97
61
  validation: true,
62
+ lenient: true,
98
63
  ...options
99
64
  };
100
65
  if (options.expandNestingRules) {
@@ -133,9 +98,10 @@ async function doParse(iterator, options = {}) {
133
98
  }
134
99
  const iter = tokenize(iterator);
135
100
  let item;
101
+ const rawTokens = [];
136
102
  while (item = iter.next().value) {
137
103
  stats.bytesIn = item.bytesIn;
138
- //
104
+ rawTokens.push(item);
139
105
  // doParse error
140
106
  if (item.hint != null && BadTokensTypes.includes(item.hint)) {
141
107
  // bad token
@@ -145,7 +111,8 @@ async function doParse(iterator, options = {}) {
145
111
  tokens.push(item);
146
112
  }
147
113
  if (item.token == ';' || item.token == '{') {
148
- let node = await parseNode(tokens, context, stats, options, errors, src, map);
114
+ let node = await parseNode(tokens, context, stats, options, errors, src, map, rawTokens);
115
+ rawTokens.length = 0;
149
116
  if (node != null) {
150
117
  // @ts-ignore
151
118
  stack.push(node);
@@ -171,7 +138,8 @@ async function doParse(iterator, options = {}) {
171
138
  map = new Map;
172
139
  }
173
140
  else if (item.token == '}') {
174
- await parseNode(tokens, context, stats, options, errors, src, map);
141
+ await parseNode(tokens, context, stats, options, errors, src, map, rawTokens);
142
+ rawTokens.length = 0;
175
143
  const previousNode = stack.pop();
176
144
  // @ts-ignore
177
145
  context = stack[stack.length - 1] ?? ast;
@@ -194,7 +162,8 @@ async function doParse(iterator, options = {}) {
194
162
  }
195
163
  }
196
164
  if (tokens.length > 0) {
197
- await parseNode(tokens, context, stats, options, errors, src, map);
165
+ await parseNode(tokens, context, stats, options, errors, src, map, rawTokens);
166
+ rawTokens.length = 0;
198
167
  if (context != null && context.typ == EnumToken.InvalidRuleTokenType) {
199
168
  const index = context.chi.findIndex(node => node == context);
200
169
  if (index > -1) {
@@ -206,6 +175,7 @@ async function doParse(iterator, options = {}) {
206
175
  const previousNode = stack.pop();
207
176
  // @ts-ignore
208
177
  context = stack[stack.length - 1] ?? ast;
178
+ // remove empty nodes
209
179
  // @ts-ignore
210
180
  if (options.removeEmpty && previousNode != null && previousNode.chi.length == 0 && context.chi[context.chi.length - 1] == previousNode) {
211
181
  // @ts-ignore
@@ -258,33 +228,6 @@ async function doParse(iterator, options = {}) {
258
228
  minify(ast, options, true, errors, false);
259
229
  }
260
230
  }
261
- // if (options.setParent) {
262
- //
263
- // const nodes: Array<AstRule | AstAtRule | AstRuleStyleSheet> = [ast];
264
- // let node: AstNode;
265
- //
266
- // while ((node = nodes.shift()!)) {
267
- //
268
- // // @ts-ignore
269
- // if (node.chi.length > 0) {
270
- //
271
- // // @ts-ignore
272
- // for (const child of node.chi) {
273
- //
274
- // if (child.parent != node) {
275
- //
276
- // Object.defineProperty(child, 'parent', {...definedPropertySettings, value: node});
277
- // }
278
- //
279
- // if ('chi' in child && child.chi.length > 0) {
280
- //
281
- // // @ts-ignore
282
- // nodes.push(<AstRule | AstAtRule>child);
283
- // }
284
- // }
285
- // }
286
- // }
287
- // }
288
231
  const endTime = performance.now();
289
232
  if (options.signal != null) {
290
233
  options.signal.removeEventListener('abort', reject);
@@ -301,7 +244,17 @@ async function doParse(iterator, options = {}) {
301
244
  }
302
245
  };
303
246
  }
304
- async function parseNode(results, context, stats, options, errors, src, map) {
247
+ function getLastNode(context) {
248
+ let i = context.chi.length;
249
+ while (i--) {
250
+ if ([EnumToken.CommentTokenType, EnumToken.CDOCOMMTokenType, EnumToken.WhitespaceTokenType].includes(context.chi[i].typ)) {
251
+ continue;
252
+ }
253
+ return context.chi[i];
254
+ }
255
+ return null;
256
+ }
257
+ async function parseNode(results, context, stats, options, errors, src, map, rawTokens) {
305
258
  let tokens = [];
306
259
  for (const t of results) {
307
260
  const node = getTokenType(t.token, t.hint);
@@ -356,24 +309,6 @@ async function parseNode(results, context, stats, options, errors, src, map) {
356
309
  if (tokens[0]?.typ == EnumToken.AtRuleTokenType) {
357
310
  const atRule = tokens.shift();
358
311
  const position = map.get(atRule);
359
- // if (atRule.val == 'charset') {
360
- //
361
- // if (context.typ != EnumToken.StyleSheetNodeType || context.chi.some(t => t.typ != EnumToken.CDOCOMMTokenType && t.typ != EnumToken.CommentNodeType)) {
362
- //
363
- // errors.push({
364
- // action: 'drop',
365
- // message: 'doParse: invalid @charset',
366
- // location: {src, ...position}
367
- // });
368
- //
369
- // return null;
370
- // }
371
- //
372
- // if (options.removeCharset) {
373
- //
374
- // return null;
375
- // }
376
- // }
377
312
  // @ts-ignore
378
313
  while ([EnumToken.WhitespaceTokenType].includes(tokens[0]?.typ)) {
379
314
  tokens.shift();
@@ -470,8 +405,43 @@ async function parseNode(results, context, stats, options, errors, src, map) {
470
405
  // https://www.w3.org/TR/css-nesting-1/#conditionals
471
406
  // allowed nesting at-rules
472
407
  // there must be a top level rule in the stack
473
- if (atRule.val == 'charset' && options.removeCharset) {
474
- return null;
408
+ if (atRule.val == 'charset') {
409
+ let spaces = 0;
410
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/@charset
411
+ for (let k = 1; k < rawTokens.length; k++) {
412
+ if (rawTokens[k].hint == EnumToken.WhitespaceTokenType) {
413
+ spaces += rawTokens[k].len;
414
+ continue;
415
+ }
416
+ if (rawTokens[k].hint == EnumToken.CommentTokenType) {
417
+ continue;
418
+ }
419
+ if (rawTokens[k].hint == EnumToken.CDOCOMMTokenType) {
420
+ continue;
421
+ }
422
+ if (spaces > 1) {
423
+ errors.push({
424
+ action: 'drop',
425
+ message: '@charset must have only one space',
426
+ // @ts-ignore
427
+ location: { src, ...(map.get(atRule) ?? position) }
428
+ });
429
+ return null;
430
+ }
431
+ if (rawTokens[k].hint != EnumToken.StringTokenType || rawTokens[k].token[0] != '"') {
432
+ errors.push({
433
+ action: 'drop',
434
+ message: '@charset expects a "<charset>"',
435
+ // @ts-ignore
436
+ location: { src, ...(map.get(atRule) ?? position) }
437
+ });
438
+ return null;
439
+ }
440
+ break;
441
+ }
442
+ if (options.removeCharset) {
443
+ return null;
444
+ }
475
445
  }
476
446
  const t = parseAtRulePrelude(parseTokens(tokens, { minify: options.minify }), atRule);
477
447
  const raw = t.reduce((acc, curr) => {
@@ -499,11 +469,36 @@ async function parseNode(results, context, stats, options, errors, src, map) {
499
469
  node.loc = loc;
500
470
  }
501
471
  if (options.validation) {
502
- const valid = validateAtRule(node, options, context);
472
+ let isValid = true;
473
+ if (node.nam == 'else') {
474
+ const prev = getLastNode(context);
475
+ if (prev != null && prev.typ == EnumToken.AtRuleNodeType && ['when', 'else'].includes(prev.nam)) {
476
+ if (prev.nam == 'else') {
477
+ isValid = Array.isArray(prev.tokens) && prev.tokens.length > 0;
478
+ }
479
+ }
480
+ else {
481
+ isValid = false;
482
+ }
483
+ }
484
+ const valid = isValid ? validateAtRule(node, options, context) : {
485
+ valid: ValidationLevel.Drop,
486
+ node,
487
+ syntax: '@' + node.nam,
488
+ error: '@' + node.nam + ' not allowed here'};
503
489
  if (valid.valid == ValidationLevel.Drop) {
490
+ errors.push({
491
+ action: 'drop',
492
+ message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
493
+ // @ts-ignore
494
+ location: { src, ...(map.get(valid.node) ?? position) }
495
+ });
504
496
  // @ts-ignore
505
497
  node.typ = EnumToken.InvalidAtRuleTokenType;
506
498
  }
499
+ else {
500
+ node.val = node.tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false, removeComments: true }), '');
501
+ }
507
502
  }
508
503
  // @ts-ignore
509
504
  context.chi.push(node);
@@ -682,7 +677,24 @@ async function parseNode(results, context, stats, options, errors, src, map) {
682
677
  };
683
678
  const result = parseDeclarationNode(node, errors, src, position);
684
679
  if (result != null) {
685
- if (options.validation) ;
680
+ // if (options.validation) {
681
+ //
682
+ // const valid: ValidationResult = validateDeclaration(result, options, context);
683
+ //
684
+ // console.error({valid});
685
+ //
686
+ // if (valid.valid == ValidationLevel.Drop) {
687
+ //
688
+ // errors.push({
689
+ // action: 'drop',
690
+ // message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, {minify: false}), '') + '"',
691
+ // // @ts-ignore
692
+ // location: {src, ...(map.get(valid.node) ?? position)}
693
+ // });
694
+ //
695
+ // return null;
696
+ // }
697
+ // }
686
698
  // @ts-ignore
687
699
  context.chi.push(result);
688
700
  Object.defineProperty(result, 'parent', { ...definedPropertySettings, value: context });
@@ -691,6 +703,11 @@ async function parseNode(results, context, stats, options, errors, src, map) {
691
703
  }
692
704
  }
693
705
  }
706
+ /**
707
+ * parse at-rule prelude
708
+ * @param tokens
709
+ * @param atRule
710
+ */
694
711
  function parseAtRulePrelude(tokens, atRule) {
695
712
  // @ts-ignore
696
713
  for (const { value, parent } of walkValues(tokens, null, null, true)) {
@@ -759,17 +776,18 @@ function parseAtRulePrelude(tokens, atRule) {
759
776
  continue;
760
777
  }
761
778
  }
762
- if (value.typ == EnumToken.ParensTokenType) {
779
+ if (value.typ == EnumToken.ParensTokenType || (value.typ == EnumToken.FunctionTokenType && ['media', 'supports', 'style', 'scroll-state'].includes(value.val))) {
763
780
  // @todo parse range and declarations
764
781
  // parseDeclaration(parent.chi);
765
782
  let i;
766
783
  let nameIndex = -1;
767
784
  let valueIndex = -1;
785
+ const dashedIdent = value.typ == EnumToken.FunctionTokenType && value.val == 'style';
768
786
  for (let i = 0; i < value.chi.length; i++) {
769
787
  if (value.chi[i].typ == EnumToken.CommentTokenType || value.chi[i].typ == EnumToken.WhitespaceTokenType) {
770
788
  continue;
771
789
  }
772
- if (value.chi[i].typ == EnumToken.IdenTokenType) {
790
+ if ((dashedIdent && value.chi[i].typ == EnumToken.DashedIdenTokenType) || value.chi[i].typ == EnumToken.IdenTokenType || value.chi[i].typ == EnumToken.FunctionTokenType || value.chi[i].typ == EnumToken.ColorTokenType) {
773
791
  nameIndex = i;
774
792
  }
775
793
  break;
@@ -798,6 +816,13 @@ function parseAtRulePrelude(tokens, atRule) {
798
816
  ].includes(value.chi[valueIndex].typ)) {
799
817
  const val = value.chi.splice(valueIndex, 1)[0];
800
818
  const node = value.chi.splice(nameIndex, 1)[0];
819
+ // 'background'
820
+ // @ts-ignore
821
+ if (node.typ == EnumToken.ColorTokenType && node.kin == 'dpsys') {
822
+ // @ts-ignore
823
+ delete node.kin;
824
+ node.typ = EnumToken.IdenTokenType;
825
+ }
801
826
  while (value.chi[0]?.typ == EnumToken.WhitespaceTokenType) {
802
827
  value.chi.shift();
803
828
  }
@@ -815,6 +840,10 @@ function parseAtRulePrelude(tokens, atRule) {
815
840
  }
816
841
  return tokens;
817
842
  }
843
+ /**
844
+ * parse selector
845
+ * @param tokens
846
+ */
818
847
  function parseSelector(tokens) {
819
848
  for (const { value, previousValue, nextValue, parent } of walkValues(tokens)) {
820
849
  if (value.typ == EnumToken.CommentTokenType ||
@@ -958,6 +987,11 @@ function parseSelector(tokens) {
958
987
  //
959
988
  // return doParse(`.x{${src}`, options).then((result: ParseResult) => <AstDeclaration[]>(<AstRule>result.ast.chi[0]).chi.filter(t => t.typ == EnumToken.DeclarationNodeType));
960
989
  // }
990
+ /**
991
+ * parse string
992
+ * @param src
993
+ * @param options
994
+ */
961
995
  function parseString(src, options = { location: false }) {
962
996
  return parseTokens([...tokenize(src)].map(t => {
963
997
  const token = getTokenType(t.token, t.hint);
@@ -1039,7 +1073,7 @@ function getTokenType(val, hint) {
1039
1073
  chi: []
1040
1074
  };
1041
1075
  }
1042
- if (['linear-gradient', 'radial-gradient', 'repeating-linear-gradient', 'repeating-radial-gradient', 'conic-gradient', 'image', 'image-set', 'element', 'cross-fade'].includes(val)) {
1076
+ if (['linear-gradient', 'radial-gradient', 'repeating-linear-gradient', 'repeating-radial-gradient', 'conic-gradient', 'image', 'image-set', 'element', 'cross-fade', 'paint'].includes(val)) {
1043
1077
  return {
1044
1078
  typ: EnumToken.ImageFunctionTokenType,
1045
1079
  val,
@@ -1139,6 +1173,11 @@ function getTokenType(val, hint) {
1139
1173
  val
1140
1174
  };
1141
1175
  }
1176
+ /**
1177
+ * parse token list
1178
+ * @param tokens
1179
+ * @param options
1180
+ */
1142
1181
  function parseTokens(tokens, options = {}) {
1143
1182
  for (let i = 0; i < tokens.length; i++) {
1144
1183
  const t = tokens[i];
@@ -1474,4 +1513,4 @@ function parseTokens(tokens, options = {}) {
1474
1513
  return tokens;
1475
1514
  }
1476
1515
 
1477
- export { doParse, parseAtRulePrelude, parseSelector, parseString, parseTokens, urlTokenMatcher };
1516
+ export { doParse, parseSelector, parseString, parseTokens, urlTokenMatcher };
@@ -16,7 +16,13 @@ function consumeWhiteSpace(parseInfo) {
16
16
  return count;
17
17
  }
18
18
  function pushToken(token, parseInfo, hint) {
19
- const result = { token, hint, position: { ...parseInfo.position }, bytesIn: parseInfo.currentPosition.ind + 1 };
19
+ const result = {
20
+ token,
21
+ len: parseInfo.currentPosition.ind - parseInfo.position.ind,
22
+ hint,
23
+ position: { ...parseInfo.position },
24
+ bytesIn: parseInfo.currentPosition.ind + 1
25
+ };
20
26
  parseInfo.position.ind = parseInfo.currentPosition.ind;
21
27
  parseInfo.position.lin = parseInfo.currentPosition.lin;
22
28
  parseInfo.position.col = Math.max(parseInfo.currentPosition.col, 1);
@@ -136,6 +142,10 @@ function next(parseInfo, count = 1) {
136
142
  }
137
143
  return char;
138
144
  }
145
+ /**
146
+ * tokenize css string
147
+ * @param stream
148
+ */
139
149
  function* tokenize(stream) {
140
150
  const parseInfo = {
141
151
  stream,
@@ -184,8 +194,10 @@ function* tokenize(stream) {
184
194
  buffer += value;
185
195
  }
186
196
  }
187
- yield pushToken(buffer, parseInfo, EnumToken.BadCommentTokenType);
188
- buffer = '';
197
+ if (buffer.length > 0) {
198
+ yield pushToken(buffer, parseInfo, EnumToken.BadCommentTokenType);
199
+ buffer = '';
200
+ }
189
201
  }
190
202
  break;
191
203
  case '&':
@@ -2,7 +2,7 @@ import { EnumToken } from '../../ast/types.js';
2
2
  import '../../ast/minify.js';
3
3
  import '../../ast/walk.js';
4
4
  import '../../parser/parse.js';
5
- import { getNumber, minmax } from './color.js';
5
+ import { minmax, getNumber } from './color.js';
6
6
  import { hsl2rgb, hwb2rgb, cmyk2rgb, oklab2rgb, oklch2rgb, lab2rgb, lch2rgb } from './rgb.js';
7
7
  import { NAMES_COLORS } from './utils/constants.js';
8
8
  import { getComponents } from './utils/components.js';
@@ -1,6 +1,6 @@
1
1
  import { hwb2hsv } from './hsv.js';
2
2
  import { getNumber } from './color.js';
3
- import { hex2rgb, lab2rgb, lch2rgb, oklab2rgb, oklch2rgb } from './rgb.js';
3
+ import { lch2rgb, lab2rgb, oklch2rgb, oklab2rgb, hex2rgb } from './rgb.js';
4
4
  import './utils/constants.js';
5
5
  import { getComponents } from './utils/components.js';
6
6
  import { EnumToken } from '../../ast/types.js';
@@ -1,12 +1,12 @@
1
1
  import { hsl2hsv } from './hsv.js';
2
2
  import './utils/constants.js';
3
3
  import { getComponents } from './utils/components.js';
4
- import { getNumber, getAngle } from './color.js';
4
+ import { getAngle, getNumber } from './color.js';
5
5
  import { EnumToken } from '../../ast/types.js';
6
6
  import '../../ast/minify.js';
7
7
  import '../../ast/walk.js';
8
8
  import '../../parser/parse.js';
9
- import { lab2srgb, lch2srgb, oklab2srgb, oklch2srgb } from './srgb.js';
9
+ import { lch2srgb, lab2srgb, oklch2srgb, oklab2srgb } from './srgb.js';
10
10
  import '../sourcemap/lib/encode.js';
11
11
  import '../../parser/utils/config.js';
12
12
 
@@ -1,7 +1,7 @@
1
1
  import { e, k, D50 } from './utils/constants.js';
2
2
  import { getComponents } from './utils/components.js';
3
3
  import { srgb2xyz, xyzd502srgb } from './xyz.js';
4
- import { hex2srgb, rgb2srgb, hsl2srgb, hwb2srgb, oklch2srgb } from './srgb.js';
4
+ import { oklch2srgb, hwb2srgb, hsl2srgb, rgb2srgb, hex2srgb } from './srgb.js';
5
5
  import { getLCHComponents } from './lch.js';
6
6
  import { OKLab_to_XYZ, getOKLABComponents } from './oklab.js';
7
7
  import { getNumber } from './color.js';
@@ -5,7 +5,7 @@ import { EnumToken } from '../../ast/types.js';
5
5
  import '../../ast/minify.js';
6
6
  import '../../ast/walk.js';
7
7
  import '../../parser/parse.js';
8
- import { srgb2lab, xyz2lab, hex2lab, rgb2lab, hsl2lab, hwb2lab, getLABComponents, oklab2lab, oklch2lab } from './lab.js';
8
+ import { srgb2lab, xyz2lab, oklch2lab, oklab2lab, getLABComponents, hwb2lab, hsl2lab, rgb2lab, hex2lab } from './lab.js';
9
9
  import '../sourcemap/lib/encode.js';
10
10
  import '../../parser/utils/config.js';
11
11
 
@@ -1,7 +1,7 @@
1
1
  import { multiplyMatrices } from './utils/matrix.js';
2
2
  import './utils/constants.js';
3
3
  import { getComponents } from './utils/components.js';
4
- import { srgb2lsrgbvalues, hex2srgb, rgb2srgb, hsl2srgb, hwb2srgb, lab2srgb, lch2srgb, lsrgb2srgbvalues } from './srgb.js';
4
+ import { srgb2lsrgbvalues, lch2srgb, lab2srgb, hwb2srgb, hsl2srgb, rgb2srgb, hex2srgb, lsrgb2srgbvalues } from './srgb.js';
5
5
  import { getNumber } from './color.js';
6
6
  import { EnumToken } from '../../ast/types.js';
7
7
  import '../../ast/minify.js';
@@ -106,7 +106,7 @@ function OKLab_to_sRGB(l, a, b) {
106
106
  1.2914855378640917399 * b, 3);
107
107
  return lsrgb2srgbvalues(
108
108
  /* r: */
109
- +4.076741661347994 * L -
109
+ 4.076741661347994 * L -
110
110
  3.307711590408193 * M +
111
111
  0.230969928729428 * S,
112
112
  /* g: */
@@ -6,7 +6,7 @@ import '../../ast/minify.js';
6
6
  import '../../ast/walk.js';
7
7
  import '../../parser/parse.js';
8
8
  import { lab2lchvalues } from './lch.js';
9
- import { srgb2oklab, hex2oklab, rgb2oklab, hsl2oklab, hwb2oklab, lab2oklab, lch2oklab, getOKLABComponents } from './oklab.js';
9
+ import { srgb2oklab, lch2oklab, getOKLABComponents, lab2oklab, hwb2oklab, hsl2oklab, rgb2oklab, hex2oklab } from './oklab.js';
10
10
  import '../sourcemap/lib/encode.js';
11
11
  import '../../parser/utils/config.js';
12
12
 
@@ -1,4 +1,4 @@
1
- import { xyz2srgb, srgb2lsrgbvalues, lsrgb2srgbvalues } from './srgb.js';
1
+ import { xyz2srgb, lsrgb2srgbvalues, srgb2lsrgbvalues } from './srgb.js';
2
2
  import { multiplyMatrices } from './utils/matrix.js';
3
3
  import './utils/constants.js';
4
4
  import '../../ast/types.js';
@@ -1,4 +1,4 @@
1
- import { xyzd502srgb, srgb2xyz } from './xyz.js';
1
+ import { srgb2xyz, xyzd502srgb } from './xyz.js';
2
2
  import { XYZ_D65_to_D50 } from './xyzd50.js';
3
3
 
4
4
  function prophotorgb2srgbvalues(r, g, b, a = null) {
@@ -1,4 +1,4 @@
1
- import { xyzd502srgb, srgb2xyz } from './xyz.js';
1
+ import { srgb2xyz, xyzd502srgb } from './xyz.js';
2
2
  import { XYZ_D65_to_D50 } from './xyzd50.js';
3
3
 
4
4
  function prophotorgb2srgbvalues(r, g, b, a = null) {
@@ -5,7 +5,7 @@ import '../../ast/minify.js';
5
5
  import '../../ast/walk.js';
6
6
  import '../../parser/parse.js';
7
7
  import { expandHexValue } from './hex.js';
8
- import { hwb2srgb, hslvalues, hsl2srgbvalues, cmyk2srgb, oklab2srgb, oklch2srgb, lab2srgb, lch2srgb } from './srgb.js';
8
+ import { hslvalues, hsl2srgbvalues, hwb2srgb, cmyk2srgb, oklab2srgb, oklch2srgb, lab2srgb, lch2srgb } from './srgb.js';
9
9
  import '../sourcemap/lib/encode.js';
10
10
  import '../../parser/utils/config.js';
11
11
 
@@ -6,8 +6,8 @@ import '../../ast/minify.js';
6
6
  import '../../ast/walk.js';
7
7
  import '../../parser/parse.js';
8
8
  import { expandHexValue } from './hex.js';
9
- import { lch2labvalues, getLABComponents, Lab_to_sRGB } from './lab.js';
10
- import { getOKLABComponents, OKLab_to_sRGB } from './oklab.js';
9
+ import { lch2labvalues, Lab_to_sRGB, getLABComponents } from './lab.js';
10
+ import { OKLab_to_sRGB, getOKLABComponents } from './oklab.js';
11
11
  import { getLCHComponents } from './lch.js';
12
12
  import { getOKLCHComponents } from './oklch.js';
13
13
  import { XYZ_to_lin_sRGB } from './xyz.js';
@@ -28,7 +28,7 @@ const colorRange = {
28
28
  }
29
29
  };
30
30
  const colorFuncColorSpace = ['srgb', 'srgb-linear', 'display-p3', 'prophoto-rgb', 'a98-rgb', 'rec2020', 'xyz', 'xyz-d65', 'xyz-d50'];
31
- ({ typ: EnumToken.IdenTokenType, val: 'none' });
31
+ ({ typ: EnumToken.IdenTokenType});
32
32
  const D50 = [0.3457 / 0.3585, 1.00000, (1.0 - 0.3457 - 0.3585) / 0.3585];
33
33
  const k = Math.pow(29, 3) / Math.pow(3, 3);
34
34
  const e = Math.pow(6, 3) / Math.pow(29, 3);
@@ -4,7 +4,7 @@ import '../../ast/types.js';
4
4
  import '../../ast/minify.js';
5
5
  import '../../ast/walk.js';
6
6
  import '../../parser/parse.js';
7
- import { lsrgb2srgbvalues, srgb2lsrgbvalues } from './srgb.js';
7
+ import { srgb2lsrgbvalues, lsrgb2srgbvalues } from './srgb.js';
8
8
  import '../sourcemap/lib/encode.js';
9
9
  import '../../parser/utils/config.js';
10
10
 
@@ -41,17 +41,27 @@ function update(position, str) {
41
41
  }
42
42
  }
43
43
  }
44
+ /**
45
+ * render ast
46
+ * @param data
47
+ * @param options
48
+ */
44
49
  function doRender(data, options = {}) {
50
+ const minify = options.minify ?? true;
51
+ const beautify = options.beautify ?? !minify;
45
52
  options = {
46
- ...(options.minify ?? true ? {
53
+ ...(beautify ? {
54
+ indent: ' ',
55
+ newLine: '\n',
56
+ } : {
47
57
  indent: '',
48
58
  newLine: '',
59
+ }),
60
+ ...(minify ? {
49
61
  removeEmpty: true,
50
62
  removeComments: true
51
63
  } : {
52
- indent: ' ',
53
- newLine: '\n',
54
- compress: false,
64
+ removeEmpty: false,
55
65
  removeComments: false,
56
66
  }), sourcemap: false, convertColor: true, expandNestingRules: false, preserveLicense: false, ...options
57
67
  };
@@ -119,7 +129,18 @@ function updateSourceMap(node, options, cache, sourcemap, position, str) {
119
129
  }
120
130
  update(position, str);
121
131
  }
122
- // @ts-ignore
132
+ /**
133
+ * render ast node
134
+ * @param data
135
+ * @param options
136
+ * @param sourcemap
137
+ * @param position
138
+ * @param errors
139
+ * @param reducer
140
+ * @param cache
141
+ * @param level
142
+ * @param indents
143
+ */
123
144
  function renderAstNode(data, options, sourcemap, position, errors, reducer, cache, level = 0, indents = []) {
124
145
  if (indents.length < level + 1) {
125
146
  indents.push(options.indent.repeat(level));
@@ -212,8 +233,15 @@ function renderAstNode(data, options, sourcemap, position, errors, reducer, cach
212
233
  // return renderToken(data as Token, options, cache, reducer, errors);
213
234
  throw new Error(`render: unexpected token ${JSON.stringify(data, null, 1)}`);
214
235
  }
215
- return '';
216
236
  }
237
+ /**
238
+ * render ast token
239
+ * @param token
240
+ * @param options
241
+ * @param cache
242
+ * @param reducer
243
+ * @param errors
244
+ */
217
245
  function renderToken(token, options = {}, cache = Object.create(null), reducer, errors) {
218
246
  if (reducer == null) {
219
247
  reducer = function (acc, curr) {