@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
package/dist/index.d.ts CHANGED
@@ -120,6 +120,15 @@ declare enum EnumToken {
120
120
  TimelineFunction = 16
121
121
  }
122
122
 
123
+ /**
124
+ * minify ast
125
+ * @param ast
126
+ * @param options
127
+ * @param recursive
128
+ * @param errors
129
+ * @param nestingContent
130
+ * @param context
131
+ */
123
132
  declare function minify(ast: AstNode, options?: ParserOptions | MinifyOptions, recursive?: boolean, errors?: ErrorDescription[], nestingContent?: boolean, context?: {
124
133
  [key: string]: any;
125
134
  }): AstNode;
@@ -128,22 +137,56 @@ declare enum WalkerValueEvent {
128
137
  Enter = 0,
129
138
  Leave = 1
130
139
  }
140
+ /**
141
+ * walk ast nodes
142
+ * @param node
143
+ * @param filter
144
+ */
131
145
  declare function walk(node: AstNode, filter?: WalkerFilter): Generator<WalkResult>;
146
+ /**
147
+ * walk ast values
148
+ * @param values
149
+ * @param root
150
+ * @param filter
151
+ * @param reverse
152
+ */
132
153
  declare function walkValues(values: Token[], root?: AstNode | Token | null, filter?: WalkerValueFilter | {
133
154
  event: WalkerValueEvent;
134
155
  fn?: WalkerValueFilter;
135
156
  type?: EnumToken | EnumToken[] | ((token: Token) => boolean);
136
157
  }, reverse?: boolean): Generator<WalkAttributesResult>;
137
158
 
159
+ /**
160
+ * expand nested css ast
161
+ * @param ast
162
+ */
138
163
  declare function expand(ast: AstNode): AstNode;
139
164
 
165
+ /**
166
+ * render ast token
167
+ * @param token
168
+ * @param options
169
+ * @param cache
170
+ * @param reducer
171
+ * @param errors
172
+ */
140
173
  declare function renderToken(token: Token, options?: RenderOptions, cache?: {
141
174
  [key: string]: any;
142
175
  }, reducer?: (acc: string, curr: Token) => string, errors?: ErrorDescription[]): string;
143
176
 
177
+ /**
178
+ * parse string
179
+ * @param src
180
+ * @param options
181
+ */
144
182
  declare function parseString(src: string, options?: {
145
183
  location: boolean;
146
184
  }): Token[];
185
+ /**
186
+ * parse token list
187
+ * @param tokens
188
+ * @param options
189
+ */
147
190
  declare function parseTokens(tokens: Token[], options?: ParseTokenOptions): Token[];
148
191
 
149
192
  export declare interface LiteralToken extends BaseToken {
@@ -567,21 +610,15 @@ export declare interface MediaFeatureToken extends BaseToken {
567
610
  val: string;
568
611
  }
569
612
 
570
- export declare interface MediaFeatureOnlyToken extends BaseToken {
571
-
572
- typ: EnumToken.MediaFeatureOnlyTokenType,
573
- val: Token;
574
- }
575
-
576
613
  export declare interface MediaFeatureNotToken extends BaseToken {
577
614
 
578
615
  typ: EnumToken.MediaFeatureNotTokenType,
579
616
  val: Token;
580
617
  }
581
618
 
582
- export declare interface MediaFeatureNotToken extends BaseToken {
619
+ export declare interface MediaFeatureOnlyToken extends BaseToken {
583
620
 
584
- typ: EnumToken.MediaFeatureNotTokenType,
621
+ typ: EnumToken.MediaFeatureOnlyTokenType,
585
622
  val: Token;
586
623
  }
587
624
 
@@ -861,6 +898,7 @@ export declare interface AstKeyFrameRule extends BaseToken {
861
898
  chi: Array<AstDeclaration | AstComment>;
862
899
  optimized?: OptimizedSelector;
863
900
  raw?: RawSelectorTokens;
901
+ tokens?: Token[]
864
902
  }
865
903
 
866
904
  export declare type RawSelectorTokens = string[][];
@@ -994,6 +1032,7 @@ export declare interface ErrorDescription {
994
1032
  interface ValidationOptions {
995
1033
 
996
1034
  validation?: boolean;
1035
+ lenient?: boolean;
997
1036
  }
998
1037
 
999
1038
  export declare interface ParserOptions extends ValidationOptions, PropertyListOptions {
@@ -1044,9 +1083,7 @@ export declare interface MinifyFeature {
1044
1083
  export declare interface MinifyFeature {
1045
1084
 
1046
1085
  ordering: number;
1047
-
1048
1086
  register: (options: MinifyOptions | ParserOptions) => void;
1049
-
1050
1087
  run: (ast: AstRule | AstAtRule, options: ParserOptions, parent: AstRule | AstAtRule | AstRuleStyleSheet, context: {
1051
1088
  [key: string]: any
1052
1089
  }) => void;
@@ -1060,6 +1097,7 @@ export declare interface ResolvedPath {
1060
1097
  export declare interface RenderOptions {
1061
1098
 
1062
1099
  minify?: boolean;
1100
+ beautify?: boolean;
1063
1101
  removeEmpty?: boolean;
1064
1102
  expandNestingRules?: boolean;
1065
1103
  preserveLicense?: boolean;
@@ -1073,7 +1111,6 @@ export declare interface RenderOptions {
1073
1111
  cwd?: string;
1074
1112
  load?: (url: string, currentUrl: string) => Promise<string>;
1075
1113
  resolve?: (url: string, currentUrl: string, currentWorkingDirectory?: string) => ResolvedPath;
1076
-
1077
1114
  }
1078
1115
 
1079
1116
  export declare interface TransformOptions extends ParserOptions, RenderOptions {
@@ -6,6 +6,10 @@ import { renderToken } from '../renderer/render.js';
6
6
  import '../renderer/color/utils/constants.js';
7
7
  import '../parser/utils/config.js';
8
8
 
9
+ /**
10
+ * expand nested css ast
11
+ * @param ast
12
+ */
9
13
  function expand(ast) {
10
14
  //
11
15
  if (![EnumToken.RuleNodeType, EnumToken.StyleSheetNodeType, EnumToken.AtRuleNodeType].includes(ast.typ)) {
@@ -50,7 +54,7 @@ function expand(ast) {
50
54
  }
51
55
  return result;
52
56
  }
53
- function expandRule(node, parent) {
57
+ function expandRule(node) {
54
58
  const ast = { ...node, chi: node.chi.slice() };
55
59
  const result = [];
56
60
  if (ast.typ == EnumToken.RuleNodeType) {
@@ -155,7 +159,10 @@ function expandRule(node, parent) {
155
159
  if (astAtRule.val.includes('&')) {
156
160
  astAtRule.val = replaceCompound(astAtRule.val, ast.sel);
157
161
  }
158
- astAtRule = expand(astAtRule);
162
+ const slice = astAtRule.chi.slice().filter(t => t.typ == EnumToken.RuleNodeType && t.sel.includes('&'));
163
+ if (slice.length > 0) {
164
+ expandRule({ ...node, chi: astAtRule.chi.slice() });
165
+ }
159
166
  }
160
167
  else {
161
168
  // @ts-ignore
@@ -194,6 +201,11 @@ function expandRule(node, parent) {
194
201
  // @ts-ignore
195
202
  return ast.chi.length > 0 ? [ast].concat(result) : result;
196
203
  }
204
+ /**
205
+ * replace compound selector
206
+ * @param input
207
+ * @param replace
208
+ */
197
209
  function replaceCompound(input, replace) {
198
210
  const tokens = parseString(input);
199
211
  let replacement = null;
@@ -1,5 +1,5 @@
1
1
  import { EnumToken } from '../types.js';
2
- import { compute, rem } from './math.js';
2
+ import { rem, compute } from './math.js';
3
3
  import { reduceNumber } from '../../renderer/render.js';
4
4
  import { mathFuncs } from '../../syntax/syntax.js';
5
5
 
@@ -2,10 +2,10 @@ import { parseString } from '../parser/parse.js';
2
2
  import { EnumToken } from './types.js';
3
3
  import { walkValues } from './walk.js';
4
4
  import { replaceCompound } from './expand.js';
5
- import { isWhiteSpace, isIdent, isFunction, isIdentStart } from '../syntax/syntax.js';
5
+ import { isIdent, isFunction, isWhiteSpace, isIdentStart } from '../syntax/syntax.js';
6
6
  import '../parser/utils/config.js';
7
7
  import { eq } from '../parser/utils/eq.js';
8
- import { renderToken, doRender } from '../renderer/render.js';
8
+ import { doRender, renderToken } from '../renderer/render.js';
9
9
  import * as index from './features/index.js';
10
10
 
11
11
  const combinators = ['+', '>', '~', '||', '|'];
@@ -13,6 +13,15 @@ const definedPropertySettings = { configurable: true, enumerable: false, writabl
13
13
  const notEndingWith = ['(', '['].concat(combinators);
14
14
  // @ts-ignore
15
15
  const features = Object.values(index).sort((a, b) => a.ordering - b.ordering);
16
+ /**
17
+ * minify ast
18
+ * @param ast
19
+ * @param options
20
+ * @param recursive
21
+ * @param errors
22
+ * @param nestingContent
23
+ * @param context
24
+ */
16
25
  function minify(ast, options = {}, recursive = false, errors, nestingContent, context = {}) {
17
26
  if (!('nodes' in context)) {
18
27
  context.nodes = new Set;
@@ -82,7 +91,8 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
82
91
  continue;
83
92
  }
84
93
  if (node.typ == EnumToken.AtRuleNodeType) {
85
- if (node.nam == 'media' && node.val == 'all') {
94
+ // @ts-ignore
95
+ if (node.nam == 'media' && ['all', '', null].includes(node.val)) {
86
96
  // @ts-ignore
87
97
  ast.chi?.splice(i, 1, ...node.chi);
88
98
  i--;
@@ -397,6 +407,18 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
397
407
  }
398
408
  return ast;
399
409
  }
410
+ function hasDeclaration(node) {
411
+ // @ts-ignore
412
+ for (let i = 0; i < node.chi?.length; i++) {
413
+ // @ts-ignore
414
+ if (node.chi[i].typ == EnumToken.CommentNodeType) {
415
+ continue;
416
+ }
417
+ // @ts-ignore
418
+ return node.chi[i].typ == EnumToken.DeclarationNodeType;
419
+ }
420
+ return true;
421
+ }
400
422
  function reduceSelector(selector) {
401
423
  if (selector.length == 0) {
402
424
  return null;
@@ -497,18 +519,10 @@ function reduceSelector(selector) {
497
519
  reducible: selector.every((selector) => !['>', '+', '~', '&'].includes(selector[0]))
498
520
  };
499
521
  }
500
- function hasDeclaration(node) {
501
- // @ts-ignore
502
- for (let i = 0; i < node.chi?.length; i++) {
503
- // @ts-ignore
504
- if (node.chi[i].typ == EnumToken.CommentNodeType) {
505
- continue;
506
- }
507
- // @ts-ignore
508
- return node.chi[i].typ == EnumToken.DeclarationNodeType;
509
- }
510
- return true;
511
- }
522
+ /**
523
+ * split selector string
524
+ * @param buffer
525
+ */
512
526
  function splitRule(buffer) {
513
527
  const result = [[]];
514
528
  let str = '';
@@ -995,4 +1009,4 @@ function reduceRuleSelector(node) {
995
1009
  }
996
1010
  }
997
1011
 
998
- export { combinators, definedPropertySettings, hasDeclaration, matchSelectors, minify, reduceSelector, splitRule };
1012
+ export { combinators, definedPropertySettings, minify, splitRule };
@@ -2,6 +2,7 @@ var ValidationLevel;
2
2
  (function (ValidationLevel) {
3
3
  ValidationLevel[ValidationLevel["Valid"] = 0] = "Valid";
4
4
  ValidationLevel[ValidationLevel["Drop"] = 1] = "Drop";
5
+ ValidationLevel[ValidationLevel["Lenient"] = 2] = "Lenient"; /* preserve unknown at-rules, declarations and pseudo-classes */
5
6
  })(ValidationLevel || (ValidationLevel = {}));
6
7
  var EnumToken;
7
8
  (function (EnumToken) {
@@ -5,6 +5,11 @@ var WalkerValueEvent;
5
5
  WalkerValueEvent[WalkerValueEvent["Enter"] = 0] = "Enter";
6
6
  WalkerValueEvent[WalkerValueEvent["Leave"] = 1] = "Leave";
7
7
  })(WalkerValueEvent || (WalkerValueEvent = {}));
8
+ /**
9
+ * walk ast nodes
10
+ * @param node
11
+ * @param filter
12
+ */
8
13
  function* walk(node, filter) {
9
14
  const parents = [node];
10
15
  const root = node;
@@ -33,6 +38,13 @@ function* walk(node, filter) {
33
38
  }
34
39
  }
35
40
  }
41
+ /**
42
+ * walk ast values
43
+ * @param values
44
+ * @param root
45
+ * @param filter
46
+ * @param reverse
47
+ */
36
48
  function* walkValues(values, root = null, filter, reverse) {
37
49
  // const set = new Set<Token>();
38
50
  const stack = values.slice();
@@ -162,55 +162,6 @@ class PropertyMap {
162
162
  }
163
163
  return this;
164
164
  }
165
- matchTypes(declaration) {
166
- const patterns = this.pattern.slice();
167
- const values = [...declaration.val];
168
- let i;
169
- let j;
170
- const map = new Map;
171
- for (i = 0; i < patterns.length; i++) {
172
- for (j = 0; j < values.length; j++) {
173
- if (!map.has(patterns[i])) {
174
- // @ts-ignore
175
- map.set(patterns[i], this.config.properties?.[patterns[i]]?.constraints?.mapping?.max ?? 1);
176
- }
177
- let count = map.get(patterns[i]);
178
- if (count > 0 && matchType(values[j], this.config.properties[patterns[i]])) {
179
- Object.defineProperty(values[j], 'propertyName', {
180
- enumerable: false,
181
- writable: true,
182
- value: patterns[i]
183
- });
184
- map.set(patterns[i], --count);
185
- values.splice(j--, 1);
186
- }
187
- }
188
- }
189
- if (this.config.set != null) {
190
- for (const [key, val] of Object.entries(this.config.set)) {
191
- if (map.has(key)) {
192
- for (const v of val) {
193
- // missing
194
- if (map.get(v) == 1) {
195
- let i = declaration.val.length;
196
- while (i--) {
197
- // @ts-ignore
198
- if (declaration.val[i].propertyName == key) {
199
- const val = { ...declaration.val[i] };
200
- Object.defineProperty(val, 'propertyName', {
201
- enumerable: false,
202
- writable: true,
203
- value: v
204
- });
205
- declaration.val.splice(i, 0, val, { typ: EnumToken.WhitespaceTokenType });
206
- }
207
- }
208
- }
209
- }
210
- }
211
- }
212
- }
213
- }
214
165
  [Symbol.iterator]() {
215
166
  let iterable;
216
167
  let requiredCount = 0;
@@ -249,9 +200,15 @@ class PropertyMap {
249
200
  // @ts-ignore
250
201
  let typ = (EnumToken[this.config.separator?.typ] ?? EnumToken.CommaTokenType);
251
202
  // @ts-ignore
252
- const sep = this.config.separator == null ? null : { ...this.config.separator, typ: EnumToken[this.config.separator.typ] };
203
+ const sep = this.config.separator == null ? null : {
204
+ ...this.config.separator,
205
+ typ: EnumToken[this.config.separator.typ]
206
+ };
253
207
  // @ts-ignore
254
- const separator = this.config.separator ? renderToken({ ...this.config.separator, typ: EnumToken[this.config.separator.typ] }) : ',';
208
+ const separator = this.config.separator ? renderToken({
209
+ ...this.config.separator,
210
+ typ: EnumToken[this.config.separator.typ]
211
+ }) : ',';
255
212
  this.matchTypes(declaration);
256
213
  values.push(value);
257
214
  for (i = 0; i < declaration.val.length; i++) {
@@ -446,7 +403,6 @@ class PropertyMap {
446
403
  acc.push(curr);
447
404
  return acc;
448
405
  }, []);
449
- // @todo remove renderToken call
450
406
  if (props.default.includes(curr[1][i].reduce((acc, curr) => acc + renderToken(curr) + ' ', '').trimEnd())) {
451
407
  if (!this.config.properties[curr[0]].required) {
452
408
  continue;
@@ -544,6 +500,7 @@ class PropertyMap {
544
500
  }
545
501
  // @ts-ignore
546
502
  if (values.length == 1 &&
503
+ // @ts-ignore
547
504
  typeof values[0].val == 'string' &&
548
505
  this.config.default.includes(values[0].val.toLowerCase()) &&
549
506
  this.config.default[0] != values[0].val.toLowerCase()) {
@@ -562,6 +519,7 @@ class PropertyMap {
562
519
  // @ts-ignore
563
520
  next() {
564
521
  let v = iterable.next();
522
+ // @ts-ignore
565
523
  while (v.done || v.value instanceof PropertySet) {
566
524
  if (v.value instanceof PropertySet) {
567
525
  // @ts-ignore
@@ -584,6 +542,55 @@ class PropertyMap {
584
542
  }
585
543
  };
586
544
  }
545
+ matchTypes(declaration) {
546
+ const patterns = this.pattern.slice();
547
+ const values = [...declaration.val];
548
+ let i;
549
+ let j;
550
+ const map = new Map;
551
+ for (i = 0; i < patterns.length; i++) {
552
+ for (j = 0; j < values.length; j++) {
553
+ if (!map.has(patterns[i])) {
554
+ // @ts-ignore
555
+ map.set(patterns[i], this.config.properties?.[patterns[i]]?.constraints?.mapping?.max ?? 1);
556
+ }
557
+ let count = map.get(patterns[i]);
558
+ if (count > 0 && matchType(values[j], this.config.properties[patterns[i]])) {
559
+ Object.defineProperty(values[j], 'propertyName', {
560
+ enumerable: false,
561
+ writable: true,
562
+ value: patterns[i]
563
+ });
564
+ map.set(patterns[i], --count);
565
+ values.splice(j--, 1);
566
+ }
567
+ }
568
+ }
569
+ if (this.config.set != null) {
570
+ for (const [key, val] of Object.entries(this.config.set)) {
571
+ if (map.has(key)) {
572
+ for (const v of val) {
573
+ // missing
574
+ if (map.get(v) == 1) {
575
+ let i = declaration.val.length;
576
+ while (i--) {
577
+ // @ts-ignore
578
+ if (declaration.val[i].propertyName == key) {
579
+ const val = { ...declaration.val[i] };
580
+ Object.defineProperty(val, 'propertyName', {
581
+ enumerable: false,
582
+ writable: true,
583
+ value: v
584
+ });
585
+ declaration.val.splice(i, 0, val, { typ: EnumToken.WhitespaceTokenType });
586
+ }
587
+ }
588
+ }
589
+ }
590
+ }
591
+ }
592
+ }
593
+ }
587
594
  removeDefaults(map, value) {
588
595
  for (const [key, val] of map) {
589
596
  const config = this.config.properties[key];
@@ -181,20 +181,8 @@ class PropertySet {
181
181
  return acc;
182
182
  }, [])
183
183
  }][Symbol.iterator]();
184
- // return {
185
- // next() {
186
- //
187
- // return iterator.next();
188
- // }
189
- // }
190
184
  }
191
185
  return iterator;
192
- // return {
193
- // next() {
194
- //
195
- // return iterator.next();
196
- // }
197
- // }
198
186
  }
199
187
  }
200
188