Skip to content

Commit aa13b47

Browse files
feat: added data URLs import with new URL
1 parent 946a5a1 commit aa13b47

8 files changed

+558
-426
lines changed

src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ export default async function loader(content, map, meta) {
102102
filter: getFilter(options.url.filter, this.resourcePath),
103103
resolver: urlResolver,
104104
urlHandler: (url) => stringifyRequest(this, url),
105+
// Support data urls as input in new URL added in [email protected]
106+
isSupportDataURLInNewURL: Boolean(this._compiler.fsStartTime),
105107
})
106108
);
107109
}

src/plugins/postcss-url-parser.js

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
requestify,
66
resolveRequests,
77
isUrlRequestable,
8+
isDataUrl,
89
WEBPACK_IGNORE_COMMENT_REGEXP,
910
} from "../utils";
1011

@@ -47,7 +48,7 @@ function getWebpackIgnoreCommentValue(index, nodes, inBetween) {
4748
return matched && matched[2] === "true";
4849
}
4950

50-
function shouldHandleURL(url, declaration, result) {
51+
function shouldHandleURL(url, declaration, result, options) {
5152
if (url.length === 0) {
5253
result.warn(`Unable to find uri in '${declaration.toString()}'`, {
5354
node: declaration,
@@ -56,14 +57,24 @@ function shouldHandleURL(url, declaration, result) {
5657
return false;
5758
}
5859

60+
if (isDataUrl(url) && options.isSupportDataURLInNewURL) {
61+
try {
62+
decodeURIComponent(url);
63+
} catch (ignoreError) {
64+
return false;
65+
}
66+
67+
return true;
68+
}
69+
5970
if (!isUrlRequestable(url)) {
6071
return false;
6172
}
6273

6374
return true;
6475
}
6576

66-
function parseDeclaration(declaration, key, result) {
77+
function parseDeclaration(declaration, key, result, options) {
6778
if (!needParseDeclaration.test(declaration[key])) {
6879
return;
6980
}
@@ -130,7 +141,7 @@ function parseDeclaration(declaration, key, result) {
130141
url = normalizeUrl(url, isStringValue);
131142

132143
// Do not traverse inside `url`
133-
if (!shouldHandleURL(url, declaration, result)) {
144+
if (!shouldHandleURL(url, declaration, result, options)) {
134145
// eslint-disable-next-line consistent-return
135146
return false;
136147
}
@@ -186,7 +197,7 @@ function parseDeclaration(declaration, key, result) {
186197
url = normalizeUrl(url, isStringValue);
187198

188199
// Do not traverse inside `url`
189-
if (!shouldHandleURL(url, declaration, result)) {
200+
if (!shouldHandleURL(url, declaration, result, options)) {
190201
// eslint-disable-next-line consistent-return
191202
return false;
192203
}
@@ -229,7 +240,7 @@ function parseDeclaration(declaration, key, result) {
229240
let url = normalizeUrl(value, true);
230241

231242
// Do not traverse inside `url`
232-
if (!shouldHandleURL(url, declaration, result)) {
243+
if (!shouldHandleURL(url, declaration, result, options)) {
233244
// eslint-disable-next-line consistent-return
234245
return false;
235246
}
@@ -271,7 +282,12 @@ const plugin = (options = {}) => {
271282

272283
return {
273284
Declaration(declaration) {
274-
const parsedURL = parseDeclaration(declaration, "value", result);
285+
const parsedURL = parseDeclaration(
286+
declaration,
287+
"value",
288+
result,
289+
options
290+
);
275291

276292
if (!parsedURL) {
277293
return;
@@ -288,10 +304,15 @@ const plugin = (options = {}) => {
288304
parsedDeclarations.map(async (parsedDeclaration) => {
289305
const { url } = parsedDeclaration;
290306

307+
if (isDataUrl(url)) {
308+
return parsedDeclaration;
309+
}
310+
291311
if (options.filter) {
292312
const needKeep = await options.filter(url);
293313

294314
if (!needKeep) {
315+
// eslint-disable-next-line consistent-return
295316
return;
296317
}
297318
}
@@ -310,6 +331,7 @@ const plugin = (options = {}) => {
310331
]);
311332

312333
if (!resolvedUrl) {
334+
// eslint-disable-next-line consistent-return
313335
return;
314336
}
315337

src/utils.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,18 @@ function defaultGetLocalIdent(
427427
return interpolatedFilename;
428428
}
429429

430+
function fixedEncodeURIComponent(str) {
431+
return str.replace(/[!'()*]/g, (c) => `%${c.charCodeAt(0).toString(16)}`);
432+
}
433+
434+
function isDataUrl(url) {
435+
if (/^data:/i.test(url)) {
436+
return true;
437+
}
438+
439+
return false;
440+
}
441+
430442
const NATIVE_WIN32_PATH = /^[A-Z]:[/\\]|^\\\\/i;
431443

432444
function normalizeUrl(url, isStringValue) {
@@ -450,6 +462,11 @@ function normalizeUrl(url, isStringValue) {
450462

451463
normalizedUrl = unescape(normalizedUrl);
452464

465+
if (isDataUrl(url)) {
466+
// Todo fixedEncodeURIComponent is workaround. Webpack resolver shouldn't handle "!" in dataURL
467+
return fixedEncodeURIComponent(normalizedUrl);
468+
}
469+
453470
try {
454471
normalizedUrl = decodeURI(normalizedUrl);
455472
} catch (error) {
@@ -1142,4 +1159,5 @@ export {
11421159
combineRequests,
11431160
camelCase,
11441161
stringifyRequest,
1162+
isDataUrl,
11451163
};

test/__snapshots__/loader.test.js.snap

Lines changed: 9 additions & 3 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)