@tbela99/css-parser 1.3.4 → 1.4.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.
package/dist/index.cjs CHANGED
@@ -434,6 +434,23 @@ exports.EnumToken = void 0;
434
434
  * invalid declaration node type
435
435
  */
436
436
  EnumToken[EnumToken["InvalidDeclarationNodeType"] = 94] = "InvalidDeclarationNodeType";
437
+ /* css module nodes */
438
+ /**
439
+ * composes token node type
440
+ */
441
+ EnumToken[EnumToken["ComposesSelectorNodeType"] = 95] = "ComposesSelectorNodeType";
442
+ /**
443
+ * css variable token type
444
+ */
445
+ EnumToken[EnumToken["CssVariableTokenType"] = 96] = "CssVariableTokenType";
446
+ /**
447
+ * css variable import token type
448
+ */
449
+ EnumToken[EnumToken["CssVariableImportTokenType"] = 97] = "CssVariableImportTokenType";
450
+ /**
451
+ * css variable declaration map token type
452
+ */
453
+ EnumToken[EnumToken["CssVariableDeclarationMapTokenType"] = 98] = "CssVariableDeclarationMapTokenType";
437
454
  /* aliases */
438
455
  /**
439
456
  * alias for time token type
@@ -550,7 +567,7 @@ exports.EnumToken = void 0;
550
567
  exports.ColorType = void 0;
551
568
  (function (ColorType) {
552
569
  /**
553
- * system colors
570
+ * deprecated system colors
554
571
  */
555
572
  ColorType[ColorType["SYS"] = 0] = "SYS";
556
573
  /**
@@ -558,7 +575,7 @@ exports.ColorType = void 0;
558
575
  */
559
576
  ColorType[ColorType["DPSYS"] = 1] = "DPSYS";
560
577
  /**
561
- * colors as literals
578
+ * named colors
562
579
  */
563
580
  ColorType[ColorType["LIT"] = 2] = "LIT";
564
581
  /**
@@ -658,6 +675,48 @@ exports.ColorType = void 0;
658
675
  */
659
676
  ColorType[ColorType["DEVICE_CMYK"] = 7] = "DEVICE_CMYK";
660
677
  })(exports.ColorType || (exports.ColorType = {}));
678
+ exports.ModuleCaseTransformEnum = void 0;
679
+ (function (ModuleCaseTransformEnum) {
680
+ /**
681
+ * export class names as-is
682
+ */
683
+ ModuleCaseTransformEnum[ModuleCaseTransformEnum["IgnoreCase"] = 1] = "IgnoreCase";
684
+ /**
685
+ * transform mapping key name to camel case
686
+ */
687
+ ModuleCaseTransformEnum[ModuleCaseTransformEnum["CamelCase"] = 2] = "CamelCase";
688
+ /**
689
+ * transform class names and mapping key name to camel case
690
+ */
691
+ ModuleCaseTransformEnum[ModuleCaseTransformEnum["CamelCaseOnly"] = 4] = "CamelCaseOnly";
692
+ /**
693
+ * transform mapping key name to dash case
694
+ */
695
+ ModuleCaseTransformEnum[ModuleCaseTransformEnum["DashCase"] = 8] = "DashCase";
696
+ /**
697
+ * transform class names and mapping key name to dash case
698
+ */
699
+ ModuleCaseTransformEnum[ModuleCaseTransformEnum["DashCaseOnly"] = 16] = "DashCaseOnly";
700
+ })(exports.ModuleCaseTransformEnum || (exports.ModuleCaseTransformEnum = {}));
701
+ exports.ModuleScopeEnumOptions = void 0;
702
+ (function (ModuleScopeEnumOptions) {
703
+ /**
704
+ * use the global scope
705
+ */
706
+ ModuleScopeEnumOptions[ModuleScopeEnumOptions["Global"] = 32] = "Global";
707
+ /**
708
+ * use the local scope
709
+ */
710
+ ModuleScopeEnumOptions[ModuleScopeEnumOptions["Local"] = 64] = "Local";
711
+ /**
712
+ * do not allow selector without an id or class
713
+ */
714
+ ModuleScopeEnumOptions[ModuleScopeEnumOptions["Pure"] = 128] = "Pure";
715
+ /**
716
+ * export using ICSS module format
717
+ */
718
+ ModuleScopeEnumOptions[ModuleScopeEnumOptions["ICSS"] = 256] = "ICSS";
719
+ })(exports.ModuleScopeEnumOptions || (exports.ModuleScopeEnumOptions = {}));
661
720
 
662
721
  // from https://www.w3.org/TR/css-color-4/multiply-matrices.js
663
722
  /**
@@ -3916,10 +3975,7 @@ function computeComponentValue(expr, converted, values) {
3916
3975
  // normalize hue
3917
3976
  for (const k of walkValues([object.h])) {
3918
3977
  if (k.value.typ == exports.EnumToken.AngleTokenType && k.value.unit == 'deg') {
3919
- // @ts-ignore
3920
3978
  k.value.typ = exports.EnumToken.NumberTokenType;
3921
- // @ts-ignore
3922
- delete k.value.unit;
3923
3979
  }
3924
3980
  }
3925
3981
  }
@@ -4122,7 +4178,7 @@ const epsilon = 1e-5;
4122
4178
  function identity() {
4123
4179
  return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
4124
4180
  }
4125
- function normalize(point) {
4181
+ function normalize$1(point) {
4126
4182
  const [x, y, z] = point;
4127
4183
  const norm = Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
4128
4184
  return norm === 0 ? [0, 0, 0] : [x / norm, y / norm, z / norm];
@@ -4249,7 +4305,7 @@ function decompose(original) {
4249
4305
  ];
4250
4306
  // Compute scale
4251
4307
  const scaleX = Math.hypot(...row0);
4252
- const row0Norm = normalize(row0);
4308
+ const row0Norm = normalize$1(row0);
4253
4309
  const skewXY = dot(row0Norm, row1);
4254
4310
  const row1Proj = [
4255
4311
  row1[0] - skewXY * row0Norm[0],
@@ -4257,7 +4313,7 @@ function decompose(original) {
4257
4313
  row1[2] - skewXY * row0Norm[2]
4258
4314
  ];
4259
4315
  const scaleY = Math.hypot(...row1Proj);
4260
- const row1Norm = normalize(row1Proj);
4316
+ const row1Norm = normalize$1(row1Proj);
4261
4317
  const skewXZ = dot(row0Norm, row2);
4262
4318
  const skewYZ = dot(row1Norm, row2);
4263
4319
  const row2Proj = [
@@ -4265,7 +4321,7 @@ function decompose(original) {
4265
4321
  row2[1] - skewXZ * row0Norm[1] - skewYZ * row1Norm[1],
4266
4322
  row2[2] - skewXZ * row0Norm[2] - skewYZ * row1Norm[2]
4267
4323
  ];
4268
- const row2Norm = normalize(row2Proj);
4324
+ const row2Norm = normalize$1(row2Proj);
4269
4325
  const determinant = row0[0] * cross[0] + row0[1] * cross[1] + row0[2] * cross[2];
4270
4326
  const scaleZ = Math.hypot(...row2Proj) * (determinant < 0 ? -1 : 1);
4271
4327
  // Build rotation matrix from orthonormalized vectors
@@ -6531,6 +6587,9 @@ var map = {
6531
6587
  },
6532
6588
  animation: {
6533
6589
  shorthand: "animation",
6590
+ separator: {
6591
+ typ: "Comma"
6592
+ },
6534
6593
  pattern: "animation-name animation-duration animation-timing-function animation-delay animation-iteration-count animation-direction animation-fill-mode animation-play-state animation-timeline",
6535
6594
  "default": [
6536
6595
  "1",
@@ -7481,6 +7540,60 @@ function parseDeclarationNode(node, errors, location) {
7481
7540
  });
7482
7541
  return null;
7483
7542
  }
7543
+ if ('composes' == node.nam.toLowerCase()) {
7544
+ let left = [];
7545
+ let right = [];
7546
+ let current = 0;
7547
+ let hasFrom = 0;
7548
+ for (; current < node.val.length; current++) {
7549
+ if (exports.EnumToken.WhitespaceTokenType == node.val[current].typ || exports.EnumToken.CommentTokenType == node.val[current].typ) {
7550
+ if (!hasFrom) {
7551
+ left.push(node.val[current]);
7552
+ }
7553
+ else {
7554
+ right.push(node.val[current]);
7555
+ }
7556
+ continue;
7557
+ }
7558
+ if (exports.EnumToken.IdenTokenType == node.val[current].typ || exports.EnumToken.DashedIdenTokenType == node.val[current].typ || exports.EnumToken.StringTokenType == node.val[current].typ) {
7559
+ if (exports.EnumToken.IdenTokenType == node.val[current].typ) {
7560
+ if ('from' == node.val[current].val) {
7561
+ if (hasFrom) {
7562
+ return null;
7563
+ }
7564
+ hasFrom++;
7565
+ continue;
7566
+ }
7567
+ }
7568
+ if (hasFrom) {
7569
+ right.push(node.val[current]);
7570
+ }
7571
+ else {
7572
+ left.push(node.val[current]);
7573
+ }
7574
+ continue;
7575
+ }
7576
+ break;
7577
+ }
7578
+ if (hasFrom <= 1 && current > 0) {
7579
+ if (hasFrom == 0) {
7580
+ node.val.splice(0, left.length, {
7581
+ typ: exports.EnumToken.ComposesSelectorNodeType,
7582
+ l: left,
7583
+ r: null
7584
+ });
7585
+ }
7586
+ else {
7587
+ node.val.splice(0, current, {
7588
+ typ: exports.EnumToken.ComposesSelectorNodeType,
7589
+ l: left,
7590
+ r: right.reduce((a, b) => {
7591
+ return a == null ? b : b.typ == exports.EnumToken.WhitespaceTokenType || b.typ == exports.EnumToken.CommentTokenType ? a : b;
7592
+ }, null)
7593
+ });
7594
+ }
7595
+ }
7596
+ }
7484
7597
  for (const { value: val, parent } of walkValues(node.val, node)) {
7485
7598
  if (val.typ == exports.EnumToken.AttrTokenType && val.chi.every((t) => [exports.EnumToken.IdenTokenType, exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType].includes(t.typ))) {
7486
7599
  // @ts-ignore
@@ -7527,6 +7640,13 @@ function parseGridTemplate(template) {
7527
7640
  return buffer.length > 0 ? result + buffer : result;
7528
7641
  }
7529
7642
 
7643
+ function dasherize(value) {
7644
+ return value.replace(/([A-Z])/g, (all, one) => `-${one.toLowerCase()}`);
7645
+ }
7646
+ function camelize(value) {
7647
+ return value.replace(/-([a-z])/g, (all, one) => one.toUpperCase());
7648
+ }
7649
+
7530
7650
  // from https://github.com/Rich-Harris/vlq/tree/master
7531
7651
  // credit: Rich Harris
7532
7652
  const integer_to_char = {};
@@ -7673,9 +7793,10 @@ function update(position, str) {
7673
7793
  * render ast
7674
7794
  * @param data
7675
7795
  * @param options
7796
+ * @param mapping
7676
7797
  * @private
7677
7798
  */
7678
- function doRender(data, options = {}) {
7799
+ function doRender(data, options = {}, mapping) {
7679
7800
  const minify = options.minify ?? true;
7680
7801
  const beautify = options.beautify ?? !minify;
7681
7802
  options = {
@@ -7712,12 +7833,23 @@ function doRender(data, options = {}) {
7712
7833
  const errors = [];
7713
7834
  const sourcemap = options.sourcemap ? new SourceMap : null;
7714
7835
  const cache = Object.create(null);
7836
+ const position = {
7837
+ ind: 0,
7838
+ lin: 1,
7839
+ col: 1
7840
+ };
7841
+ let code = '';
7842
+ if (mapping != null) {
7843
+ if (mapping.importMapping != null) {
7844
+ for (const [key, value] of Object.entries(mapping.importMapping)) {
7845
+ code += `:import("${key}")${options.indent}{${options.newLine}${Object.entries(value).reduce((acc, [k, v]) => acc + (acc.length > 0 ? options.newLine : '') + `${options.indent}${v}:${options.indent}${k};`, '')}${options.newLine}}${options.newLine}`;
7846
+ }
7847
+ }
7848
+ code += `:export${options.indent}{${options.newLine}${Object.entries(mapping.mapping).reduce((acc, [k, v]) => acc + (acc.length > 0 ? options.newLine : '') + `${options.indent}${k}:${options.indent}${v};`, '')}${options.newLine}}${options.newLine}`;
7849
+ update(position, code);
7850
+ }
7715
7851
  const result = {
7716
- code: renderAstNode(options.expandNestingRules && [exports.EnumToken.StyleSheetNodeType, exports.EnumToken.AtRuleNodeType, exports.EnumToken.RuleNodeType].includes(data.typ) && 'chi' in data ? expand(data) : data, options, sourcemap, {
7717
- ind: 0,
7718
- lin: 1,
7719
- col: 1
7720
- }, errors, function reducer(acc, curr) {
7852
+ code: code + renderAstNode(options.expandNestingRules && [exports.EnumToken.StyleSheetNodeType, exports.EnumToken.AtRuleNodeType, exports.EnumToken.RuleNodeType].includes(data.typ) && 'chi' in data ? expand(data) : data, options, sourcemap, position, errors, function reducer(acc, curr) {
7721
7853
  if (curr.typ == exports.EnumToken.CommentTokenType && options.removeComments) {
7722
7854
  if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
7723
7855
  return acc;
@@ -7876,6 +8008,11 @@ function renderAstNode(data, options, sourcemap, position, errors, reducer, cach
7876
8008
  return `@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val}${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
7877
8009
  }
7878
8010
  return data.sel + `${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
8011
+ case exports.EnumToken.CssVariableTokenType:
8012
+ case exports.EnumToken.CssVariableImportTokenType:
8013
+ return `@value ${data.nam}:${options.indent}${filterValues((options.minify ? data.val : data.val)).reduce(reducer, '').trim()};`;
8014
+ case exports.EnumToken.CssVariableDeclarationMapTokenType:
8015
+ return `@value ${filterValues(data.vars).reduce((acc, curr) => acc + renderToken(curr), '').trim()} from ${filterValues(data.from).reduce((acc, curr) => acc + renderToken(curr), '').trim()};`;
7879
8016
  case exports.EnumToken.InvalidDeclarationNodeType:
7880
8017
  case exports.EnumToken.InvalidRuleTokenType:
7881
8018
  case exports.EnumToken.InvalidAtRuleTokenType:
@@ -8030,6 +8167,8 @@ function renderToken(token, options = {}, cache = Object.create(null), reducer,
8030
8167
  case exports.EnumToken.NameSpaceAttributeTokenType:
8031
8168
  return (token.l == null ? '' : renderToken(token.l, options, cache, reducer, errors)) + '|' +
8032
8169
  renderToken(token.r, options, cache, reducer, errors);
8170
+ case exports.EnumToken.ComposesSelectorNodeType:
8171
+ return token.l.reduce((acc, curr) => acc + renderToken(curr, options, cache), '') + (token.r == null ? '' : ' from ' + renderToken(token.r, options, cache, reducer, errors));
8033
8172
  case exports.EnumToken.BlockStartTokenType:
8034
8173
  return '{';
8035
8174
  case exports.EnumToken.BlockEndTokenType:
@@ -8400,23 +8539,27 @@ function* consumeString(quoteStr, buffer, parseInfo) {
8400
8539
  }
8401
8540
  }
8402
8541
  function match$1(parseInfo, input) {
8403
- return parseInfo.stream.slice(parseInfo.currentPosition.ind + 1, parseInfo.currentPosition.ind + input.length + 1) == input;
8542
+ const position = parseInfo.currentPosition.ind - parseInfo.offset;
8543
+ return parseInfo.stream.slice(position + 1, position + input.length + 1) == input;
8404
8544
  }
8405
8545
  function peek(parseInfo, count = 1) {
8406
8546
  if (count == 1) {
8407
- return parseInfo.stream.charAt(parseInfo.currentPosition.ind + 1);
8547
+ return parseInfo.stream.charAt(parseInfo.currentPosition.ind - parseInfo.offset + 1);
8408
8548
  }
8409
- return parseInfo.stream.slice(parseInfo.currentPosition.ind + 1, parseInfo.currentPosition.ind + count + 1);
8549
+ const position = parseInfo.currentPosition.ind - parseInfo.offset;
8550
+ return parseInfo.stream.slice(position + 1, position + count + 1);
8410
8551
  }
8411
8552
  function prev(parseInfo) {
8412
- return parseInfo.stream.charAt(parseInfo.currentPosition.ind - 1);
8553
+ return parseInfo.offset == parseInfo.currentPosition.ind ? parseInfo.buffer.slice(-1) : parseInfo.stream.charAt(parseInfo.currentPosition.ind - parseInfo.offset - 1);
8413
8554
  }
8414
8555
  function next(parseInfo, count = 1) {
8415
8556
  let char = '';
8416
8557
  let chr = '';
8417
- while (count-- && (chr = parseInfo.stream.charAt(parseInfo.currentPosition.ind + 1))) {
8558
+ let position = parseInfo.currentPosition.ind - parseInfo.offset;
8559
+ while (count-- && (chr = parseInfo.stream.charAt(position + 1))) {
8418
8560
  char += chr;
8419
- const codepoint = parseInfo.stream.charCodeAt(++parseInfo.currentPosition.ind);
8561
+ const codepoint = parseInfo.stream.charCodeAt(++position);
8562
+ ++parseInfo.currentPosition.ind;
8420
8563
  if (isNewLine(codepoint)) {
8421
8564
  parseInfo.currentPosition.lin++;
8422
8565
  parseInfo.currentPosition.col = 0;
@@ -8832,6 +8975,7 @@ async function* tokenizeStream(input) {
8832
8975
  const parseInfo = {
8833
8976
  stream: '',
8834
8977
  buffer: '',
8978
+ offset: 0,
8835
8979
  position: { ind: 0, lin: 1, col: 1 },
8836
8980
  currentPosition: { ind: -1, lin: 1, col: 0 }
8837
8981
  };
@@ -8839,7 +8983,17 @@ async function* tokenizeStream(input) {
8839
8983
  const reader = input.getReader();
8840
8984
  while (true) {
8841
8985
  const { done, value } = await reader.read();
8842
- parseInfo.stream += ArrayBuffer.isView(value) ? decoder.decode(value, { stream: true }) : value;
8986
+ const stream = ArrayBuffer.isView(value) ? decoder.decode(value, { stream: true }) : value;
8987
+ if (!done) {
8988
+ if (parseInfo.stream.length > 2) {
8989
+ parseInfo.stream = parseInfo.stream.slice(-2) + stream;
8990
+ parseInfo.offset = parseInfo.currentPosition.ind - 1;
8991
+ }
8992
+ else {
8993
+ parseInfo.stream = stream;
8994
+ parseInfo.offset = Math.max(0, parseInfo.currentPosition.ind);
8995
+ }
8996
+ }
8843
8997
  yield* tokenize$1(parseInfo, done);
8844
8998
  if (done) {
8845
8999
  break;
@@ -9602,7 +9756,7 @@ var declarations = {
9602
9756
  syntax: "[ <counter-name> <integer>? ]+ | none"
9603
9757
  },
9604
9758
  cursor: {
9605
- syntax: "[ [ <url> [ <x> <y> ]? , ]* [ auto | default | none | context-menu | help | pointer | progress | wait | cell | crosshair | text | vertical-text | alias | copy | move | no-drop | not-allowed | e-resize | n-resize | ne-resize | nw-resize | s-resize | se-resize | sw-resize | w-resize | ew-resize | ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | all-scroll | zoom-in | zoom-out | grab | grabbing ] ] [ [ <url> [ <x> <y> ]? , ]* [ auto | default | none | context-menu | help | pointer | progress | wait | cell | crosshair | text | vertical-text | alias | copy | move | no-drop | not-allowed | e-resize | n-resize | ne-resize | nw-resize | s-resize | se-resize | sw-resize | w-resize | ew-resize | ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | all-scroll | zoom-in | zoom-out | grab | grabbing | hand | -webkit-grab | -webkit-grabbing | -webkit-zoom-in | -webkit-zoom-out | -moz-grab | -moz-grabbing | -moz-zoom-in | -moz-zoom-out ] ]"
9759
+ syntax: "[ [ <url> [ <x> <y> ]? , ]* <cursor-predefined> ] [ [ <url> [ <x> <y> ]? , ]* [ auto | default | none | context-menu | help | pointer | progress | wait | cell | crosshair | text | vertical-text | alias | copy | move | no-drop | not-allowed | e-resize | n-resize | ne-resize | nw-resize | s-resize | se-resize | sw-resize | w-resize | ew-resize | ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | all-scroll | zoom-in | zoom-out | grab | grabbing | hand | -webkit-grab | -webkit-grabbing | -webkit-zoom-in | -webkit-zoom-out | -moz-grab | -moz-grabbing | -moz-zoom-in | -moz-zoom-out ] ]"
9606
9760
  },
9607
9761
  cx: {
9608
9762
  syntax: "<length> | <percentage>"
@@ -10830,6 +10984,12 @@ var declarations = {
10830
10984
  },
10831
10985
  "white-space-trim": {
10832
10986
  syntax: "none | discard-before || discard-after || discard-inner"
10987
+ },
10988
+ composes: {
10989
+ syntax: "<composes-selector>#"
10990
+ },
10991
+ "composes-selector": {
10992
+ syntax: "<ident>+ [from [global&&<string>]]?"
10833
10993
  }
10834
10994
  };
10835
10995
  var functions = {
@@ -10855,7 +11015,7 @@ var functions = {
10855
11015
  syntax: "atan2( <calc-sum>, <calc-sum> )"
10856
11016
  },
10857
11017
  attr: {
10858
- syntax: "attr( <attr-name> <type-or-unit>? [, <attr-fallback> ]? )"
11018
+ syntax: "attr( <attr-name> <attr-type>? , <declaration-value>? )"
10859
11019
  },
10860
11020
  blur: {
10861
11021
  syntax: "blur( <length>? )"
@@ -11208,7 +11368,7 @@ var syntaxes = {
11208
11368
  syntax: "scroll | fixed | local"
11209
11369
  },
11210
11370
  "attr()": {
11211
- syntax: "attr( <attr-name> <type-or-unit>? [, <attr-fallback> ]? )"
11371
+ syntax: "attr( <attr-name> <attr-type>? , <declaration-value>? )"
11212
11372
  },
11213
11373
  "attr-matcher": {
11214
11374
  syntax: "[ '~' | '|' | '^' | '$' | '*' ]? '='"
@@ -11216,6 +11376,9 @@ var syntaxes = {
11216
11376
  "attr-modifier": {
11217
11377
  syntax: "i | s"
11218
11378
  },
11379
+ "attr-type": {
11380
+ syntax: "type( <syntax> ) | raw-string | number | <attr-unit>"
11381
+ },
11219
11382
  "attribute-selector": {
11220
11383
  syntax: "'[' <wq-name> ']' | '[' <wq-name> <attr-matcher> [ <string-token> | <ident-token> ] <attr-modifier>? ']'"
11221
11384
  },
@@ -11429,6 +11592,9 @@ var syntaxes = {
11429
11592
  "cubic-bezier-easing-function": {
11430
11593
  syntax: "ease | ease-in | ease-out | ease-in-out | cubic-bezier( <number [0,1]> , <number> , <number [0,1]> , <number> )"
11431
11594
  },
11595
+ "cursor-predefined": {
11596
+ syntax: "auto | default | none | context-menu | help | pointer | progress | wait | cell | crosshair | text | vertical-text | alias | copy | move | no-drop | not-allowed | e-resize | n-resize | ne-resize | nw-resize | s-resize | se-resize | sw-resize | w-resize | ew-resize | ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | all-scroll | zoom-in | zoom-out | grab | grabbing"
11597
+ },
11432
11598
  "custom-color-space": {
11433
11599
  syntax: "<dashed-ident>"
11434
11600
  },
@@ -14350,8 +14516,7 @@ function validateCompoundSelector(tokens, root, options) {
14350
14516
  node: root,
14351
14517
  // @ts-ignore
14352
14518
  syntax: null,
14353
- error: 'expected selector',
14354
- tokens
14519
+ error: 'expected selector'
14355
14520
  };
14356
14521
  }
14357
14522
  tokens = tokens.slice();
@@ -14599,15 +14764,12 @@ function validateRelativeSelectorList(tokens, root, options) {
14599
14764
  return result;
14600
14765
  }
14601
14766
  }
14767
+ // @ts-ignore
14602
14768
  return {
14603
14769
  valid: SyntaxValidationResult.Valid,
14604
- matches: [],
14605
- // @ts-ignore
14606
14770
  node: root,
14607
- // @ts-ignore
14608
14771
  syntax: null,
14609
- error: '',
14610
- tokens
14772
+ error: ''
14611
14773
  };
14612
14774
  }
14613
14775
 
@@ -14661,6 +14823,9 @@ function dirname(path) {
14661
14823
  //
14662
14824
  // return path;
14663
14825
  // }
14826
+ if (path === '') {
14827
+ return '';
14828
+ }
14664
14829
  let i = 0;
14665
14830
  let parts = [''];
14666
14831
  for (; i < path.length; i++) {
@@ -14685,6 +14850,12 @@ function dirname(path) {
14685
14850
  * @private
14686
14851
  */
14687
14852
  function splitPath(result) {
14853
+ if (result.length == 0) {
14854
+ return { parts: [], i: 0 };
14855
+ }
14856
+ if (result === '/') {
14857
+ return { parts: ['/'], i: 0 };
14858
+ }
14688
14859
  const parts = [''];
14689
14860
  let i = 0;
14690
14861
  for (; i < result.length; i++) {
@@ -14728,6 +14899,21 @@ function resolve(url, currentDirectory, cwd) {
14728
14899
  }
14729
14900
  cwd ??= '';
14730
14901
  currentDirectory ??= '';
14902
+ if (currentDirectory !== '' && url.startsWith(currentDirectory + '/')) {
14903
+ return {
14904
+ absolute: url,
14905
+ relative: url.slice(currentDirectory.length + 1)
14906
+ };
14907
+ }
14908
+ if (currentDirectory === '' && cwd !== '' && url.startsWith(cwd == '/' ? cwd : cwd + '/')) {
14909
+ cwd = normalize(cwd);
14910
+ const absolute = normalize(url);
14911
+ const prefix = cwd == '/' ? cwd : cwd + '/';
14912
+ return {
14913
+ absolute,
14914
+ relative: absolute.startsWith(prefix) ? absolute.slice(prefix.length) : diff$1(absolute, cwd)
14915
+ };
14916
+ }
14731
14917
  if (matchUrl.test(currentDirectory)) {
14732
14918
  const path = new URL(url, currentDirectory).href;
14733
14919
  return {
@@ -14742,9 +14928,15 @@ function resolve(url, currentDirectory, cwd) {
14742
14928
  else if (currentDirectory.charAt(0) == '/') {
14743
14929
  result = dirname(currentDirectory) + '/' + url;
14744
14930
  }
14745
- let { parts, i } = splitPath(result);
14746
- const absolute = parts.join('/');
14747
- const { parts: dirs } = splitPath(cwd ?? currentDirectory);
14931
+ const absolute = normalize(result);
14932
+ return {
14933
+ absolute,
14934
+ relative: absolute === '' ? '' : diff$1(absolute, cwd ?? currentDirectory),
14935
+ };
14936
+ }
14937
+ function diff$1(path1, path2) {
14938
+ let { parts } = splitPath(path1);
14939
+ const { parts: dirs } = splitPath(path2);
14748
14940
  for (const p of dirs) {
14749
14941
  if (parts[0] == p) {
14750
14942
  parts.shift();
@@ -14753,16 +14945,61 @@ function resolve(url, currentDirectory, cwd) {
14753
14945
  parts.unshift('..');
14754
14946
  }
14755
14947
  }
14756
- return {
14757
- absolute,
14758
- relative: parts.join('/') + (i < result.length ? result.slice(i) : '')
14759
- };
14948
+ return parts.join('/');
14949
+ }
14950
+ function normalize(path) {
14951
+ let parts = [];
14952
+ let i = 0;
14953
+ for (; i < path.length; i++) {
14954
+ const chr = path.charAt(i);
14955
+ if (chr == '/') {
14956
+ if (parts.length == 0 || parts[parts.length - 1] !== '') {
14957
+ parts.push('');
14958
+ }
14959
+ }
14960
+ else if (chr == '?' || chr == '#') {
14961
+ break;
14962
+ }
14963
+ else {
14964
+ parts[parts.length - 1] += chr;
14965
+ }
14966
+ }
14967
+ let k = -1;
14968
+ while (++k < parts.length) {
14969
+ if (parts[k] == '.') {
14970
+ parts.splice(k--, 1);
14971
+ }
14972
+ else if (parts[k] == '..') {
14973
+ parts.splice(k - 1, 2);
14974
+ k -= 2;
14975
+ }
14976
+ }
14977
+ return (path.charAt(0) == '/' ? '/' : '') + parts.join('/');
14760
14978
  }
14761
14979
 
14980
+ /**
14981
+ * response type
14982
+ */
14983
+ exports.ResponseType = void 0;
14984
+ (function (ResponseType) {
14985
+ /**
14986
+ * return text
14987
+ */
14988
+ ResponseType[ResponseType["Text"] = 0] = "Text";
14989
+ /**
14990
+ * return a readable stream
14991
+ */
14992
+ ResponseType[ResponseType["ReadableStream"] = 1] = "ReadableStream";
14993
+ /**
14994
+ * return an arraybuffer
14995
+ */
14996
+ ResponseType[ResponseType["ArrayBuffer"] = 2] = "ArrayBuffer";
14997
+ })(exports.ResponseType || (exports.ResponseType = {}));
14998
+
14762
14999
  /**
14763
15000
  * feature walk mode
14764
15001
  *
14765
- * @internal
15002
+ * @private
14766
15003
  */
14767
15004
  exports.FeatureWalkMode = void 0;
14768
15005
  (function (FeatureWalkMode) {
@@ -15378,6 +15615,7 @@ function matchPropertyType(syntax, context, options) {
15378
15615
  'color',
15379
15616
  'integer',
15380
15617
  'bg-position',
15618
+ 'composes-selector',
15381
15619
  'length-percentage', 'flex', 'calc-sum', 'color',
15382
15620
  'color-base', 'system-color', 'deprecated-system-color',
15383
15621
  'pseudo-class-selector', 'pseudo-element-selector', 'feature-value-declaration'
@@ -15408,6 +15646,9 @@ function matchPropertyType(syntax, context, options) {
15408
15646
  return { ...result, context };
15409
15647
  }
15410
15648
  switch (syntax.val) {
15649
+ case 'composes-selector':
15650
+ success = token.typ == exports.EnumToken.ComposesSelectorNodeType;
15651
+ break;
15411
15652
  case 'bg-position': {
15412
15653
  let val;
15413
15654
  let keyworkMatchCount = 0;
@@ -15575,7 +15816,7 @@ function matchPropertyType(syntax, context, options) {
15575
15816
  }
15576
15817
  break;
15577
15818
  case 'integer':
15578
- success = (token.typ == exports.EnumToken.NumberTokenType && Number.isInteger(+token.val) && token.val > 0) || (token.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(token.val.toLowerCase()) || (token.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val)));
15819
+ success = (token.typ == exports.EnumToken.NumberTokenType && /^[+-]?\d+$/.test(token.val.toString())) || (token.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(token.val.toLowerCase()) || (token.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val)));
15579
15820
  if ('range' in syntax) {
15580
15821
  success = success && +token.val >= +syntax.range[0] && +token.val <= +syntax.range[1];
15581
15822
  }
@@ -17738,6 +17979,91 @@ function validateAtRule(atRule, options, root) {
17738
17979
  };
17739
17980
  }
17740
17981
 
17982
+ // Alphabet: a-z, A-Z, 0-9, _, -
17983
+ const LOWER = "abcdefghijklmnopqrstuvwxyz";
17984
+ const DIGITS = "0123456789";
17985
+ const FULL_ALPHABET = (LOWER + DIGITS).split(""); // 64 chars
17986
+ const FIRST_ALPHABET = (LOWER).split(""); // 54 chars (no digits)
17987
+ /**
17988
+ * supported hash algorithms
17989
+ */
17990
+ const hashAlgorithms = ['hex', 'base64', 'base64url', 'sha1', 'sha256', 'sha384', 'sha512'];
17991
+ // simple deterministic hash → number
17992
+ function hashCode(str) {
17993
+ let hash = 0;
17994
+ let l = str.length;
17995
+ let i = 0;
17996
+ while (i < l) {
17997
+ hash = (hash * 31 + str.charCodeAt(i++)) >>> 0;
17998
+ }
17999
+ return hash;
18000
+ }
18001
+ /**
18002
+ * generate a hash id
18003
+ * @param input
18004
+ * @param length
18005
+ */
18006
+ function hashId(input, length = 6) {
18007
+ let n = hashCode(input);
18008
+ const chars = [];
18009
+ // First character: must not be a digit
18010
+ chars.push(FIRST_ALPHABET[n % FIRST_ALPHABET.length]);
18011
+ // Remaining characters
18012
+ for (let i = 1; i < length; i++) {
18013
+ n = (n + chars.length + i) % FULL_ALPHABET.length;
18014
+ chars.push(FULL_ALPHABET[n]);
18015
+ }
18016
+ return chars.join("");
18017
+ }
18018
+ /**
18019
+ * convert input to hex
18020
+ * @param input
18021
+ */
18022
+ function toHex(input) {
18023
+ let result = '';
18024
+ if (input instanceof ArrayBuffer || ArrayBuffer.isView(input)) {
18025
+ for (const byte of Array.from(new Uint8Array(input))) {
18026
+ result += byte.toString(16).padStart(2, '0');
18027
+ }
18028
+ }
18029
+ else {
18030
+ for (const char of String(input)) {
18031
+ result += char.charCodeAt(0).toString(16).padStart(2, '0');
18032
+ }
18033
+ }
18034
+ return result;
18035
+ }
18036
+ /**
18037
+ * generate a hash
18038
+ * @param input
18039
+ * @param length
18040
+ * @param algo
18041
+ */
18042
+ async function hash(input, length = 6, algo) {
18043
+ let result;
18044
+ if (algo != null) {
18045
+ switch (algo) {
18046
+ case 'hex':
18047
+ return toHex(input).slice(0, length);
18048
+ case 'base64':
18049
+ case 'base64url':
18050
+ result = btoa(input);
18051
+ if (algo == 'base64url') {
18052
+ result = result.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
18053
+ }
18054
+ return result.slice(0, length);
18055
+ case 'sha1':
18056
+ case 'sha256':
18057
+ case 'sha384':
18058
+ case 'sha512':
18059
+ return toHex(await crypto.subtle.digest(algo.replace('sha', 'SHA-'), new TextEncoder().encode(input))).slice(0, length);
18060
+ default:
18061
+ throw new Error(`Unsupported hash algorithm: ${algo}`);
18062
+ }
18063
+ }
18064
+ return hashId(input, length);
18065
+ }
18066
+
17741
18067
  const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
17742
18068
  const trimWhiteSpace = [exports.EnumToken.CommentTokenType, exports.EnumToken.GtTokenType, exports.EnumToken.GteTokenType, exports.EnumToken.LtTokenType, exports.EnumToken.LteTokenType, exports.EnumToken.ColumnCombinatorTokenType];
17743
18069
  const BadTokensTypes = [
@@ -17756,9 +18082,12 @@ const enumTokenHints = new Set([
17756
18082
  function reject(reason) {
17757
18083
  throw new Error(reason ?? 'Parsing aborted');
17758
18084
  }
17759
- function normalizeVisitorKeyName(keyName) {
17760
- return keyName.replace(/-([a-z])/g, (all, one) => one.toUpperCase());
17761
- }
18085
+ /**
18086
+ * replace token in its parent node
18087
+ * @param parent
18088
+ * @param value
18089
+ * @param replacement
18090
+ */
17762
18091
  function replaceToken(parent, value, replacement) {
17763
18092
  for (const node of (Array.isArray(replacement) ? replacement : [replacement])) {
17764
18093
  if ('parent' in value && value.parent != node.parent) {
@@ -17786,11 +18115,129 @@ function replaceToken(parent, value, replacement) {
17786
18115
  target.splice(index, 1, ...(Array.isArray(replacement) ? replacement : [replacement]));
17787
18116
  }
17788
18117
  }
18118
+ /**
18119
+ * transform case of key name
18120
+ * @param key
18121
+ * @param how
18122
+ *
18123
+ * @throws Error
18124
+ * @private
18125
+ */
18126
+ function getKeyName(key, how) {
18127
+ switch (how) {
18128
+ case exports.ModuleCaseTransformEnum.CamelCase:
18129
+ case exports.ModuleCaseTransformEnum.CamelCaseOnly:
18130
+ return camelize(key);
18131
+ case exports.ModuleCaseTransformEnum.DashCase:
18132
+ case exports.ModuleCaseTransformEnum.DashCaseOnly:
18133
+ return dasherize(key);
18134
+ }
18135
+ return key;
18136
+ }
18137
+ /**
18138
+ * generate scoped name
18139
+ * @param localName
18140
+ * @param filePath
18141
+ * @param pattern
18142
+ * @param hashLength
18143
+ *
18144
+ * @throws Error
18145
+ * @private
18146
+ */
18147
+ async function generateScopedName(localName, filePath, pattern, hashLength = 5) {
18148
+ if (localName.startsWith('--')) {
18149
+ localName = localName.slice(2);
18150
+ }
18151
+ const matches = /.*?(([^/]+)\/)?([^/\\]*?)(\.([^?/]+))?([?].*)?$/.exec(filePath);
18152
+ const folder = matches?.[2]?.replace?.(/[^A-Za-z0-9_-]/g, "_") ?? '';
18153
+ const fileBase = matches?.[3] ?? '';
18154
+ const ext = matches?.[5] ?? '';
18155
+ const path = filePath.replace(/[^A-Za-z0-9_-]/g, "_");
18156
+ // sanitize localName for safe char set (replace spaces/illegal chars)
18157
+ const safeLocal = localName.replace(/[^A-Za-z0-9_-]/g, "_");
18158
+ const hashString = `${localName}::${filePath}`;
18159
+ let result = '';
18160
+ let inParens = 0;
18161
+ let key = '';
18162
+ let position = 0;
18163
+ // Compose final scoped name. Ensure the entire class doesn't start with digit:
18164
+ for (const char of pattern) {
18165
+ position += char.length;
18166
+ if (char == '[') {
18167
+ inParens++;
18168
+ if (inParens != 1) {
18169
+ throw new Error(`Unexpected character: '${char} at position ${position - 1}' in pattern '${pattern}'`);
18170
+ }
18171
+ continue;
18172
+ }
18173
+ if (char == ']') {
18174
+ inParens--;
18175
+ if (inParens != 0) {
18176
+ throw new Error(`Unexpected character: '${char}:${position - 1}'`);
18177
+ }
18178
+ let hashAlgo = null;
18179
+ let length = null;
18180
+ if (key.includes(':')) {
18181
+ const parts = key.split(':');
18182
+ if (parts.length == 2) {
18183
+ // @ts-ignore
18184
+ [key, length] = parts;
18185
+ // @ts-ignore
18186
+ if (key == 'hash' && hashAlgorithms.includes(length)) {
18187
+ // @ts-ignore
18188
+ hashAlgo = length;
18189
+ length = null;
18190
+ }
18191
+ }
18192
+ if (parts.length == 3) {
18193
+ // @ts-ignore
18194
+ [key, hashAlgo, length] = parts;
18195
+ }
18196
+ if (length != null && !Number.isInteger(+length)) {
18197
+ throw new Error(`Unsupported hash length: '${length}'. expecting format [hash:length] or [hash:hash-algo:length]`);
18198
+ }
18199
+ }
18200
+ switch (key) {
18201
+ case 'hash':
18202
+ result += await hash(hashString, length ?? hashLength, hashAlgo);
18203
+ break;
18204
+ case 'name':
18205
+ result += length != null ? fileBase.slice(0, +length) : fileBase;
18206
+ break;
18207
+ case 'local':
18208
+ result += length != null ? safeLocal.slice(0, +length) : localName;
18209
+ break;
18210
+ case 'ext':
18211
+ result += length != null ? ext.slice(0, +length) : ext;
18212
+ break;
18213
+ case 'path':
18214
+ result += length != null ? path.slice(0, +length) : path;
18215
+ break;
18216
+ case 'folder':
18217
+ result += length != null ? folder.slice(0, +length) : folder;
18218
+ break;
18219
+ default:
18220
+ throw new Error(`Unsupported key: '${key}'`);
18221
+ }
18222
+ key = '';
18223
+ continue;
18224
+ }
18225
+ if (inParens > 0) {
18226
+ key += char;
18227
+ }
18228
+ else {
18229
+ result += char;
18230
+ }
18231
+ }
18232
+ // if leading char is digit, prefix underscore (very rare)
18233
+ return (/^[0-9]/.test(result) ? '_' : '') + result;
18234
+ }
17789
18235
  /**
17790
18236
  * parse css string
17791
18237
  * @param iter
17792
18238
  * @param options
17793
18239
  *
18240
+ * @throws Error
17794
18241
  * @private
17795
18242
  */
17796
18243
  async function doParse(iter, options = {}) {
@@ -17822,6 +18269,9 @@ async function doParse(iter, options = {}) {
17822
18269
  if (typeof options.validation == 'boolean') {
17823
18270
  options.validation = options.validation ? exports.ValidationLevel.All : exports.ValidationLevel.None;
17824
18271
  }
18272
+ if (options.module) {
18273
+ options.expandNestingRules = true;
18274
+ }
17825
18275
  if (options.expandNestingRules) {
17826
18276
  options.nestingRules = false;
17827
18277
  }
@@ -18087,6 +18537,7 @@ async function doParse(iter, options = {}) {
18087
18537
  const root = await doParse(stream instanceof ReadableStream ? tokenizeStream(stream) : tokenize$1({
18088
18538
  stream,
18089
18539
  buffer: '',
18540
+ offset: 0,
18090
18541
  position: { ind: 0, lin: 1, col: 1 },
18091
18542
  currentPosition: { ind: -1, lin: 1, col: 0 }
18092
18543
  }), Object.assign({}, options, {
@@ -18146,7 +18597,7 @@ async function doParse(iter, options = {}) {
18146
18597
  }
18147
18598
  let node = result.node;
18148
18599
  for (const handler of handlers) {
18149
- callable = typeof handler == 'function' ? handler : handler[normalizeVisitorKeyName(node.typ == exports.EnumToken.DeclarationNodeType || node.typ == exports.EnumToken.AtRuleNodeType ? node.nam : node.val)];
18600
+ callable = typeof handler == 'function' ? handler : handler[camelize(node.typ == exports.EnumToken.DeclarationNodeType || node.typ == exports.EnumToken.AtRuleNodeType ? node.nam : node.val)];
18150
18601
  if (callable == null) {
18151
18602
  continue;
18152
18603
  }
@@ -18281,12 +18732,9 @@ async function doParse(iter, options = {}) {
18281
18732
  }
18282
18733
  }
18283
18734
  }
18284
- const endTime = performance.now();
18285
- if (options.signal != null) {
18286
- options.signal.removeEventListener('abort', reject);
18287
- }
18288
18735
  stats.bytesIn += stats.importedBytesIn;
18289
- return {
18736
+ let endTime = performance.now();
18737
+ const result = {
18290
18738
  ast,
18291
18739
  errors,
18292
18740
  stats: {
@@ -18296,6 +18744,503 @@ async function doParse(iter, options = {}) {
18296
18744
  total: `${(endTime - startTime).toFixed(2)}ms`
18297
18745
  }
18298
18746
  };
18747
+ if (options.module) {
18748
+ const moduleSettings = {
18749
+ hashLength: 5,
18750
+ filePath: '',
18751
+ scoped: exports.ModuleScopeEnumOptions.Local,
18752
+ naming: exports.ModuleCaseTransformEnum.IgnoreCase,
18753
+ pattern: '',
18754
+ generateScopedName,
18755
+ ...(typeof options.module != 'object' ? {} : options.module)
18756
+ };
18757
+ const parseModuleTime = performance.now();
18758
+ const namesMapping = {};
18759
+ const global = new Set;
18760
+ const processed = new Set;
18761
+ const pattern = typeof options.module == 'boolean' ? null : moduleSettings.pattern;
18762
+ const importMapping = {};
18763
+ const cssVariablesMap = {};
18764
+ const importedCssVariables = {};
18765
+ let mapping = {};
18766
+ let revMapping = {};
18767
+ let filePath = typeof options.module == 'boolean' ? options.src : (moduleSettings.filePath ?? options.src);
18768
+ filePath = filePath === '' ? options.src : options.resolve(filePath, options.dirname(options.src), options.cwd).relative;
18769
+ if (typeof options.module == 'number') {
18770
+ if (options.module & exports.ModuleCaseTransformEnum.CamelCase) {
18771
+ moduleSettings.naming = exports.ModuleCaseTransformEnum.CamelCase;
18772
+ }
18773
+ else if (options.module & exports.ModuleCaseTransformEnum.CamelCaseOnly) {
18774
+ moduleSettings.naming = exports.ModuleCaseTransformEnum.CamelCaseOnly;
18775
+ }
18776
+ else if (options.module & exports.ModuleCaseTransformEnum.DashCase) {
18777
+ moduleSettings.naming = exports.ModuleCaseTransformEnum.DashCase;
18778
+ }
18779
+ else if (options.module & exports.ModuleCaseTransformEnum.DashCaseOnly) {
18780
+ moduleSettings.naming = exports.ModuleCaseTransformEnum.DashCaseOnly;
18781
+ }
18782
+ if (options.module & exports.ModuleScopeEnumOptions.Global) {
18783
+ moduleSettings.scoped = exports.ModuleScopeEnumOptions.Global;
18784
+ }
18785
+ if (options.module & exports.ModuleScopeEnumOptions.Pure) {
18786
+ // @ts-ignore
18787
+ moduleSettings.scoped |= exports.ModuleScopeEnumOptions.Pure;
18788
+ }
18789
+ if (options.module & exports.ModuleScopeEnumOptions.ICSS) {
18790
+ // @ts-ignore
18791
+ moduleSettings.scoped |= exports.ModuleScopeEnumOptions.ICSS;
18792
+ }
18793
+ }
18794
+ if (typeof moduleSettings.scoped == 'boolean') {
18795
+ moduleSettings.scoped = moduleSettings.scoped ? exports.ModuleScopeEnumOptions.Local : exports.ModuleScopeEnumOptions.Global;
18796
+ }
18797
+ moduleSettings.filePath = filePath;
18798
+ moduleSettings.pattern = pattern != null && pattern !== '' ? pattern : (filePath === '' ? `[local]_[hash]` : `[local]_[hash]_[name]`);
18799
+ for (const { node, parent } of walk(ast)) {
18800
+ if (node.typ == exports.EnumToken.CssVariableImportTokenType) {
18801
+ const url = node.val.find(t => t.typ == exports.EnumToken.StringTokenType).val.slice(1, -1);
18802
+ const src = options.resolve(url, options.dirname(options.src), options.cwd);
18803
+ const result = options.load(url, options.src);
18804
+ const stream = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction' ? await result : result;
18805
+ const root = await doParse(stream instanceof ReadableStream ? tokenizeStream(stream) : tokenize$1({
18806
+ stream,
18807
+ buffer: '',
18808
+ offset: 0,
18809
+ position: { ind: 0, lin: 1, col: 1 },
18810
+ currentPosition: { ind: -1, lin: 1, col: 0 }
18811
+ }), Object.assign({}, options, {
18812
+ minify: false,
18813
+ setParent: false,
18814
+ src: src.relative
18815
+ }));
18816
+ cssVariablesMap[node.nam] = root.cssModuleVariables;
18817
+ parent.chi.splice(parent.chi.indexOf(node), 1);
18818
+ continue;
18819
+ }
18820
+ if (node.typ == exports.EnumToken.CssVariableDeclarationMapTokenType) {
18821
+ const from = node.from.find(t => t.typ == exports.EnumToken.IdenTokenType || isIdentColor(t));
18822
+ if (!(from.val in cssVariablesMap)) {
18823
+ errors.push({
18824
+ node,
18825
+ message: `could not resolve @value import from '${from.val}'`,
18826
+ action: 'drop'
18827
+ });
18828
+ }
18829
+ else {
18830
+ for (const token of node.vars) {
18831
+ if (token.typ == exports.EnumToken.IdenTokenType || isIdentColor(token)) {
18832
+ if (!(token.val in cssVariablesMap[from.val])) {
18833
+ errors.push({
18834
+ node,
18835
+ message: `value '${token.val}' is not exported from '${from.val}'`,
18836
+ action: 'drop'
18837
+ });
18838
+ continue;
18839
+ }
18840
+ result.cssModuleVariables ??= {};
18841
+ result.cssModuleVariables[token.val] = importedCssVariables[token.val] = cssVariablesMap[from.val][token.val];
18842
+ }
18843
+ }
18844
+ }
18845
+ parent.chi.splice(parent.chi.indexOf(node), 1);
18846
+ continue;
18847
+ }
18848
+ if (node.typ == exports.EnumToken.CssVariableTokenType) {
18849
+ if (parent?.typ == exports.EnumToken.StyleSheetNodeType) {
18850
+ if (result.cssModuleVariables == null) {
18851
+ result.cssModuleVariables = {};
18852
+ }
18853
+ result.cssModuleVariables[node.nam] = node;
18854
+ }
18855
+ parent.chi.splice(parent.chi.indexOf(node), 1);
18856
+ continue;
18857
+ }
18858
+ if (node.typ == exports.EnumToken.DeclarationNodeType) {
18859
+ if (node.nam.startsWith('--')) {
18860
+ if (!(node.nam in namesMapping)) {
18861
+ let result = (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Global) ? node.nam : moduleSettings.generateScopedName(node.nam, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
18862
+ let value = result instanceof Promise ? await result : result;
18863
+ mapping[node.nam] = '--' + (moduleSettings.naming & exports.ModuleCaseTransformEnum.DashCaseOnly || moduleSettings.naming & exports.ModuleCaseTransformEnum.CamelCaseOnly ? getKeyName(value, moduleSettings.naming) : value);
18864
+ revMapping[node.nam] = node.nam;
18865
+ }
18866
+ node.nam = mapping[node.nam];
18867
+ }
18868
+ if ('composes' == node.nam.toLowerCase()) {
18869
+ const tokens = [];
18870
+ let isValid = true;
18871
+ for (const token of node.val) {
18872
+ if (token.typ == exports.EnumToken.ComposesSelectorNodeType) {
18873
+ if (!(token.r == null || token.r.typ == exports.EnumToken.StringTokenType || token.r.typ == exports.EnumToken.IdenTokenType)) {
18874
+ errors.push({
18875
+ action: 'drop',
18876
+ message: `composes '${exports.EnumToken[token.r.typ]}' is not supported`,
18877
+ node
18878
+ });
18879
+ isValid = false;
18880
+ break;
18881
+ }
18882
+ tokens.push(token);
18883
+ }
18884
+ }
18885
+ // find parent rule
18886
+ let parentRule = node.parent;
18887
+ while (parentRule != null && parentRule.typ != exports.EnumToken.RuleNodeType) {
18888
+ parentRule = parentRule.parent;
18889
+ }
18890
+ if (!isValid || tokens.length == 0) {
18891
+ if (tokens.length == 0) {
18892
+ errors.push({
18893
+ action: 'drop',
18894
+ message: `composes is empty`,
18895
+ node
18896
+ });
18897
+ }
18898
+ parentRule.chi.splice(parentRule.chi.indexOf(node), 1);
18899
+ continue;
18900
+ }
18901
+ for (const token of tokens) {
18902
+ // composes: a b c;
18903
+ if (token.r == null) {
18904
+ for (const rule of token.l) {
18905
+ if (rule.typ == exports.EnumToken.WhitespaceTokenType || rule.typ == exports.EnumToken.CommentTokenType) {
18906
+ continue;
18907
+ }
18908
+ if (!(rule.val in mapping)) {
18909
+ let result = (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Global) ? rule.val : moduleSettings.generateScopedName(rule.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
18910
+ let value = result instanceof Promise ? await result : result;
18911
+ mapping[rule.val] = (rule.typ == exports.EnumToken.DashedIdenTokenType ? '--' : '') + (moduleSettings.naming & exports.ModuleCaseTransformEnum.DashCaseOnly || moduleSettings.naming & exports.ModuleCaseTransformEnum.CamelCaseOnly ? getKeyName(value, moduleSettings.naming) : value);
18912
+ revMapping[mapping[rule.val]] = rule.val;
18913
+ }
18914
+ if (parentRule != null) {
18915
+ for (const tk of parentRule.tokens) {
18916
+ if (tk.typ == exports.EnumToken.ClassSelectorTokenType) {
18917
+ const val = tk.val.slice(1);
18918
+ if (val in revMapping) {
18919
+ const key = revMapping[val];
18920
+ mapping[key] = [...new Set([...mapping[key].split(' '), mapping[rule.val]])].join(' ');
18921
+ }
18922
+ }
18923
+ }
18924
+ }
18925
+ }
18926
+ }
18927
+ // composes: a b c from 'file.css';
18928
+ else if (token.r.typ == exports.EnumToken.String) {
18929
+ const url = token.r.val.slice(1, -1);
18930
+ const src = options.resolve(url, options.dirname(options.src), options.cwd);
18931
+ const result = options.load(url, options.src);
18932
+ const stream = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction' ? await result : result;
18933
+ const root = await doParse(stream instanceof ReadableStream ? tokenizeStream(stream) : tokenize$1({
18934
+ stream,
18935
+ buffer: '',
18936
+ offset: 0,
18937
+ position: { ind: 0, lin: 1, col: 1 },
18938
+ currentPosition: { ind: -1, lin: 1, col: 0 }
18939
+ }), Object.assign({}, options, {
18940
+ minify: false,
18941
+ setParent: false,
18942
+ src: src.relative
18943
+ }));
18944
+ const srcIndex = (src.relative.startsWith('/') || src.relative.startsWith('../') ? '' : './') + src.relative;
18945
+ if (Object.keys(root.mapping).length > 0) {
18946
+ importMapping[srcIndex] = {};
18947
+ }
18948
+ if (parentRule != null) {
18949
+ for (const tk of parentRule.tokens) {
18950
+ if (tk.typ == exports.EnumToken.ClassSelectorTokenType) {
18951
+ const val = tk.val.slice(1);
18952
+ if (val in revMapping) {
18953
+ const key = revMapping[val];
18954
+ const values = [];
18955
+ for (const iden of token.l) {
18956
+ if (iden.typ != exports.EnumToken.IdenTokenType && iden.typ != exports.EnumToken.DashedIdenTokenType) {
18957
+ continue;
18958
+ }
18959
+ if (!(iden.val in root.mapping)) {
18960
+ const result = (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Global) ? iden.val : moduleSettings.generateScopedName(iden.val, srcIndex, moduleSettings.pattern, moduleSettings.hashLength);
18961
+ let value = result instanceof Promise ? await result : result;
18962
+ root.mapping[iden.val] = (moduleSettings.naming & exports.ModuleCaseTransformEnum.DashCaseOnly || moduleSettings.naming & exports.ModuleCaseTransformEnum.CamelCaseOnly ? getKeyName(value, moduleSettings.naming) : value);
18963
+ root.revMapping[root.mapping[iden.val]] = iden.val;
18964
+ }
18965
+ importMapping[srcIndex][iden.val] = root.mapping[iden.val];
18966
+ values.push(root.mapping[iden.val]);
18967
+ }
18968
+ mapping[key] = [...new Set([...mapping[key].split(' '), ...values])].join(' ');
18969
+ }
18970
+ }
18971
+ }
18972
+ }
18973
+ }
18974
+ // composes: a b c from global;
18975
+ else if (token.r.typ == exports.EnumToken.IdenTokenType) {
18976
+ // global
18977
+ if (parentRule != null) {
18978
+ if ('global' == token.r.val.toLowerCase()) {
18979
+ for (const tk of parentRule.tokens) {
18980
+ if (tk.typ == exports.EnumToken.ClassSelectorTokenType) {
18981
+ const val = tk.val.slice(1);
18982
+ if (val in revMapping) {
18983
+ const key = revMapping[val];
18984
+ mapping[key] = [...new Set([...mapping[key].split(' '), ...(token.l.reduce((acc, curr) => {
18985
+ if (curr.typ == exports.EnumToken.IdenTokenType) {
18986
+ acc.push(curr.val);
18987
+ }
18988
+ return acc;
18989
+ }, []))])].join(' ');
18990
+ }
18991
+ }
18992
+ }
18993
+ }
18994
+ else {
18995
+ errors.push({
18996
+ action: 'drop',
18997
+ message: `composes '${token.r.val}' is not supported`,
18998
+ node
18999
+ });
19000
+ }
19001
+ }
19002
+ }
19003
+ }
19004
+ parentRule.chi.splice(parentRule.chi.indexOf(node), 1);
19005
+ }
19006
+ if (node.typ == exports.EnumToken.DeclarationNodeType && ['grid-column', 'grid-column-start', 'grid-column-end', 'grid-row', 'grid-row-start', 'grid-row-end', 'grid-template', 'grid-template-columns', 'grid-template-rows'].includes(node.nam)) {
19007
+ for (const { value } of walkValues(node.val, node)) {
19008
+ if (value.typ != exports.EnumToken.IdenTokenType) {
19009
+ continue;
19010
+ }
19011
+ let idenToken = value.val;
19012
+ let suffix = '';
19013
+ if (idenToken.endsWith('-start')) {
19014
+ suffix = '-start';
19015
+ idenToken = idenToken.slice(0, -6);
19016
+ }
19017
+ else if (idenToken.endsWith('-end')) {
19018
+ suffix = '-end';
19019
+ idenToken = idenToken.slice(0, -4);
19020
+ }
19021
+ if (!(idenToken in mapping)) {
19022
+ let result = (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Global) ? idenToken : moduleSettings.generateScopedName(idenToken, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
19023
+ if (result instanceof Promise) {
19024
+ result = await result;
19025
+ }
19026
+ mapping[idenToken] = result;
19027
+ revMapping[result] = idenToken;
19028
+ if (suffix !== '') {
19029
+ idenToken += suffix;
19030
+ if (!(idenToken in mapping)) {
19031
+ mapping[idenToken] = result + suffix;
19032
+ revMapping[result + suffix] = idenToken;
19033
+ }
19034
+ }
19035
+ }
19036
+ value.val = mapping[idenToken];
19037
+ }
19038
+ }
19039
+ else if (node.nam == 'grid-template-areas' || node.nam == 'grid-template') {
19040
+ for (let i = 0; i < node.val.length; i++) {
19041
+ if (node.val[i].typ == exports.EnumToken.String) {
19042
+ const tokens = parseString(node.val[i].val.slice(1, -1), { location: true });
19043
+ for (const { value } of walkValues(tokens)) {
19044
+ if (value.typ == exports.EnumToken.IdenTokenType || value.typ == exports.EnumToken.DashedIdenTokenType) {
19045
+ if (value.val in mapping) {
19046
+ value.val = mapping[value.val];
19047
+ }
19048
+ else {
19049
+ let result = (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Global) ? value.val : moduleSettings.generateScopedName(value.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
19050
+ if (result instanceof Promise) {
19051
+ result = await result;
19052
+ }
19053
+ mapping[value.val] = result;
19054
+ revMapping[result] = value.val;
19055
+ value.val = result;
19056
+ }
19057
+ }
19058
+ }
19059
+ node.val[i].val = node.val[i].val.charAt(0) + tokens.reduce((acc, curr) => acc + renderToken(curr), '') + node.val[i].val.charAt(node.val[i].val.length - 1);
19060
+ }
19061
+ }
19062
+ }
19063
+ else if (node.nam == 'animation' || node.nam == 'animation-name') {
19064
+ for (const { value } of walkValues(node.val, node)) {
19065
+ if (value.typ == exports.EnumToken.IdenTokenType && ![
19066
+ 'none', 'infinite', 'normal', 'reverse', 'alternate',
19067
+ 'alternate-reverse', 'forwards', 'backwards', 'both',
19068
+ 'running', 'paused', 'linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out',
19069
+ 'step-start', 'step-end', 'jump-start', 'jump-end',
19070
+ 'jump-none', 'jump-both', 'start', 'end',
19071
+ 'inherit', 'initial', 'unset'
19072
+ ].includes(value.val)) {
19073
+ if (!(value.val in mapping)) {
19074
+ const result = (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Global) ? value.val : moduleSettings.generateScopedName(value.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
19075
+ mapping[value.val] = result instanceof Promise ? await result : result;
19076
+ revMapping[mapping[value.val]] = value.val;
19077
+ }
19078
+ value.val = mapping[value.val];
19079
+ }
19080
+ }
19081
+ }
19082
+ for (const { value, parent } of walkValues(node.val, node)) {
19083
+ if (value.typ == exports.EnumToken.DashedIdenTokenType) {
19084
+ if (!(value.val in mapping)) {
19085
+ const result = (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Global) ? value.val : moduleSettings.generateScopedName(value.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
19086
+ let val = result instanceof Promise ? await result : result;
19087
+ mapping[value.val] = '--' + (moduleSettings.naming & exports.ModuleCaseTransformEnum.DashCaseOnly || moduleSettings.naming & exports.ModuleCaseTransformEnum.CamelCaseOnly ? getKeyName(val, moduleSettings.naming) : val);
19088
+ revMapping[mapping[value.val]] = value.val;
19089
+ }
19090
+ value.val = mapping[value.val];
19091
+ }
19092
+ else if ((value.typ == exports.EnumToken.IdenTokenType || isIdentColor(value)) && value.val in importedCssVariables) {
19093
+ replaceToken(parent, value, importedCssVariables[value.val].val);
19094
+ }
19095
+ }
19096
+ }
19097
+ else if (node.typ == exports.EnumToken.RuleNodeType) {
19098
+ if (node.tokens == null) {
19099
+ Object.defineProperty(node, 'tokens', {
19100
+ ...definedPropertySettings,
19101
+ value: parseSelector(parseString(node.sel, { location: true }))
19102
+ });
19103
+ }
19104
+ let hasIdOrClass = false;
19105
+ for (const { value } of walkValues(node.tokens, node,
19106
+ // @ts-ignore
19107
+ (value, parent) => {
19108
+ if (value.typ == exports.EnumToken.PseudoClassTokenType) {
19109
+ const val = value.val.toLowerCase();
19110
+ switch (val) {
19111
+ case ':local':
19112
+ case ':global':
19113
+ {
19114
+ let index = parent.tokens.indexOf(value);
19115
+ parent.tokens.splice(index, 1);
19116
+ if (parent.tokens[index]?.typ == exports.EnumToken.WhitespaceTokenType || parent.tokens[index]?.typ == exports.EnumToken.DescendantCombinatorTokenType) {
19117
+ parent.tokens.splice(index, 1);
19118
+ }
19119
+ if (val == ':global') {
19120
+ for (; index < parent.tokens.length; index++) {
19121
+ if (parent.tokens[index].typ == exports.EnumToken.CommaTokenType ||
19122
+ ([exports.EnumToken.PseudoClassFuncTokenType, exports.EnumToken.PseudoClassTokenType].includes(parent.tokens[index].typ) &&
19123
+ [':global', ':local'].includes(parent.tokens[index].val.toLowerCase()))) {
19124
+ break;
19125
+ }
19126
+ global.add(parent.tokens[index]);
19127
+ }
19128
+ }
19129
+ }
19130
+ break;
19131
+ }
19132
+ }
19133
+ else if (value.typ == exports.EnumToken.PseudoClassFuncTokenType) {
19134
+ switch (value.val.toLowerCase()) {
19135
+ case ':global':
19136
+ for (const token of value.chi) {
19137
+ global.add(token);
19138
+ }
19139
+ parent.tokens.splice(parent.tokens.indexOf(value), 1, ...value.chi);
19140
+ break;
19141
+ case ':local':
19142
+ parent.tokens.splice(parent.tokens.indexOf(value), 1, ...value.chi);
19143
+ break;
19144
+ }
19145
+ }
19146
+ })) {
19147
+ if (value.typ == exports.EnumToken.HashTokenType || value.typ == exports.EnumToken.ClassSelectorTokenType) {
19148
+ hasIdOrClass = true;
19149
+ }
19150
+ if (processed.has(value)) {
19151
+ continue;
19152
+ }
19153
+ processed.add(value);
19154
+ if (value.typ == exports.EnumToken.PseudoClassTokenType) ;
19155
+ else if (value.typ == exports.EnumToken.PseudoClassFuncTokenType) ;
19156
+ else {
19157
+ if (global.has(value)) {
19158
+ continue;
19159
+ }
19160
+ if (value.typ == exports.EnumToken.ClassSelectorTokenType) {
19161
+ const val = value.val.slice(1);
19162
+ if (!(val in mapping)) {
19163
+ const result = (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Global) ? val : moduleSettings.generateScopedName(val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
19164
+ let value = result instanceof Promise ? await result : result;
19165
+ mapping[val] = (moduleSettings.naming & exports.ModuleCaseTransformEnum.DashCaseOnly || moduleSettings.naming & exports.ModuleCaseTransformEnum.CamelCaseOnly ? getKeyName(value, moduleSettings.naming) : value);
19166
+ revMapping[mapping[val]] = val;
19167
+ }
19168
+ value.val = '.' + mapping[val];
19169
+ }
19170
+ }
19171
+ }
19172
+ if (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Pure) {
19173
+ if (!hasIdOrClass) {
19174
+ throw new Error(`pure module: No id or class found in selector '${node.sel}' at '${node.loc?.src ?? ''}':${node.loc?.sta?.lin ?? ''}:${node.loc?.sta?.col ?? ''}`);
19175
+ }
19176
+ }
19177
+ node.sel = '';
19178
+ for (const token of node.tokens) {
19179
+ node.sel += renderToken(token);
19180
+ }
19181
+ }
19182
+ else if (node.typ == exports.EnumToken.AtRuleNodeType || node.typ == exports.EnumToken.KeyframesAtRuleNodeType) {
19183
+ const val = node.nam.toLowerCase();
19184
+ if (node.tokens == null) {
19185
+ Object.defineProperty(node, 'tokens', {
19186
+ ...definedPropertySettings,
19187
+ // @ts-ignore
19188
+ value: parseAtRulePrelude(parseString(node.val), node)
19189
+ });
19190
+ }
19191
+ if (val == 'property' || val == 'keyframes') {
19192
+ const prefix = val == 'property' ? '--' : '';
19193
+ for (const value of node.tokens) {
19194
+ if ((prefix == '--' && value.typ == exports.EnumToken.DashedIdenTokenType) || (prefix == '' && value.typ == exports.EnumToken.IdenTokenType)) {
19195
+ if (!(value.val in mapping)) {
19196
+ const result = (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Global) ? value.val : moduleSettings.generateScopedName(value.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
19197
+ let val = result instanceof Promise ? await result : result;
19198
+ mapping[value.val] = prefix + (moduleSettings.naming & exports.ModuleCaseTransformEnum.DashCaseOnly || moduleSettings.naming & exports.ModuleCaseTransformEnum.CamelCaseOnly ? getKeyName(val, moduleSettings.naming) : val);
19199
+ revMapping[mapping[value.val]] = value.val;
19200
+ }
19201
+ value.val = mapping[value.val];
19202
+ }
19203
+ }
19204
+ node.val = node.tokens.reduce((a, b) => a + renderToken(b), '');
19205
+ }
19206
+ else {
19207
+ let isReplaced = false;
19208
+ for (const { value, parent } of walkValues(node.tokens, node)) {
19209
+ if (exports.EnumToken.MediaQueryConditionTokenType == parent.typ && value != parent.l) {
19210
+ if ((value.typ == exports.EnumToken.IdenTokenType || isIdentColor(value)) && value.val in importedCssVariables) {
19211
+ isReplaced = true;
19212
+ parent.r.splice(parent.r.indexOf(value), 1, ...importedCssVariables[value.val].val);
19213
+ }
19214
+ }
19215
+ }
19216
+ if (isReplaced) {
19217
+ node.val = node.tokens.reduce((a, b) => a + renderToken(b), '');
19218
+ }
19219
+ }
19220
+ }
19221
+ }
19222
+ if (moduleSettings.naming != exports.ModuleCaseTransformEnum.IgnoreCase) {
19223
+ revMapping = {};
19224
+ mapping = Object.entries(mapping).reduce((acc, [key, value]) => {
19225
+ const keyName = getKeyName(key, moduleSettings.naming);
19226
+ acc[keyName] = value;
19227
+ revMapping[value] = keyName;
19228
+ return acc;
19229
+ }, {});
19230
+ }
19231
+ result.mapping = mapping;
19232
+ result.revMapping = revMapping;
19233
+ if ((moduleSettings.scoped & exports.ModuleScopeEnumOptions.ICSS) && Object.keys(importMapping).length > 0) {
19234
+ result.importMapping = importMapping;
19235
+ }
19236
+ endTime = performance.now();
19237
+ result.stats.module = `${(endTime - parseModuleTime).toFixed(2)}ms`;
19238
+ result.stats.total = `${(endTime - startTime).toFixed(2)}ms`;
19239
+ }
19240
+ if (options.signal != null) {
19241
+ options.signal.removeEventListener('abort', reject);
19242
+ }
19243
+ return result;
18299
19244
  }
18300
19245
  function getLastNode(context) {
18301
19246
  let i = context.chi.length;
@@ -18513,6 +19458,147 @@ function parseNode(results, context, options, errors, src, map, rawTokens, stats
18513
19458
  isValid = false;
18514
19459
  }
18515
19460
  }
19461
+ if (node.nam == 'value') {
19462
+ let i = 0;
19463
+ while (i < tokens.length) {
19464
+ if (tokens[i].typ == exports.EnumToken.WhitespaceTokenType || tokens[i].typ == exports.EnumToken.CommentTokenType) {
19465
+ i++;
19466
+ continue;
19467
+ }
19468
+ break;
19469
+ }
19470
+ if (i < tokens.length) {
19471
+ if (tokens[i].typ == exports.EnumToken.IdenTokenType || isIdentColor(tokens[i])) {
19472
+ let k = i + 1;
19473
+ while (k < tokens.length) {
19474
+ if (tokens[k].typ == exports.EnumToken.WhitespaceTokenType || tokens[k].typ == exports.EnumToken.CommentTokenType) {
19475
+ k++;
19476
+ continue;
19477
+ }
19478
+ // var or import
19479
+ if (tokens[k].typ == exports.EnumToken.ColonTokenType) {
19480
+ let j = k;
19481
+ while (++j < tokens.length) {
19482
+ if (tokens[j].typ != exports.EnumToken.WhitespaceTokenType && tokens[j].typ != exports.EnumToken.CommentTokenType) {
19483
+ break;
19484
+ }
19485
+ }
19486
+ let offset = k + 1;
19487
+ while (offset < tokens.length && tokens[offset].typ == exports.EnumToken.WhitespaceTokenType) {
19488
+ offset++;
19489
+ }
19490
+ if (tokens[j].typ == exports.EnumToken.StringTokenType) {
19491
+ Object.assign(node, {
19492
+ typ: exports.EnumToken.CssVariableImportTokenType,
19493
+ nam: tokens[i].val,
19494
+ val: tokens.slice(offset)
19495
+ });
19496
+ delete node.tokens;
19497
+ // @ts-ignore
19498
+ delete node.raw;
19499
+ context.chi.push(node);
19500
+ return null;
19501
+ }
19502
+ Object.assign(node, {
19503
+ typ: exports.EnumToken.CssVariableTokenType,
19504
+ nam: tokens[i].val,
19505
+ val: tokens.slice(offset)
19506
+ });
19507
+ context.chi.push(node);
19508
+ return null;
19509
+ }
19510
+ if (tokens[k].typ == exports.EnumToken.PseudoClassTokenType) {
19511
+ Object.assign(tokens[k], {
19512
+ typ: exports.EnumToken.IdenTokenType,
19513
+ val: tokens[k].val.slice(1)
19514
+ });
19515
+ Object.assign(node, {
19516
+ typ: exports.EnumToken.CssVariableTokenType,
19517
+ nam: tokens[i].val,
19518
+ val: tokens.slice(k)
19519
+ });
19520
+ context.chi.push(node);
19521
+ return null;
19522
+ }
19523
+ if (tokens[k].typ == exports.EnumToken.CommaTokenType) {
19524
+ let j = i;
19525
+ while (++j < tokens.length) {
19526
+ if (tokens[j].typ == exports.EnumToken.IdenTokenType && tokens[j].val.toLowerCase() == 'from') {
19527
+ const vars = tokens.slice(i, j);
19528
+ const from = tokens.slice(j + 1);
19529
+ let l = 0;
19530
+ let expect = exports.EnumToken.IdenTokenType;
19531
+ for (; l < vars.length; l++) {
19532
+ if (vars[l].typ == exports.EnumToken.WhitespaceTokenType || vars[l].typ == exports.EnumToken.CommentTokenType) {
19533
+ continue;
19534
+ }
19535
+ if (expect == vars[l].typ || (expect == exports.EnumToken.IdenTokenType && isIdentColor(vars[l]))) {
19536
+ expect = expect == exports.EnumToken.CommaTokenType ? exports.EnumToken.IdenTokenType : exports.EnumToken.CommaTokenType;
19537
+ continue;
19538
+ }
19539
+ errors.push({
19540
+ action: 'drop',
19541
+ node: node,
19542
+ location: map.get(vars[l]) ?? location,
19543
+ message: `expecting '${exports.EnumToken[expect]}' but found ${renderToken(vars[l])}`
19544
+ });
19545
+ return null;
19546
+ }
19547
+ l = 0;
19548
+ expect = exports.EnumToken.IdenTokenType;
19549
+ for (; l < from.length; l++) {
19550
+ if (from[l].typ == exports.EnumToken.WhitespaceTokenType || from[l].typ == exports.EnumToken.CommentTokenType) {
19551
+ continue;
19552
+ }
19553
+ if (expect == from[l].typ || isIdentColor(from[l])) {
19554
+ while (++l < from.length) {
19555
+ if (from[l].typ == exports.EnumToken.WhitespaceTokenType || from[l].typ == exports.EnumToken.CommentTokenType) {
19556
+ continue;
19557
+ }
19558
+ errors.push({
19559
+ action: 'drop',
19560
+ node: node,
19561
+ location: map.get(from[l]) ?? location,
19562
+ message: `unexpected '${renderToken(from[l])}'`
19563
+ });
19564
+ return null;
19565
+ }
19566
+ break;
19567
+ }
19568
+ errors.push({
19569
+ action: 'drop',
19570
+ node: node,
19571
+ location: map.get(from[l]) ?? location,
19572
+ message: `expecting <string> but found ${renderToken(from[l])}`
19573
+ });
19574
+ return null;
19575
+ }
19576
+ // @ts-ignore
19577
+ delete node.nam;
19578
+ // @ts-ignore
19579
+ delete node.val;
19580
+ Object.assign(node, {
19581
+ typ: exports.EnumToken.CssVariableDeclarationMapTokenType,
19582
+ vars,
19583
+ from
19584
+ });
19585
+ context.chi.push(node);
19586
+ return null;
19587
+ }
19588
+ }
19589
+ }
19590
+ k++;
19591
+ }
19592
+ Object.assign(node, {
19593
+ typ: exports.EnumToken.CssVariableTokenType,
19594
+ nam: tokens[i].val,
19595
+ val: tokens.slice(k)
19596
+ });
19597
+ context.chi.push(node);
19598
+ return null;
19599
+ }
19600
+ }
19601
+ }
18516
19602
  // @ts-ignore
18517
19603
  const skipValidate = (options.validation & exports.ValidationLevel.AtRule) == 0;
18518
19604
  const isAllowed = skipValidate || isNodeAllowedInContext(node, context);
@@ -19051,6 +20137,7 @@ async function parseDeclarations(declaration) {
19051
20137
  return doParse(tokenize$1({
19052
20138
  stream: `.x{${declaration}}`,
19053
20139
  buffer: '',
20140
+ offset: 0,
19054
20141
  position: { ind: 0, lin: 1, col: 1 },
19055
20142
  currentPosition: { ind: -1, lin: 1, col: 0 }
19056
20143
  }), { setParent: false, minify: false, validation: false }).then(result => {
@@ -19171,6 +20258,7 @@ function parseString(src, options = { location: false }) {
19171
20258
  const parseInfo = {
19172
20259
  stream: src,
19173
20260
  buffer: '',
20261
+ offset: 0,
19174
20262
  position: { ind: 0, lin: 1, col: 1 },
19175
20263
  currentPosition: { ind: -1, lin: 1, col: 0 }
19176
20264
  };
@@ -19296,12 +20384,10 @@ function getTokenType(val, hint) {
19296
20384
  val: +val.slice(0, -1)
19297
20385
  };
19298
20386
  }
19299
- // if (isDimension(val)) {
19300
20387
  const dimension = parseDimension(val);
19301
20388
  if (dimension != null) {
19302
20389
  return dimension;
19303
20390
  }
19304
- // }
19305
20391
  const v = val.toLowerCase();
19306
20392
  if (v == 'currentcolor' || v == 'transparent' || v in COLORS_NAMES) {
19307
20393
  return {
@@ -19330,6 +20416,12 @@ function getTokenType(val, hint) {
19330
20416
  val
19331
20417
  };
19332
20418
  }
20419
+ if (val.charAt(0) == '.' && isIdent(val.slice(1))) {
20420
+ return {
20421
+ typ: exports.EnumToken.ClassSelectorTokenType,
20422
+ val
20423
+ };
20424
+ }
19333
20425
  if (val.charAt(0) == '#' && isHexColor(val)) {
19334
20426
  return {
19335
20427
  typ: exports.EnumToken.ColorTokenType,
@@ -19377,6 +20469,55 @@ function getTokenType(val, hint) {
19377
20469
  function parseTokens(tokens, options = {}) {
19378
20470
  for (let i = 0; i < tokens.length; i++) {
19379
20471
  const t = tokens[i];
20472
+ if (t.typ == exports.EnumToken.IdenTokenType && t.val == 'from' && i > 0) {
20473
+ const left = [];
20474
+ const right = [];
20475
+ let foundLeft = 0;
20476
+ let foundRight = 0;
20477
+ let k = i;
20478
+ let l = i;
20479
+ while (k > 0) {
20480
+ if (tokens[k - 1].typ == exports.EnumToken.CommentTokenType || tokens[k - 1].typ == exports.EnumToken.WhitespaceTokenType) {
20481
+ left.push(tokens[--k]);
20482
+ continue;
20483
+ }
20484
+ if (tokens[k - 1].typ == exports.EnumToken.IdenTokenType || tokens[k - 1].typ == exports.EnumToken.DashedIdenTokenType) {
20485
+ foundLeft++;
20486
+ left.push(tokens[--k]);
20487
+ continue;
20488
+ }
20489
+ break;
20490
+ }
20491
+ while (++l < tokens.length) {
20492
+ if (tokens[l].typ == exports.EnumToken.CommentTokenType || tokens[l].typ == exports.EnumToken.WhitespaceTokenType) {
20493
+ right.push(tokens[l]);
20494
+ continue;
20495
+ }
20496
+ if (tokens[l].typ == exports.EnumToken.IdenTokenType || tokens[l].typ == exports.EnumToken.StringTokenType) {
20497
+ foundRight++;
20498
+ right.push(tokens[l]);
20499
+ continue;
20500
+ }
20501
+ break;
20502
+ }
20503
+ if (foundLeft > 0 && foundRight == 1) {
20504
+ while (left?.[0].typ == exports.EnumToken.WhitespaceTokenType) {
20505
+ left.shift();
20506
+ }
20507
+ while (left.at(-1)?.typ == exports.EnumToken.WhitespaceTokenType) {
20508
+ left.pop();
20509
+ }
20510
+ tokens.splice(k, l - k + 1, {
20511
+ typ: exports.EnumToken.ComposesSelectorNodeType,
20512
+ l: left,
20513
+ r: right.reduce((a, b) => {
20514
+ return a == null ? b : b.typ == exports.EnumToken.IdenTokenType || b.typ == exports.EnumToken.StringTokenType ? b : a;
20515
+ }, null)
20516
+ });
20517
+ i = k;
20518
+ continue;
20519
+ }
20520
+ }
19380
20521
  if (t.typ == exports.EnumToken.WhitespaceTokenType && ((i == 0 ||
19381
20522
  i + 1 == tokens.length ||
19382
20523
  [exports.EnumToken.CommaTokenType, exports.EnumToken.GteTokenType, exports.EnumToken.LteTokenType, exports.EnumToken.ColumnCombinatorTokenType].includes(tokens[i + 1].typ)) ||
@@ -19885,7 +21026,6 @@ function* walk(node, filter, reverse) {
19885
21026
  * ```
19886
21027
  */
19887
21028
  function* walkValues(values, root = null, filter, reverse) {
19888
- // const set = new Set<Token>();
19889
21029
  const stack = values.slice();
19890
21030
  const map = new Map;
19891
21031
  let previous = null;
@@ -19919,8 +21059,12 @@ function* walkValues(values, root = null, filter, reverse) {
19919
21059
  continue;
19920
21060
  }
19921
21061
  // @ts-ignore
19922
- if (option != null && typeof option == 'object' && 'typ' in option) {
19923
- map.set(option, map.get(value) ?? root);
21062
+ if (option != null && typeof option == 'object' && ('typ' in option || Array.isArray(option))) {
21063
+ const op = Array.isArray(option) ? option : [option];
21064
+ for (const o of op) {
21065
+ map.set(o, map.get(value) ?? root);
21066
+ }
21067
+ stack[reverse ? 'push' : 'unshift'](...op);
19924
21068
  }
19925
21069
  }
19926
21070
  }
@@ -19943,12 +21087,12 @@ function* walkValues(values, root = null, filter, reverse) {
19943
21087
  const values = [];
19944
21088
  if ('l' in value && value.l != null) {
19945
21089
  // @ts-ignore
19946
- values[reverse ? 'push' : 'unshift'](value.l);
21090
+ values.push(value.l);
19947
21091
  // @ts-ignore
19948
21092
  map.set(value.l, value);
19949
21093
  }
19950
21094
  if ('op' in value && typeof value.op == 'object') {
19951
- values[reverse ? 'push' : 'unshift'](value.op);
21095
+ values.push(value.op);
19952
21096
  // @ts-ignore
19953
21097
  map.set(value.op, value);
19954
21098
  }
@@ -19956,14 +21100,14 @@ function* walkValues(values, root = null, filter, reverse) {
19956
21100
  if (Array.isArray(value.r)) {
19957
21101
  for (const r of value.r) {
19958
21102
  // @ts-ignore
19959
- values[reverse ? 'push' : 'unshift'](r);
21103
+ values.push(r);
19960
21104
  // @ts-ignore
19961
21105
  map.set(r, value);
19962
21106
  }
19963
21107
  }
19964
21108
  else {
19965
21109
  // @ts-ignore
19966
- values[reverse ? 'push' : 'unshift'](value.r);
21110
+ values.push(value.r);
19967
21111
  // @ts-ignore
19968
21112
  map.set(value.r, value);
19969
21113
  }
@@ -19979,8 +21123,12 @@ function* walkValues(values, root = null, filter, reverse) {
19979
21123
  if (isValid) {
19980
21124
  option = filter.fn(value, map.get(value), exports.WalkerEvent.Leave);
19981
21125
  // @ts-ignore
19982
- if (option != null && 'typ' in option) {
19983
- map.set(option, map.get(value) ?? root);
21126
+ if (option != null && ('typ' in option || Array.isArray(option))) {
21127
+ const op = Array.isArray(option) ? option : [option];
21128
+ for (const o of op) {
21129
+ map.set(o, map.get(value) ?? root);
21130
+ }
21131
+ stack[reverse ? 'push' : 'unshift'](...op);
19984
21132
  }
19985
21133
  }
19986
21134
  }
@@ -21058,9 +22206,12 @@ class PropertyList {
21058
22206
  });
21059
22207
  }
21060
22208
  add(...declarations) {
22209
+ let name;
21061
22210
  for (const declaration of declarations) {
22211
+ name = declaration.typ != exports.EnumToken.DeclarationNodeType ? null : declaration.nam.toLowerCase();
21062
22212
  if (declaration.typ != exports.EnumToken.DeclarationNodeType ||
21063
- (typeof this.options.removeDuplicateDeclarations === 'string' && this.options.removeDuplicateDeclarations === declaration.nam.toLowerCase()) ||
22213
+ 'composes' === name ||
22214
+ (typeof this.options.removeDuplicateDeclarations === 'string' && this.options.removeDuplicateDeclarations === name) ||
21064
22215
  (Array.isArray(this.options.removeDuplicateDeclarations) ? this.options.removeDuplicateDeclarations.includes(declaration.nam) : !this.options.removeDuplicateDeclarations)) {
21065
22216
  this.declarations.set(Number(Math.random().toString().slice(2)).toString(36), declaration);
21066
22217
  continue;
@@ -22668,7 +23819,7 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
22668
23819
  nodeIndex = i;
22669
23820
  }
22670
23821
  if (recursive && node != null && ('chi' in node)) {
22671
- if (node.typ == exports.EnumToken.KeyframesAtRuleNodeType || !node.chi.some(n => n.typ == exports.EnumToken.DeclarationNodeType)) {
23822
+ if (node.typ == exports.EnumToken.KeyframesAtRuleNodeType || !node.chi.some((n) => n.typ == exports.EnumToken.DeclarationNodeType)) {
22672
23823
  if (!(node.typ == exports.EnumToken.AtRuleNodeType && node.nam != 'font-face')) {
22673
23824
  doMinify(node, options, recursive, errors, nestingContent, context);
22674
23825
  }
@@ -23491,28 +24642,40 @@ function replaceCompoundLiteral(selector, replace) {
23491
24642
  * load file or url as stream
23492
24643
  * @param url
23493
24644
  * @param currentFile
23494
- * @param asStream
24645
+ * @param responseType
23495
24646
  * @throws Error file not found
23496
24647
  *
23497
24648
  * @private
23498
24649
  */
23499
- async function load(url, currentFile = '.', asStream = false) {
24650
+ async function load(url, currentFile = '.', responseType = false) {
23500
24651
  const resolved = resolve(url, currentFile);
24652
+ if (typeof responseType == 'boolean') {
24653
+ responseType = responseType ? exports.ResponseType.ReadableStream : exports.ResponseType.Text;
24654
+ }
23501
24655
  if (matchUrl.test(resolved.absolute)) {
23502
24656
  return fetch(resolved.absolute).then(async (response) => {
23503
24657
  if (!response.ok) {
23504
24658
  throw new Error(`${response.status} ${response.statusText} ${response.url}`);
23505
24659
  }
23506
- return asStream ? response.body : await response.text();
24660
+ if (responseType == exports.ResponseType.ArrayBuffer) {
24661
+ return response.arrayBuffer();
24662
+ }
24663
+ return responseType == exports.ResponseType.ReadableStream ? response.body : await response.text();
23507
24664
  });
23508
24665
  }
23509
24666
  try {
23510
- if (!asStream) {
24667
+ if (responseType == exports.ResponseType.Text) {
23511
24668
  return promises.readFile(resolved.absolute, 'utf-8');
23512
24669
  }
24670
+ if (responseType == exports.ResponseType.ArrayBuffer) {
24671
+ return promises.readFile(resolved.absolute).then(buffer => buffer.buffer);
24672
+ }
23513
24673
  const stats = await promises.lstat(resolved.absolute);
23514
24674
  if (stats.isFile()) {
23515
- return node_stream.Readable.toWeb(node_fs.createReadStream(resolved.absolute, { encoding: 'utf-8', highWaterMark: 64 * 1024 }));
24675
+ return node_stream.Readable.toWeb(node_fs.createReadStream(resolved.absolute, {
24676
+ encoding: 'utf-8',
24677
+ highWaterMark: 64 * 1024
24678
+ }));
23516
24679
  }
23517
24680
  }
23518
24681
  catch (error) {
@@ -23524,6 +24687,7 @@ async function load(url, currentFile = '.', asStream = false) {
23524
24687
  * render the ast tree
23525
24688
  * @param data
23526
24689
  * @param options
24690
+ * @param mapping
23527
24691
  *
23528
24692
  * Example:
23529
24693
  *
@@ -23548,8 +24712,8 @@ async function load(url, currentFile = '.', asStream = false) {
23548
24712
  * // }
23549
24713
  * ```
23550
24714
  */
23551
- function render(data, options = {}) {
23552
- return doRender(data, Object.assign(options, { resolve, dirname, cwd: options.cwd ?? process.cwd() }));
24715
+ function render(data, options = {}, mapping) {
24716
+ return doRender(data, Object.assign(options, { resolve, dirname, cwd: options.cwd ?? process.cwd() }), mapping);
23553
24717
  }
23554
24718
  /**
23555
24719
  * parse css file
@@ -23624,9 +24788,18 @@ async function parse(stream, options = {}) {
23624
24788
  return doParse(stream instanceof ReadableStream ? tokenizeStream(stream) : tokenize$1({
23625
24789
  stream,
23626
24790
  buffer: '',
24791
+ offset: 0,
23627
24792
  position: { ind: 0, lin: 1, col: 1 },
23628
24793
  currentPosition: { ind: -1, lin: 1, col: 0 }
23629
- }), Object.assign(options, { load, resolve, dirname, cwd: options.cwd ?? process.cwd() }));
24794
+ }), Object.assign(options, {
24795
+ load,
24796
+ resolve,
24797
+ dirname,
24798
+ cwd: options.cwd ?? process.cwd()
24799
+ })).then(result => {
24800
+ const { revMapping, ...res } = result;
24801
+ return res;
24802
+ });
23630
24803
  }
23631
24804
  /**
23632
24805
  * transform css file
@@ -23701,8 +24874,21 @@ async function transform(css, options = {}) {
23701
24874
  options = { minify: true, removeEmpty: true, removeCharset: true, ...options };
23702
24875
  const startTime = performance.now();
23703
24876
  return parse(css, options).then((parseResult) => {
24877
+ let mapping = null;
24878
+ let importMapping = null;
24879
+ if (typeof options.module == 'number' && (options.module & exports.ModuleScopeEnumOptions.ICSS)) {
24880
+ mapping = parseResult.mapping;
24881
+ importMapping = parseResult.importMapping;
24882
+ }
24883
+ else if (typeof options.module == 'object' && typeof options.module.scoped == 'number' && (options.module.scoped & exports.ModuleScopeEnumOptions.ICSS)) {
24884
+ mapping = parseResult.mapping;
24885
+ importMapping = parseResult.importMapping;
24886
+ }
23704
24887
  // ast already expanded by parse
23705
- const rendered = render(parseResult.ast, { ...options, expandNestingRules: false });
24888
+ const rendered = render(parseResult.ast, {
24889
+ ...options,
24890
+ expandNestingRules: false
24891
+ }, mapping != null ? { mapping, importMapping } : null);
23706
24892
  return {
23707
24893
  ...parseResult,
23708
24894
  ...rendered,