CssLocalIdentifierDependency.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Ivan Kopeykin @vankop
  4. */
  5. "use strict";
  6. const makeSerializable = require("../util/makeSerializable");
  7. const NullDependency = require("./NullDependency");
  8. /** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
  9. /** @typedef {import("../Dependency")} Dependency */
  10. /** @typedef {import("../Dependency").ExportsSpec} ExportsSpec */
  11. /** @typedef {import("../DependencyTemplate").CssDependencyTemplateContext} DependencyTemplateContext */
  12. /** @typedef {import("../ModuleGraph")} ModuleGraph */
  13. /** @typedef {import("../css/CssParser").Range} Range */
  14. /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
  15. /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
  16. class CssLocalIdentifierDependency extends NullDependency {
  17. /**
  18. * @param {string} name name
  19. * @param {Range} range range
  20. * @param {string=} prefix prefix
  21. */
  22. constructor(name, range, prefix = "") {
  23. super();
  24. this.name = name;
  25. this.range = range;
  26. this.prefix = prefix;
  27. }
  28. get type() {
  29. return "css local identifier";
  30. }
  31. /**
  32. * Returns the exported names
  33. * @param {ModuleGraph} moduleGraph module graph
  34. * @returns {ExportsSpec | undefined} export names
  35. */
  36. getExports(moduleGraph) {
  37. const name = this.name;
  38. return {
  39. exports: [
  40. {
  41. name,
  42. canMangle: true
  43. }
  44. ],
  45. dependencies: undefined
  46. };
  47. }
  48. /**
  49. * @param {ObjectSerializerContext} context context
  50. */
  51. serialize(context) {
  52. const { write } = context;
  53. write(this.name);
  54. write(this.range);
  55. write(this.prefix);
  56. super.serialize(context);
  57. }
  58. /**
  59. * @param {ObjectDeserializerContext} context context
  60. */
  61. deserialize(context) {
  62. const { read } = context;
  63. this.name = read();
  64. this.range = read();
  65. this.prefix = read();
  66. super.deserialize(context);
  67. }
  68. }
  69. /**
  70. * @param {string} str string
  71. * @param {string | boolean} omitUnderscore true if you need to omit underscore
  72. * @returns {string} escaped css identifier
  73. */
  74. const escapeCssIdentifier = (str, omitUnderscore) => {
  75. const escaped = `${str}`.replace(
  76. // cspell:word uffff
  77. /[^a-zA-Z0-9_\u0081-\uffff-]/g,
  78. s => `\\${s}`
  79. );
  80. return !omitUnderscore && /^(?!--)[0-9-]/.test(escaped)
  81. ? `_${escaped}`
  82. : escaped;
  83. };
  84. CssLocalIdentifierDependency.Template = class CssLocalIdentifierDependencyTemplate extends (
  85. NullDependency.Template
  86. ) {
  87. /**
  88. * @param {Dependency} dependency the dependency for which the template should be applied
  89. * @param {ReplaceSource} source the current replace source which can be modified
  90. * @param {DependencyTemplateContext} templateContext the context object
  91. * @returns {void}
  92. */
  93. apply(
  94. dependency,
  95. source,
  96. { module, moduleGraph, chunkGraph, runtime, runtimeTemplate, cssExports }
  97. ) {
  98. const dep = /** @type {CssLocalIdentifierDependency} */ (dependency);
  99. const used = moduleGraph
  100. .getExportInfo(module, dep.name)
  101. .getUsedName(dep.name, runtime);
  102. if (!used) return;
  103. const moduleId = chunkGraph.getModuleId(module);
  104. const identifier =
  105. dep.prefix +
  106. (runtimeTemplate.outputOptions.uniqueName
  107. ? runtimeTemplate.outputOptions.uniqueName + "-"
  108. : "") +
  109. (used ? moduleId + "-" + used : "-");
  110. source.replace(
  111. dep.range[0],
  112. dep.range[1] - 1,
  113. escapeCssIdentifier(identifier, dep.prefix)
  114. );
  115. if (used) cssExports.set(used, identifier);
  116. }
  117. };
  118. makeSerializable(
  119. CssLocalIdentifierDependency,
  120. "webpack/lib/dependencies/CssLocalIdentifierDependency"
  121. );
  122. module.exports = CssLocalIdentifierDependency;