CssIcssImportDependency.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Ivan Kopeykin @vankop
  4. */
  5. "use strict";
  6. const WebpackError = require("../errors/WebpackError");
  7. const { cssExportConvention } = require("../util/conventions");
  8. const makeSerializable = require("../util/makeSerializable");
  9. const CssImportDependency = require("./CssImportDependency");
  10. /** @import { ReplaceSource } from "webpack-sources" */
  11. /** @import Dependency, { ReferencedExports } from "../Dependency" */
  12. /**
  13. * @import {
  14. * CssDependencyTemplateContext as DependencyTemplateContext
  15. * } from "../DependencyTemplate"
  16. */
  17. /** @import CssGenerator from "../css/CssGenerator" */
  18. /** @import CssModule from "../css/CssModule" */
  19. /** @import ModuleGraph from "../ModuleGraph" */
  20. /** @import { RuntimeSpec } from "../util/runtime" */
  21. /** @import { Range } from "../javascript/JavascriptParser" */
  22. /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext<[string, string]>} ObjectDeserializerContext */
  23. /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext<[string, string]>} ObjectSerializerContext */
  24. /**
  25. * @import {
  26. * CssGeneratorExportsConvention
  27. * } from "../../declarations/WebpackOptions"
  28. */
  29. class CssIcssImportDependency extends CssImportDependency {
  30. /**
  31. * Example of dependency:
  32. *
  33. * :import('./style.css') { value: name }
  34. * @param {string} request request request path which needs resolving
  35. * @param {Range} range the range of dependency
  36. * @param {"local" | "global"} mode mode of the parsed CSS
  37. * @param {string} importName import name (`name` from example)
  38. * @param {string} localName local name (`value` from example)
  39. */
  40. constructor(request, range, mode, importName, localName) {
  41. super(request, range, mode);
  42. /** @type {string} */
  43. this.importName = importName;
  44. /** @type {string} */
  45. this.localName = localName;
  46. /** @type {undefined | string[]} */
  47. this._importNameConventionNames = undefined;
  48. }
  49. /**
  50. * Memoized `cssExportConvention(this.importName, convention)`. The target
  51. * module is fixed for a given dep, so its `exportsConvention` is fixed,
  52. * so the convention-derived aliases of `importName` can be cached on the dep.
  53. * @param {CssGeneratorExportsConvention} convention convention from the target module's generator
  54. * @returns {string[]} convention results
  55. */
  56. getImportNameConventionNames(convention) {
  57. if (this._importNameConventionNames) {
  58. return this._importNameConventionNames;
  59. }
  60. this._importNameConventionNames = cssExportConvention(
  61. this.importName,
  62. convention
  63. );
  64. return this._importNameConventionNames;
  65. }
  66. get type() {
  67. return "css :import";
  68. }
  69. /**
  70. * Returns list of exports referenced by this dependency
  71. * @param {ModuleGraph} moduleGraph module graph
  72. * @param {RuntimeSpec} runtime the runtime for which the module is analysed
  73. * @returns {ReferencedExports} referenced exports
  74. */
  75. getReferencedExports(moduleGraph, runtime) {
  76. return [
  77. {
  78. name: [this.importName],
  79. canMangle: true
  80. }
  81. ];
  82. }
  83. /**
  84. * Returns warnings.
  85. * @param {ModuleGraph} moduleGraph module graph
  86. * @returns {WebpackError[] | null | undefined} warnings
  87. */
  88. getWarnings(moduleGraph) {
  89. const module = /** @type {CssModule | undefined} */ (
  90. moduleGraph.getModule(this)
  91. );
  92. if (!module) return null;
  93. // The target module stores exports under the names produced by its
  94. // `exportsConvention`, so a raw `isExportProvided(this.importName)`
  95. // would false-positive against `camel-case-only` / `dashes-only` (and
  96. // any custom function that drops the original spelling). Expand
  97. // `importName` through the *target* module's convention and accept
  98. // if any alias is provided.
  99. const generator =
  100. /** @type {CssGenerator | undefined} */
  101. (module.generator);
  102. const convention =
  103. generator &&
  104. /** @type {CssGeneratorExportsConvention | undefined} */
  105. (generator.options && generator.options.exportsConvention);
  106. const exportsInfo = moduleGraph.getExportsInfo(module);
  107. const names = convention
  108. ? this.getImportNameConventionNames(convention)
  109. : [this.importName];
  110. const isProvided = names.some((name) => exportsInfo.isExportProvided(name));
  111. if (!isProvided) {
  112. const error = new WebpackError(
  113. `Referenced name "${this.importName}" in "${this.userRequest}" not found`
  114. );
  115. error.module = module;
  116. return [error];
  117. }
  118. return null;
  119. }
  120. /**
  121. * Serializes this instance into the provided serializer context.
  122. * @param {ObjectSerializerContext} context context
  123. */
  124. serialize(context) {
  125. context.write(this.importName).write(this.localName);
  126. super.serialize(context);
  127. }
  128. /**
  129. * Restores this instance from the provided deserializer context.
  130. * @param {ObjectDeserializerContext} context context
  131. */
  132. deserialize(context) {
  133. this.importName = context.read();
  134. const c1 = context.rest;
  135. this.localName = c1.read();
  136. super.deserialize(c1.rest);
  137. }
  138. }
  139. CssIcssImportDependency.Template = class CssIcssImportDependencyTemplate extends (
  140. CssImportDependency.Template
  141. ) {
  142. /**
  143. * Applies the plugin by registering its hooks on the compiler.
  144. * @param {Dependency} dependency the dependency for which the template should be applied
  145. * @param {ReplaceSource} source the current replace source which can be modified
  146. * @param {DependencyTemplateContext} templateContext the context object
  147. * @returns {void}
  148. */
  149. apply(dependency, source, templateContext) {
  150. // Nothing
  151. }
  152. };
  153. makeSerializable(
  154. CssIcssImportDependency,
  155. "webpack/lib/dependencies/CssIcssImportDependency"
  156. );
  157. module.exports = CssIcssImportDependency;