Skip to content

Commit 6f9a687

Browse files
fix: handling unquoted syntax url with escaped characters
1 parent 880344b commit 6f9a687

File tree

3 files changed

+114
-14
lines changed

3 files changed

+114
-14
lines changed

src/plugins/postcss-url-parser.js

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,20 @@ function getNodeFromUrlFunc(node) {
1111
return node.nodes && node.nodes[0];
1212
}
1313

14-
function getUrlFromUrlFunc(node) {
15-
return node.nodes.length !== 0 && node.nodes[0].type === 'string'
16-
? node.nodes[0].value
17-
: valueParser.stringify(node.nodes);
18-
}
19-
2014
function walkUrls(parsed, callback) {
2115
parsed.walk((node) => {
2216
if (node.type !== 'function') {
2317
return;
2418
}
2519

2620
if (isUrlFunc.test(node.value)) {
27-
callback(getNodeFromUrlFunc(node), getUrlFromUrlFunc(node), false);
21+
const isStringNode =
22+
node.nodes.length !== 0 && node.nodes[0].type === 'string';
23+
const url = isStringNode
24+
? node.nodes[0].value
25+
: valueParser.stringify(node.nodes);
26+
27+
callback(getNodeFromUrlFunc(node), url, false, isStringNode);
2828

2929
// Do not traverse inside `url`
3030
// eslint-disable-next-line consistent-return
@@ -34,11 +34,17 @@ function walkUrls(parsed, callback) {
3434
if (isImageSetFunc.test(node.value)) {
3535
node.nodes.forEach((nNode) => {
3636
if (nNode.type === 'function' && isUrlFunc.test(nNode.value)) {
37-
callback(getNodeFromUrlFunc(nNode), getUrlFromUrlFunc(nNode), false);
37+
const isStringNode =
38+
nNode.nodes.length !== 0 && nNode.nodes[0].type === 'string';
39+
const url = isStringNode
40+
? nNode.nodes[0].value
41+
: valueParser.stringify(nNode.nodes);
42+
43+
callback(getNodeFromUrlFunc(nNode), url, false, isStringNode);
3844
}
3945

4046
if (nNode.type === 'string') {
41-
callback(nNode, nNode.value, true);
47+
callback(nNode, nNode.value, true, true);
4248
}
4349
});
4450

@@ -57,7 +63,7 @@ function getUrlsFromValue(value, result, filter, decl) {
5763
const parsed = valueParser(value);
5864
const urls = [];
5965

60-
walkUrls(parsed, (node, url, needQuotes) => {
66+
walkUrls(parsed, (node, url, needQuotes, isStringNode) => {
6167
if (url.trim().replace(/\\[\r\n]/g, '').length === 0) {
6268
result.warn(`Unable to find uri in '${decl ? decl.toString() : value}'`, {
6369
node: decl,
@@ -70,12 +76,20 @@ function getUrlsFromValue(value, result, filter, decl) {
7076
return;
7177
}
7278

73-
const [normalizedUrl, singleQuery, hashValue] = url.split(/(\?)?#/);
79+
const splittedUrl = url.split(/(\?)?#/);
80+
let [normalizedUrl] = splittedUrl;
81+
const [, singleQuery, hashValue] = splittedUrl;
7482
const hash =
7583
singleQuery || hashValue
7684
? `${singleQuery ? '?' : ''}${hashValue ? `#${hashValue}` : ''}`
7785
: '';
7886

87+
// Remove extra escaping requirements for `require`
88+
// See https://drafts.csswg.org/css-values-3/#urls
89+
if (!isStringNode && /\\["'() \t\n]/.test(normalizedUrl)) {
90+
normalizedUrl = normalizedUrl.replace(/\\(["'() \t\n])/g, '$1');
91+
}
92+
7993
urls.push({ node, url: normalizedUrl, hash, needQuotes });
8094
});
8195

0 commit comments

Comments
 (0)