| | |
| | | |
| | | "use strict"; |
| | | |
| | | const { CSS_TYPE, JAVASCRIPT_TYPE } = require("../ModuleSourceTypeConstants"); |
| | | const { interpolate } = require("../TemplatedPathPlugin"); |
| | | const WebpackError = require("../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 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("../CssModule")} CssModule */ |
| | | /** @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("../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("../RuntimeTemplate")} RuntimeTemplate */ |
| | | /** @typedef {import("../css/CssParser").Range} Range */ |
| | | |
| | | /** @typedef {(name: string) => string} ExportsConventionFn */ |
| | | |
| | | /** |
| | | * Returns local ident. |
| | | * @param {string} local css local |
| | | * @param {CssModule} module module |
| | | * @param {ChunkGraph} chunkGraph chunk graph |
| | |
| | | const generator = /** @type {CssGenerator} */ (module.generator); |
| | | const localIdentName = |
| | | /** @type {CssGeneratorLocalIdentName} */ |
| | | (generator.localIdentName); |
| | | (generator.options.localIdentName); |
| | | const relativeResourcePath = makePathsRelative( |
| | | /** @type {string} */ |
| | | (module.context), |
| | | (runtimeTemplate.compilation.compiler.context), |
| | | /** @type {string} */ |
| | | (module.getResource()), |
| | | runtimeTemplate.compilation.compiler.root |
| | | ); |
| | | const { hashFunction, hashDigest, hashDigestLength, hashSalt, uniqueName } = |
| | | runtimeTemplate.outputOptions; |
| | | const hash = createHash(hashFunction); |
| | | const { uniqueName } = runtimeTemplate.outputOptions; |
| | | |
| | | if (hashSalt) { |
| | | hash.update(hashSalt); |
| | | } |
| | | let localIdentHash = ""; |
| | | |
| | | hash.update(relativeResourcePath); |
| | | 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); |
| | | |
| | | if (!/\[local\]/.test(localIdentName)) { |
| | | 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); |
| | | } |
| | | |
| | | const localIdentHash = hash.digest(hashDigest).slice(0, hashDigestLength); |
| | | let contentHash = ""; |
| | | |
| | | return runtimeTemplate.compilation |
| | | .getPath(localIdentName, { |
| | | filename: relativeResourcePath, |
| | | hash: localIdentHash, |
| | | contentHash: localIdentHash, |
| | | chunkGraph, |
| | | module |
| | | }) |
| | | .replace(/\[local\]/g, local) |
| | | .replace(/\[uniqueName\]/g, /** @type {string} */ (uniqueName)) |
| | | .replace(/^((-?[0-9])|--)/, "_$1"); |
| | | if ( |
| | | typeof localIdentName === "function" || |
| | | /\[contenthash\]/.test(localIdentName) |
| | | ) { |
| | | const hash = createHash(runtimeTemplate.outputOptions.hashFunction); |
| | | const source = module.originalSource(); |
| | | |
| | | if (source) { |
| | | hash.update(source.buffer()); |
| | | } |
| | | |
| | | 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"); |
| | | }; |
| | | // 0 - replace, 1 - append, 2 - once |
| | | /** @typedef {0 | 1 | 2} ExportMode */ |
| | | // 0 - none, 1 - name, 1 - value |
| | | /** @typedef {0 | 1 | 2} InterpolationMode */ |
| | | |
| | | /** @typedef {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 */ |
| | | |
| | | class CssIcssExportDependency extends NullDependency { |
| | | /** |
| | |
| | | * |
| | | * :export { LOCAL_NAME: EXPORT_NAME } |
| | | * @param {string} name export name |
| | | * @param {string} value export value or true when we need interpolate name as a value |
| | | * @param {string=} reexport reexport 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, reexport, range) { |
| | | constructor( |
| | | name, |
| | | value, |
| | | range, |
| | | interpolate = false, |
| | | exportMode = CssIcssExportDependency.EXPORT_MODE.REPLACE, |
| | | exportType = CssIcssExportDependency.EXPORT_TYPE.NORMAL |
| | | ) { |
| | | super(); |
| | | this.name = name; |
| | | this.value = value; |
| | | this.reexport = reexport; |
| | | this.range = range; |
| | | /** @type {undefined | InterpolationMode} */ |
| | | this.interpolationMode = undefined; |
| | | /** @type {ExportMode} */ |
| | | this.exportMode = CssIcssExportDependency.EXPORT_MODE.REPLACE; |
| | | this.interpolate = interpolate; |
| | | this.exportMode = exportMode; |
| | | this.exportType = exportType; |
| | | /** @type {undefined | string} */ |
| | | this._hashUpdate = undefined; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * Gets exports convention names. |
| | | * @param {string} name export name |
| | | * @param {CssGeneratorExportsConvention} convention convention of the export name |
| | | * @returns {string[]} convention results |
| | |
| | | } |
| | | |
| | | /** |
| | | * 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 |
| | | ) { |
| | | return [ |
| | | { |
| | | name: [this.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.convention) |
| | | (generator.options.exportsConvention) |
| | | ); |
| | | |
| | | return { |
| | | exports: names.map((name) => ({ |
| | | exports: [...names].map((name) => ({ |
| | | name, |
| | | canMangle: true |
| | | })), |
| | |
| | | } |
| | | |
| | | /** |
| | | * Update the hash |
| | | * Returns warnings. |
| | | * @param {ModuleGraph} moduleGraph module graph |
| | | * @returns {WebpackError[] | null | undefined} warnings |
| | | */ |
| | | getWarnings(moduleGraph) { |
| | | if ( |
| | | this.exportMode === CssIcssExportDependency.EXPORT_MODE.SELF_REFERENCE && |
| | | !Array.isArray(this.value) |
| | | ) { |
| | | const module = moduleGraph.getParentModule(this); |
| | | |
| | | if ( |
| | | module && |
| | | !moduleGraph.getExportsInfo(module).isExportProvided(this.value) |
| | | ) { |
| | | 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} |
| | |
| | | const names = this.getExportsConventionNames( |
| | | this.name, |
| | | /** @type {CssGeneratorExportsConvention} */ |
| | | (generator.convention) |
| | | (generator.options.exportsConvention) |
| | | ); |
| | | this._hashUpdate = `exportsConvention|${JSON.stringify(names)}|localIdentName|${JSON.stringify(generator.localIdentName)}`; |
| | | this._hashUpdate = `exportsConvention|${JSON.stringify(names)}|localIdentName|${JSON.stringify(generator.options.localIdentName)}`; |
| | | } |
| | | 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.reexport); |
| | | write(this.range); |
| | | write(this.interpolationMode); |
| | | 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.reexport = read(); |
| | | this.range = read(); |
| | | this.interpolationMode = read(); |
| | | this.interpolate = read(); |
| | | this.exportMode = read(); |
| | | this.exportType = read(); |
| | | super.deserialize(context); |
| | | } |
| | | } |
| | |
| | | ) { |
| | | // TODO looking how to cache |
| | | /** |
| | | * @param {string} symbol the name of symbol |
| | | * Returns found reference. |
| | | * @param {string} localName local name |
| | | * @param {string} importName import name |
| | | * @param {DependencyTemplateContext} templateContext the context object |
| | | * @param {Set<CssIcssExportDependency>} seen seen to prevent cyclical problems |
| | | * @returns {string | undefined} found reference |
| | | */ |
| | | static findReference(symbol, templateContext) { |
| | | for (const item of templateContext.module.dependencies) { |
| | | if (item instanceof CssIcssImportDependency) { |
| | | // Looking for the referring module |
| | | const module = templateContext.moduleGraph.getModule(item); |
| | | static resolve(localName, importName, templateContext, seen = new Set()) { |
| | | const { moduleGraph } = templateContext; |
| | | const importDep = |
| | | /** @type {CssIcssImportDependency | undefined} */ |
| | | ( |
| | | templateContext.module.dependencies.find( |
| | | (d) => |
| | | d instanceof CssIcssImportDependency && d.localName === localName |
| | | ) |
| | | ); |
| | | if (!importDep) return undefined; |
| | | |
| | | if (!module) { |
| | | return undefined; |
| | | } |
| | | const module = /** @type {CssModule} */ (moduleGraph.getModule(importDep)); |
| | | if (!module) return undefined; |
| | | |
| | | for (let i = module.dependencies.length - 1; i >= 0; i--) { |
| | | const nestedDep = module.dependencies[i]; |
| | | if ( |
| | | nestedDep instanceof CssIcssExportDependency && |
| | | symbol === nestedDep.name |
| | | ) { |
| | | if (nestedDep.reexport) { |
| | | return this.findReference(nestedDep.reexport, { |
| | | 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 this.resolve( |
| | | value[0], |
| | | value[1], |
| | | { |
| | | ...templateContext, |
| | | module |
| | | }, |
| | | seen |
| | | ); |
| | | } |
| | | |
| | | if (interpolate) { |
| | | return CssIcssExportDependency.Template.getIdentifier(value, exportDep, { |
| | | ...templateContext, |
| | | module |
| | | }); |
| | | } |
| | | |
| | | return value; |
| | | } |
| | | |
| | | /** |
| | | * Resolves references. |
| | | * @param {CssIcssExportDependency} dep value |
| | | * @param {DependencyTemplateContext} templateContext template context |
| | | * @param {Set<CssIcssExportDependency>} seen to prevent cyclical problems |
| | | * @returns {string[]} final names |
| | | */ |
| | | static resolveReferences(dep, templateContext, seen = new Set()) { |
| | | /** @type {string[]} */ |
| | | const references = []; |
| | | |
| | | if (seen.has(dep)) return references; |
| | | seen.add(dep); |
| | | |
| | | if (Array.isArray(dep.value)) { |
| | | const importDep = |
| | | /** @type {CssIcssImportDependency | undefined} */ |
| | | ( |
| | | templateContext.module.dependencies.find( |
| | | (d) => |
| | | d instanceof CssIcssImportDependency && |
| | | d.localName === dep.value[0] |
| | | ) |
| | | ); |
| | | 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.resolveReferences( |
| | | 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 |
| | | ) |
| | | ); |
| | | |
| | | return CssIcssExportDependency.Template.getIdentifier(nestedDep, { |
| | | ...templateContext, |
| | | module |
| | | }); |
| | | 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.resolveReferences( |
| | | d, |
| | | templateContext, |
| | | seen |
| | | ); |
| | | |
| | | references.push(...deepReferences); |
| | | } else { |
| | | references.push( |
| | | CssIcssExportDependencyTemplate.getIdentifier( |
| | | d.value, |
| | | d, |
| | | templateContext |
| | | ) |
| | | ); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | return [...new Set(references)]; |
| | | } |
| | | |
| | | /** |
| | | * Returns identifier. |
| | | * @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(dependency, templateContext) { |
| | | static getIdentifier(value, dependency, templateContext) { |
| | | const dep = /** @type {CssIcssExportDependency} */ (dependency); |
| | | |
| | | if ( |
| | | dep.interpolationMode === |
| | | CssIcssExportDependency.INTERPOLATION_MODE.NAME || |
| | | dep.interpolationMode === CssIcssExportDependency.INTERPOLATION_MODE.VALUE |
| | | ) { |
| | | const { module: m, moduleGraph, runtime } = templateContext; |
| | | if (dep.interpolate) { |
| | | const { module: m } = templateContext; |
| | | const module = /** @type {CssModule} */ (m); |
| | | const generator = /** @type {CssGenerator} */ (module.generator); |
| | | const names = dep.getExportsConventionNames( |
| | | dep.interpolationMode === |
| | | CssIcssExportDependency.INTERPOLATION_MODE.NAME |
| | | ? dep.name |
| | | : dep.value, |
| | | const local = cssExportConvention( |
| | | value, |
| | | /** @type {CssGeneratorExportsConvention} */ |
| | | (generator.convention) |
| | | (generator.options.exportsConvention) |
| | | )[0]; |
| | | const prefix = |
| | | dep.exportType === CssIcssExportDependency.EXPORT_TYPE.CUSTOM_VARIABLE |
| | | ? "--" |
| | | : ""; |
| | | |
| | | return ( |
| | | prefix + |
| | | getCssParser().escapeIdentifier( |
| | | getLocalIdent( |
| | | local, |
| | | /** @type {CssModule} */ |
| | | (m), |
| | | templateContext.chunkGraph, |
| | | templateContext.runtimeTemplate |
| | | ) |
| | | ) |
| | | ); |
| | | } |
| | | |
| | | return value; |
| | | } |
| | | |
| | | /** |
| | | * 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 |
| | | ); |
| | | |
| | | // 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[]} */ |
| | |
| | | ) |
| | | .filter(Boolean) |
| | | ); |
| | | const local = usedNames.length === 0 ? names[0] : usedNames[0]; |
| | | const prefix = |
| | | /** @type {CssIcssExportDependency & { prefix: string }} */ |
| | | (dependency).prefix; |
| | | const allNames = new Set([...usedNames, ...names]); |
| | | const unescaped = getCssParser().unescapeIdentifier(value); |
| | | |
| | | return ( |
| | | (prefix || "") + |
| | | getCssParser().escapeIdentifier( |
| | | getLocalIdent( |
| | | local, |
| | | /** @type {CssModule} */ |
| | | (templateContext.module), |
| | | templateContext.chunkGraph, |
| | | templateContext.runtimeTemplate |
| | | ) |
| | | ) |
| | | ); |
| | | } |
| | | |
| | | return /** @type {string} */ (dep.value); |
| | | } |
| | | |
| | | /** |
| | | * @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") return; |
| | | const { cssData } = templateContext; |
| | | const { module: m, moduleGraph, runtime } = templateContext; |
| | | const module = /** @type {CssModule} */ (m); |
| | | const generator = /** @type {CssGenerator} */ (module.generator); |
| | | const names = dep.getExportsConventionNames( |
| | | dep.name, |
| | | /** @type {CssGeneratorExportsConvention} */ |
| | | (generator.convention) |
| | | ); |
| | | const usedNames = |
| | | /** @type {string[]} */ |
| | | ( |
| | | names |
| | | .map((name) => |
| | | moduleGraph.getExportInfo(module, name).getUsedName(name, runtime) |
| | | ) |
| | | .filter(Boolean) |
| | | ); |
| | | |
| | | const allNames = new Set([...usedNames, ...names]); |
| | | |
| | | /** @type {string} */ |
| | | let value; |
| | | |
| | | if (dep.reexport) { |
| | | const resolved = CssIcssExportDependencyTemplate.findReference( |
| | | dep.reexport, |
| | | templateContext |
| | | ); |
| | | |
| | | if (resolved) { |
| | | dep.value = resolved; |
| | | } |
| | | } |
| | | |
| | | if (typeof dep.interpolationMode !== "undefined") { |
| | | value = CssIcssExportDependencyTemplate.getIdentifier( |
| | | dep, |
| | | templateContext |
| | | ); |
| | | } else { |
| | | value = dep.value; |
| | | } |
| | | |
| | | if (templateContext.type === "javascript") { |
| | | for (const used of allNames) { |
| | | if (dep.exportMode === 2) { |
| | | if (dep.exportMode === CssIcssExportDependency.EXPORT_MODE.ONCE) { |
| | | if (cssData.exports.has(used)) return; |
| | | cssData.exports.set( |
| | | used, |
| | | `${getCssParser().unescapeIdentifier(value)}` |
| | | ); |
| | | cssData.exports.set(used, unescaped); |
| | | } else { |
| | | const originalValue = |
| | | dep.exportMode === 0 ? undefined : cssData.exports.get(used); |
| | | const newValue = getCssParser().unescapeIdentifier(value); |
| | | dep.exportMode === CssIcssExportDependency.EXPORT_MODE.REPLACE |
| | | ? undefined |
| | | : cssData.exports.get(used); |
| | | |
| | | cssData.exports.set( |
| | | used, |
| | | `${originalValue ? `${originalValue}${newValue ? " " : ""}` : ""}${newValue}` |
| | | `${originalValue ? `${originalValue}${unescaped ? " " : ""}` : ""}${unescaped}` |
| | | ); |
| | | } |
| | | } |
| | | } else if ( |
| | | dep.range && |
| | | templateContext.type === "css" && |
| | | dep.exportMode !== 1 |
| | | 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<"REPLACE" | "APPEND" | "ONCE", ExportMode>} */ |
| | | /** @type {Record<"NONE" | "REPLACE" | "APPEND" | "ONCE" | "SELF_REFERENCE", ExportMode>} */ |
| | | CssIcssExportDependency.EXPORT_MODE = { |
| | | REPLACE: 0, |
| | | APPEND: 1, |
| | | ONCE: 2 |
| | | NONE: 0, |
| | | REPLACE: 1, |
| | | APPEND: 2, |
| | | ONCE: 3, |
| | | SELF_REFERENCE: 4 |
| | | }; |
| | | |
| | | /** @type {Record<"NONE" | "NAME" | "VALUE", InterpolationMode>} */ |
| | | CssIcssExportDependency.INTERPOLATION_MODE = { |
| | | NONE: 0, |
| | | NAME: 1, |
| | | VALUE: 2 |
| | | /** @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( |