UNPKG

3.64 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Ivan Kopeykin @vankop
4*/
5
6"use strict";
7
8const makeSerializable = require("../util/makeSerializable");
9const memoize = require("../util/memoize");
10const ModuleDependency = require("./ModuleDependency");
11
12/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
13/** @typedef {import("../ChunkGraph")} ChunkGraph */
14/** @typedef {import("../Dependency")} Dependency */
15/** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
16/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
17/** @typedef {import("../Module")} Module */
18/** @typedef {import("../ModuleGraph")} ModuleGraph */
19/** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
20/** @typedef {import("../ModuleGraphConnection").ConnectionState} ConnectionState */
21/** @typedef {import("../util/Hash")} Hash */
22/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
23
24const getRawDataUrlModule = memoize(() => require("../asset/RawDataUrlModule"));
25
26class CssUrlDependency extends ModuleDependency {
27 /**
28 * @param {string} request request
29 * @param {[number, number]} range range of the argument
30 * @param {string} cssFunctionKind kind of css function, e. g. url(), image()
31 */
32 constructor(request, range, cssFunctionKind) {
33 super(request);
34 this.range = range;
35 this.cssFunctionKind = cssFunctionKind;
36 }
37
38 get type() {
39 return "css url()";
40 }
41
42 get category() {
43 return "url";
44 }
45
46 /**
47 * @param {string} context context directory
48 * @returns {Module} a module
49 */
50 createIgnoredModule(context) {
51 const RawDataUrlModule = getRawDataUrlModule();
52 return new RawDataUrlModule("data:,", `ignored-asset`, `(ignored asset)`);
53 }
54
55 serialize(context) {
56 const { write } = context;
57 write(this.cssFunctionKind);
58 super.serialize(context);
59 }
60
61 deserialize(context) {
62 const { read } = context;
63 this.cssFunctionKind = read();
64 super.deserialize(context);
65 }
66}
67
68const cssEscapeString = str => {
69 let countWhiteOrBracket = 0;
70 let countQuotation = 0;
71 let countApostrophe = 0;
72 for (let i = 0; i < str.length; i++) {
73 const cc = str.charCodeAt(i);
74 switch (cc) {
75 case 9: // tab
76 case 10: // nl
77 case 32: // space
78 case 40: // (
79 case 41: // )
80 countWhiteOrBracket++;
81 break;
82 case 34:
83 countQuotation++;
84 break;
85 case 39:
86 countApostrophe++;
87 break;
88 }
89 }
90 if (countWhiteOrBracket < 2) {
91 return str.replace(/[\n\t ()'"\\]/g, m => `\\${m}`);
92 } else if (countQuotation <= countApostrophe) {
93 return `"${str.replace(/[\n"\\]/g, m => `\\${m}`)}"`;
94 } else {
95 return `'${str.replace(/[\n'\\]/g, m => `\\${m}`)}'`;
96 }
97};
98
99CssUrlDependency.Template = class CssUrlDependencyTemplate extends (
100 ModuleDependency.Template
101) {
102 /**
103 * @param {Dependency} dependency the dependency for which the template should be applied
104 * @param {ReplaceSource} source the current replace source which can be modified
105 * @param {DependencyTemplateContext} templateContext the context object
106 * @returns {void}
107 */
108 apply(
109 dependency,
110 source,
111 { runtime, moduleGraph, runtimeTemplate, codeGenerationResults }
112 ) {
113 const dep = /** @type {CssUrlDependency} */ (dependency);
114
115 source.replace(
116 dep.range[0],
117 dep.range[1] - 1,
118 `${dep.cssFunctionKind}(${cssEscapeString(
119 runtimeTemplate.assetUrl({
120 publicPath: "",
121 runtime,
122 module: moduleGraph.getModule(dep),
123 codeGenerationResults
124 })
125 )})`
126 );
127 }
128};
129
130makeSerializable(CssUrlDependency, "webpack/lib/dependencies/CssUrlDependency");
131
132module.exports = CssUrlDependency;