Skip to content

Commit 1e3e671

Browse files
authored
Merge pull request #15155 from webpack/fix-handle-data-uri-in-loader
fix: handle content from loaders
2 parents b26793d + eaaccf9 commit 1e3e671

4 files changed

Lines changed: 67 additions & 22 deletions

File tree

lib/asset/AssetGenerator.js

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,41 @@ const mergeRelatedInfo = (a, b) => {
7474
return result;
7575
};
7676

77+
const encodeDataUri = (encoding, source) => {
78+
let encodedContent;
79+
80+
switch (encoding) {
81+
case "base64": {
82+
encodedContent = source.buffer().toString("base64");
83+
break;
84+
}
85+
case false: {
86+
const content = source.source();
87+
88+
if (typeof content !== "string") {
89+
encodedContent = content.toString("utf-8");
90+
}
91+
92+
encodedContent = encodeURIComponent(encodedContent).replace(
93+
/[!'()*]/g,
94+
character => "%" + character.codePointAt(0).toString(16)
95+
);
96+
break;
97+
}
98+
default:
99+
throw new Error(`Unsupported encoding '${encoding}'`);
100+
}
101+
102+
return encodedContent;
103+
};
104+
105+
const decodeDataUriContent = (encoding, content) => {
106+
const isBase64 = encoding === "base64";
107+
return isBase64
108+
? Buffer.from(content, "base64")
109+
: Buffer.from(decodeURIComponent(content), "ascii");
110+
};
111+
77112
const JS_TYPES = new Set(["javascript"]);
78113
const JS_AND_ASSET_TYPES = new Set(["javascript", "asset"]);
79114

@@ -158,33 +193,18 @@ class AssetGenerator extends Generator {
158193
}
159194

160195
let encodedContent;
196+
161197
if (
162198
module.resourceResolveData &&
163-
module.resourceResolveData.encoding === encoding
199+
module.resourceResolveData.encoding === encoding &&
200+
decodeDataUriContent(
201+
module.resourceResolveData.encoding,
202+
module.resourceResolveData.encodedContent
203+
).equals(originalSource.buffer())
164204
) {
165205
encodedContent = module.resourceResolveData.encodedContent;
166206
} else {
167-
switch (encoding) {
168-
case "base64": {
169-
encodedContent = originalSource.buffer().toString("base64");
170-
break;
171-
}
172-
case false: {
173-
const content = originalSource.source();
174-
175-
if (typeof content !== "string") {
176-
encodedContent = content.toString("utf-8");
177-
}
178-
179-
encodedContent = encodeURIComponent(encodedContent).replace(
180-
/[!'()*]/g,
181-
character => "%" + character.codePointAt(0).toString(16)
182-
);
183-
break;
184-
}
185-
default:
186-
throw new Error(`Unsupported encoding '${encoding}'`);
187-
}
207+
encodedContent = encodeDataUri(encoding, originalSource);
188208
}
189209

190210
encodedSource = `data:${mimeType}${

test/configCases/asset-modules/data-url/index.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,27 @@ import dataSvg from "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53M
55
const urlSvg = new URL(
66
"data:image/svg;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MDAgNjAwIj48dGl0bGU+aWNvbi1zcXVhcmUtc21hbGw8L3RpdGxlPjxwYXRoIGZpbGw9IiNGRkYiIGQ9Ik0zMDAgLjFMNTY1IDE1MHYyOTkuOUwzMDAgNTk5LjggMzUgNDQ5LjlWMTUweiIvPjxwYXRoIGZpbGw9IiM4RUQ2RkIiIGQ9Ik01MTcuNyA0MzkuNUwzMDguOCA1NTcuOHYtOTJMNDM5IDM5NC4xbDc4LjcgNDUuNHptMTQuMy0xMi45VjE3OS40bC03Ni40IDQ0LjF2MTU5bDc2LjQgNDQuMXpNODEuNSA0MzkuNWwyMDguOSAxMTguMnYtOTJsLTEzMC4yLTcxLjYtNzguNyA0NS40em0tMTQuMy0xMi45VjE3OS40bDc2LjQgNDQuMXYxNTlsLTc2LjQgNDQuMXptOC45LTI2My4yTDI5MC40IDQyLjJ2ODlsLTEzNy4zIDc1LjUtMS4xLjYtNzUuOS00My45em00NDYuOSAwTDMwOC44IDQyLjJ2ODlMNDQ2IDIwNi44bDEuMS42IDc1LjktNDR6Ii8+PHBhdGggZmlsbD0iIzFDNzhDMCIgZD0iTTI5MC40IDQ0NC44TDE2MiAzNzQuMVYyMzQuMmwxMjguNCA3NC4xdjEzNi41em0xOC40IDBsMTI4LjQtNzAuNnYtMTQwbC0xMjguNCA3NC4xdjEzNi41ek0yOTkuNiAzMDN6bS0xMjktODVsMTI5LTcwLjlMNDI4LjUgMjE4bC0xMjguOSA3NC40LTEyOS03NC40eiIvPjwvc3ZnPgo="
77
);
8+
const urlSvg2 = new URL(
9+
"data:image/svg+xml;p=1;q=2,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke=\"%23343a40\" stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e",
10+
import.meta.url
11+
);
12+
const helloWorld = new URL("data:text/plain,Hello", import.meta.url);
13+
const helloWorldBase64 = new URL(
14+
"data:text/plain;base64,SGVsbG8=",
15+
import.meta.url
16+
);
817

918
it("should generate various data-url types", () => {
1019
expect(png).toContain("data:image/png;base64,");
1120
expect(svg).toContain("data:image/svg+xml;base64");
1221
expect(jpg).toContain("data:image/jpeg;base64,");
1322
expect(dataSvg).toContain("data:image/svg+xml;base64,");
1423
expect(urlSvg.href).toContain("data:image/svg;base64,");
24+
expect(urlSvg2.href).toContain(
25+
"data:image/svg+xml;p=1;q=2,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke=\"%23343a40\" stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"
26+
);
27+
expect(helloWorld.href).toContain("data:text/plain,Hello%2C%20World%21");
28+
expect(helloWorldBase64.href).toContain(
29+
"data:text/plain;base64,SGVsbG8sIFdvcmxkIQ=="
30+
);
1531
});
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/** @type {import("../../../../").LoaderDefinition<{ f(): any }>} */
2+
module.exports = function (source) {
3+
return `${source}, World!`;
4+
};

test/configCases/asset-modules/data-url/webpack.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ module.exports = {
1919
maxSize: Infinity
2020
}
2121
}
22+
},
23+
{
24+
mimetype: "text/plain",
25+
type: "asset/inline",
26+
loader: "./loader"
2227
}
2328
]
2429
}

0 commit comments

Comments
 (0)