@tbela99/css-parser 1.2.0 → 1.3.1

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 (70) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +29 -11
  3. package/dist/index-umd-web.js +2041 -1967
  4. package/dist/index.cjs +2129 -1964
  5. package/dist/index.d.ts +1936 -77
  6. package/dist/lib/ast/expand.js +4 -65
  7. package/dist/lib/ast/features/calc.js +3 -27
  8. package/dist/lib/ast/features/inlinecssvariables.js +2 -21
  9. package/dist/lib/ast/features/prefix.js +2 -1
  10. package/dist/lib/ast/features/transform.js +4 -3
  11. package/dist/lib/ast/features/type.js +9 -0
  12. package/dist/lib/ast/math/expression.js +26 -149
  13. package/dist/lib/ast/math/math.js +9 -9
  14. package/dist/lib/ast/minify.js +82 -171
  15. package/dist/lib/ast/transform/compute.js +4 -37
  16. package/dist/lib/ast/transform/matrix.js +33 -34
  17. package/dist/lib/ast/transform/minify.js +32 -51
  18. package/dist/lib/ast/transform/perspective.js +1 -1
  19. package/dist/lib/ast/transform/rotate.js +13 -13
  20. package/dist/lib/ast/transform/scale.js +8 -8
  21. package/dist/lib/ast/transform/skew.js +4 -4
  22. package/dist/lib/ast/transform/translate.js +8 -8
  23. package/dist/lib/ast/transform/utils.js +31 -39
  24. package/dist/lib/ast/types.js +459 -5
  25. package/dist/lib/ast/walk.js +18 -0
  26. package/dist/lib/fs/resolve.js +11 -3
  27. package/dist/lib/parser/declaration/map.js +1 -0
  28. package/dist/lib/parser/declaration/set.js +2 -2
  29. package/dist/lib/parser/parse.js +139 -32
  30. package/dist/lib/parser/tokenize.js +41 -93
  31. package/dist/lib/parser/utils/type.js +1 -1
  32. package/dist/lib/renderer/render.js +61 -30
  33. package/dist/lib/renderer/sourcemap/sourcemap.js +34 -0
  34. package/dist/lib/syntax/color/cmyk.js +2 -2
  35. package/dist/lib/syntax/color/color-mix.js +11 -12
  36. package/dist/lib/syntax/color/color.js +14 -7
  37. package/dist/lib/syntax/color/hsl.js +4 -4
  38. package/dist/lib/syntax/color/hwb.js +27 -8
  39. package/dist/lib/syntax/color/lab.js +4 -4
  40. package/dist/lib/syntax/color/lch.js +4 -4
  41. package/dist/lib/syntax/color/oklab.js +4 -4
  42. package/dist/lib/syntax/color/oklch.js +4 -4
  43. package/dist/lib/syntax/color/relativecolor.js +1 -1
  44. package/dist/lib/syntax/color/rgb.js +4 -4
  45. package/dist/lib/syntax/color/utils/components.js +15 -3
  46. package/dist/lib/syntax/color/utils/distance.js +15 -1
  47. package/dist/lib/syntax/syntax.js +18 -17
  48. package/dist/lib/syntax/utils.js +1 -1
  49. package/dist/lib/validation/at-rules/document.js +1 -1
  50. package/dist/lib/validation/at-rules/import.js +4 -4
  51. package/dist/lib/validation/at-rules/keyframes.js +0 -11
  52. package/dist/lib/validation/at-rules/supports.js +6 -6
  53. package/dist/lib/validation/config.js +0 -4
  54. package/dist/lib/validation/config.json.js +33 -30
  55. package/dist/lib/validation/parser/parse.js +0 -8
  56. package/dist/lib/validation/selector.js +0 -9
  57. package/dist/lib/validation/syntax.js +17 -135
  58. package/dist/lib/validation/syntaxes/complex-selector-list.js +0 -11
  59. package/dist/lib/validation/syntaxes/family-name.js +0 -32
  60. package/dist/lib/validation/syntaxes/keyframe-selector.js +0 -11
  61. package/dist/lib/validation/syntaxes/relative-selector-list.js +0 -26
  62. package/dist/lib/validation/syntaxes/url.js +0 -33
  63. package/dist/lib/validation/utils/list.js +0 -8
  64. package/dist/node.js +229 -0
  65. package/dist/web.js +158 -0
  66. package/package.json +14 -11
  67. package/dist/node/index.js +0 -57
  68. package/dist/node/load.js +0 -20
  69. package/dist/web/index.js +0 -66
  70. package/dist/web/load.js +0 -31
@@ -7,6 +7,7 @@ import '../../ast/walk.js';
7
7
  import { parseString } from '../parse.js';
8
8
  import '../tokenize.js';
9
9
  import { renderToken } from '../../renderer/render.js';
10
+ import '../../renderer/sourcemap/lib/encode.js';
10
11
  import '../../syntax/color/utils/constants.js';
11
12
  import { PropertySet } from './set.js';
12
13
 
@@ -15,7 +15,7 @@ function dedup(values) {
15
15
  while (i-- > 1) {
16
16
  const t = value[i];
17
17
  const k = value[i == 1 ? 0 : i % 2];
18
- if (t.val == k.val && t.val == '0') {
18
+ if (t.val == k.val && t.val == 0) {
19
19
  if ((t.typ == EnumToken.NumberTokenType && isLength(k)) ||
20
20
  (k.typ == EnumToken.NumberTokenType && isLength(t)) ||
21
21
  (isLength(k) || isLength(t))) {
@@ -52,7 +52,7 @@ class PropertySet {
52
52
  // @ts-ignore
53
53
  for (let token of this.declarations.get(this.config.shorthand).val) {
54
54
  // @ts-ignore
55
- if (this.config.types.some(t => token.typ == EnumToken[t]) || (token.typ == EnumToken.NumberTokenType && token.val == '0' &&
55
+ if (this.config.types.some(t => token.typ == EnumToken[t]) || (token.typ == EnumToken.NumberTokenType && token.val == 0 &&
56
56
  (this.config.types.includes('Length') ||
57
57
  this.config.types.includes('Angle') ||
58
58
  this.config.types.includes('Dimension')))) {
@@ -6,9 +6,10 @@ import { expand } from '../ast/expand.js';
6
6
  import './utils/config.js';
7
7
  import { parseDeclarationNode } from './utils/declaration.js';
8
8
  import { renderToken } from '../renderer/render.js';
9
+ import '../renderer/sourcemap/lib/encode.js';
9
10
  import { funcLike, timingFunc, timelineFunc, COLORS_NAMES, systemColors, deprecatedSystemColors, colorsFunc } from '../syntax/color/utils/constants.js';
10
11
  import { buildExpression } from '../ast/math/expression.js';
11
- import { tokenize } from './tokenize.js';
12
+ import { tokenize, tokenizeStream } from './tokenize.js';
12
13
  import '../validation/config.js';
13
14
  import '../validation/parser/types.js';
14
15
  import '../validation/parser/parse.js';
@@ -40,10 +41,12 @@ function reject(reason) {
40
41
  }
41
42
  /**
42
43
  * parse css string
43
- * @param iterator
44
+ * @param iter
44
45
  * @param options
46
+ *
47
+ * @private
45
48
  */
46
- async function doParse(iterator, options = {}) {
49
+ async function doParse(iter, options = {}) {
47
50
  if (options.signal != null) {
48
51
  options.signal.addEventListener('abort', reject);
49
52
  }
@@ -113,15 +116,28 @@ async function doParse(iterator, options = {}) {
113
116
  src: ''
114
117
  };
115
118
  }
116
- const iter = tokenize(iterator);
117
119
  let item;
118
120
  let node;
119
121
  const rawTokens = [];
120
122
  const imports = [];
121
- while (item = iter.next().value) {
123
+ // @ts-ignore ignore error
124
+ const isAsync = typeof iter[Symbol.asyncIterator] === 'function';
125
+ while (item = isAsync ? (await iter.next()).value : iter.next().value) {
122
126
  stats.bytesIn = item.bytesIn;
123
127
  rawTokens.push(item);
124
128
  if (item.hint != null && BadTokensTypes.includes(item.hint)) {
129
+ const node = getTokenType(item.token, item.hint);
130
+ errors.push({
131
+ action: 'drop',
132
+ message: 'Bad token',
133
+ syntax: null,
134
+ node,
135
+ location: {
136
+ src,
137
+ sta: item.sta,
138
+ end: item.end
139
+ }
140
+ });
125
141
  // bad token
126
142
  continue;
127
143
  }
@@ -150,7 +166,7 @@ async function doParse(iterator, options = {}) {
150
166
  let inBlock = 1;
151
167
  tokens = [item];
152
168
  do {
153
- item = iter.next().value;
169
+ item = isAsync ? (await iter.next()).value : iter.next().value;
154
170
  if (item == null) {
155
171
  break;
156
172
  }
@@ -166,7 +182,12 @@ async function doParse(iterator, options = {}) {
166
182
  errors.push({
167
183
  action: 'drop',
168
184
  message: 'invalid block',
169
- rawTokens: tokens.slice()
185
+ rawTokens: tokens.slice(),
186
+ location: {
187
+ src,
188
+ sta: tokens[0].sta,
189
+ end: tokens[tokens.length - 1].end
190
+ }
170
191
  });
171
192
  }
172
193
  }
@@ -207,8 +228,8 @@ async function doParse(iterator, options = {}) {
207
228
  }
208
229
  }
209
230
  if (context != null && context.typ == EnumToken.InvalidRuleTokenType) {
210
- // @ts-ignore
211
- const index = context.chi.findIndex((node) => node == context);
231
+ // @ts-ignore ignore error
232
+ const index = context.chi.findIndex((node) => node === context);
212
233
  if (index > -1) {
213
234
  context.chi.splice(index, 1);
214
235
  }
@@ -219,13 +240,21 @@ async function doParse(iterator, options = {}) {
219
240
  const token = node.tokens[0];
220
241
  const url = token.typ == EnumToken.StringTokenType ? token.val.slice(1, -1) : token.val;
221
242
  try {
222
- const root = await options.load(url, options.src).then((src) => {
223
- return doParse(src, Object.assign({}, options, {
243
+ const root = await options.getStream(url, options.src).then(async (stream) => {
244
+ return doParse(tokenizeStream(stream), Object.assign({}, options, {
224
245
  minify: false,
225
246
  setParent: false,
226
247
  src: options.resolve(url, options.src).absolute
227
- }));
248
+ })); // )
228
249
  });
250
+ // const root: ParseResult = await options.load!(url, <string>options.src).then((src: string) => {
251
+ //
252
+ // return doParse(src, Object.assign({}, options, {
253
+ // minify: false,
254
+ // setParent: false,
255
+ // src: options.resolve!(url, options.src as string).absolute
256
+ // }))
257
+ // });
229
258
  stats.importedBytesIn += root.stats.bytesIn;
230
259
  stats.imports.push(root.stats);
231
260
  node.parent.chi.splice(node.parent.chi.indexOf(node), 1, ...root.ast.chi);
@@ -234,7 +263,7 @@ async function doParse(iterator, options = {}) {
234
263
  }
235
264
  }
236
265
  catch (error) {
237
- // @ts-ignore
266
+ // @ts-ignore ignore error
238
267
  errors.push({ action: 'ignore', message: 'doParse: ' + error.message, error });
239
268
  }
240
269
  }));
@@ -258,28 +287,33 @@ async function doParse(iterator, options = {}) {
258
287
  if (result.node.typ == EnumToken.DeclarationNodeType &&
259
288
  (typeof options.visitor.Declaration == 'function' || options.visitor.Declaration?.[result.node.nam] != null)) {
260
289
  const callable = typeof options.visitor.Declaration == 'function' ? options.visitor.Declaration : options.visitor.Declaration[result.node.nam];
261
- const results = await callable(result.node);
290
+ const isAsync = Object.getPrototypeOf(callable).constructor.name == 'AsyncFunction';
291
+ const results = isAsync ? await callable(result.node) : callable(result.node);
262
292
  if (results == null || (Array.isArray(results) && results.length == 0)) {
263
293
  continue;
264
294
  }
295
+ // @ts-ignore
265
296
  result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
266
297
  }
267
298
  else if (options.visitor.Rule != null && result.node.typ == EnumToken.RuleNodeType) {
268
- const results = await options.visitor.Rule(result.node);
299
+ const isAsync = Object.getPrototypeOf(options.visitor.Rule).constructor.name == 'AsyncFunction';
300
+ const results = isAsync ? await options.visitor.Rule(result.node) : options.visitor.Rule(result.node);
269
301
  if (results == null || (Array.isArray(results) && results.length == 0)) {
270
302
  continue;
271
303
  }
304
+ // @ts-ignore
272
305
  result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
273
306
  }
274
307
  else if (options.visitor.AtRule != null &&
275
308
  result.node.typ == EnumToken.AtRuleNodeType &&
276
- // @ts-ignore
277
309
  (typeof options.visitor.AtRule == 'function' || options.visitor.AtRule?.[result.node.nam] != null)) {
278
310
  const callable = typeof options.visitor.AtRule == 'function' ? options.visitor.AtRule : options.visitor.AtRule[result.node.nam];
279
- const results = await callable(result.node);
311
+ const isAsync = Object.getPrototypeOf(callable).constructor.name == 'AsyncFunction';
312
+ const results = isAsync ? await callable(result.node) : callable(result.node);
280
313
  if (results == null || (Array.isArray(results) && results.length == 0)) {
281
314
  continue;
282
315
  }
316
+ // @ts-ignore
283
317
  result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
284
318
  }
285
319
  }
@@ -334,6 +368,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
334
368
  errors.push({
335
369
  action: 'drop',
336
370
  message: `CDOCOMM not allowed here ${JSON.stringify(tokens[i], null, 1)}`,
371
+ node: tokens[i],
337
372
  location
338
373
  });
339
374
  continue;
@@ -388,7 +423,14 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
388
423
  if (!(type == EnumToken.InvalidAtRuleTokenType &&
389
424
  // @ts-ignore
390
425
  ['charset', 'layer', 'import'].includes(context.chi[i].nam))) {
391
- errors.push({ action: 'drop', message: 'invalid @import', location });
426
+ // @ts-ignore
427
+ errors.push({
428
+ action: 'drop',
429
+ message: 'invalid @import',
430
+ location,
431
+ // @ts-ignore
432
+ rawTokens: [atRule, ...tokens]
433
+ });
392
434
  return null;
393
435
  }
394
436
  }
@@ -464,7 +506,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
464
506
  action: 'drop',
465
507
  message: '@charset must have only one space',
466
508
  // @ts-ignore
467
- location
509
+ location, rawTokens: [atRule, ...tokens]
468
510
  });
469
511
  return null;
470
512
  }
@@ -533,6 +575,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
533
575
  errors.push({
534
576
  action: 'drop',
535
577
  message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
578
+ node,
536
579
  // @ts-ignore
537
580
  location: { src, ...(map.get(valid.node) ?? location) }
538
581
  });
@@ -581,7 +624,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
581
624
  if (curr.typ == EnumToken.IdenTokenType && curr.val == 'from') {
582
625
  Object.assign(curr, { typ: EnumToken.PercentageTokenType, val: '0' });
583
626
  }
584
- else if (curr.typ == EnumToken.PercentageTokenType && curr.val == '100') {
627
+ else if (curr.typ == EnumToken.PercentageTokenType && curr.val == 100) {
585
628
  Object.assign(curr, { typ: EnumToken.IdenTokenType, val: 'to' });
586
629
  }
587
630
  }
@@ -634,6 +677,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
634
677
  errors.push({
635
678
  action: 'drop',
636
679
  message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
680
+ node,
637
681
  // @ts-ignore
638
682
  location
639
683
  });
@@ -658,7 +702,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
658
702
  val: tokens[i].val.charAt(0)
659
703
  }, {
660
704
  typ: EnumToken.NumberTokenType,
661
- val: tokens[i].val.slice(1)
705
+ val: +tokens[i].val.slice(1)
662
706
  });
663
707
  }
664
708
  else if (start == '/' && isFunction(val)) {
@@ -859,9 +903,10 @@ function parseAtRulePrelude(tokens, atRule) {
859
903
  }
860
904
  }
861
905
  }
906
+ const val = value.typ == EnumToken.IdenTokenType ? value.val.toLowerCase() : null;
862
907
  if (value.typ == EnumToken.IdenTokenType) {
863
908
  if (parent == null && mediaTypes.some((t) => {
864
- if (value.val.localeCompare(t, 'en', { sensitivity: 'base' }) == 0) {
909
+ if (val === t) {
865
910
  // @ts-ignore
866
911
  value.typ = EnumToken.MediaFeatureTokenType;
867
912
  return true;
@@ -870,18 +915,18 @@ function parseAtRulePrelude(tokens, atRule) {
870
915
  })) {
871
916
  continue;
872
917
  }
873
- if (value.typ == EnumToken.IdenTokenType && 'and'.localeCompare(value.val, 'en', { sensitivity: 'base' }) == 0) {
918
+ if (value.typ == EnumToken.IdenTokenType && 'and' === val) {
874
919
  // @ts-ignore
875
920
  value.typ = EnumToken.MediaFeatureAndTokenType;
876
921
  continue;
877
922
  }
878
- if (value.typ == EnumToken.IdenTokenType && 'or'.localeCompare(value.val, 'en', { sensitivity: 'base' }) == 0) {
923
+ if (value.typ == EnumToken.IdenTokenType && 'or' === val) {
879
924
  // @ts-ignore
880
925
  value.typ = EnumToken.MediaFeatureOrTokenType;
881
926
  continue;
882
927
  }
883
928
  if (value.typ == EnumToken.IdenTokenType &&
884
- ['not', 'only'].some((t) => t.localeCompare(value.val, 'en', { sensitivity: 'base' }) == 0)) {
929
+ ['not', 'only'].some((t) => val === t)) {
885
930
  // @ts-ignore
886
931
  const array = parent?.chi ?? tokens;
887
932
  const startIndex = array.indexOf(value);
@@ -982,6 +1027,27 @@ function parseAtRulePrelude(tokens, atRule) {
982
1027
  }
983
1028
  return tokens;
984
1029
  }
1030
+ /**
1031
+ * parse a string as an array of declaration nodes
1032
+ * @param declaration
1033
+ *
1034
+ * Example:
1035
+ * ````ts
1036
+ *
1037
+ * const declarations = await parseDeclarations('color: red; background: blue');
1038
+ * console.log(declarations);
1039
+ * ```
1040
+ */
1041
+ async function parseDeclarations(declaration) {
1042
+ return doParse(tokenize({
1043
+ stream: `.x{${declaration}}`,
1044
+ buffer: '',
1045
+ position: { ind: 0, lin: 1, col: 1 },
1046
+ currentPosition: { ind: -1, lin: 1, col: 0 }
1047
+ }), { setParent: false, minify: false, validation: false }).then(result => {
1048
+ return result.ast.chi[0].chi.filter(t => t.typ == EnumToken.DeclarationNodeType);
1049
+ });
1050
+ }
985
1051
  /**
986
1052
  * parse selector
987
1053
  * @param tokens
@@ -1083,12 +1149,33 @@ function parseSelector(tokens) {
1083
1149
  return tokens;
1084
1150
  }
1085
1151
  /**
1086
- * parse css string
1152
+ * parse css string and return an array of tokens
1087
1153
  * @param src
1088
1154
  * @param options
1155
+ *
1156
+ * @private
1157
+ *
1158
+ * Example:
1159
+ *
1160
+ * ```ts
1161
+ *
1162
+ * import {parseString} from '@tbela99/css-parser';
1163
+ *
1164
+ * let tokens = parseString('body { color: red; }');
1165
+ * console.log(tokens);
1166
+ *
1167
+ * tokens = parseString('#c322c980');
1168
+ * console.log(tokens);
1169
+ * ```
1089
1170
  */
1090
1171
  function parseString(src, options = { location: false }) {
1091
- return parseTokens([...tokenize(src)].reduce((acc, t) => {
1172
+ const parseInfo = {
1173
+ stream: src,
1174
+ buffer: '',
1175
+ position: { ind: 0, lin: 1, col: 1 },
1176
+ currentPosition: { ind: -1, lin: 1, col: 0 }
1177
+ };
1178
+ return parseTokens([...tokenize(parseInfo)].reduce((acc, t) => {
1092
1179
  if (t.hint == EnumToken.EOFTokenType) {
1093
1180
  return acc;
1094
1181
  }
@@ -1100,6 +1187,11 @@ function parseString(src, options = { location: false }) {
1100
1187
  return acc;
1101
1188
  }, []));
1102
1189
  }
1190
+ /**
1191
+ * get token type from a string
1192
+ * @param val
1193
+ * @param hint
1194
+ */
1103
1195
  function getTokenType(val, hint) {
1104
1196
  if (hint != null) {
1105
1197
  return enumTokenHints.has(hint) ? { typ: hint } : { typ: hint, val };
@@ -1194,19 +1286,19 @@ function getTokenType(val, hint) {
1194
1286
  if (isNumber(val)) {
1195
1287
  return {
1196
1288
  typ: EnumToken.NumberTokenType,
1197
- val
1289
+ val: +val
1198
1290
  };
1199
1291
  }
1200
1292
  if (isPercentage(val)) {
1201
1293
  return {
1202
1294
  typ: EnumToken.PercentageTokenType,
1203
- val: val.slice(0, -1)
1295
+ val: +val.slice(0, -1)
1204
1296
  };
1205
1297
  }
1206
1298
  if (isFlex(val)) {
1207
1299
  return {
1208
1300
  typ: EnumToken.FlexTokenType,
1209
- val: val.slice(0, -2)
1301
+ val: +val.slice(0, -2)
1210
1302
  };
1211
1303
  }
1212
1304
  if (isDimension(val)) {
@@ -1265,9 +1357,24 @@ function getTokenType(val, hint) {
1265
1357
  };
1266
1358
  }
1267
1359
  /**
1268
- * parse token array into a tree structure
1360
+ * parse function tokens in a token array
1269
1361
  * @param tokens
1270
1362
  * @param options
1363
+ *
1364
+ * Example:
1365
+ *
1366
+ * ```ts
1367
+ *
1368
+ * import {parseString, parseTokens} from '@tbela99/css-parser';
1369
+ *
1370
+ * let tokens = parseString('body { color: red; }');
1371
+ * console.log(parseTokens(tokens));
1372
+ *
1373
+ * tokens = parseString('#c322c980');
1374
+ * console.log(parseTokens(tokens));
1375
+ * ```
1376
+ *
1377
+ * @private
1271
1378
  */
1272
1379
  function parseTokens(tokens, options = {}) {
1273
1380
  for (let i = 0; i < tokens.length; i++) {
@@ -1555,4 +1662,4 @@ function parseTokens(tokens, options = {}) {
1555
1662
  return tokens;
1556
1663
  }
1557
1664
 
1558
- export { doParse, getTokenType, parseAtRulePrelude, parseSelector, parseString, parseTokens, urlTokenMatcher };
1665
+ export { doParse, getTokenType, parseAtRulePrelude, parseDeclarations, parseSelector, parseString, parseTokens, urlTokenMatcher };
@@ -3,7 +3,7 @@ import '../ast/minify.js';
3
3
  import '../ast/walk.js';
4
4
  import './parse.js';
5
5
  import './utils/config.js';
6
- import { isWhiteSpace, isIdentStart, isIdent, isNewLine, isDigit, isNonPrintable } from '../syntax/syntax.js';
6
+ import { isWhiteSpace, isIdentStart, isIdent, isNewLine, isDigit } from '../syntax/syntax.js';
7
7
  import '../syntax/color/utils/constants.js';
8
8
  import '../renderer/sourcemap/lib/encode.js';
9
9
 
@@ -40,7 +40,7 @@ var TokenMap;
40
40
  })(TokenMap || (TokenMap = {}));
41
41
  function consumeWhiteSpace(parseInfo) {
42
42
  let count = 0;
43
- while (isWhiteSpace(parseInfo.stream.charAt(count + parseInfo.currentPosition.ind + 1).charCodeAt(0))) {
43
+ while (isWhiteSpace(parseInfo.stream.charCodeAt(count + parseInfo.currentPosition.ind + 1))) {
44
44
  count++;
45
45
  }
46
46
  next(parseInfo, count);
@@ -146,11 +146,8 @@ function peek(parseInfo, count = 1) {
146
146
  }
147
147
  return parseInfo.stream.slice(parseInfo.currentPosition.ind + 1, parseInfo.currentPosition.ind + count + 1);
148
148
  }
149
- function prev(parseInfo, count = 1) {
150
- if (count == 1) {
151
- return parseInfo.currentPosition.ind == 0 ? '' : parseInfo.stream.charAt(parseInfo.currentPosition.ind - 1);
152
- }
153
- return parseInfo.stream.slice(parseInfo.currentPosition.ind - 1 - count, parseInfo.currentPosition.ind - 1);
149
+ function prev(parseInfo) {
150
+ return parseInfo.stream.charAt(parseInfo.currentPosition.ind - 1);
154
151
  }
155
152
  function next(parseInfo, count = 1) {
156
153
  let char = '';
@@ -170,17 +167,14 @@ function next(parseInfo, count = 1) {
170
167
  }
171
168
  /**
172
169
  * tokenize css string
173
- * @param stream
170
+ * @param parseInfo
171
+ * @param yieldEOFToken
174
172
  */
175
- function* tokenize(stream) {
176
- const parseInfo = {
177
- stream,
178
- position: { ind: 0, lin: 1, col: 1 },
179
- currentPosition: { ind: -1, lin: 1, col: 0 }
180
- };
173
+ function* tokenize(parseInfo, yieldEOFToken = true) {
181
174
  let value;
182
- let buffer = '';
175
+ let buffer = parseInfo.buffer;
183
176
  let charCode;
177
+ parseInfo.buffer = '';
184
178
  while (value = next(parseInfo)) {
185
179
  charCode = value.charCodeAt(0);
186
180
  if (isWhiteSpace(charCode)) {
@@ -424,8 +418,6 @@ function* tokenize(stream) {
424
418
  value = peek(parseInfo);
425
419
  // let cp: number;
426
420
  let whitespace = '';
427
- let hasWhiteSpace = false;
428
- let errorState = false;
429
421
  if (value == '"' || value == "'") {
430
422
  const quote = value;
431
423
  let inquote = true;
@@ -445,11 +437,6 @@ function* tokenize(stream) {
445
437
  break;
446
438
  }
447
439
  }
448
- if (value === '') {
449
- yield pushToken(buffer, parseInfo, EnumToken.BadUrlTokenType);
450
- buffer = '';
451
- break;
452
- }
453
440
  charCode = value.charCodeAt(0);
454
441
  }
455
442
  // '\\'
@@ -465,7 +452,6 @@ function* tokenize(stream) {
465
452
  if (isWhiteSpace(charCode)) {
466
453
  whitespace += value;
467
454
  while (value = peek(parseInfo)) {
468
- hasWhiteSpace = true;
469
455
  if (isWhiteSpace(value?.charCodeAt(0))) {
470
456
  whitespace += next(parseInfo);
471
457
  continue;
@@ -488,16 +474,6 @@ function* tokenize(stream) {
488
474
  }
489
475
  while (value = next(parseInfo)) {
490
476
  charCode = value.charCodeAt(0);
491
- if (charCode == 0x5c) {
492
- buffer += value + next(parseInfo);
493
- continue;
494
- }
495
- if (charCode == 0x29) {
496
- yield pushToken(buffer, parseInfo, EnumToken.BadStringTokenType);
497
- yield pushToken('', parseInfo, EnumToken.EndParensTokenType);
498
- buffer = '';
499
- break;
500
- }
501
477
  buffer += value;
502
478
  }
503
479
  if (hasNewLine) {
@@ -514,49 +490,12 @@ function* tokenize(stream) {
514
490
  buffer = '';
515
491
  while (value = next(parseInfo)) {
516
492
  charCode = value.charCodeAt(0);
517
- // ')'
518
- if (charCode == 0x29) {
493
+ if (charCode == 0x29) { // ')'
519
494
  yield pushToken(buffer, parseInfo, EnumToken.UrlTokenTokenType);
520
495
  yield pushToken('', parseInfo, EnumToken.EndParensTokenType);
521
496
  buffer = '';
522
497
  break;
523
498
  }
524
- if (isWhiteSpace(charCode)) {
525
- hasWhiteSpace = true;
526
- whitespace = value;
527
- while (isWhiteSpace(peek(parseInfo)?.charCodeAt(0))) {
528
- whitespace += next(parseInfo);
529
- }
530
- continue;
531
- }
532
- if (isNonPrintable(charCode) ||
533
- // '"'
534
- charCode == 0x22 ||
535
- // "'"
536
- charCode == 0x27 ||
537
- // \('
538
- charCode == 0x28 ||
539
- hasWhiteSpace) {
540
- errorState = true;
541
- }
542
- if (errorState) {
543
- buffer += whitespace + value;
544
- while (value = peek(parseInfo)) {
545
- charCode = value.charCodeAt(0);
546
- if (charCode == 0x5c) {
547
- buffer += next(parseInfo, 2);
548
- continue;
549
- }
550
- // ')'
551
- if (charCode == 0x29) {
552
- break;
553
- }
554
- buffer += next(parseInfo);
555
- }
556
- yield pushToken(buffer, parseInfo, EnumToken.BadUrlTokenType);
557
- buffer = '';
558
- break;
559
- }
560
499
  buffer += value;
561
500
  }
562
501
  }
@@ -595,10 +534,6 @@ function* tokenize(stream) {
595
534
  buffer = '!';
596
535
  break;
597
536
  case 64 /* TokenMap.AT */:
598
- if (buffer.length > 0) {
599
- yield pushToken(buffer, parseInfo);
600
- buffer = '';
601
- }
602
537
  buffer = value;
603
538
  {
604
539
  let val = peek(parseInfo);
@@ -616,27 +551,40 @@ function* tokenize(stream) {
616
551
  break;
617
552
  default:
618
553
  buffer += value;
619
- if (buffer.length == 1) {
620
- if (buffer == 'h') {
621
- if (match(parseInfo, 'ttp://') || match(parseInfo, 'ttps://')) {
622
- let val = peek(parseInfo);
623
- while (val != ')' && val != ';' && !isWhiteSpace(val.charCodeAt(0))) {
624
- buffer += next(parseInfo);
625
- val = peek(parseInfo);
626
- }
627
- yield pushToken(buffer, parseInfo);
628
- buffer = '';
629
- break;
630
- }
631
- }
632
- }
633
554
  break;
634
555
  }
635
556
  }
636
- if (buffer.length > 0) {
637
- yield pushToken(buffer, parseInfo);
557
+ if (yieldEOFToken) {
558
+ if (buffer.length > 0) {
559
+ yield pushToken(buffer, parseInfo);
560
+ }
561
+ yield pushToken('', parseInfo, EnumToken.EOFTokenType);
562
+ }
563
+ else {
564
+ parseInfo.buffer = buffer;
565
+ }
566
+ }
567
+ /**
568
+ * tokenize readable stream
569
+ * @param input
570
+ */
571
+ async function* tokenizeStream(input) {
572
+ const parseInfo = {
573
+ stream: '',
574
+ buffer: '',
575
+ position: { ind: 0, lin: 1, col: 1 },
576
+ currentPosition: { ind: -1, lin: 1, col: 0 }
577
+ };
578
+ const decoder = new TextDecoder('utf-8');
579
+ const reader = input.getReader();
580
+ while (true) {
581
+ const { done, value } = await reader.read();
582
+ parseInfo.stream += decoder.decode(value, { stream: true });
583
+ yield* tokenize(parseInfo, done);
584
+ if (done) {
585
+ break;
586
+ }
638
587
  }
639
- yield pushToken('', parseInfo, EnumToken.EOFTokenType);
640
588
  }
641
589
 
642
- export { tokenize };
590
+ export { tokenize, tokenizeStream };
@@ -14,7 +14,7 @@ function matchType(val, properties) {
14
14
  (properties.types.some((t) => EnumToken[t] == val.typ))) {
15
15
  return true;
16
16
  }
17
- if (val.typ == EnumToken.NumberTokenType && val.val == '0') {
17
+ if (val.typ == EnumToken.NumberTokenType && val.val == 0) {
18
18
  // @ts-ignore
19
19
  return properties.types.some((type) => {
20
20
  // @ts-ignore