WXL
3 天以前 3bd962a6d7f61239c020e2dbbeb7341e5b842dd1
node_modules/webpack/lib/css/CssParser.js
@@ -7,7 +7,6 @@
const vm = require("vm");
const CommentCompilationWarning = require("../CommentCompilationWarning");
const CssModule = require("../CssModule");
const ModuleDependencyWarning = require("../ModuleDependencyWarning");
const { CSS_MODULE_TYPE_AUTO } = require("../ModuleTypeConstants");
const Parser = require("../Parser");
@@ -15,11 +14,7 @@
const WebpackError = require("../WebpackError");
const ConstDependency = require("../dependencies/ConstDependency");
const CssIcssExportDependency = require("../dependencies/CssIcssExportDependency");
const CssIcssFromIdentifierDependency = require("../dependencies/CssIcssFromIdentifierDependency");
const CssIcssGlobalIdentifierDependency = require("../dependencies/CssIcssGlobalIdentifierDependency");
const CssIcssImportDependency = require("../dependencies/CssIcssImportDependency");
const CssIcssLocalIdentifierDependency = require("../dependencies/CssIcssLocalIdentifierDependency");
const CssIcssSelfLocalIdentifierDependency = require("../dependencies/CssIcssSelfLocalIdentifierDependency");
const CssIcssSymbolDependency = require("../dependencies/CssIcssSymbolDependency");
const CssImportDependency = require("../dependencies/CssImportDependency");
const CssUrlDependency = require("../dependencies/CssUrlDependency");
@@ -37,7 +32,8 @@
/** @typedef {import("../Parser").ParserState} ParserState */
/** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
/** @typedef {import("./walkCssTokens").CssTokenCallbacks} CssTokenCallbacks */
/** @typedef {import("../../declarations/WebpackOptions").CssParserExportType} CssParserExportType */
/** @typedef {import("../../declarations/WebpackOptions").CssModuleParserOptions} CssModuleParserOptions */
/** @typedef {import("../CssModule")} CssModule */
/** @typedef {[number, number]} Range */
/** @typedef {{ line: number, column: number }} Position */
@@ -46,28 +42,53 @@
const CC_COLON = ":".charCodeAt(0);
const CC_SEMICOLON = ";".charCodeAt(0);
const CC_COMMA = ",".charCodeAt(0);
const CC_SLASH = "/".charCodeAt(0);
const CC_LEFT_PARENTHESIS = "(".charCodeAt(0);
const CC_RIGHT_PARENTHESIS = ")".charCodeAt(0);
const CC_LOWER_F = "f".charCodeAt(0);
const CC_UPPER_F = "F".charCodeAt(0);
const CC_RIGHT_CURLY = "}".charCodeAt(0);
const CC_HYPHEN_MINUS = "-".charCodeAt(0);
const CC_TILDE = "~".charCodeAt(0);
const CC_EQUAL = "=".charCodeAt(0);
const CC_FULL_STOP = ".".charCodeAt(0);
const CC_EXCLAMATION = "!".charCodeAt(0);
// https://www.w3.org/TR/css-syntax-3/#newline
// We don't have `preprocessing` stage, so we need specify all of them
const STRING_MULTILINE = /\\[\n\r\f]/g;
// https://www.w3.org/TR/css-syntax-3/#whitespace
const TRIM_WHITE_SPACES = /(^[ \t\n\r\f]*|[ \t\n\r\f]*$)/g;
const UNESCAPE = /\\([0-9a-fA-F]{1,6}[ \t\n\r\f]?|[\s\S])/g;
const IMAGE_SET_FUNCTION = /^(-\w+-)?image-set$/i;
const OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE = /^@(-\w+-)?keyframes$/;
const OPTIONALLY_VENDOR_PREFIXED_ANIMATION_PROPERTY =
   /^(-\w+-)?animation(-name)?$/i;
const COMPOSES_PROPERTY = /^(composes|compose-with)$/i;
const IS_MODULES = /\.module(s)?\.[^.]+$/i;
const CSS_COMMENT = /\/\*((?!\*\/).*?)\*\//g;
const UNESCAPE = /\\([0-9a-f]{1,6}[ \t\n\r\f]?|[\s\S])/gi;
const IMAGE_SET_FUNCTION = /^(?:-\w+-)?image-set$/i;
const OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE = /^@(?:-\w+-)?keyframes$/;
const COMPOSES_PROPERTY = /^(?:composes|compose-with)$/i;
const IS_MODULES = /\.modules?\.[^.]+$/i;
const CSS_COMMENT = /\/\*((?!\*\/)[\s\S]*?)\*\//g;
/**
 * Returns matches.
 * @param {RegExp} regexp a regexp
 * @param {string} str a string
 * @returns {RegExpExecArray[]} matches
 */
const matchAll = (regexp, str) => {
   /** @type {RegExpExecArray[]} */
   const result = [];
   /** @type {null | RegExpExecArray} */
   let match;
   // Use a while loop with exec() to find all matches
   while ((match = regexp.exec(str)) !== null) {
      result.push(match);
   }
   // Return an array to be easily iterable (note: a true spec-compliant polyfill
   // returns an iterator object, but an array spread often suffices for basic use)
   return result;
};
/**
 * Returns normalized url.
 * @param {string} str url string
 * @param {boolean} isString is url wrapped in quotes
 * @returns {string} normalized url
@@ -107,12 +128,12 @@
   return str;
};
// eslint-disable-next-line no-useless-escape
const regexSingleEscape = /[ -,.\/:-@[\]\^`{-~]/;
const regexSingleEscape = /[ -,./:-@[\]^`{-~]/;
const regexExcessiveSpaces =
   /(^|\\+)?(\\[A-F0-9]{1,6})\u0020(?![a-fA-F0-9\u0020])/g;
/**
 * Returns escaped identifier.
 * @param {string} str string
 * @returns {string} escaped identifier
 */
@@ -123,10 +144,10 @@
   while (counter < str.length) {
      const character = str.charAt(counter++);
      /** @type {string} */
      let value;
      // eslint-disable-next-line no-control-regex
      if (/[\t\n\f\r\u000B]/.test(character)) {
      if (/[\t\n\f\r\v]/.test(character)) {
         const codePoint = character.charCodeAt(0);
         value = `\\${codePoint.toString(16).toUpperCase()} `;
@@ -166,6 +187,7 @@
const CONTAINS_ESCAPE = /\\/;
/**
 * Returns hex.
 * @param {string} str string
 * @returns {[string, number] | undefined} hex
 */
@@ -203,6 +225,7 @@
};
/**
 * Unescape identifier.
 * @param {string} str string
 * @returns {string} unescaped string
 */
@@ -238,32 +261,90 @@
   return ret;
};
/**
 * A custom property is any property whose name starts with two dashes (U+002D HYPHEN-MINUS), like --foo.
 * The <custom-property-name> production corresponds to this:
 * it’s defined as any <dashed-ident> (a valid identifier that starts with two dashes),
 * except -- itself, which is reserved for future use by CSS.
 * @param {string} identifier identifier
 * @returns {boolean} true when identifier is dashed, otherwise false
 */
const isDashedIdentifier = (identifier) =>
   identifier.startsWith("--") && identifier.length >= 3;
/** @type {Record<string, number>} */
const ANIMATION_KEYWORDS = {
   // animation-direction
   normal: 1,
   reverse: 1,
   alternate: 1,
   "alternate-reverse": 1,
   // animation-fill-mode
   forwards: 1,
   backwards: 1,
   both: 1,
   // animation-iteration-count
   infinite: 1,
   // animation-play-state
   paused: 1,
   running: 1,
   // animation-timing-function
   ease: 1,
   "ease-in": 1,
   "ease-out": 1,
   "ease-in-out": 1,
   linear: 1,
   "step-end": 1,
   "step-start": 1,
   // Special
   none: Infinity, // No matter how many times you write none, it will never be an animation name
const PREDEFINED_COUNTER_STYLES = {
   decimal: 1,
   "decimal-leading-zero": 1,
   "arabic-indic": 1,
   armenian: 1,
   "upper-armenian": 1,
   "lower-armenian": 1,
   bengali: 1,
   cambodian: 1,
   khmer: 1,
   "cjk-decimal": 1,
   devanagari: 1,
   georgian: 1,
   gujarati: 1,
   /* cspell:disable-next-line */
   gurmukhi: 1,
   hebrew: 1,
   kannada: 1,
   lao: 1,
   malayalam: 1,
   mongolian: 1,
   myanmar: 1,
   oriya: 1,
   persian: 1,
   "lower-roman": 1,
   "upper-roman": 1,
   tamil: 1,
   telugu: 1,
   thai: 1,
   tibetan: 1,
   "lower-alpha": 1,
   "lower-latin": 1,
   "upper-alpha": 1,
   "upper-latin": 1,
   "lower-greek": 1,
   hiragana: 1,
   /* cspell:disable-next-line */
   "hiragana-iroha": 1,
   katakana: 1,
   /* cspell:disable-next-line */
   "katakana-iroha": 1,
   disc: 1,
   circle: 1,
   square: 1,
   "disclosure-open": 1,
   "disclosure-closed": 1,
   "cjk-earthly-branch": 1,
   "cjk-heavenly-stem": 1,
   "japanese-informal": 1,
   "japanese-formal": 1,
   "korean-hangul-formal": 1,
   /* cspell:disable-next-line */
   "korean-hanja-informal": 1,
   /* cspell:disable-next-line */
   "korean-hanja-formal": 1,
   "simp-chinese-informal": 1,
   "simp-chinese-formal": 1,
   "trad-chinese-informal": 1,
   "trad-chinese-formal": 1,
   "cjk-ideographic": 1,
   "ethiopic-numeric": 1
};
/** @type {Record<string, number>} */
const GLOBAL_VALUES = {
   // Global values
   initial: Infinity,
   inherit: Infinity,
@@ -272,8 +353,187 @@
   "revert-layer": Infinity
};
/** @type {Record<string, number>} */
const GRID_AREA_OR_COLUMN_OR_ROW = {
   auto: Infinity,
   span: Infinity,
   ...GLOBAL_VALUES
};
/** @type {Record<string, number>} */
const GRID_AUTO_COLUMNS_OR_ROW = {
   "min-content": Infinity,
   "max-content": Infinity,
   auto: Infinity,
   ...GLOBAL_VALUES
};
/** @type {Record<string, number>} */
const GRID_AUTO_FLOW = {
   row: 1,
   column: 1,
   dense: 1,
   ...GLOBAL_VALUES
};
/** @type {Record<string, number>} */
const GRID_TEMPLATE_AREAS = {
   // Special
   none: 1,
   ...GLOBAL_VALUES
};
/** @type {Record<string, number>} */
const GRID_TEMPLATE_COLUMNS_OR_ROWS = {
   none: 1,
   subgrid: 1,
   masonry: 1,
   "max-content": Infinity,
   "min-content": Infinity,
   auto: Infinity,
   ...GLOBAL_VALUES
};
/** @type {Record<string, number>} */
const GRID_TEMPLATE = {
   ...GRID_TEMPLATE_AREAS,
   ...GRID_TEMPLATE_COLUMNS_OR_ROWS
};
/** @type {Record<string, number>} */
const GRID = {
   "auto-flow": 1,
   dense: 1,
   ...GRID_AUTO_COLUMNS_OR_ROW,
   ...GRID_AUTO_FLOW,
   ...GRID_TEMPLATE_AREAS,
   ...GRID_TEMPLATE_COLUMNS_OR_ROWS
};
/**
 * Gets known properties.
 * @param {{ animation?: boolean, container?: boolean, customIdents?: boolean, grid?: boolean }=} options options
 * @returns {Map<string, Record<string, number>>} list of known properties
 */
const getKnownProperties = (options = {}) => {
   /** @type {Map<string, Record<string, number>>} */
   const knownProperties = new Map();
   if (options.animation) {
      knownProperties.set("animation", {
         // animation-direction
         normal: 1,
         reverse: 1,
         alternate: 1,
         "alternate-reverse": 1,
         // animation-fill-mode
         forwards: 1,
         backwards: 1,
         both: 1,
         // animation-iteration-count
         infinite: 1,
         // animation-play-state
         paused: 1,
         running: 1,
         // animation-timing-function
         ease: 1,
         "ease-in": 1,
         "ease-out": 1,
         "ease-in-out": 1,
         linear: 1,
         "step-end": 1,
         "step-start": 1,
         // Special
         none: Infinity, // No matter how many times you write none, it will never be an animation name
         ...GLOBAL_VALUES
      });
      knownProperties.set("animation-name", {
         // Special
         none: Infinity, // No matter how many times you write none, it will never be an animation name
         ...GLOBAL_VALUES
      });
   }
   if (options.container) {
      knownProperties.set("container", {
         // container-type
         normal: 1,
         size: 1,
         "inline-size": 1,
         "scroll-state": 1,
         // Special
         none: Infinity,
         ...GLOBAL_VALUES
      });
      knownProperties.set("container-name", {
         // Special
         none: Infinity,
         ...GLOBAL_VALUES
      });
   }
   if (options.customIdents) {
      knownProperties.set("list-style", {
         // list-style-position
         inside: 1,
         outside: 1,
         // list-style-type
         ...PREDEFINED_COUNTER_STYLES,
         // Special
         none: Infinity,
         ...GLOBAL_VALUES
      });
      knownProperties.set("list-style-type", {
         // list-style-type
         ...PREDEFINED_COUNTER_STYLES,
         // Special
         none: Infinity,
         ...GLOBAL_VALUES
      });
      knownProperties.set("system", {
         cyclic: 1,
         numeric: 1,
         alphabetic: 1,
         symbolic: 1,
         additive: 1,
         fixed: 1,
         extends: 1,
         ...PREDEFINED_COUNTER_STYLES
      });
      knownProperties.set("fallback", {
         ...PREDEFINED_COUNTER_STYLES
      });
      knownProperties.set("speak-as", {
         auto: 1,
         bullets: 1,
         numbers: 1,
         words: 1,
         "spell-out": 1,
         ...PREDEFINED_COUNTER_STYLES
      });
   }
   if (options.grid) {
      knownProperties.set("grid", GRID);
      knownProperties.set("grid-area", GRID_AREA_OR_COLUMN_OR_ROW);
      knownProperties.set("grid-column", GRID_AREA_OR_COLUMN_OR_ROW);
      knownProperties.set("grid-column-end", GRID_AREA_OR_COLUMN_OR_ROW);
      knownProperties.set("grid-column-start", GRID_AREA_OR_COLUMN_OR_ROW);
      knownProperties.set("grid-row", GRID_AREA_OR_COLUMN_OR_ROW);
      knownProperties.set("grid-row-end", GRID_AREA_OR_COLUMN_OR_ROW);
      knownProperties.set("grid-row-start", GRID_AREA_OR_COLUMN_OR_ROW);
      knownProperties.set("grid-template", GRID_TEMPLATE);
      knownProperties.set("grid-template-areas", GRID_TEMPLATE_AREAS);
      knownProperties.set("grid-template-columns", GRID_TEMPLATE_COLUMNS_OR_ROWS);
      knownProperties.set("grid-template-rows", GRID_TEMPLATE_COLUMNS_OR_ROWS);
   }
   return knownProperties;
};
class LocConverter {
   /**
    * Creates an instance of LocConverter.
    * @param {string} input input
    */
   constructor(input) {
@@ -284,6 +544,7 @@
   }
   /**
    * Returns location converter.
    * @param {number} pos position
    * @returns {LocConverter} location converter
    */
@@ -323,42 +584,48 @@
const CSS_MODE_TOP_LEVEL = 0;
const CSS_MODE_IN_BLOCK = 1;
const LOCAL_MODE = 0;
const GLOBAL_MODE = 1;
const eatUntilSemi = walkCssTokens.eatUntil(";");
const eatUntilLeftCurly = walkCssTokens.eatUntil("{");
const eatSemi = walkCssTokens.eatUntil(";");
/**
 * @typedef {object} CssParserOptions
 * @property {boolean=} importOption need handle `@import`
 * @property {boolean=} url need handle URLs
 * Defines the css parser own options type used by this module.
 * @typedef {object} CssParserOwnOptions
 * @property {("pure" | "global" | "local" | "auto")=} defaultMode default mode
 * @property {boolean=} namedExports is named exports
 * @property {CssParserExportType=} exportType export type
 */
/** @typedef {CssModuleParserOptions & CssParserOwnOptions} CssParserOptions */
class CssParser extends Parser {
   /**
    * Creates an instance of CssParser.
    * @param {CssParserOptions=} options options
    */
   constructor({
      defaultMode = "pure",
      importOption = true,
      url = true,
      namedExports = true,
      exportType
   } = {}) {
   constructor(options = {}) {
      super();
      this.defaultMode = defaultMode;
      this.import = importOption;
      this.url = url;
      this.namedExports = namedExports;
      this.exportType = exportType;
      this.defaultMode =
         typeof options.defaultMode !== "undefined" ? options.defaultMode : "pure";
      this.options = {
         url: true,
         import: true,
         namedExports: true,
         animation: true,
         container: true,
         customIdents: true,
         dashedIdents: true,
         function: true,
         grid: true,
         ...options
      };
      /** @type {Comment[] | undefined} */
      this.comments = undefined;
      this.magicCommentContext = createMagicCommentContext();
   }
   /**
    * Processes the provided state.
    * @param {ParserState} state parser state
    * @param {string} message warning message
    * @param {LocConverter} locConverter location converter
@@ -378,6 +645,7 @@
   }
   /**
    * Parses the provided source and updates the parser state.
    * @param {string | Buffer | PreparsedAst} source the source to parse
    * @param {ParserState} state the parser state
    * @returns {ParserState} the parser state
@@ -407,6 +675,12 @@
      }
      const isModules = mode === "global" || mode === "local";
      const knownProperties = getKnownProperties({
         animation: this.options.animation,
         container: this.options.container,
         customIdents: this.options.customIdents,
         grid: this.options.grid
      });
      /** @type {BuildMeta} */
      (module.buildMeta).isCSSModule = isModules;
@@ -417,7 +691,7 @@
      let scope = CSS_MODE_TOP_LEVEL;
      /** @type {boolean} */
      let allowImportAtRule = true;
      /** @type {[string, number, number][]} */
      /** @type {[string, number, number, boolean?][]} */
      const balanced = [];
      let lastTokenEndForComments = 0;
@@ -425,78 +699,59 @@
      let isNextRulePrelude = isModules;
      /** @type {number} */
      let blockNestingLevel = 0;
      /** @type {"local" | "global" | undefined} */
      /** @type {0 | 1 | undefined} */
      let modeData;
      /** @type {Set<string>} */
      const declaredCssVariables = new Set();
      /** @type {number} */
      let counter = 0;
      /** @type {string[]} */
      let lastLocalIdentifiers = [];
      /** @typedef {{ value: string, isReference?: boolean }} IcssDefinition */
      /** @typedef {{ value?: string, importName?: string, localName?: string }} IcssDefinition */
      /** @type {Map<string, IcssDefinition>} */
      const icssDefinitions = new Map();
      /**
       * Checks whether this css parser is next nested syntax.
       * @param {string} input input
       * @param {number} pos position
       * @returns {boolean} true, when next is nested syntax
       */
      const isNextNestedSyntax = (input, pos) => {
         pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
         pos = walkCssTokens.eatWhitespaceAndComments(input, pos)[0];
         if (input[pos] === "}") {
         if (
            input.charCodeAt(pos) === CC_RIGHT_CURLY ||
            (input.charCodeAt(pos) === CC_HYPHEN_MINUS &&
               input.charCodeAt(pos + 1) === CC_HYPHEN_MINUS)
         ) {
            return false;
         }
         // According spec only identifier can be used as a property name
         const isIdentifier = walkCssTokens.isIdentStartCodePoint(
            input.charCodeAt(pos)
         );
         const identifier = walkCssTokens.eatIdentSequence(input, pos);
         return !isIdentifier;
         if (!identifier) {
            return true;
         }
         const leftCurly = eatUntilLeftCurly(input, pos);
         const content = input.slice(identifier[0], leftCurly);
         if (content.includes(";") || content.includes("}")) {
            return false;
         }
         return true;
      };
      /**
       * Checks whether this css parser is local mode.
       * @returns {boolean} true, when in local scope
       */
      const isLocalMode = () =>
         modeData === "local" || (mode === "local" && modeData === undefined);
         modeData === LOCAL_MODE || (mode === "local" && modeData === undefined);
      /**
       * @param {string} input input
       * @param {number} pos start position
       * @param {(input: string, pos: number) => number} eater eater
       * @returns {[number,string]} new position and text
       */
      const eatText = (input, pos, eater) => {
         let text = "";
         for (;;) {
            if (input.charCodeAt(pos) === CC_SLASH) {
               const newPos = walkCssTokens.eatComments(input, pos);
               if (pos !== newPos) {
                  pos = newPos;
                  if (pos === input.length) break;
               } else {
                  text += "/";
                  pos++;
                  if (pos === input.length) break;
               }
            }
            const newPos = eater(input, pos);
            if (pos !== newPos) {
               text += input.slice(pos, newPos);
               pos = newPos;
            } else {
               break;
            }
            if (pos === input.length) break;
         }
         return [pos, text.trimEnd()];
      };
      const eatPropertyName = walkCssTokens.eatUntil(":{};");
      /**
       * Returns end.
       * @param {string} input input
       * @param {number} start start
       * @param {number} end end
@@ -523,6 +778,7 @@
      // Vanilla CSS stuff
      /**
       * Processes the provided input.
       * @param {string} input input
       * @param {number} start name start position
       * @param {number} end name end position
@@ -591,12 +847,14 @@
            return newline;
         }
         /** @type {undefined | string} */
         let layer;
         if (tokens[1]) {
            layer = input.slice(tokens[1][0] + 6, tokens[1][1] - 1).trim();
         }
         /** @type {undefined | string} */
         let supports;
         if (tokens[2]) {
@@ -604,8 +862,12 @@
         }
         const last = tokens[2] || tokens[1] || tokens[0];
         const mediaStart = walkCssTokens.eatWhitespaceAndComments(input, last[1]);
         const mediaStart = walkCssTokens.eatWhitespaceAndComments(
            input,
            last[1]
         )[0];
         /** @type {undefined | string} */
         let media;
         if (mediaStart !== semi - 1) {
@@ -629,6 +891,7 @@
      };
      /**
       * Process url function.
       * @param {string} input input
       * @param {number} end end position
       * @param {string} name the name of function
@@ -691,6 +954,7 @@
      };
      /**
       * Process old url function.
       * @param {string} input input
       * @param {number} start start position
       * @param {number} end end position
@@ -753,6 +1017,7 @@
      };
      /**
       * Process image set function.
       * @param {string} input input
       * @param {number} start start position
       * @param {number} end end position
@@ -817,13 +1082,48 @@
      // CSS modules stuff
      /**
       * Returns resolved reexport (localName and importName).
       * @param {string} value value to resolve
       * @param {string=} localName override local name
       * @param {boolean=} isCustomProperty true when it is custom property, otherwise false
       * @returns {string | [string, string]} resolved reexport (`localName` and `importName`)
       */
      const getReexport = (value, localName, isCustomProperty) => {
         const reexport = icssDefinitions.get(
            isCustomProperty ? `--${value}` : value
         );
         if (reexport) {
            if (reexport.importName) {
               return [
                  reexport.localName || (isCustomProperty ? `--${value}` : value),
                  reexport.importName
               ];
            }
            if (isCustomProperty) {
               return /** @type {string} */ (reexport.value).slice(2);
            }
            return /** @type {string} */ (reexport.value);
         }
         if (localName) {
            return [localName, value];
         }
         return value;
      };
      /**
       * Process import or export.
       * @param {0 | 1} type import or export
       * @param {string} input input
       * @param {number} pos start position
       * @returns {number} position after parse
       */
      const processImportOrExport = (type, input, pos) => {
         pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
         pos = walkCssTokens.eatWhitespaceAndComments(input, pos)[0];
         /** @type {string | undefined} */
         let request;
         if (type === 0) {
@@ -844,7 +1144,7 @@
            if (!str) {
               this._emitWarning(
                  state,
                  `Unexpected '${input[pos]}' at ${pos} during parsing of '${type ? ":import" : ":export"}' (expected string)`,
                  `Unexpected '${input[pos]}' at ${pos} during parsing of '${type === 0 ? ":import" : ":export"}' (expected string)`,
                  locConverter,
                  stringStart,
                  pos
@@ -853,7 +1153,7 @@
            }
            request = input.slice(str[0] + 1, str[1] - 1);
            pos = str[1];
            pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
            pos = walkCssTokens.eatWhitespaceAndComments(input, pos)[0];
            cc = input.charCodeAt(pos);
            if (cc !== CC_RIGHT_PARENTHESIS) {
               this._emitWarning(
@@ -866,10 +1166,11 @@
               return pos;
            }
            pos++;
            pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
            pos = walkCssTokens.eatWhitespaceAndComments(input, pos)[0];
         }
         /**
          * Creates a dep from the provided name.
          * @param {string} name name
          * @param {string} value value
          * @param {number} start start of position
@@ -883,22 +1184,17 @@
                  [0, 0],
                  /** @type {"local" | "global"} */
                  (mode),
                  value
                  value,
                  name
               );
               const { line: sl, column: sc } = locConverter.get(start);
               const { line: el, column: ec } = locConverter.get(end);
               dep.setLoc(sl, sc, el, ec);
               module.addDependency(dep);
               icssDefinitions.set(name, { value, isReference: true });
               icssDefinitions.set(name, { importName: value });
            } else if (type === 1) {
               const reexport = icssDefinitions.get(value);
               const dep = new CssIcssExportDependency(
                  name,
                  value,
                  reexport && reexport.isReference ? reexport.value : undefined,
                  undefined
               );
               const dep = new CssIcssExportDependency(name, getReexport(value));
               const { line: sl, column: sc } = locConverter.get(start);
               const { line: el, column: ec } = locConverter.get(end);
               dep.setLoc(sl, sc, el, ec);
@@ -989,7 +1285,79 @@
         return pos;
      };
      /** @typedef {{ from: string, items: ({ localName: string, importName: string })[] }} ValueAtRuleImport */
      /** @typedef {{ localName: string, value: string }} ValueAtRuleValue */
      /**
       * Parses value at rule params.
       * @param {string} str value at-rule params
       * @returns {ValueAtRuleImport | ValueAtRuleValue} parsed result
       */
      const parseValueAtRuleParams = (str) => {
         if (/from(\/\*|\s)(?:[\s\S]+)$/i.test(str)) {
            str = str.replace(CSS_COMMENT, " ").trim().replace(/;$/, "");
            const fromIdx = str.lastIndexOf("from");
            const path = str
               .slice(fromIdx + 5)
               .trim()
               .replace(/['"]/g, "");
            let content = str.slice(0, fromIdx).trim();
            if (content.startsWith("(") && content.endsWith(")")) {
               content = content.slice(1, -1);
            }
            return {
               from: path,
               items: content.split(",").map((item) => {
                  item = item.trim();
                  if (item.includes(":")) {
                     const [local, remote] = item.split(":");
                     return { localName: local.trim(), importName: remote.trim() };
                  }
                  const asParts = item.split(/\s+as\s+/);
                  if (asParts.length === 2) {
                     return {
                        localName: asParts[1].trim(),
                        importName: asParts[0].trim()
                     };
                  }
                  return { localName: item, importName: item };
               })
            };
         }
         /** @type {string} */
         let localName;
         /** @type {string} */
         let value;
         const idx = str.indexOf(":");
         if (idx !== -1) {
            localName = str.slice(0, idx).replace(CSS_COMMENT, "").trim();
            value = str.slice(idx + 1);
         } else {
            const mask = str.replace(CSS_COMMENT, (m) => " ".repeat(m.length));
            const idx = mask.search(/\S\s/) + 1;
            localName = str.slice(0, idx).replace(CSS_COMMENT, "").trim();
            value = str.slice(idx + (str[idx] === " " ? 1 : 0));
         }
         if (value.length > 0 && !/^\s+$/.test(value.replace(CSS_COMMENT, ""))) {
            value = value.trim();
         }
         return { localName, value };
      };
      /**
       * Processes the provided input.
       * @param {string} input input
       * @param {number} start name start position
       * @param {number} end name end position
@@ -999,83 +1367,12 @@
         const semi = eatUntilSemi(input, end);
         const atRuleEnd = semi + 1;
         const params = input.slice(end, semi);
         let [alias, request] = params.split(/\s*from\s*/);
         const parsed = parseValueAtRuleParams(params);
         if (request) {
            const aliases = alias
               .replace(CSS_COMMENT, " ")
               .trim()
               .replace(/^\(\s*|\s*\)$/g, "")
               .split(/\s*,\s*/);
            request = request.replace(CSS_COMMENT, "").trim();
            const isExplicitImport = request[0] === "'" || request[0] === '"';
            if (isExplicitImport) {
               request = request.slice(1, -1);
            }
            for (const alias of aliases) {
               const [name, aliasName] = alias.split(/\s+as\s+/);
               {
                  const reexport = icssDefinitions.get(request);
                  if (reexport) {
                     request = reexport.value.slice(1, -1);
                  }
                  const dep = new CssIcssImportDependency(
                     request,
                     [0, 0],
                     /** @type {"local" | "global"} */
                     (mode),
                     name
                  );
                  const { line: sl, column: sc } = locConverter.get(start);
                  const { line: el, column: ec } = locConverter.get(end);
                  dep.setLoc(sl, sc, el, ec);
                  module.addDependency(dep);
                  icssDefinitions.set(aliasName || name, {
                     value: name,
                     isReference: true
                  });
               }
               if (aliasName) {
                  const reexport = icssDefinitions.get(aliasName);
                  const dep = new CssIcssExportDependency(
                     aliasName,
                     name,
                     reexport && reexport.isReference ? reexport.value : undefined,
                     undefined
                  );
                  const { line: sl, column: sc } = locConverter.get(start);
                  const { line: el, column: ec } = locConverter.get(end);
                  dep.setLoc(sl, sc, el, ec);
                  module.addDependency(dep);
               }
               {
                  const reexport = icssDefinitions.get(name);
                  const dep = new CssIcssExportDependency(
                     name,
                     name,
                     reexport && reexport.isReference ? reexport.value : undefined,
                     undefined
                  );
                  const { line: sl, column: sc } = locConverter.get(start);
                  const { line: el, column: ec } = locConverter.get(end);
                  dep.setLoc(sl, sc, el, ec);
                  module.addDependency(dep);
               }
            }
         } else {
            const ident = walkCssTokens.eatIdentSequence(alias, 0);
            if (!ident) {
         if (
            typeof (/** @type {ValueAtRuleImport} */ (parsed).from) !== "undefined"
         ) {
            if (/** @type {ValueAtRuleImport} */ (parsed).from.length === 0) {
               this._emitWarning(
                  state,
                  `Broken '@value' at-rule: ${input.slice(start, atRuleEnd)}'`,
@@ -1089,33 +1386,87 @@
               return atRuleEnd;
            }
            const pos = walkCssTokens.eatWhitespaceAndComments(alias, ident[1]);
            let { from, items } = /** @type {ValueAtRuleImport} */ (parsed);
            const name = alias.slice(ident[0], ident[1]);
            let value =
               alias.charCodeAt(pos) === CC_COLON
                  ? alias.slice(pos + 1)
                  : alias.slice(ident[1]);
            for (const { importName, localName } of items) {
               {
                  const reexport = icssDefinitions.get(from);
            if (value && !/^\s+$/.test(value.replace(CSS_COMMENT, ""))) {
               value = value.trim();
                  if (reexport && reexport.value) {
                     from = reexport.value.slice(1, -1);
                  }
                  const dep = new CssIcssImportDependency(
                     from,
                     [0, 0],
                     /** @type {"local" | "global"} */
                     (mode),
                     importName,
                     localName
                  );
                  const { line: sl, column: sc } = locConverter.get(start);
                  const { line: el, column: ec } = locConverter.get(end);
                  dep.setLoc(sl, sc, el, ec);
                  module.addDependency(dep);
                  icssDefinitions.set(localName, { importName });
               }
               {
                  const dep = new CssIcssExportDependency(
                     localName,
                     getReexport(localName),
                     undefined,
                     false,
                     CssIcssExportDependency.EXPORT_MODE.REPLACE
                  );
                  const { line: sl, column: sc } = locConverter.get(start);
                  const { line: el, column: ec } = locConverter.get(end);
                  dep.setLoc(sl, sc, el, ec);
                  module.addDependency(dep);
               }
            }
         } else {
            if (/** @type {ValueAtRuleValue} */ (parsed).localName.length === 0) {
               this._emitWarning(
                  state,
                  `Broken '@value' at-rule: ${input.slice(start, atRuleEnd)}'`,
                  locConverter,
                  start,
                  atRuleEnd
               );
               const dep = new ConstDependency("", [start, atRuleEnd]);
               module.addPresentationalDependency(dep);
               return atRuleEnd;
            }
            const { localName, value } = /** @type {ValueAtRuleValue} */ (parsed);
            const { line: sl, column: sc } = locConverter.get(start);
            const { line: el, column: ec } = locConverter.get(end);
            if (icssDefinitions.has(value)) {
               const def =
                  /** @type {IcssDefinition} */
                  (icssDefinitions.get(value));
               value = def.value;
               def.localName = value;
               icssDefinitions.set(localName, def);
               const dep = new CssIcssExportDependency(
                  localName,
                  getReexport(value)
               );
               dep.setLoc(sl, sc, el, ec);
               module.addDependency(dep);
            } else {
               icssDefinitions.set(localName, { value });
               const dep = new CssIcssExportDependency(localName, value);
               dep.setLoc(sl, sc, el, ec);
               module.addDependency(dep);
            }
            icssDefinitions.set(name, { value });
            const dep = new CssIcssExportDependency(name, value);
            const { line: sl, column: sc } = locConverter.get(start);
            const { line: el, column: ec } = locConverter.get(end);
            dep.setLoc(sl, sc, el, ec);
            module.addDependency(dep);
         }
         const dep = new ConstDependency("", [start, atRuleEnd]);
@@ -1124,22 +1475,23 @@
      };
      /**
       * Process icss symbol.
       * @param {string} name ICSS symbol name
       * @param {number} start start position
       * @param {number} end end position
       * @returns {number} position after handling
       */
      const processICSSSymbol = (name, start, end) => {
         const { value, isReference } =
         const def =
            /** @type {IcssDefinition} */
            (icssDefinitions.get(name));
         const { line: sl, column: sc } = locConverter.get(start);
         const { line: el, column: ec } = locConverter.get(end);
         const dep = new CssIcssSymbolDependency(
            name,
            value,
            def.localName || name,
            [start, end],
            isReference
            def.value,
            def.importName
         );
         dep.setLoc(sl, sc, el, ec);
         module.addDependency(dep);
@@ -1147,6 +1499,7 @@
      };
      /**
       * Process local or global function.
       * @param {string} input input
       * @param {1 | 2} type type of function
       * @param {number} start start position
@@ -1164,23 +1517,36 @@
         end = walkCssTokens.consumeUntil(
            input,
            start,
            type === 1
               ? {
                     identifier(input, start, end) {
                        const name = unescapeIdentifier(input.slice(start, end));
                        const { line: sl, column: sc } = locConverter.get(start);
                        const { line: el, column: ec } = locConverter.get(end);
                        const dep = new CssIcssLocalIdentifierDependency(name, [
                           start,
                           end
                        ]);
                        dep.setLoc(sl, sc, el, ec);
                        module.addDependency(dep);
            {
               identifier(input, start, end) {
                  if (type === 1) {
                     let identifier = unescapeIdentifier(input.slice(start, end));
                     const { line: sl, column: sc } = locConverter.get(start);
                     const { line: el, column: ec } = locConverter.get(end);
                     const isDashedIdent = isDashedIdentifier(identifier);
                        return end;
                     if (isDashedIdent) {
                        identifier = identifier.slice(2);
                     }
                     const dep = new CssIcssExportDependency(
                        identifier,
                        getReexport(identifier),
                        [start, end],
                        true,
                        CssIcssExportDependency.EXPORT_MODE.ONCE,
                        isDashedIdent
                           ? CssIcssExportDependency.EXPORT_TYPE.CUSTOM_VARIABLE
                           : CssIcssExportDependency.EXPORT_TYPE.NORMAL
                     );
                     dep.setLoc(sl, sc, el, ec);
                     module.addDependency(dep);
                  }
               : {},
                  return end;
               }
            },
            {},
            { onlyTopLevel: true, functionValue: true }
         );
@@ -1195,37 +1561,72 @@
      };
      /**
       * Process local at rule.
       * @param {string} input input
       * @param {number} end name end position
       * @param {{ string?: boolean, identifier: boolean, validate?: (name: string) => boolean, dashed?: boolean }} options types which allowed to handle
       * @param {{ string?: boolean, identifier?: boolean | RegExp }} options types which allowed to handle
       * @returns {number} position after handling
       */
      const processLocalAtRule = (input, end, options) => {
         /** @type {[number, number, boolean] | undefined} */
         let value;
         let found = false;
         walkCssTokens.consumeUntil(
         return walkCssTokens.consumeUntil(
            input,
            end,
            {
               string(_input, start, end) {
                  if (!found && options.string) {
                     const value = unescapeIdentifier(input.slice(start + 1, end - 1));
                     const { line: sl, column: sc } = locConverter.get(start);
                     const { line: el, column: ec } = locConverter.get(end);
                     const dep = new CssIcssExportDependency(
                        value,
                        value,
                        [start, end],
                        true,
                        CssIcssExportDependency.EXPORT_MODE.ONCE
                     );
                     dep.setLoc(sl, sc, el, ec);
                     module.addDependency(dep);
                     found = true;
                     value = [start, end, true];
                  }
                  return end;
               },
               identifier(_input, start, end) {
                  if (!found && options.identifier) {
                     found = true;
                     value = [start, end, false];
               identifier(input, start, end) {
                  if (!found) {
                     const value = input.slice(start, end);
                     if (options.identifier) {
                        const identifier = unescapeIdentifier(value);
                        if (
                           options.identifier instanceof RegExp &&
                           options.identifier.test(identifier)
                        ) {
                           return end;
                        }
                        const { line: sl, column: sc } = locConverter.get(start);
                        const { line: el, column: ec } = locConverter.get(end);
                        const dep = new CssIcssExportDependency(
                           identifier,
                           getReexport(identifier),
                           [start, end],
                           true,
                           CssIcssExportDependency.EXPORT_MODE.ONCE,
                           CssIcssExportDependency.EXPORT_TYPE.NORMAL
                        );
                        dep.setLoc(sl, sc, el, ec);
                        module.addDependency(dep);
                        found = true;
                     }
                  }
                  return end;
               }
            },
            {
               function(input, start, end) {
               function: (input, start, end) => {
                  // No need to handle `:` (COLON), because it's always a function
                  const name = input
                     .slice(start, end - 1)
@@ -1240,53 +1641,37 @@
                     return processLocalOrGlobalFunction(input, type, start, end);
                  }
                  if (
                     this.options.dashedIdents &&
                     isLocalMode() &&
                     (name === "var" || name === "style")
                  ) {
                     return processDashedIdent(input, end, end);
                  }
                  return end;
               }
            },
            { onlyTopLevel: true, atRulePrelude: true }
         );
         if (!value) return end;
         let name = value[2]
            ? input.slice(value[0] + 1, value[1] - 1)
            : input.slice(value[0], value[1]);
         if (options.validate && !options.validate(name)) return end;
         name = unescapeIdentifier(name);
         const { line: sl, column: sc } = locConverter.get(value[0]);
         const { line: el, column: ec } = locConverter.get(value[1]);
         if (options.dashed) {
            name = name.slice(2);
            declaredCssVariables.add(name);
         }
         const dep = new CssIcssLocalIdentifierDependency(
            name,
            [value[0], value[1]],
            options.dashed ? "--" : ""
         );
         dep.setLoc(sl, sc, el, ec);
         module.addDependency(dep);
         return value[1];
      };
      /**
       * Process dashed ident.
       * @param {string} input input
       * @param {number} start start position
       * @param {number} end end position
       * @returns {number} position after handling
       */
      const processVarFunction = (input, end) => {
         const customIdent = walkCssTokens.eatIdentSequence(input, end);
      const processDashedIdent = (input, start, end) => {
         const customIdent = walkCssTokens.eatIdentSequence(input, start);
         if (!customIdent) return end;
         let name = input.slice(customIdent[0], customIdent[1]);
         // A custom property is any property whose name starts with two dashes (U+002D HYPHEN-MINUS), like --foo.
         // The <custom-property-name> production corresponds to this:
         // it’s defined as any <dashed-ident> (a valid identifier that starts with two dashes),
         // except -- itself, which is reserved for future use by CSS.
         if (!name.startsWith("--") || name.length < 3) return end;
         name = unescapeIdentifier(
         const identifier = unescapeIdentifier(
            input.slice(customIdent[0] + 2, customIdent[1])
         );
         const afterCustomIdent = walkCssTokens.eatWhitespaceAndComments(
            input,
            customIdent[1]
         );
         )[0];
         if (
            input.charCodeAt(afterCustomIdent) === CC_LOWER_F ||
            input.charCodeAt(afterCustomIdent) === CC_UPPER_F
@@ -1303,7 +1688,7 @@
            }
            const from = walkCssTokens.eatIdentSequenceOrString(
               input,
               walkCssTokens.eatWhitespaceAndComments(input, fromWord[1])
               walkCssTokens.eatWhitespaceAndComments(input, fromWord[1])[0]
            );
            if (!from) {
               return end;
@@ -1316,18 +1701,35 @@
            } else if (from[2] === false) {
               const { line: sl, column: sc } = locConverter.get(customIdent[0]);
               const { line: el, column: ec } = locConverter.get(from[1] - 1);
               const dep = new CssIcssFromIdentifierDependency(
                  path.slice(1, -1),
                  /** @type {"local" | "global"} */
                  (mode),
                  [customIdent[0], from[1] - 1],
                  name,
                  name,
                  "--"
               );
               const localName = `__ICSS_IMPORT_${counter++}__`;
               dep.setLoc(sl, sc, el, ec);
               module.addDependency(dep);
               {
                  const dep = new CssIcssImportDependency(
                     path.slice(1, -1),
                     [customIdent[0], from[1] - 1],
                     /** @type {"local" | "global"} */
                     (mode),
                     identifier,
                     localName
                  );
                  dep.setLoc(sl, sc, el, ec);
                  module.addDependency(dep);
               }
               {
                  const dep = new CssIcssExportDependency(
                     identifier,
                     getReexport(identifier, localName, true),
                     [customIdent[0], from[1] - 1],
                     true,
                     CssIcssExportDependency.EXPORT_MODE.ONCE,
                     CssIcssExportDependency.EXPORT_TYPE.CUSTOM_VARIABLE
                  );
                  dep.setLoc(sl, sc, el, ec);
                  module.addDependency(dep);
               }
               {
                  const dep = new ConstDependency("", [fromWord[0], from[1]]);
@@ -1338,12 +1740,13 @@
         } else {
            const { line: sl, column: sc } = locConverter.get(customIdent[0]);
            const { line: el, column: ec } = locConverter.get(customIdent[1]);
            const dep = new CssIcssSelfLocalIdentifierDependency(
               name,
               undefined,
            const dep = new CssIcssExportDependency(
               identifier,
               getReexport(identifier, undefined, true),
               [customIdent[0], customIdent[1]],
               "--",
               declaredCssVariables
               true,
               CssIcssExportDependency.EXPORT_MODE.ONCE,
               CssIcssExportDependency.EXPORT_TYPE.CUSTOM_VARIABLE
            );
            dep.setLoc(sl, sc, el, ec);
            module.addDependency(dep);
@@ -1353,86 +1756,148 @@
         return end;
      };
      /**
       * Process local declaration.
       * @param {string} input input
       * @param {number} pos name start position
       * @param {number} end name end position
       * @returns {number} position after handling
       */
      const processLocalDeclaration = (input, pos, end) => {
         modeData = undefined;
         pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
         const propertyNameStart = pos;
         const [propertyNameEnd, propertyName] = eatText(
            input,
            pos,
            eatPropertyName
         );
         if (input.charCodeAt(propertyNameEnd) !== CC_COLON) return end;
         pos = propertyNameEnd + 1;
         if (propertyName.startsWith("--") && propertyName.length >= 3) {
            // CSS Variable
            const { line: sl, column: sc } = locConverter.get(propertyNameStart);
            const { line: el, column: ec } = locConverter.get(propertyNameEnd);
            const name = unescapeIdentifier(propertyName.slice(2));
            const dep = new CssIcssLocalIdentifierDependency(
               name,
               [propertyNameStart, propertyNameEnd],
               "--"
            );
            dep.setLoc(sl, sc, el, ec);
            module.addDependency(dep);
            declaredCssVariables.add(name);
         } else if (
            OPTIONALLY_VENDOR_PREFIXED_ANIMATION_PROPERTY.test(propertyName)
         ) {
            /** @type {[number, number, boolean][]} */
            const animationNames = [];
         pos = walkCssTokens.eatWhitespaceAndComments(input, pos)[0];
         const identifier = walkCssTokens.eatIdentSequence(input, pos);
         if (!identifier) {
            return end;
         }
         const propertyNameStart = identifier[0];
         pos = walkCssTokens.eatWhitespaceAndComments(input, identifier[1])[0];
         if (input.charCodeAt(pos) !== CC_COLON) {
            return end;
         }
         pos += 1;
         // Remove prefix and lowercase
         const propertyName = input
            .slice(identifier[0], identifier[1])
            .replace(/^(-\w+-)/, "")
            .toLowerCase();
         if (isLocalMode() && knownProperties.has(propertyName)) {
            /** @type {[number, number, boolean?][]} */
            const values = [];
            /** @type {Record<string, number>} */
            let parsedAnimationKeywords = Object.create(null);
            let parsedKeywords = Object.create(null);
            const isGridProperty = Boolean(propertyName.startsWith("grid"));
            const isGridTemplate = isGridProperty
               ? Boolean(
                     propertyName === "grid" ||
                     propertyName === "grid-template" ||
                     propertyName === "grid-template-columns" ||
                     propertyName === "grid-template-rows"
                  )
               : false;
            let afterExclamation = false;
            const end = walkCssTokens.consumeUntil(
               input,
               pos,
               {
                  delim(input, start, end) {
                     afterExclamation = input.charCodeAt(start) === CC_EXCLAMATION;
                     return end;
                  },
                  leftSquareBracket(input, start, end) {
                     let i = end;
                     while (true) {
                        i = walkCssTokens.eatWhitespaceAndComments(input, i)[0];
                        const name = walkCssTokens.eatIdentSequence(input, i);
                        if (!name) {
                           break;
                        }
                        values.push(name);
                        i = name[1];
                     }
                     return end;
                  },
                  string(_input, start, end) {
                     animationNames.push([start, end, true]);
                     if (
                        propertyName === "animation" ||
                        propertyName === "animation-name"
                     ) {
                        values.push([start, end, true]);
                     }
                     if (
                        propertyName === "grid" ||
                        propertyName === "grid-template" ||
                        propertyName === "grid-template-areas"
                     ) {
                        const areas = unescapeIdentifier(
                           input.slice(start + 1, end - 1)
                        );
                        const matches = matchAll(/\b\w+\b/g, areas);
                        for (const match of matches) {
                           const areaStart = start + 1 + match.index;
                           values.push([areaStart, areaStart + match[0].length, false]);
                        }
                     }
                     return end;
                  },
                  identifier(input, start, end) {
                     const keyword = input.slice(start, end).toLowerCase();
                     if (isGridTemplate) {
                        return end;
                     }
                     parsedAnimationKeywords[keyword] =
                        typeof parsedAnimationKeywords[keyword] !== "undefined"
                           ? parsedAnimationKeywords[keyword] + 1
                     if (afterExclamation) {
                        afterExclamation = false;
                        return end;
                     }
                     const identifier = input.slice(start, end);
                     const keyword = identifier.toLowerCase();
                     parsedKeywords[keyword] =
                        typeof parsedKeywords[keyword] !== "undefined"
                           ? parsedKeywords[keyword] + 1
                           : 0;
                     const keywords =
                        /** @type {Record<string, number>} */
                        (knownProperties.get(propertyName));
                     if (
                        ANIMATION_KEYWORDS[keyword] &&
                        parsedAnimationKeywords[keyword] < ANIMATION_KEYWORDS[keyword]
                        keywords[keyword] &&
                        parsedKeywords[keyword] < keywords[keyword]
                     ) {
                        return end;
                     }
                     animationNames.push([start, end, false]);
                     values.push([start, end]);
                     return end;
                  },
                  comma(_input, _start, end) {
                     parsedAnimationKeywords = {};
                     parsedKeywords = {};
                     return end;
                  }
               },
               {
                  function(input, start, end) {
                  function: (input, start, end) => {
                     const name = input
                        .slice(start, end - 1)
                        .replace(/\\/g, "")
                        .toLowerCase();
                     if (isLocalMode() && name === "var") {
                        return processVarFunction(input, end);
                     }
                     const type =
                        name === "local" ? 1 : name === "global" ? 2 : undefined;
@@ -1441,26 +1906,50 @@
                        return processLocalOrGlobalFunction(input, type, start, end);
                     }
                     if (
                        this.options.dashedIdents &&
                        isLocalMode() &&
                        name === "var"
                     ) {
                        return processDashedIdent(input, end, end);
                     }
                     if (this.options.url) {
                        if (name === "src" || name === "url") {
                           return processURLFunction(input, end, name);
                        } else if (IMAGE_SET_FUNCTION.test(name)) {
                           return processImageSetFunction(input, start, end);
                        }
                     }
                     return end;
                  }
               },
               { onlyTopLevel: true, declarationValue: true }
               {
                  onlyTopLevel: !isGridTemplate,
                  declarationValue: true
               }
            );
            if (animationNames.length > 0) {
               for (const animationName of animationNames) {
                  const { line: sl, column: sc } = locConverter.get(animationName[0]);
                  const { line: el, column: ec } = locConverter.get(animationName[1]);
                  const [start, end, isString] = animationName;
            if (values.length > 0) {
               for (const value of values) {
                  const { line: sl, column: sc } = locConverter.get(value[0]);
                  const { line: el, column: ec } = locConverter.get(value[1]);
                  const [start, end, isString] = value;
                  const name = unescapeIdentifier(
                     isString
                        ? input.slice(start + 1, end - 1)
                        : input.slice(start, end)
                  );
                  const dep = new CssIcssSelfLocalIdentifierDependency(
                  const dep = new CssIcssExportDependency(
                     name,
                     undefined,
                     [start, end]
                     getReexport(name),
                     [start, end],
                     true,
                     CssIcssExportDependency.EXPORT_MODE.ONCE,
                     isGridProperty
                        ? CssIcssExportDependency.EXPORT_TYPE.GRID_CUSTOM_IDENTIFIER
                        : CssIcssExportDependency.EXPORT_TYPE.NORMAL
                  );
                  dep.setLoc(sl, sc, el, ec);
                  module.addDependency(dep);
@@ -1491,7 +1980,7 @@
            const classNames = new Set();
            while (true) {
               pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
               pos = walkCssTokens.eatWhitespaceAndComments(input, pos)[0];
               let className = walkCssTokens.eatIdentSequence(input, pos);
@@ -1509,14 +1998,20 @@
                  pos = walkCssTokens.eatWhitespaceAndComments(
                     input,
                     className[1] + 1
                  );
                  )[0];
                  className = walkCssTokens.eatIdentSequence(input, pos);
                  if (className) {
                     pos = walkCssTokens.eatWhitespaceAndComments(input, className[1]);
                     pos = walkCssTokens.eatWhitespaceAndComments(
                        input,
                        className[1]
                     )[0];
                     pos += 1;
                  }
               } else if (className) {
                  pos = walkCssTokens.eatWhitespaceAndComments(input, className[1]);
                  pos = walkCssTokens.eatWhitespaceAndComments(
                     input,
                     className[1]
                  )[0];
                  pos = className[1];
               }
@@ -1533,26 +2028,16 @@
                  for (const className of classNames) {
                     const [start, end] = className;
                     const identifier = unescapeIdentifier(input.slice(start, end));
                     const reexport = icssDefinitions.get(identifier);
                     const dep = isGlobalFunction
                        ? new CssIcssGlobalIdentifierDependency(
                              lastLocalIdentifier,
                              identifier,
                              reexport && reexport.isReference
                                 ? reexport.value
                                 : undefined,
                              [start, end]
                           )
                        : new CssIcssSelfLocalIdentifierDependency(
                              lastLocalIdentifier,
                              identifier,
                              [start, end],
                              undefined,
                              undefined,
                              reexport && reexport.isReference
                                 ? reexport.value
                                 : undefined
                           );
                     const dep = new CssIcssExportDependency(
                        lastLocalIdentifier,
                        getReexport(identifier),
                        [start, end],
                        !isGlobalFunction,
                        isGlobalFunction
                           ? CssIcssExportDependency.EXPORT_MODE.APPEND
                           : CssIcssExportDependency.EXPORT_MODE.SELF_REFERENCE,
                        CssIcssExportDependency.EXPORT_TYPE.COMPOSES
                     );
                     const { line: sl, column: sc } = locConverter.get(start);
                     const { line: el, column: ec } = locConverter.get(end);
                     dep.setLoc(sl, sc, el, ec);
@@ -1582,19 +2067,35 @@
                     for (const className of classNames) {
                        const [start, end] = className;
                        const identifier = unescapeIdentifier(input.slice(start, end));
                        const dep = new CssIcssFromIdentifierDependency(
                           request,
                           /** @type {"local" | "global"} */
                           (mode),
                           [start, end],
                           identifier,
                           /** @type {string} */
                           (lastLocalIdentifier)
                        );
                        const { line: sl, column: sc } = locConverter.get(start);
                        const { line: el, column: ec } = locConverter.get(end);
                        dep.setLoc(sl, sc, el, ec);
                        module.addDependency(dep);
                        const localName = `__ICSS_IMPORT_${counter++}__`;
                        {
                           const dep = new CssIcssImportDependency(
                              request,
                              [start, end],
                              /** @type {"local" | "global"} */
                              (mode),
                              identifier,
                              localName
                           );
                           dep.setLoc(sl, sc, el, ec);
                           module.addDependency(dep);
                        }
                        {
                           const dep = new CssIcssExportDependency(
                              lastLocalIdentifier,
                              getReexport(identifier, localName),
                              [start, end],
                              true,
                              CssIcssExportDependency.EXPORT_MODE.APPEND,
                              CssIcssExportDependency.EXPORT_TYPE.COMPOSES
                           );
                           dep.setLoc(sl, sc, el, ec);
                           module.addDependency(dep);
                        }
                     }
                     classNames.clear();
@@ -1608,15 +2109,14 @@
                           const identifier = unescapeIdentifier(
                              input.slice(start, end)
                           );
                           const reexport = icssDefinitions.get(identifier);
                           const dep = new CssIcssGlobalIdentifierDependency(
                           const dep = new CssIcssExportDependency(
                              /** @type {string} */
                              (lastLocalIdentifier),
                              identifier,
                              reexport && reexport.isReference
                                 ? reexport.value
                                 : undefined,
                              [start, end]
                              getReexport(identifier),
                              [start, end],
                              false,
                              CssIcssExportDependency.EXPORT_MODE.APPEND,
                              CssIcssExportDependency.EXPORT_TYPE.COMPOSES
                           );
                           const { line: sl, column: sc } = locConverter.get(start);
                           const { line: el, column: ec } = locConverter.get(end);
@@ -1657,24 +2157,122 @@
            const dep = new ConstDependency("", [propertyNameStart, end]);
            module.addPresentationalDependency(dep);
         }
         return pos;
      };
      /**
       * Process id selector.
       * @param {string} input input
       * @param {number} start start position
       * @param {number} end end position
       * @returns {number} position after handling
       */
      const processHashID = (input, start, end) => {
      const processIdSelector = (input, start, end) => {
         const valueStart = start + 1;
         const name = unescapeIdentifier(input.slice(valueStart, end));
         const dep = new CssIcssLocalIdentifierDependency(name, [valueStart, end]);
         const dep = new CssIcssExportDependency(
            name,
            getReexport(name),
            [valueStart, end],
            true,
            CssIcssExportDependency.EXPORT_MODE.ONCE
         );
         const { line: sl, column: sc } = locConverter.get(start);
         const { line: el, column: ec } = locConverter.get(end);
         dep.setLoc(sl, sc, el, ec);
         module.addDependency(dep);
         return end;
      };
      /**
       * Process class selector.
       * @param {string} input input
       * @param {number} start start position
       * @param {number} end end position
       * @returns {number} position after handling
       */
      const processClassSelector = (input, start, end) => {
         const ident = walkCssTokens.skipCommentsAndEatIdentSequence(input, end);
         if (!ident) return end;
         const name = unescapeIdentifier(input.slice(ident[0], ident[1]));
         lastLocalIdentifiers.push(name);
         const dep = new CssIcssExportDependency(
            name,
            getReexport(name),
            [ident[0], ident[1]],
            true,
            CssIcssExportDependency.EXPORT_MODE.ONCE
         );
         const { line: sl, column: sc } = locConverter.get(ident[0]);
         const { line: el, column: ec } = locConverter.get(ident[1]);
         dep.setLoc(sl, sc, el, ec);
         module.addDependency(dep);
         return ident[1];
      };
      /**
       * Process attribute selector.
       * @param {string} input input
       * @param {number} start start position
       * @param {number} end end position
       * @returns {number} position after handling
       */
      const processAttributeSelector = (input, start, end) => {
         end = walkCssTokens.eatWhitespaceAndComments(input, end)[0];
         const identifier = walkCssTokens.eatIdentSequence(input, end);
         if (!identifier) return end;
         const name = unescapeIdentifier(
            input.slice(identifier[0], identifier[1])
         );
         if (name.toLowerCase() !== "class") {
            return end;
         }
         end = walkCssTokens.eatWhitespaceAndComments(input, identifier[1])[0];
         const isTilde = input.charCodeAt(end) === CC_TILDE;
         if (
            input.charCodeAt(end) !== CC_EQUAL &&
            input.charCodeAt(end) !== CC_TILDE
         ) {
            return end;
         }
         end += 1;
         if (isTilde) {
            if (input.charCodeAt(end) !== CC_EQUAL) {
               return end;
            }
            end += 1;
         }
         end = walkCssTokens.eatWhitespaceAndComments(input, end)[0];
         const value = walkCssTokens.eatIdentSequenceOrString(input, end);
         if (!value) {
            return end;
         }
         const classNameStart = value[2] ? value[0] : value[0] + 1;
         const classNameEnd = value[2] ? value[1] : value[1] - 1;
         const className = unescapeIdentifier(
            input.slice(classNameStart, classNameEnd)
         );
         const dep = new CssIcssExportDependency(
            className,
            getReexport(className),
            [classNameStart, classNameEnd],
            true,
            CssIcssExportDependency.EXPORT_MODE.NONE
         );
         const { line: sl, column: sc } = locConverter.get(classNameStart);
         const { line: el, column: ec } = locConverter.get(classNameEnd);
         dep.setLoc(sl, sc, el, ec);
         module.addDependency(dep);
         return value[2] ? classNameEnd : classNameEnd + 1;
      };
      walkCssTokens(source, 0, {
@@ -1722,7 +2320,7 @@
            return end;
         },
         url: (input, start, end, contentStart, contentEnd) => {
            if (!this.url) {
            if (!this.options.url) {
               return end;
            }
@@ -1749,9 +2347,32 @@
                  return eatUntilSemi(input, start);
               }
               case "@charset": {
                  const atRuleEnd = eatUntilSemi(input, start);
                  if (/** @type {CssModule} */ (module).exportType === "style") {
                     return atRuleEnd;
                  }
                  const dep = new ConstDependency("", [start, atRuleEnd + 1]);
                  module.addPresentationalDependency(dep);
                  const value = walkCssTokens.eatString(input, end);
                  if (!value) {
                     return atRuleEnd;
                  }
                  /** @type {BuildInfo} */
                  (module.buildInfo).charset = input
                     .slice(value[0] + 1, value[1] - 1)
                     .toUpperCase();
                  return atRuleEnd;
               }
               case "@import": {
                  if (!this.import) {
                     return eatSemi(input, end);
                  if (!this.options.import) {
                     return eatUntilSemi(input, end);
                  }
                  if (!allowImportAtRule) {
@@ -1762,7 +2383,7 @@
                        start,
                        end
                     );
                     return end;
                     return eatUntilSemi(input, end);
                  }
                  return processAtImport(input, start, end);
@@ -1772,6 +2393,7 @@
                     if (name === "@value") {
                        return processAtValue(input, start, end);
                     } else if (
                        this.options.animation &&
                        OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE.test(name) &&
                        isLocalMode()
                     ) {
@@ -1779,11 +2401,21 @@
                           string: true,
                           identifier: true
                        });
                     } else if (name === "@property" && isLocalMode()) {
                     } else if (
                        this.options.customIdents &&
                        name === "@counter-style" &&
                        isLocalMode()
                     ) {
                        return processLocalAtRule(input, end, {
                           identifier: true,
                           dashed: true,
                           validate: (name) => name.startsWith("--") && name.length >= 3
                           identifier: true
                        });
                     } else if (
                        this.options.container &&
                        name === "@container" &&
                        isLocalMode()
                     ) {
                        return processLocalAtRule(input, end, {
                           identifier: /^(none|and|or|not)$/
                        });
                     } else if (name === "@scope") {
                        isNextRulePrelude = true;
@@ -1805,15 +2437,23 @@
         },
         identifier: (input, start, end) => {
            if (isModules) {
               const name = input.slice(start, end);
               const identifier = input.slice(start, end);
               if (icssDefinitions.has(name)) {
                  return processICSSSymbol(name, start, end);
               if (
                  this.options.dashedIdents &&
                  isLocalMode() &&
                  isDashedIdentifier(identifier)
               ) {
                  return processDashedIdent(input, start, end);
               }
               if (icssDefinitions.has(identifier)) {
                  return processICSSSymbol(identifier, start, end);
               }
               switch (scope) {
                  case CSS_MODE_IN_BLOCK: {
                     if (isLocalMode()) {
                     if (isModules && !isNextRulePrelude) {
                        // Handle only top level values and not inside functions
                        return processLocalDeclaration(input, start, end);
                     }
@@ -1825,30 +2465,19 @@
            return end;
         },
         delim: (input, start, end) => {
            if (isNextRulePrelude && isLocalMode()) {
               const ident = walkCssTokens.skipCommentsAndEatIdentSequence(
                  input,
                  end
               );
               if (!ident) return end;
               const name = unescapeIdentifier(input.slice(ident[0], ident[1]));
               lastLocalIdentifiers.push(name);
               const dep = new CssIcssLocalIdentifierDependency(name, [
                  ident[0],
                  ident[1]
               ]);
               const { line: sl, column: sc } = locConverter.get(ident[0]);
               const { line: el, column: ec } = locConverter.get(ident[1]);
               dep.setLoc(sl, sc, el, ec);
               module.addDependency(dep);
               return ident[1];
            if (
               input.charCodeAt(start) === CC_FULL_STOP &&
               isNextRulePrelude &&
               isLocalMode()
            ) {
               return processClassSelector(input, start, end);
            }
            return end;
         },
         hash: (input, start, end, isID) => {
            if (isNextRulePrelude && isLocalMode() && isID) {
               return processHashID(input, start, end);
               return processIdSelector(input, start, end);
            }
            return end;
@@ -1883,18 +2512,23 @@
                        if (isFn && name === "local") {
                           // Eat extra whitespace
                           const end = walkCssTokens.eatWhitespace(input, ident[1] + 1);
                           modeData = "local";
                           const end = walkCssTokens.eatWhitespaceAndComments(
                              input,
                              ident[1] + 1
                           )[0];
                           modeData = LOCAL_MODE;
                           const dep = new ConstDependency("", [start, end]);
                           module.addPresentationalDependency(dep);
                           balanced.push([":local", start, end]);
                           balanced.push([":local", start, end, true]);
                           return end;
                        } else if (name === "local") {
                           modeData = "local";
                           // Eat extra whitespace
                           end = walkCssTokens.eatWhitespace(input, ident[1]);
                           modeData = LOCAL_MODE;
                           const found = walkCssTokens.eatWhitespaceAndComments(
                              input,
                              ident[1]
                           );
                           if (ident[1] === end) {
                           if (!found[1]) {
                              this._emitWarning(
                                 state,
                                 `Missing whitespace after ':local' in '${input.slice(
@@ -1907,23 +2541,30 @@
                              );
                           }
                           end = walkCssTokens.eatWhitespace(input, ident[1]);
                           const dep = new ConstDependency("", [start, end]);
                           module.addPresentationalDependency(dep);
                           return end;
                        } else if (isFn && name === "global") {
                           // Eat extra whitespace
                           const end = walkCssTokens.eatWhitespace(input, ident[1] + 1);
                           modeData = "global";
                           const end = walkCssTokens.eatWhitespaceAndComments(
                              input,
                              ident[1] + 1
                           )[0];
                           modeData = GLOBAL_MODE;
                           const dep = new ConstDependency("", [start, end]);
                           module.addPresentationalDependency(dep);
                           balanced.push([":global", start, end]);
                           balanced.push([":global", start, end, true]);
                           return end;
                        } else if (name === "global") {
                           modeData = "global";
                           modeData = GLOBAL_MODE;
                           // Eat extra whitespace
                           end = walkCssTokens.eatWhitespace(input, ident[1]);
                           const found = walkCssTokens.eatWhitespaceAndComments(
                              input,
                              ident[1]
                           );
                           if (ident[1] === end) {
                           if (!found[1]) {
                              this._emitWarning(
                                 state,
                                 `Missing whitespace after ':global' in '${input.slice(
@@ -1936,6 +2577,7 @@
                              );
                           }
                           end = walkCssTokens.eatWhitespace(input, ident[1]);
                           const dep = new ConstDependency("", [start, end]);
                           module.addPresentationalDependency(dep);
                           return end;
@@ -1960,21 +2602,42 @@
            switch (name) {
               case "src":
               case "url": {
                  if (!this.url) {
                  if (!this.options.url) {
                     return end;
                  }
                  return processURLFunction(input, end, name);
               }
               default: {
                  if (this.url && IMAGE_SET_FUNCTION.test(name)) {
                  if (this.options.url && IMAGE_SET_FUNCTION.test(name)) {
                     return processImageSetFunction(input, start, end);
                  } else if (isLocalMode() && name === "var") {
                     return processVarFunction(input, end);
                  }
                  if (isModules) {
                     if (
                        this.options.function &&
                        isLocalMode() &&
                        isDashedIdentifier(name)
                     ) {
                        return processDashedIdent(input, start, end);
                     }
                     const type =
                        name === "local" ? 1 : name === "global" ? 2 : undefined;
                     if (type && !isNextRulePrelude) {
                        return processLocalOrGlobalFunction(input, type, start, end);
                     }
                  }
               }
            }
            return end;
         },
         leftSquareBracket: (input, start, end) => {
            if (isNextRulePrelude && isLocalMode()) {
               return processAttributeSelector(input, start, end);
            }
            return end;
         },
         leftParenthesis: (input, start, end) => {
@@ -1985,29 +2648,35 @@
         rightParenthesis: (input, start, end) => {
            const popped = balanced.pop();
            if (
               isModules &&
               popped &&
               (popped[0] === ":local" || popped[0] === ":global")
            ) {
               modeData = balanced[balanced.length - 1]
                  ? /** @type {"local" | "global"} */
                     (balanced[balanced.length - 1][0])
                  : undefined;
               const dep = new ConstDependency("", [start, end]);
               module.addPresentationalDependency(dep);
            if (isModules && popped) {
               const isLocal = popped[0] === ":local";
               const isGlobal = popped[0] === ":global";
               if (isLocal || isGlobal) {
                  modeData = balanced[balanced.length - 1]
                     ? balanced[balanced.length - 1][0] === ":local"
                        ? LOCAL_MODE
                        : balanced[balanced.length - 1][0] === ":global"
                           ? GLOBAL_MODE
                           : undefined
                     : undefined;
                  if (popped[3] && isLocal) {
                     while (walkCssTokens.isWhiteSpace(input.charCodeAt(start - 1))) {
                        start -= 1;
                     }
                  }
                  const dep = new ConstDependency("", [start, end]);
                  module.addPresentationalDependency(dep);
               } else if (isNextRulePrelude) {
                  modeData = undefined;
               }
            }
            return end;
         },
         comma: (input, start, end) => {
            if (isModules) {
               const popped = balanced.pop();
               if (!popped) {
                  // Reset stack for `:global .class :local .class-other` selector after
                  modeData = undefined;
               }
            if (isModules && balanced.length === 0) {
               // Reset stack for `:global .class :local .class-other` selector after
               modeData = undefined;
            }
            lastTokenEndForComments = start;
@@ -2021,29 +2690,14 @@
      const buildMeta = /** @type {BuildMeta} */ (state.module.buildMeta);
      buildMeta.exportsType = this.namedExports ? "namespace" : "default";
      buildMeta.defaultObject = this.namedExports ? false : "redirect-warn";
      buildMeta.exportType = this.exportType;
      buildMeta.exportsType = this.options.namedExports ? "namespace" : "default";
      buildMeta.defaultObject = this.options.namedExports
         ? false
         : "redirect-warn";
      if (!buildMeta.exportType) {
         // Inherit exportType from parent module to ensure consistency.
         // When a CSS file is imported with syntax like `import "./basic.css" with { type: "css" }`,
         // the parent module's exportType is set to "css-style-sheet".
         // Child modules imported via @import should inherit this exportType
         // instead of using the default "link", ensuring that the entire
         // import chain uses the same export format.
         const parent = state.compilation.moduleGraph.getIssuer(module);
         if (parent instanceof CssModule) {
            buildMeta.exportType = /** @type {BuildMeta} */ (
               parent.buildMeta
            ).exportType;
         }
      }
      // TODO this.namedExports?
      if (
         buildMeta.exportType === "text" ||
         buildMeta.exportType === "css-style-sheet"
         /** @type {CssModule} */ (module).exportType === "text" ||
         /** @type {CssModule} */ (module).exportType === "css-style-sheet"
      ) {
         module.addDependency(new StaticExportsDependency(["default"], true));
      } else {
@@ -2054,6 +2708,7 @@
   }
   /**
    * Returns comments in the range.
    * @param {Range} range range
    * @returns {Comment[]} comments in the range
    */
@@ -2061,6 +2716,7 @@
      if (!this.comments) return [];
      const [rangeStart, rangeEnd] = range;
      /**
       * Returns compared.
       * @param {Comment} comment comment
       * @param {number} needle needle
       * @returns {number} compared
@@ -2083,6 +2739,7 @@
   }
   /**
    * Parses comment options.
    * @param {Range} range range of the comment
    * @returns {{ options: Record<string, EXPECTED_ANY> | null, errors: (Error & { comment: Comment })[] | null }} result
    */
@@ -2091,7 +2748,7 @@
      if (comments.length === 0) {
         return EMPTY_COMMENT_OPTIONS;
      }
      /** @type {Record<string, EXPECTED_ANY> } */
      /** @type {Record<string, EXPECTED_ANY>} */
      const options = {};
      /** @type {(Error & { comment: Comment })[]} */
      const errors = [];