fix: match parens recursively on URLs to not fix embeded calls (#192)
parent
b48121e77c
commit
71e0908536
28
fixUrls.js
28
fixUrls.js
|
@ -29,9 +29,35 @@ module.exports = function (css) {
|
||||||
var currentDir = baseUrl + location.pathname.replace(/\/[^\/]*$/, "/");
|
var currentDir = baseUrl + location.pathname.replace(/\/[^\/]*$/, "/");
|
||||||
|
|
||||||
// convert each url(...)
|
// convert each url(...)
|
||||||
var fixedCss = css.replace(/url *\( *(.+?) *\)/g, function(fullMatch, origUrl) {
|
/*
|
||||||
|
This regular expression is just a way to recursively match brackets within
|
||||||
|
a string.
|
||||||
|
|
||||||
|
/url\s*\( = Match on the word "url" with any whitespace after it and then a parens
|
||||||
|
( = Start a capturing group
|
||||||
|
(?: = Start a non-capturing group
|
||||||
|
[^)(] = Match anything that isn't a parentheses
|
||||||
|
| = OR
|
||||||
|
\( = Match a start parentheses
|
||||||
|
(?: = Start another non-capturing groups
|
||||||
|
[^)(]+ = Match anything that isn't a parentheses
|
||||||
|
| = OR
|
||||||
|
\( = Match a start parentheses
|
||||||
|
[^)(]* = Match anything that isn't a parentheses
|
||||||
|
\) = Match a end parentheses
|
||||||
|
) = End Group
|
||||||
|
*\) = Match anything and then a close parens
|
||||||
|
) = Close non-capturing group
|
||||||
|
* = Match anything
|
||||||
|
) = Close capturing group
|
||||||
|
\) = Match a close parens
|
||||||
|
|
||||||
|
/gi = Get all matches, not the first. Be case insensitive.
|
||||||
|
*/
|
||||||
|
var fixedCss = css.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi, function(fullMatch, origUrl) {
|
||||||
// strip quotes (if they exist)
|
// strip quotes (if they exist)
|
||||||
var unquotedOrigUrl = origUrl
|
var unquotedOrigUrl = origUrl
|
||||||
|
.trim()
|
||||||
.replace(/^"(.*)"$/, function(o, $1){ return $1; })
|
.replace(/^"(.*)"$/, function(o, $1){ return $1; })
|
||||||
.replace(/^'(.*)'$/, function(o, $1){ return $1; });
|
.replace(/^'(.*)'$/, function(o, $1){ return $1; });
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ describe("fix urls tests", function() {
|
||||||
var resultCss = fixUrls(origCss, specialUrl || defaultUrl);
|
var resultCss = fixUrls(origCss, specialUrl || defaultUrl);
|
||||||
expectedCss = expectedCss || origCss;
|
expectedCss = expectedCss || origCss;
|
||||||
|
|
||||||
assert.equal(resultCss, expectedCss);
|
assert.equal(expectedCss, resultCss);
|
||||||
};
|
};
|
||||||
|
|
||||||
// no change
|
// no change
|
||||||
|
@ -100,11 +100,18 @@ describe("fix urls tests", function() {
|
||||||
// relative urls
|
// relative urls
|
||||||
it("Relative url", function() {
|
it("Relative url", function() {
|
||||||
assertUrl(
|
assertUrl(
|
||||||
"body { background-image:url(bg.jpg); }",
|
"body { background-image:url (bg.jpg); }",
|
||||||
"body { background-image:url(\"https://x.y.z/a/bg.jpg\"); }"
|
"body { background-image:url(\"https://x.y.z/a/bg.jpg\"); }"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Relative url case sensitivity", function() {
|
||||||
|
assertUrl(
|
||||||
|
"body { background-image:URL (bg.jpg); }",
|
||||||
|
"body { background-image:url(\"https://x.y.z/a/bg.jpg\"); }"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it("Relative url with path", function() {
|
it("Relative url with path", function() {
|
||||||
assertUrl(
|
assertUrl(
|
||||||
"body { background-image:url(c/d/bg.jpg); }",
|
"body { background-image:url(c/d/bg.jpg); }",
|
||||||
|
@ -180,4 +187,12 @@ describe("fix urls tests", function() {
|
||||||
"http://x.y.z"
|
"http://x.y.z"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Doesn't break inline SVG", function() {
|
||||||
|
const svg = "url('data:image/svg+xml;charset=utf-8,<svg><feFlood flood-color=\"rgba(0,0,0,0.5)\" /></svg>')";
|
||||||
|
|
||||||
|
assertUrl(
|
||||||
|
"body: { background: " + svg + " }"
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue