Skip to content

Commit ac5ad35

Browse files
cap-Bernarditoalexander-akait
authored andcommitted
feat: added data URLs import with new URL
1 parent 09675d9 commit ac5ad35

File tree

6 files changed

+90
-30
lines changed

6 files changed

+90
-30
lines changed

src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ export default async function loader(content, map, meta) {
101101
: // eslint-disable-next-line no-undefined
102102
undefined,
103103
urlHandler: (url) => stringifyRequest(this, url),
104+
// Support data urls as input in new URL added in [email protected]
105+
isSupportDataURLInNewURL: Boolean(this._compiler.fsStartTime),
104106
})
105107
);
106108
}

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
normalizeUrl,
66
requestify,
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
}
@@ -320,6 +341,7 @@ const plugin = (options = {}) => {
320341
]);
321342

322343
if (!resolvedUrl) {
344+
// eslint-disable-next-line consistent-return
323345
return;
324346
}
325347

src/utils.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,18 @@ function defaultGetLocalIdent(
390390
return loaderContext._compilation.getPath(localIdentName, data);
391391
}
392392

393+
function fixedEncodeURIComponent(str) {
394+
return str.replace(/[!'()*]/g, (c) => `%${c.charCodeAt(0).toString(16)}`);
395+
}
396+
397+
function isDataUrl(url) {
398+
if (/^data:/i.test(url)) {
399+
return true;
400+
}
401+
402+
return false;
403+
}
404+
393405
const NATIVE_WIN32_PATH = /^[A-Z]:[/\\]|^\\\\/i;
394406

395407
function normalizeUrl(url, isStringValue) {
@@ -413,6 +425,11 @@ function normalizeUrl(url, isStringValue) {
413425

414426
normalizedUrl = unescape(normalizedUrl);
415427

428+
if (isDataUrl(url)) {
429+
// Todo fixedEncodeURIComponent is workaround. Webpack resolver shouldn't handle "!" in dataURL
430+
return fixedEncodeURIComponent(normalizedUrl);
431+
}
432+
416433
try {
417434
normalizedUrl = decodeURI(normalizedUrl);
418435
} catch (error) {
@@ -1099,4 +1116,5 @@ export {
10991116
combineRequests,
11001117
camelCase,
11011118
stringifyRequest,
1119+
isDataUrl,
11021120
};

0 commit comments

Comments
 (0)