/* MIT License http://www.opensource.org/licenses/mit-license.php Author Ivan Kopeykin @vankop */ "use strict"; const { CSS_TYPE, JAVASCRIPT_TYPE } = require("../ModuleSourceTypeConstants"); const { interpolate } = require("../TemplatedPathPlugin"); const WebpackError = require("../errors/WebpackError"); const { cssExportConvention } = require("../util/conventions"); const createHash = require("../util/createHash"); const { makePathsRelative } = require("../util/identifier"); const makeSerializable = require("../util/makeSerializable"); const memoize = require("../util/memoize"); const nonNumericOnlyHash = require("../util/nonNumericOnlyHash"); const { updateHashFromSource } = require("../util/source"); const CssIcssImportDependency = require("./CssIcssImportDependency"); const NullDependency = require("./NullDependency"); const getCssParser = memoize(() => require("../css/CssParser")); /** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */ /** @typedef {import("../../declarations/WebpackOptions").HashFunction} HashFunction */ /** @typedef {import("../../declarations/WebpackOptions").CssGeneratorExportsConvention} CssGeneratorExportsConvention */ /** @typedef {import("../../declarations/WebpackOptions").CssGeneratorLocalIdentName} CssGeneratorLocalIdentName */ /** @typedef {import("../css/CssModule")} CssModule */ /** @typedef {import("../Module").BuildInfo} BuildInfo */ /** @typedef {import("../Dependency")} Dependency */ /** @typedef {import("../Dependency").ReferencedExports} ReferencedExports */ /** @typedef {import("../Dependency").ExportsSpec} ExportsSpec */ /** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */ /** @typedef {import("../DependencyTemplate").CssDependencyTemplateContext} DependencyTemplateContext */ /** @typedef {import("../ModuleGraph")} ModuleGraph */ /** @typedef {import("../css/CssGenerator")} CssGenerator */ /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */ /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */ /** @typedef {import("../util/Hash")} Hash */ /** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */ /** @typedef {import("../ChunkGraph")} ChunkGraph */ /** @typedef {import("../Compilation").ModulePathData} ModulePathData */ /** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */ /** @typedef {import("../css/CssParser").Range} Range */ /** @typedef {(name: string) => string | string[]} ExportsConventionFn */ /** * Returns local ident. * @param {string} local css local * @param {CssModule} module module * @param {ChunkGraph} chunkGraph chunk graph * @param {RuntimeTemplate} runtimeTemplate runtime template * @returns {string} local ident */ const getLocalIdent = (local, module, chunkGraph, runtimeTemplate) => { const generator = /** @type {CssGenerator} */ (module.generator); const localIdentName = /** @type {CssGeneratorLocalIdentName} */ (generator.options.localIdentName); const relativeResourcePath = makePathsRelative( /** @type {string} */ (runtimeTemplate.compilation.compiler.context), /** @type {string} */ (module.getResource()), runtimeTemplate.compilation.compiler.root ); const { uniqueName } = runtimeTemplate.outputOptions; let localIdentHash = ""; if ( typeof localIdentName === "function" || /\[(?:fullhash|hash)\]/.test(localIdentName) ) { const hashSalt = generator.options.localIdentHashSalt; const hashDigest = /** @type {string} */ (generator.options.localIdentHashDigest); const hashDigestLength = generator.options.localIdentHashDigestLength; const hashFunction = /** @type {HashFunction} */ (generator.options.localIdentHashFunction); const hash = createHash(hashFunction); if (hashSalt) { hash.update(hashSalt); } if (uniqueName) { hash.update(uniqueName); } hash.update(relativeResourcePath); hash.update(local); localIdentHash = hash.digest(hashDigest).slice(0, hashDigestLength); } let contentHash = ""; if ( typeof localIdentName === "function" || /\[contenthash\]/.test(localIdentName) ) { const hash = createHash(runtimeTemplate.outputOptions.hashFunction); const source = module.originalSource(); if (source) { updateHashFromSource(hash, source); } if (module.error) { hash.update(module.error.toString()); } const fullContentHash = hash.digest( runtimeTemplate.outputOptions.hashDigest ); contentHash = nonNumericOnlyHash( fullContentHash, runtimeTemplate.outputOptions.hashDigestLength ); } let localIdent = interpolate(localIdentName, { prepareId: (id) => { if (typeof id !== "string") return id; return ( id .replace(/^([.-]|[^a-z0-9_-])+/i, "") // We keep the `@` symbol because it can be used in the package name (e.g. `@company/package`), and if we replace it with `_`, a class conflict may occur. // For example - `@import "@foo/package/style.module.css"` and `@import "foo/package/style.module.css"` (`foo` is a package, `package` is just a directory) will create a class conflict. .replace(/[^a-z0-9@_-]+/gi, "_") ); }, filename: relativeResourcePath, hash: localIdentHash, local, contentHash, chunkGraph, module }); // TODO move these things into interpolate if (/\[local\]/.test(localIdent)) { localIdent = localIdent.replace(/\[local\]/g, local); } if (/\[uniqueName\]/.test(localIdent)) { localIdent = localIdent.replace( /\[uniqueName\]/g, /** @type {string} */ (uniqueName) ); } // Protect the first character from unsupported values return localIdent.replace(/^((-?\d)|--)/, "_$1"); }; /** @typedef {string | [string, string] | [string, string, string]} Value */ // 0 - replace, 1 - replace, 2 - append, 2 - once /** @typedef {0 | 1 | 2 | 3 | 4} ExportMode */ // 0 - normal, 1 - custom css variable, 2 - grid custom ident, 3 - composes /** @typedef {0 | 1 | 2 | 3} ExportType */ /** * Computes the interpolated identifier for `(module, value, exportType)`. * Module-level reference so `moduleGraph.cached` can use it as a stable * computer key — repeated lookups during a build skip * `cssExportConvention`, `getLocalIdent` (with its content / path hashing) * and `escapeIdentifier`. * @param {ModuleGraph} _moduleGraph module graph (unused, kept for `cached` signature) * @param {CssModule} module css module the value resolves in * @param {string} value raw value to interpolate * @param {ExportType} exportType export type discriminator * @param {ChunkGraph} chunkGraph chunk graph * @param {RuntimeTemplate} runtimeTemplate runtime template * @returns {string} interpolated identifier */ const computeInterpolatedIdentifier = ( _moduleGraph, module, value, exportType, chunkGraph, runtimeTemplate ) => { const generator = /** @type {CssGenerator} */ (module.generator); const local = cssExportConvention( value, /** @type {CssGeneratorExportsConvention} */ (generator.options.exportsConvention) )[0]; const prefix = exportType === CssIcssExportDependency.EXPORT_TYPE.CUSTOM_VARIABLE ? "--" : ""; return ( prefix + getCssParser().escapeIdentifier( getLocalIdent(local, module, chunkGraph, runtimeTemplate), runtimeTemplate.compilation.compiler.root ) ); }; /** * Top-level computer for `resolve`. Allocates a fresh `seen` set; recursive * calls go through the un-cached inner path so cycle detection still works. * @param {ModuleGraph} moduleGraph module graph * @param {CssModule} module module to search * @param {string} localName local name * @param {string} importName imported export name * @param {string | undefined} request request of the active `@value` import * @param {ChunkGraph} chunkGraph chunk graph * @param {RuntimeTemplate} runtimeTemplate runtime template * @returns {string | undefined} resolved value or undefined */ const computeResolve = ( moduleGraph, module, localName, importName, request, chunkGraph, runtimeTemplate ) => CssIcssExportDependency.Template._doResolve( localName, importName, /** @type {DependencyTemplateContext} */ ( /** @type {unknown} */ ({ moduleGraph, module, chunkGraph, runtimeTemplate }) ), request, new Set() ); /** * Top-level computer for `resolveReferences`. See `computeResolve`. * @param {ModuleGraph} moduleGraph module graph * @param {CssIcssExportDependency} dep export dependency * @param {CssModule} module module that hosts `dep` * @param {ChunkGraph} chunkGraph chunk graph * @param {RuntimeTemplate} runtimeTemplate runtime template * @returns {string[]} final references, deduplicated */ const computeResolveReferences = ( moduleGraph, dep, module, chunkGraph, runtimeTemplate ) => CssIcssExportDependency.Template._doResolveReferences( dep, /** @type {DependencyTemplateContext} */ ( /** @type {unknown} */ ({ moduleGraph, module, chunkGraph, runtimeTemplate }) ), new Set() ); class CssIcssExportDependency extends NullDependency { /** * Example of dependency: * * :export { LOCAL_NAME: EXPORT_NAME } * @param {string} name export name * @param {Value} value value or local name and import name * @param {Range=} range range * @param {boolean=} interpolate true when value need to be interpolated, otherwise false * @param {ExportMode=} exportMode export mode * @param {ExportType=} exportType export type */ constructor( name, value, range, interpolate = false, exportMode = CssIcssExportDependency.EXPORT_MODE.REPLACE, exportType = CssIcssExportDependency.EXPORT_TYPE.NORMAL ) { super(); this.name = name; this.value = value; this.range = range; this.interpolate = interpolate; this.exportMode = exportMode; this.exportType = exportType; /** @type {undefined | string} */ this._hashUpdate = undefined; /** @type {undefined | string[]} */ this._conventionNames = undefined; /** @type {undefined | string[]} */ this._valueConventionNames = undefined; } get type() { return "css :export"; } /** * Gets exports convention names. * @param {string} name export name * @param {CssGeneratorExportsConvention} convention convention of the export name * @returns {string[]} convention results */ getExportsConventionNames(name, convention) { if (this._conventionNames) { return this._conventionNames; } this._conventionNames = cssExportConvention(name, convention); return this._conventionNames; } /** * Memoized `cssExportConvention(this.value, convention)`. Used by every * code path that needs the convention-derived aliases of the composed / * referenced class: `getReferencedExports`, `getWarnings`, and the template's * `getIdentifier`. Caller guarantees `typeof this.value === "string"` — * the array form (cross-module references) is resolved separately. * @param {CssGeneratorExportsConvention} convention convention of the export name * @returns {string[]} convention results */ getValueConventionNames(convention) { if (this._valueConventionNames) { return this._valueConventionNames; } this._valueConventionNames = cssExportConvention( /** @type {string} */ (this.value), convention ); return this._valueConventionNames; } /** * Returns list of exports referenced by this dependency * @param {ModuleGraph} moduleGraph module graph * @param {RuntimeSpec} runtime the runtime for which the module is analysed * @returns {ReferencedExports} referenced exports */ getReferencedExports(moduleGraph, runtime) { if ( this.exportMode === CssIcssExportDependency.EXPORT_MODE.SELF_REFERENCE && typeof this.value === "string" ) { // `composes: foo;` — the composed class (`this.value`) is the one // referenced, not the class doing the composing (`this.name`). Apply // the generator's `exportsConvention` so the export names produced // by the convention are what the optimizer sees. const module = /** @type {CssModule | undefined} */ (moduleGraph.getParentModule(this)); if (!module) return super.getReferencedExports(moduleGraph, runtime); const generator = /** @type {CssGenerator} */ (module.generator); const names = this.getValueConventionNames( /** @type {CssGeneratorExportsConvention} */ (generator.options.exportsConvention) ); return names.map((name) => ({ name: [name], canMangle: true })); } return super.getReferencedExports(moduleGraph, runtime); } /** * Returns the exported names * @param {ModuleGraph} moduleGraph module graph * @returns {ExportsSpec | undefined} export names */ getExports(moduleGraph) { if ( this.exportMode === CssIcssExportDependency.EXPORT_MODE.NONE || this.exportMode === CssIcssExportDependency.EXPORT_MODE.SELF_REFERENCE ) { return; } const module = /** @type {CssModule} */ (moduleGraph.getParentModule(this)); const generator = /** @type {CssGenerator} */ (module.generator); const names = this.getExportsConventionNames( this.name, /** @type {CssGeneratorExportsConvention} */ (generator.options.exportsConvention) ); return { exports: [...names].map((name) => ({ name, canMangle: true })), dependencies: undefined }; } /** * Returns warnings. * @param {ModuleGraph} moduleGraph module graph * @returns {WebpackError[] | null | undefined} warnings */ getWarnings(moduleGraph) { if ( this.exportMode === CssIcssExportDependency.EXPORT_MODE.SELF_REFERENCE && typeof this.value === "string" ) { const module = /** @type {CssModule | undefined} */ (moduleGraph.getParentModule(this)); if (!module) return null; // `ExportsInfo` only stores names produced by `exportsConvention`, // so a raw `isExportProvided(this.value)` check is a false-positive // for `camel-case-only` / `dashes-only` (and any custom function // that drops the original spelling). Treat the composed class as // provided if *any* of its convention-produced aliases is provided. const generator = /** @type {CssGenerator} */ (module.generator); const exportsInfo = moduleGraph.getExportsInfo(module); const names = this.getValueConventionNames( /** @type {CssGeneratorExportsConvention} */ (generator.options.exportsConvention) ); const isProvided = names.some((name) => exportsInfo.isExportProvided(name) ); if (!isProvided) { const error = new WebpackError( `Self-referencing name "${this.value}" not found` ); error.module = module; return [error]; } } return null; } /** * Updates the hash with the data contributed by this instance. * @param {Hash} hash hash to be updated * @param {UpdateHashContext} context context * @returns {void} */ updateHash(hash, { chunkGraph }) { if (this._hashUpdate === undefined) { const module = /** @type {CssModule} */ (chunkGraph.moduleGraph.getParentModule(this)); const generator = /** @type {CssGenerator} */ (module.generator); const names = this.getExportsConventionNames( this.name, /** @type {CssGeneratorExportsConvention} */ (generator.options.exportsConvention) ); // Include all instance state that affects the emitted output — // `name`, `value`, `range`, `interpolate`, `exportMode`, // `exportType` — so changes like switching `composes: foo` → // `composes: bar` or `ONCE` → `APPEND` invalidate caches. this._hashUpdate = `exportsConvention|${JSON.stringify(names)}|localIdentName|${JSON.stringify(generator.options.localIdentName)}|value|${JSON.stringify(this.value)}|range|${JSON.stringify(this.range)}|interpolate|${this.interpolate}|exportMode|${this.exportMode}|exportType|${this.exportType}`; } hash.update(this._hashUpdate); } /** * Serializes this instance into the provided serializer context. * @param {ObjectSerializerContext} context context */ serialize(context) { const { write } = context; write(this.name); write(this.value); write(this.range); write(this.interpolate); write(this.exportMode); write(this.exportType); super.serialize(context); } /** * Restores this instance from the provided deserializer context. * @param {ObjectDeserializerContext} context context */ deserialize(context) { const { read } = context; this.name = read(); this.value = read(); this.range = read(); this.interpolate = read(); this.exportMode = read(); this.exportType = read(); super.deserialize(context); } } CssIcssExportDependency.Template = class CssIcssExportDependencyTemplate extends ( NullDependency.Template ) { /** * Returns found reference. The top-level call (no `seen` argument) is * memoized via `moduleGraph.cached` keyed by `(module, localName, * importName, request, chunkGraph, runtimeTemplate)`. Recursive callers * pass `seen` and skip the cache so the cycle guard is preserved — only * completed top-level resolutions land in the cache. * @param {string} localName local name * @param {string} importName import name * @param {DependencyTemplateContext} templateContext the context object * @param {string | undefined} request user request of the `@value` import that was active when the reference was parsed — used to disambiguate when the same local name is imported from multiple modules * @param {Set=} seen seen to prevent cyclical problems * @returns {string | undefined} found reference */ static resolve(localName, importName, templateContext, request, seen) { if (seen !== undefined) { return CssIcssExportDependencyTemplate._doResolve( localName, importName, templateContext, request, seen ); } const { moduleGraph, module, chunkGraph, runtimeTemplate } = templateContext; return moduleGraph.cached( computeResolve, /** @type {CssModule} */ (module), localName, importName, request, chunkGraph, runtimeTemplate ); } /** * Inner recursive worker for `resolve`. Not memoized — see `resolve`. * @param {string} localName local name * @param {string} importName import name * @param {DependencyTemplateContext} templateContext the context object * @param {string | undefined} request user request * @param {Set} seen seen to prevent cyclical problems * @returns {string | undefined} found reference */ static _doResolve(localName, importName, templateContext, request, seen) { const { moduleGraph } = templateContext; const importDep = /** @type {CssIcssImportDependency | undefined} */ ( CssIcssExportDependencyTemplate.findImportDep( templateContext.module.dependencies, localName, request ) ); if (!importDep) return undefined; const module = /** @type {CssModule} */ (moduleGraph.getModule(importDep)); if (!module) return undefined; const exportDep = /** @type {CssIcssExportDependency} */ ( module.dependencies.find( (d) => d instanceof CssIcssExportDependency && d.name === importName ) ); if (!exportDep) return undefined; if (seen.has(exportDep)) return undefined; seen.add(exportDep); const { value, interpolate } = exportDep; if (Array.isArray(value)) { return CssIcssExportDependencyTemplate._doResolve( value[0], value[1], { ...templateContext, module }, value[2], seen ); } if (interpolate) { return CssIcssExportDependency.Template.getIdentifier(value, exportDep, { ...templateContext, module }); } return value; } /** * Finds the active `CssIcssImportDependency` for a given local name. When a * `request` is provided the lookup also requires the import dependency's * `request` to match — this lets references that appear between two * `@value foo from "..."` declarations resolve through the import that was * in scope at the reference site, rather than always picking the first. * @param {Iterable} dependencies module dependencies to search * @param {string} localName local name * @param {string=} request user request of the `@value` import to match * @returns {CssIcssImportDependency | undefined} matching import dep, if any */ static findImportDep(dependencies, localName, request) { /** @type {CssIcssImportDependency | undefined} */ let firstMatch; for (const d of dependencies) { if (d instanceof CssIcssImportDependency && d.localName === localName) { if (request === undefined) return d; if (d.request === request) return d; if (firstMatch === undefined) firstMatch = d; } } return firstMatch; } /** * Resolves references. The top-level call (no `seen` argument) is * memoized via `moduleGraph.cached`; recursive callers pass `seen` and * bypass the cache to keep the cycle guard intact. * @param {CssIcssExportDependency} dep value * @param {DependencyTemplateContext} templateContext template context * @param {Set=} seen to prevent cyclical problems * @returns {string[]} final names */ static resolveReferences(dep, templateContext, seen) { if (seen !== undefined) { return CssIcssExportDependencyTemplate._doResolveReferences( dep, templateContext, seen ); } const { moduleGraph, module, chunkGraph, runtimeTemplate } = templateContext; return moduleGraph.cached( computeResolveReferences, dep, /** @type {CssModule} */ (module), chunkGraph, runtimeTemplate ); } /** * Inner recursive worker for `resolveReferences`. Not memoized. * @param {CssIcssExportDependency} dep value * @param {DependencyTemplateContext} templateContext template context * @param {Set} seen to prevent cyclical problems * @returns {string[]} final names */ static _doResolveReferences(dep, templateContext, seen) { /** @type {string[]} */ const references = []; if (seen.has(dep)) return references; seen.add(dep); if (Array.isArray(dep.value)) { const importDep = /** @type {CssIcssImportDependency | undefined} */ ( CssIcssExportDependencyTemplate.findImportDep( templateContext.module.dependencies, dep.value[0], dep.value[2] ) ); if (!importDep) return references; const module = /** @type {CssModule} */ (templateContext.moduleGraph.getModule(importDep)); if (!module) return references; for (const d of module.dependencies) { if (d instanceof CssIcssExportDependency && d.name === dep.value[1]) { if (Array.isArray(d.value)) { const deepReferences = CssIcssExportDependencyTemplate._doResolveReferences( d, { ...templateContext, module }, seen ); references.push(...deepReferences); } else { references.push( CssIcssExportDependencyTemplate.getIdentifier(d.value, d, { ...templateContext, module }) ); } } } } else { // Adding basic class references.push( CssIcssExportDependencyTemplate.getIdentifier( dep.value, dep, templateContext ) ); for (const d of templateContext.module.dependencies) { if ( d instanceof CssIcssExportDependency && d.exportType === CssIcssExportDependency.EXPORT_TYPE.COMPOSES && d.name === dep.value ) { if (Array.isArray(d.value)) { const deepReferences = CssIcssExportDependencyTemplate._doResolveReferences( d, templateContext, seen ); references.push(...deepReferences); } else { references.push( CssIcssExportDependencyTemplate.getIdentifier( d.value, d, templateContext ) ); } } } } return [...new Set(references)]; } /** * Returns identifier. When the dep opts into interpolation the full * computation is memoized via `moduleGraph.cached` keyed by * `(module, value, exportType, chunkGraph, runtimeTemplate)` so * `cssExportConvention` / `getLocalIdent` / `escapeIdentifier` are not * re-run for the same identifier during code generation. * @param {string} value value to identifier * @param {Dependency} dependency the dependency for which the template should be applied * @param {DependencyTemplateContext} templateContext the context object * @returns {string} identifier */ static getIdentifier(value, dependency, templateContext) { const dep = /** @type {CssIcssExportDependency} */ (dependency); if (!dep.interpolate) return value; const { moduleGraph, module, chunkGraph, runtimeTemplate } = templateContext; return moduleGraph.cached( computeInterpolatedIdentifier, /** @type {CssModule} */ (module), value, dep.exportType, chunkGraph, runtimeTemplate ); } /** * Applies the plugin by registering its hooks on the compiler. * @param {Dependency} dependency the dependency for which the template should be applied * @param {ReplaceSource} source the current replace source which can be modified * @param {DependencyTemplateContext} templateContext the context object * @returns {void} */ apply(dependency, source, templateContext) { const dep = /** @type {CssIcssExportDependency} */ (dependency); if (!dep.range && templateContext.type !== JAVASCRIPT_TYPE) return; const { module: m, moduleGraph, runtime, cssData } = templateContext; const module = /** @type {CssModule} */ (m); const generator = /** @type {CssGenerator} */ (module.generator); const isReference = Array.isArray(dep.value); /** @type {string} */ let value; // The `composes` has more complex logic for collecting all the classes if ( dep.exportType === CssIcssExportDependency.EXPORT_TYPE.COMPOSES && templateContext.type === JAVASCRIPT_TYPE ) { value = CssIcssExportDependencyTemplate.resolveReferences( dep, templateContext ).join(" "); } else if (isReference) { const resolved = CssIcssExportDependencyTemplate.resolve( dep.value[0], dep.value[1], templateContext, dep.value[2] ); // Fallback to the local name if not resolved value = resolved || dep.value[0]; } else { value = CssIcssExportDependencyTemplate.getIdentifier( /** @type {string} */ (dep.value), dep, templateContext ); } if ( dep.exportType === CssIcssExportDependency.EXPORT_TYPE.GRID_CUSTOM_IDENTIFIER ) { value += `-${dep.name}`; } if ( templateContext.type === JAVASCRIPT_TYPE && dep.exportMode !== CssIcssExportDependency.EXPORT_MODE.NONE ) { const names = dep.getExportsConventionNames( dep.name, /** @type {CssGeneratorExportsConvention} */ (generator.options.exportsConvention) ); const usedNames = /** @type {string[]} */ ( names .map((name) => moduleGraph.getExportInfo(module, name).getUsedName(name, runtime) ) .filter(Boolean) ); const allNames = new Set([...usedNames, ...names]); const unescaped = getCssParser().unescapeIdentifier( value, templateContext.runtimeTemplate.compilation.compiler.root ); const depLocStart = dep.loc && /** @type {{ start?: { line: number, column: number } }} */ (dep.loc) .start; for (const used of allNames) { if (dep.exportMode === CssIcssExportDependency.EXPORT_MODE.ONCE) { if (cssData.exports.has(used)) return; cssData.exports.set(used, unescaped); if ( depLocStart && cssData.exportLocs && !cssData.exportLocs.has(used) ) { cssData.exportLocs.set(used, { line: depLocStart.line, column: depLocStart.column }); } } else { const originalValue = dep.exportMode === CssIcssExportDependency.EXPORT_MODE.REPLACE ? undefined : cssData.exports.get(used); cssData.exports.set( used, `${originalValue ? `${originalValue}${unescaped ? " " : ""}` : ""}${unescaped}` ); // Record the source location once per export (use the first // occurrence — for APPEND/REPLACE this corresponds to the // first selector seen, which is a reasonable anchor). if ( depLocStart && cssData.exportLocs && !cssData.exportLocs.has(used) ) { cssData.exportLocs.set(used, { line: depLocStart.line, column: depLocStart.column }); } } } } else if ( dep.range && templateContext.type === CSS_TYPE && dep.exportMode !== CssIcssExportDependency.EXPORT_MODE.APPEND && dep.exportMode !== CssIcssExportDependency.EXPORT_MODE.SELF_REFERENCE ) { source.replace(dep.range[0], dep.range[1] - 1, value); } } }; /** @type {Record<"NONE" | "REPLACE" | "APPEND" | "ONCE" | "SELF_REFERENCE", ExportMode>} */ CssIcssExportDependency.EXPORT_MODE = { NONE: 0, REPLACE: 1, APPEND: 2, ONCE: 3, SELF_REFERENCE: 4 }; /** @type {Record<"NORMAL" | "CUSTOM_VARIABLE" | "GRID_CUSTOM_IDENTIFIER" | "COMPOSES", ExportType>} */ CssIcssExportDependency.EXPORT_TYPE = { NORMAL: 0, CUSTOM_VARIABLE: 1, GRID_CUSTOM_IDENTIFIER: 2, COMPOSES: 3 }; makeSerializable( CssIcssExportDependency, "webpack/lib/dependencies/CssIcssExportDependency" ); module.exports = CssIcssExportDependency;