@jesscss/css-parser 1.0.8-alpha.6 → 2.0.0-alpha.2

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 (52) hide show
  1. package/lib/advancedActionsParser.d.ts +60 -0
  2. package/lib/advancedActionsParser.js +203 -0
  3. package/lib/advancedActionsParser.js.map +1 -0
  4. package/lib/cssActionsParser.d.ts +155 -0
  5. package/lib/cssActionsParser.js +376 -0
  6. package/lib/cssActionsParser.js.map +1 -0
  7. package/lib/cssErrorMessageProvider.d.ts +14 -0
  8. package/lib/cssErrorMessageProvider.js +40 -0
  9. package/lib/cssErrorMessageProvider.js.map +1 -0
  10. package/lib/cssParser.d.ts +36 -103
  11. package/lib/cssParser.js +75 -58
  12. package/lib/cssParser.js.map +1 -0
  13. package/lib/cssTokens.d.ts +539 -5
  14. package/lib/cssTokens.js +488 -232
  15. package/lib/cssTokens.js.map +1 -0
  16. package/lib/index.d.ts +8 -16
  17. package/lib/index.js +9 -41
  18. package/lib/index.js.map +1 -0
  19. package/lib/productions.d.ts +273 -0
  20. package/lib/productions.js +3499 -0
  21. package/lib/productions.js.map +1 -0
  22. package/lib/test/ast-serialize.test.d.ts +1 -0
  23. package/lib/test/ast-serialize.test.js +157 -0
  24. package/lib/test/ast-serialize.test.js.map +1 -0
  25. package/lib/test/container.test.d.ts +1 -0
  26. package/lib/test/container.test.js +369 -0
  27. package/lib/test/container.test.js.map +1 -0
  28. package/lib/test/css-files.test.d.ts +1 -0
  29. package/lib/test/css-files.test.js +21 -0
  30. package/lib/test/css-files.test.js.map +1 -0
  31. package/lib/test/less-output.test.d.ts +1 -0
  32. package/lib/test/less-output.test.js +52 -0
  33. package/lib/test/less-output.test.js.map +1 -0
  34. package/lib/util/cst.d.ts +7 -2
  35. package/lib/util/cst.js +5 -9
  36. package/lib/util/cst.js.map +1 -0
  37. package/lib/util/index.d.ts +19 -13
  38. package/lib/util/index.js +98 -87
  39. package/lib/util/index.js.map +1 -0
  40. package/package.json +43 -20
  41. package/lib/productions/atRules.d.ts +0 -2
  42. package/lib/productions/atRules.js +0 -196
  43. package/lib/productions/blocks.d.ts +0 -2
  44. package/lib/productions/blocks.js +0 -181
  45. package/lib/productions/declarations.d.ts +0 -14
  46. package/lib/productions/declarations.js +0 -59
  47. package/lib/productions/root.d.ts +0 -2
  48. package/lib/productions/root.js +0 -49
  49. package/lib/productions/selectors.d.ts +0 -2
  50. package/lib/productions/selectors.js +0 -231
  51. package/lib/productions/values.d.ts +0 -2
  52. package/lib/productions/values.js +0 -114
package/lib/cssTokens.js CHANGED
@@ -1,269 +1,525 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Tokens = exports.groupCapture = exports.Fragments = void 0;
4
- /* eslint no-control-regex: "off" */
5
- const util_1 = require("./util");
1
+ import { LexerType } from './util/index.js';
2
+ import { SKIPPED_LABEL } from './advancedActionsParser.js';
3
+ import { buildFragments, createLexerDefinition } from './util/index.js';
6
4
  /**
7
5
  * references:
8
6
  * https://github.com/antlr/grammars-v4/blob/master/css3/css3.g4
9
7
  * https://www.lifewire.com/css2-vs-css3-3466978
10
8
  * https://www.w3.org/TR/css-syntax-3/
11
9
  *
12
- * Fragments and Tokens must be defined in order
13
- * ({{references}} must follow definitions)
10
+ * @todo
11
+ * XRegExp should accept an object rather than an array of arrays,
12
+ * which would make extending easier.
14
13
  */
15
- exports.Fragments = [
14
+ export const rawCssFragments = () => [
16
15
  ['newline', '\\n|\\r\\n?|\\f'],
17
16
  ['whitespace', '[ ]|\\t|{{newline}}'],
17
+ /** @todo - use in order to attach newlines to node ends? */
18
+ ['sepws', '(?:[ ]|\\t)*{{newline}}|(?:[ ]|\\t)+'],
18
19
  ['ws', '{{whitespace}}+'],
19
20
  ['comment', '\\/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*\\/'],
20
21
  ['hex', '[\\da-fA-F]'],
21
22
  ['unicode', '\\\\{{hex}}{1,6}{{whitespace}}?'],
22
23
  ['escape', '{{unicode}}|\\\\[^\\r\\n\\f0-9a-fA-F]'],
23
- ['string1', '\\"(\\\\"|[^\\n\\r\\f\\"]|{{newline}}|{{escape}})*\\"'],
24
- ['string2', "\\'(\\\\'|[^\\n\\r\\f\\']|{{newline}}|{{escape}})*\\'"],
25
24
  ['nonascii', '[\\u0240-\\uffff]'],
26
25
  ['nmstart', '[_a-zA-Z]|{{nonascii}}|{{escape}}'],
27
26
  ['nmchar', '[_a-zA-Z0-9-]|{{nonascii}}|{{escape}}'],
28
27
  ['ident', '-?{{nmstart}}{{nmchar}}*'],
29
- /** Reference: https://www.w3.org/TR/css-syntax-3/#consume-url-token */
30
- ['url', '(?:[^(\'"]|{{escape}})*'],
28
+ /**
29
+ * This diverts from spec -- we narrow units to not contain dashes or numbers
30
+ * This prevents 6px-1px from being parsed as '6' as number and 'px-1px' as unit,
31
+ * which causes problems for Less / Sass.
32
+ */
33
+ ['unit', '(?:[a-zA-Z]|{{nonascii}}|{{escape}})+'],
34
+ ['string1', '\\"(\\\\"|\\\\{{newline}}|[^\\n\\r\\f\\"]|{{newline}}|{{escape}})*\\"'],
35
+ ['string2', '\\\'(\\\\\'|\\\\{{newline}}|[^\\n\\r\\f\\\']|{{newline}}|{{escape}})*\\\''],
31
36
  ['integer', '[+-]?\\d+'],
32
- /** Any number that's not simply an integer e.g. 1.1 or 1e+1 */
33
- ['number', '[+-]?(?:\\d*\\.\\d+(?:[eE][+-]\\d+)?|\\d+(?:[eE][+-]\\d+))'],
37
+ /**
38
+ * Any (signless) number that's not simply an integer e.g. 1.1 or 1e+1
39
+ */
40
+ ['number', '(?:\\d*\\.\\d+(?:[eE][+-]\\d+)?|\\d+(?:[eE][+-]\\d+))'],
34
41
  ['wsorcomment', '({{ws}})|({{comment}})']
35
42
  ];
36
- class matchValue {
37
- constructor(str, index) {
38
- this.value = str;
39
- this.index = index;
40
- }
41
- }
43
+ // interface Match { value: string, index: number }
44
+ // class MatchValue implements Match {
45
+ // value: string
46
+ // index: number
47
+ // constructor(str: string, index: number) {
48
+ // this.value = str
49
+ // this.index = index
50
+ // }
51
+ // }
42
52
  /**
43
53
  * When bound to a Regular Expression, it will aggregrate capture groups onto the payload
44
54
  */
45
- function groupCapture(text, startOffset) {
55
+ export function groupCapture(text, startOffset) {
46
56
  let endOffset = startOffset;
47
- let match;
48
- let lastMatch = null;
49
- const matches = [];
50
57
  this.lastIndex = startOffset;
51
- while ((match = this.exec(text))) {
52
- endOffset = this.lastIndex;
53
- lastMatch = match;
54
- matches.push(match);
55
- }
56
- if (lastMatch !== null) {
57
- const payload = new Array(lastMatch.length - 1);
58
- matches.forEach(match => {
59
- match.forEach((group, i) => {
60
- if (i > 0 && group) {
61
- const item = payload[i - 1];
62
- if (item) {
63
- item.push(new matchValue(group, match.index));
64
- }
65
- else {
66
- payload[i - 1] = [new matchValue(group, match.index)];
67
- }
68
- }
69
- });
70
- });
71
- const returnObj = [text.substring(startOffset, endOffset)];
58
+ let match = this.exec(text);
59
+ endOffset = this.lastIndex;
60
+ const payload = match?.filter((m, i) => {
61
+ return i !== 0 && typeof m === 'string';
62
+ });
63
+ const returnObj = [text.substring(startOffset, endOffset)];
64
+ if (payload) {
72
65
  returnObj.payload = payload;
73
66
  return returnObj;
74
67
  }
75
- return lastMatch;
68
+ return match;
76
69
  }
77
- exports.groupCapture = groupCapture;
78
70
  /**
79
71
  * Anything that is not 'BlockMarker' will be parsed as a generic 'Value',
80
72
  * so 'Value' can be considered `!BlockMarker`
73
+ *
74
+ * @todo Change to Map implementation? May allow easier replacement of
75
+ * tokens, in extended parsers, as well as easier TokenMap.
81
76
  */
82
- exports.Tokens = [
83
- { name: 'Value', pattern: util_1.LexerType.NA },
84
- { name: 'NonIdent', pattern: util_1.LexerType.NA },
85
- { name: 'AtName', pattern: util_1.LexerType.NA },
86
- // This can match anything, so it must be given the lowest priority
87
- { name: 'Unknown', pattern: /[\u0000-\uffff]/ },
88
- { name: 'BlockMarker', pattern: util_1.LexerType.NA },
89
- { name: 'ListMarker', pattern: util_1.LexerType.NA },
90
- { name: 'CompareOperator', pattern: util_1.LexerType.NA },
91
- { name: 'Selector', pattern: util_1.LexerType.NA },
92
- { name: 'Combinator', pattern: util_1.LexerType.NA },
93
- { name: 'Color', pattern: util_1.LexerType.NA },
94
- { name: 'Function', pattern: util_1.LexerType.NA },
95
- { name: 'Assign', pattern: util_1.LexerType.NA },
96
- // TODO: can use string literals for simple patterns (e.g: /\)/ vs ')')
97
- { name: 'Gt', pattern: />/, categories: ['CompareOperator', 'Combinator'] },
98
- { name: 'Lt', pattern: /</, categories: ['CompareOperator'] },
99
- { name: 'GtEq', pattern: />=/, categories: ['CompareOperator'] },
100
- { name: 'LtEq', pattern: /<=/, categories: ['CompareOperator'] },
101
- { name: 'LCurly', pattern: /{/, categories: ['BlockMarker'] },
102
- { name: 'RCurly', pattern: /}/, categories: ['BlockMarker'] },
103
- { name: 'LParen', pattern: /\(/, categories: ['BlockMarker'] },
104
- { name: 'RParen', pattern: /\)/, categories: ['BlockMarker'] },
105
- { name: 'LSquare', pattern: /\[/, categories: ['BlockMarker'] },
106
- { name: 'RSquare', pattern: /\]/, categories: ['BlockMarker'] },
107
- { name: 'SemiColon', pattern: /;/, categories: ['BlockMarker'] },
108
- { name: 'AdditionOperator', pattern: util_1.LexerType.NA },
109
- { name: 'MultiplicationOperator', pattern: util_1.LexerType.NA },
110
- { name: 'Plus', pattern: /\+/, categories: ['AdditionOperator', 'Combinator'] },
111
- { name: 'Minus', pattern: /-/, categories: ['AdditionOperator'] },
112
- { name: 'Divide', pattern: /\//, categories: ['MultiplicationOperator'] },
113
- { name: 'Comma', pattern: /,/, categories: ['BlockMarker'] },
114
- { name: 'Colon', pattern: /:/, categories: ['BlockMarker', 'Assign'] },
115
- { name: 'AttrMatchOperator', pattern: util_1.LexerType.NA },
116
- // Some tokens have to appear after AttrMatch
117
- { name: 'Eq', pattern: /=/, categories: ['CompareOperator', 'AttrMatchOperator'] },
118
- { name: 'Star', pattern: /\*/, categories: ['MultiplicationOperator'] },
119
- { name: 'Tilde', pattern: /~/, categories: ['Combinator'] },
120
- /** a namespace or column combinator */
121
- { name: 'Pipe', pattern: /\|\|?/, categories: ['Combinator'] },
122
- { name: 'AttrMatch', pattern: /[*~|^$]=/, categories: ['AttrMatchOperator'] },
123
- { name: 'Ident', pattern: util_1.LexerType.NA },
124
- { name: 'PropertyName', pattern: util_1.LexerType.NA },
125
- { name: 'PlainIdent', pattern: '{{ident}}', categories: ['Ident', 'PropertyName'] },
126
- { name: 'CustomProperty', pattern: '--{{ident}}', categories: ['BlockMarker', 'PropertyName'] },
127
- { name: 'CDOToken', pattern: /<!--/, group: util_1.LexerType.SKIPPED },
128
- { name: 'CDCToken', pattern: /-->/, group: util_1.LexerType.SKIPPED },
129
- /** Ignore BOM */
130
- { name: 'UnicodeBOM', pattern: /\uFFFE/, group: util_1.LexerType.SKIPPED },
131
- { name: 'AttrFlag', pattern: /[is]/, longer_alt: 'PlainIdent', categories: ['Ident'] },
132
- { name: 'PlainFunction', pattern: '{{ident}}\\(', categories: ['BlockMarker', 'Function'] },
133
- { name: 'And', pattern: /and/, longer_alt: 'PlainIdent', categories: ['Ident'] },
134
- { name: 'Or', pattern: /or/, longer_alt: 'PlainIdent', categories: ['Ident'] },
135
- { name: 'Not', pattern: /not/, longer_alt: 'PlainIdent', categories: ['Ident'] },
136
- { name: 'Only', pattern: /only/, longer_alt: 'PlainIdent', categories: ['Ident'] },
137
- { name: 'AtKeyword', pattern: '@{{ident}}', categories: ['BlockMarker', 'AtName'] },
138
- { name: 'Uri', pattern: util_1.LexerType.NA },
139
- {
140
- name: 'UriString',
141
- pattern: 'url\\((:?{{ws}})?({{string1}}|{{string2}})(:?{{ws}})?\\)',
142
- line_breaks: true,
143
- categories: ['Uri']
144
- },
145
- {
146
- name: 'UriUrl',
147
- pattern: 'url\\((:?{{ws}})?{{url}}(:?{{ws}})?\\)',
148
- line_breaks: true,
149
- categories: ['Uri']
150
- },
151
- {
152
- name: 'StringLiteral',
153
- pattern: '{{string1}}|{{string2}}'
154
- },
155
- {
156
- name: 'Important',
157
- pattern: '!{{ws}}?important',
158
- categories: ['BlockMarker']
159
- },
160
- {
161
- name: 'AtImport',
162
- pattern: /@import/,
163
- longer_alt: 'AtKeyword',
164
- categories: ['BlockMarker', 'AtName']
165
- },
166
- {
167
- name: 'AtMedia',
168
- pattern: /@media/,
169
- longer_alt: 'AtKeyword',
170
- categories: ['BlockMarker', 'AtName']
171
- },
172
- {
173
- name: 'AtSupports',
174
- pattern: /@supports/,
175
- longer_alt: 'AtKeyword',
176
- categories: ['BlockMarker', 'AtName']
177
- },
178
- {
179
- name: 'AtNested',
180
- pattern: /@page|@font-face|@keyframes|@viewport|@document/,
181
- longer_alt: 'AtKeyword',
182
- categories: ['BlockMarker', 'AtName']
183
- },
184
- {
185
- name: 'AtNonNested',
186
- pattern: /@charset|@namespace/,
187
- longer_alt: 'AtKeyword',
188
- categories: ['BlockMarker', 'AtName']
189
- },
190
- {
191
- name: 'UnicodeRange',
192
- pattern: /[uU]\+[0-9a-fA-F?]+(-[0-9a-fA-F?]+)?/
193
- },
194
- {
195
- name: 'DotName',
196
- pattern: '\\.{{ident}}',
197
- categories: ['Selector']
198
- },
199
- {
200
- name: 'HashName',
201
- pattern: '#{{ident}}',
202
- categories: ['Selector']
203
- },
204
- {
205
- name: 'ColorIntStart',
206
- pattern: /#(?:(?:[0-9][0-9a-f]{7})|(?:[0-9][0-9a-f]{5})|(?:[0-9][0-9a-f]{2,3}))/i,
207
- categories: ['Color']
208
- },
209
- // This is in the Selector category because a value may get lexed as a color,
210
- // but will be intended as an ID selector. ONLY valid as ID if it doesn't start with a number
211
- {
212
- name: 'ColorIdentStart',
213
- pattern: /#(?:(?:[a-f][0-9a-f]{7})|(?:[a-f][0-9a-f]{5})|(?:[a-f][0-9a-f]{2,3}))/i,
214
- longer_alt: 'HashName',
215
- categories: ['Color', 'Selector']
216
- },
217
- /**
218
- * CSS syntax says we should identify integers as separate from numbers,
219
- * probably because there are parts of the syntax where one is allowed but not the other?
220
- */
221
- { name: 'Number', pattern: util_1.LexerType.NA },
222
- { name: 'Dimension', pattern: util_1.LexerType.NA },
223
- { name: 'Integer', pattern: util_1.LexerType.NA },
224
- {
225
- name: 'DimensionNum',
226
- pattern: ['({{number}})({{ident}}|%)', groupCapture],
227
- start_chars_hint: [
228
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
229
- '-', '+'
77
+ export const rawCssTokens = () => ({
78
+ modes: {
79
+ Default: [
80
+ { name: 'Value', pattern: LexerType.NA },
81
+ { name: 'NonIdent', pattern: LexerType.NA },
82
+ { name: 'AtName', pattern: LexerType.NA },
83
+ { name: 'MfLt', pattern: LexerType.NA },
84
+ { name: 'MfGt', pattern: LexerType.NA },
85
+ // This can match anything, so it must be given the lowest priority
86
+ { name: 'Unknown', pattern: /[\u0000-\uffff]/ },
87
+ { name: 'BlockMarker', pattern: LexerType.NA },
88
+ { name: 'ListMarker', pattern: LexerType.NA },
89
+ { name: 'CompareOperator', pattern: LexerType.NA },
90
+ { name: 'Slash', pattern: LexerType.NA },
91
+ { name: 'Selector', pattern: LexerType.NA },
92
+ { name: 'Combinator', pattern: LexerType.NA },
93
+ { name: 'Color', pattern: LexerType.NA },
94
+ { name: 'FunctionStart', pattern: LexerType.NA },
95
+ { name: 'FunctionalPseudoClass', pattern: LexerType.NA },
96
+ { name: 'Assign', pattern: LexerType.NA },
97
+ { name: 'QuoteStart', pattern: LexerType.NA },
98
+ // TODO: can use string literals for simple patterns (e.g: /\)/ vs ')')
99
+ { name: 'Gt', pattern: />/, categories: ['CompareOperator', 'Combinator', 'MfGt'] },
100
+ { name: 'Lt', pattern: /</, categories: ['CompareOperator', 'MfLt'] },
101
+ { name: 'GtEq', pattern: />=/, categories: ['CompareOperator', 'MfGt'] },
102
+ { name: 'LtEq', pattern: /<=/, categories: ['CompareOperator', 'MfGt'] },
103
+ { name: 'LCurly', pattern: /{/, categories: ['BlockMarker'] },
104
+ { name: 'RCurly', pattern: /}/, categories: ['BlockMarker'] },
105
+ { name: 'LParen', pattern: /\(/, categories: ['BlockMarker'] },
106
+ { name: 'RParen', pattern: /\)/, categories: ['BlockMarker'] },
107
+ { name: 'LSquare', pattern: /\[/, categories: ['BlockMarker'] },
108
+ { name: 'RSquare', pattern: /\]/, categories: ['BlockMarker'] },
109
+ { name: 'Semi', pattern: /;/, categories: ['BlockMarker'] },
110
+ { name: 'AdditionOperator', pattern: LexerType.NA },
111
+ { name: 'MultiplicationOperator', pattern: LexerType.NA },
112
+ { name: 'Plus', pattern: /\+/, categories: ['AdditionOperator', 'Combinator'] },
113
+ { name: 'Minus', pattern: /-/, categories: ['AdditionOperator'] },
114
+ { name: 'Divide', pattern: /\//, categories: ['MultiplicationOperator', 'Slash'] },
115
+ { name: 'Comma', pattern: /,/, categories: ['BlockMarker'] },
116
+ { name: 'Colon', pattern: /:/, categories: ['BlockMarker', 'Assign'] },
117
+ { name: 'AttrMatchOperator', pattern: LexerType.NA },
118
+ // Some tokens have to appear after AttrMatch
119
+ { name: 'Eq', pattern: /=/, categories: ['CompareOperator', 'AttrMatchOperator'] },
120
+ { name: 'Star', pattern: /\*/, categories: ['MultiplicationOperator'] },
121
+ { name: 'Tilde', pattern: /~/, categories: ['Combinator'] },
122
+ /** a namespace or column combinator */
123
+ { name: 'Pipe', pattern: /\|/, categories: ['Combinator'] },
124
+ { name: 'Column', pattern: /\|\|/, categories: ['Combinator'] },
125
+ { name: 'AttrMatch', pattern: /[*~|^$]=/, categories: ['AttrMatchOperator'] },
126
+ { name: 'Ident', pattern: LexerType.NA },
127
+ {
128
+ name: 'PlainIdent',
129
+ pattern: '{{ident}}',
130
+ categories: ['Ident']
131
+ },
132
+ { name: 'LegacyPropIdent', pattern: '(?:\\*|_){{ident}}' },
133
+ {
134
+ name: 'CustomProperty',
135
+ pattern: '--{{ident}}',
136
+ categories: ['BlockMarker']
137
+ },
138
+ { name: 'CDOToken', pattern: /<!--/, group: LexerType.SKIPPED },
139
+ { name: 'CDCToken', pattern: /-->/, group: LexerType.SKIPPED },
140
+ /** Ignore BOM */
141
+ { name: 'UnicodeBOM', pattern: /\uFFFE/, group: LexerType.SKIPPED },
142
+ { name: 'AttrFlag', pattern: /[is]/i, longer_alt: 'PlainIdent', categories: ['Ident'] },
143
+ /**
144
+ * Needs to appear after keywords like `even` which starts with `e`
145
+ * (Reminder that tokens are in reverse order in this file.)
146
+ */
147
+ {
148
+ name: 'MathConstant',
149
+ pattern: /pi|e|-?infinity|nan/i,
150
+ longer_alt: 'PlainIdent',
151
+ categories: ['Ident']
152
+ },
153
+ /** Logical Keywords */
154
+ { name: 'Only', pattern: /only/, longer_alt: 'PlainIdent', categories: ['Ident'] },
155
+ /** Query words */
156
+ { name: 'Screen', pattern: /screen/, longer_alt: 'PlainIdent', categories: ['Ident'] },
157
+ { name: 'Print', pattern: /print/, longer_alt: 'PlainIdent', categories: ['Ident'] },
158
+ { name: 'All', pattern: /all/, longer_alt: 'PlainIdent', categories: ['Ident'] },
159
+ // Match a generic function start: identifier followed immediately by '('
160
+ {
161
+ name: 'GenericFunctionStart',
162
+ pattern: '{{ident}}\\(',
163
+ categories: ['BlockMarker', 'FunctionStart']
164
+ },
165
+ /**
166
+ * Move these under GenericFunctionStart so that they are not parsed as `and(`
167
+ * in Less / Jess.
168
+ */
169
+ { name: 'And', pattern: /and/, longer_alt: 'PlainIdent', categories: ['Ident'] },
170
+ { name: 'Or', pattern: /or/, longer_alt: 'PlainIdent', categories: ['Ident'] },
171
+ /**
172
+ * Special function names in CSS
173
+ */
174
+ { name: 'Layer', pattern: /layer\(/i, categories: ['BlockMarker', 'FunctionStart'] },
175
+ { name: 'Supports', pattern: /supports\(/i, categories: ['BlockMarker', 'FunctionStart'] },
176
+ { name: 'Var', pattern: /var\(/i, categories: ['BlockMarker', 'FunctionStart'] },
177
+ { name: 'Calc', pattern: /calc\(/i, categories: ['BlockMarker', 'FunctionStart'] },
178
+ /** Keyframe keywords */
179
+ { name: 'From', pattern: /from/, longer_alt: 'PlainIdent', categories: ['Ident'] },
180
+ { name: 'To', pattern: /to/, longer_alt: 'PlainIdent', categories: ['Ident'] },
181
+ { name: 'AtKeyword', pattern: '@{{ident}}', categories: ['BlockMarker', 'AtName'] },
182
+ {
183
+ name: 'UrlStart',
184
+ pattern: /url\(/i,
185
+ push_mode: 'Url',
186
+ categories: ['BlockMarker', 'FunctionStart']
187
+ },
188
+ /** Supports the very old alpha(opacity=[number]) */
189
+ {
190
+ name: 'LegacyMSFilter',
191
+ pattern: /alpha\(opacity=\d{1,3}\)|progid:(?:[\w]+\.)*\w+(?:\([^)]*\))?/,
192
+ categories: ['BlockMarker']
193
+ },
194
+ /**
195
+ * Rather than consume the whole string, we push
196
+ * a string mode. This makes string parsing
197
+ * extensible to languages with embedded expressions.
198
+ */
199
+ {
200
+ name: 'SingleQuoteStart',
201
+ pattern: /'/,
202
+ push_mode: 'SingleQuoteString',
203
+ categories: ['BlockMarker', 'QuoteStart']
204
+ },
205
+ {
206
+ name: 'DoubleQuoteStart',
207
+ pattern: /"/,
208
+ push_mode: 'DoubleQuoteString',
209
+ categories: ['BlockMarker', 'QuoteStart']
210
+ },
211
+ {
212
+ name: 'Important',
213
+ pattern: '!(?:{{ws}}|{{comment}})*important',
214
+ categories: ['BlockMarker']
215
+ },
216
+ {
217
+ name: 'AtImport',
218
+ pattern: /@import/i,
219
+ longer_alt: 'AtKeyword',
220
+ categories: ['BlockMarker', 'AtName']
221
+ },
222
+ {
223
+ name: 'AtMedia',
224
+ pattern: /@media/i,
225
+ longer_alt: 'AtKeyword',
226
+ categories: ['BlockMarker', 'AtName']
227
+ },
228
+ {
229
+ name: 'AtSupports',
230
+ pattern: /@supports/i,
231
+ longer_alt: 'AtKeyword',
232
+ categories: ['BlockMarker', 'AtName']
233
+ },
234
+ {
235
+ name: 'AtLayer',
236
+ pattern: /@layer/i,
237
+ longer_alt: 'AtKeyword',
238
+ categories: ['BlockMarker', 'AtName']
239
+ },
240
+ {
241
+ name: 'AtContainer',
242
+ pattern: /@container/i,
243
+ longer_alt: 'AtKeyword',
244
+ categories: ['BlockMarker', 'AtName']
245
+ },
246
+ {
247
+ name: 'AtScope',
248
+ pattern: /@scope/i,
249
+ longer_alt: 'AtKeyword',
250
+ categories: ['BlockMarker', 'AtName']
251
+ },
252
+ {
253
+ name: 'AtDocument',
254
+ pattern: /@(?:-moz-)?document/i,
255
+ longer_alt: 'AtKeyword',
256
+ categories: ['BlockMarker', 'AtName']
257
+ },
258
+ {
259
+ name: 'AtPage',
260
+ pattern: /@page/i,
261
+ longer_alt: 'AtKeyword',
262
+ categories: ['BlockMarker', 'AtName']
263
+ },
264
+ {
265
+ name: 'AtFontFace',
266
+ pattern: /@font-face/i,
267
+ categories: ['BlockMarker', 'AtName']
268
+ },
269
+ // Keyframes (standard and vendor-prefixed)
270
+ { name: 'AtKeyframes', pattern: /@(?:-[a-z]+-)?keyframes/i, longer_alt: 'AtKeyword', categories: ['BlockMarker', 'AtName'] },
271
+ {
272
+ name: 'AtNested',
273
+ pattern: /@starting-style|@property|@counter-style|@viewport|@-ms-viewport|@color-profile|@font-palette-values/i,
274
+ longer_alt: 'AtKeyword',
275
+ categories: ['BlockMarker', 'AtName']
276
+ },
277
+ {
278
+ name: 'AtNonNested',
279
+ pattern: /@namespace/i,
280
+ longer_alt: 'AtKeyword',
281
+ categories: ['BlockMarker', 'AtName']
282
+ },
283
+ /** Not a rule, but a special token */
284
+ {
285
+ name: 'Charset',
286
+ pattern: '@charset{{ws}}?(?:{{string1}}|{{string2}});'
287
+ },
288
+ {
289
+ name: 'UnicodeRange',
290
+ pattern: /[uU]\+[0-9a-fA-F?]+(-[0-9a-fA-F?]+)?/
291
+ },
292
+ /** Selectors */
293
+ {
294
+ name: 'Ampersand',
295
+ pattern: /&/,
296
+ categories: ['Selector']
297
+ },
298
+ {
299
+ name: 'DotName',
300
+ pattern: '\\.{{ident}}',
301
+ categories: ['Selector']
302
+ },
303
+ /** There are some cases where we might need this tokenized separately? */
304
+ // {
305
+ // name: 'Dot',
306
+ // pattern: /\./,
307
+ // categories: ['BlockMarker']
308
+ // },
309
+ {
310
+ name: 'HashName',
311
+ pattern: '#{{ident}}',
312
+ categories: ['Selector']
313
+ },
314
+ {
315
+ name: 'NthPseudoClass',
316
+ pattern: /:(?:nth-child|nth-last-child|nth-of-type|nth-last-of-type)\(/i,
317
+ categories: ['BlockMarker', 'FunctionalPseudoClass']
318
+ },
319
+ {
320
+ name: 'SelectorPseudoClass',
321
+ pattern: /:(?:is|not|where|has)\(/i,
322
+ categories: ['BlockMarker', 'FunctionalPseudoClass']
323
+ },
324
+ /** @see https://developer.mozilla.org/en-US/docs/Web/CSS/@page */
325
+ {
326
+ name: 'PagePseudoClassKeywords',
327
+ pattern: /(?:first|left|right|blank)/i,
328
+ categories: ['Ident'],
329
+ longer_alt: 'PlainIdent'
330
+ },
331
+ /** Nth Keywords */
332
+ { name: 'NthOdd', pattern: /odd/, longer_alt: 'PlainIdent', categories: ['Ident'] },
333
+ { name: 'NthEven', pattern: /even/, longer_alt: 'PlainIdent', categories: ['Ident'] },
334
+ { name: 'Of', pattern: /of/, longer_alt: 'PlainIdent', categories: ['Ident'] },
335
+ {
336
+ name: 'ColorIntStart',
337
+ pattern: /#(?:(?:[0-9][0-9a-f]{7})|(?:[0-9][0-9a-f]{5})|(?:[0-9][0-9a-f]{2,3}))/i,
338
+ categories: ['Color']
339
+ },
340
+ // This is in the Selector category because a value may get lexed as a color,
341
+ // but will be intended as an ID selector. ONLY valid as ID if it doesn't start with a number
342
+ {
343
+ name: 'ColorIdentStart',
344
+ pattern: /#(?:(?:[a-f][0-9a-f]{7})|(?:[a-f][0-9a-f]{5})|(?:[a-f][0-9a-f]{2,3}))/i,
345
+ longer_alt: 'HashName',
346
+ categories: ['Color', 'Selector']
347
+ },
348
+ /**
349
+ * CSS syntax says we should identify integers as separate from numbers,
350
+ * probably because there are parts of the syntax where one is allowed but not the other?
351
+ */
352
+ { name: 'Number', pattern: LexerType.NA },
353
+ { name: 'Dimension', pattern: LexerType.NA },
354
+ { name: 'Integer', pattern: LexerType.NA },
355
+ { name: 'Signed', pattern: LexerType.NA },
356
+ {
357
+ name: 'DimensionNum',
358
+ pattern: ['({{number}})({{unit}}|%)', groupCapture],
359
+ start_chars_hint: [
360
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.'
361
+ ],
362
+ line_breaks: false,
363
+ categories: ['Dimension', 'Selector']
364
+ },
365
+ {
366
+ name: 'DimensionInt',
367
+ pattern: ['({{integer}})({{unit}}|%)', groupCapture],
368
+ start_chars_hint: [
369
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
370
+ ],
371
+ line_breaks: false,
372
+ categories: ['Dimension', 'Integer', 'Selector']
373
+ },
374
+ {
375
+ name: 'SignedDimensionNum',
376
+ pattern: ['([+-]{{number}})({{unit}}|%)', groupCapture],
377
+ start_chars_hint: ['-', '+'],
378
+ line_breaks: false,
379
+ categories: ['Dimension', 'Signed']
380
+ },
381
+ {
382
+ name: 'SignedDimensionInt',
383
+ pattern: ['([+-]{{integer}})({{unit}}|%)', groupCapture],
384
+ start_chars_hint: ['-', '+'],
385
+ line_breaks: false,
386
+ categories: ['Dimension', 'Integer', 'Signed']
387
+ },
388
+ {
389
+ name: 'SignedInt',
390
+ pattern: /[+-]\d+/,
391
+ longer_alt: 'SignedDimensionInt',
392
+ categories: ['Integer', 'Number', 'Signed']
393
+ },
394
+ {
395
+ name: 'UnsignedInt',
396
+ pattern: /\d+/,
397
+ longer_alt: 'DimensionInt',
398
+ categories: ['Integer', 'Number']
399
+ },
400
+ {
401
+ name: 'SignedNum',
402
+ pattern: '[+-]{{number}}',
403
+ longer_alt: 'SignedDimensionNum',
404
+ categories: ['Integer', 'Number', 'Signed']
405
+ },
406
+ {
407
+ name: 'UnsignedNum',
408
+ pattern: '{{number}}',
409
+ longer_alt: 'DimensionNum',
410
+ categories: ['Number']
411
+ },
412
+ /**
413
+ * This has to be parsed carefully because the plus / minus can
414
+ * continue into different token types.
415
+ */
416
+ {
417
+ name: 'NthSignedDimension',
418
+ pattern: /[+-]\dn/,
419
+ longer_alt: 'SignedDimensionInt',
420
+ line_breaks: false,
421
+ categories: ['Dimension', 'Signed']
422
+ },
423
+ {
424
+ name: 'NthUnsignedDimension',
425
+ pattern: /\dn/,
426
+ longer_alt: 'DimensionNum',
427
+ line_breaks: false,
428
+ categories: ['Dimension']
429
+ },
430
+ {
431
+ name: 'NthSignedPlus',
432
+ pattern: /[+]n/,
433
+ line_breaks: false
434
+ },
435
+ {
436
+ name: 'NthIdent',
437
+ // Only match bare `n`/`-n` forms used by :nth-* grammar.
438
+ // Without this guard, identifiers like `negation` are tokenized as PlainIdent
439
+ // via longer_alt, preventing GenericFunctionStart tokenization.
440
+ pattern: '-?n(?!{{nmchar}})',
441
+ longer_alt: 'PlainIdent',
442
+ line_breaks: false,
443
+ categories: ['Ident']
444
+ },
445
+ /** Moved under 'n' parsing */
446
+ { name: 'Not', pattern: /not/, longer_alt: 'PlainIdent', categories: ['Ident'] },
447
+ {
448
+ name: 'WS',
449
+ pattern: '{{ws}}',
450
+ line_breaks: true,
451
+ label: SKIPPED_LABEL
452
+ },
453
+ {
454
+ name: 'Comment',
455
+ pattern: '{{comment}}',
456
+ line_breaks: true,
457
+ label: SKIPPED_LABEL
458
+ }
230
459
  ],
231
- line_breaks: false,
232
- categories: ['Dimension']
233
- },
234
- {
235
- name: 'DimensionInt',
236
- pattern: ['({{integer}})({{ident}}|%)', groupCapture],
237
- start_chars_hint: [
238
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
239
- '-', '+'
460
+ SingleQuoteString: [
461
+ /**
462
+ * Note that:
463
+ * - "\u0022" === `"`
464
+ * - "\u0027" === `'`
465
+ * - "\u005C" === `\`
466
+ */
467
+ {
468
+ name: 'SingleQuoteStringContents',
469
+ pattern: '(?:[\\u0000-\\u0026\\u0028-\\u005B\\u005D-\\uFFFF]|\\\\\'|\\\\{{newline}}|{{newline}}|{{escape}})+'
470
+ },
471
+ {
472
+ name: 'SingleQuoteEnd',
473
+ pattern: /'/,
474
+ pop_mode: true
475
+ }
240
476
  ],
241
- line_breaks: false,
242
- categories: ['Dimension', 'Integer']
243
- },
244
- {
245
- name: 'SignedInt',
246
- pattern: /[+-]\d+/,
247
- longer_alt: 'DimensionInt',
248
- categories: ['Integer', 'Number']
249
- },
250
- {
251
- name: 'UnsignedInt',
252
- pattern: /\d+/,
253
- longer_alt: 'DimensionInt',
254
- categories: ['Integer', 'Number']
255
- },
256
- {
257
- name: 'UnitlessNum',
258
- pattern: '{{number}}',
259
- longer_alt: 'DimensionNum',
260
- categories: ['Number']
477
+ DoubleQuoteString: [
478
+ {
479
+ name: 'DoubleQuoteStringContents',
480
+ pattern: '(?:[\\u0000-\\u0021\\u0023-\\u005B\\u005D-\\uFFFF]|\\\\"|\\\\{{newline}}|{{newline}}|{{escape}})+'
481
+ },
482
+ {
483
+ name: 'DoubleQuoteEnd',
484
+ pattern: /"/,
485
+ pop_mode: true
486
+ }
487
+ ],
488
+ Url: [
489
+ /** Reference: https://www.w3.org/TR/css-syntax-3/#consume-url-token */
490
+ {
491
+ name: 'NonQuotedUrl',
492
+ /**
493
+ * Equivalent to: /[^)(\'"]+/ but a-lot less clear :(
494
+ * @see https://chevrotain.io/docs/guide/resolving_lexer_errors.html#COMPLEMENT
495
+ *
496
+ * Note that:
497
+ * - "\u0022" === `"`
498
+ * - "\u0027" === `'`
499
+ * - "\u0028" === `(`
500
+ * - "\u0029" === `)`
501
+ * - "\u005C" === `\`
502
+ */
503
+ pattern: '(?:[\\u0000-\\u0021\\u0023-\\u0026\\u002A-\\u005B\\u005D-\\uFFFF]|{{escape}})+'
504
+ },
505
+ /**
506
+ * We need to be careful to think about this token from the URL mode
507
+ * when we're gating the RParen token for any reason. This is a separate token.
508
+ */
509
+ {
510
+ name: 'UrlEnd',
511
+ pattern: /\)/,
512
+ pop_mode: true
513
+ },
514
+ 'SingleQuoteStart',
515
+ 'DoubleQuoteStart',
516
+ 'WS'
517
+ ]
261
518
  },
262
- {
263
- name: 'WS',
264
- pattern: ['{{wsorcomment}}', groupCapture],
265
- start_chars_hint: [' ', '\t', '\n', '\r', '\f', '/'],
266
- line_breaks: true,
267
- categories: ['BlockMarker']
268
- }
269
- ];
519
+ defaultMode: 'Default'
520
+ });
521
+ let fragments = rawCssFragments();
522
+ let tokens = rawCssTokens();
523
+ export const cssFragments = buildFragments(fragments);
524
+ export const cssLexer = createLexerDefinition(fragments, tokens);
525
+ //# sourceMappingURL=cssTokens.js.map