-
-
Notifications
You must be signed in to change notification settings - Fork 470
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(fixUrls): add param to fix relative urls (#186)
- Loading branch information
Showing
5 changed files
with
269 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
/node_modules | ||
/node_modules | ||
.idea/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
|
||
/** | ||
* When source maps are enabled, `style-loader` uses a link element with a data-uri to | ||
* embed the css on the page. This breaks all relative urls because now they are relative to a | ||
* bundle instead of the current page. | ||
* | ||
* One solution is to only use full urls, but that may be impossible. | ||
* | ||
* Instead, this function "fixes" the relative urls to be absolute according to the current page location. | ||
* | ||
* A rudimentary test suite is located at `test/fixUrls.js` and can be run via the `npm test` command. | ||
* | ||
*/ | ||
|
||
module.exports = function (css) { | ||
// get current location | ||
var location = typeof window !== "undefined" && window.location; | ||
|
||
if (!location) { | ||
throw new Error("fixUrls requires window.location"); | ||
} | ||
|
||
// blank or null? | ||
if (!css || typeof css !== "string") { | ||
return css; | ||
} | ||
|
||
var baseUrl = location.protocol + "//" + location.host; | ||
var currentDir = baseUrl + location.pathname.replace(/\/[^\/]*$/, "/"); | ||
|
||
// convert each url(...) | ||
var fixedCss = css.replace(/url *\( *(.+?) *\)/g, function(fullMatch, origUrl) { | ||
// strip quotes (if they exist) | ||
var unquotedOrigUrl = origUrl | ||
.replace(/^"(.*)"$/, function(o, $1){ return $1; }) | ||
.replace(/^'(.*)'$/, function(o, $1){ return $1; }); | ||
|
||
// already a full url? no change | ||
if (/^(#|data:|http:\/\/|https:\/\/|file:\/\/\/)/i.test(unquotedOrigUrl)) { | ||
return fullMatch; | ||
} | ||
|
||
// convert the url to a full url | ||
var newUrl; | ||
|
||
if (unquotedOrigUrl.indexOf("//") === 0) { | ||
//TODO: should we add protocol? | ||
newUrl = unquotedOrigUrl; | ||
} else if (unquotedOrigUrl.indexOf("/") === 0) { | ||
// path should be relative to the base url | ||
newUrl = baseUrl + unquotedOrigUrl; // already starts with '/' | ||
} else { | ||
// path should be relative to current directory | ||
newUrl = currentDir + unquotedOrigUrl.replace(/^\.\//, ""); // Strip leading './' | ||
} | ||
|
||
// send back the fixed url(...) | ||
return "url(" + JSON.stringify(newUrl) + ")"; | ||
}); | ||
|
||
// send back the fixed css | ||
return fixedCss; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
// Node v4 requires "use strict" to allow block scoped let & const | ||
"use strict"; | ||
var assert = require("assert"); | ||
var url = require('url'); | ||
|
||
describe("fix urls tests", function() { | ||
var fixUrls = require("../fixUrls"); | ||
var defaultUrl = "https://x.y.z/a/b.html"; | ||
|
||
beforeEach(function() { | ||
global.window = { | ||
location: url.parse(defaultUrl) | ||
This comment has been minimized.
Sorry, something went wrong.
cbonita13
|
||
}; | ||
}); | ||
|
||
var assertUrl = function (origCss, expectedCss, specialUrl) { | ||
if (specialUrl) { | ||
global.window = { | ||
location: url.parse(specialUrl) | ||
}; | ||
} | ||
var resultCss = fixUrls(origCss, specialUrl || defaultUrl); | ||
expectedCss = expectedCss || origCss; | ||
|
||
assert.equal(resultCss, expectedCss); | ||
}; | ||
|
||
// no change | ||
it("Null css is not modified", function() { | ||
assertUrl(null) | ||
}); | ||
|
||
it("Blank css is not modified", function() { assertUrl("") }); | ||
|
||
it("No url is not modified", function () { assertUrl("body { }") }); | ||
|
||
it("Full url isn't changed (no quotes)", function() { | ||
assertUrl("body { background-image:url(http://example.com/bg.jpg); }") | ||
}); | ||
|
||
it("Full url isn't changed (no quotes, spaces)", function() { | ||
assertUrl("body { background-image:url ( http://example.com/bg.jpg ); }"); | ||
}); | ||
|
||
it("Full url isn't changed (double quotes)", function() { | ||
assertUrl("body { background-image:url(\"http://example.com/bg.jpg\"); }") | ||
}); | ||
|
||
it("Full url isn't changed (double quotes, spaces)", function() { | ||
assertUrl("body { background-image:url ( \"http://example.com/bg.jpg\" ); }") | ||
}); | ||
|
||
it("Full url isn't changed (single quotes)", function() { | ||
assertUrl("body { background-image:url('http://example.com/bg.jpg'); }") | ||
}); | ||
|
||
it("Full url isn't changed (single quotes, spaces)", function() { | ||
assertUrl("body { background-image:url ( 'http://example.com/bg.jpg' ); }") | ||
}); | ||
|
||
it("Multiple full urls are not changed", function() { | ||
assertUrl( | ||
"body { background-image:url(http://example.com/bg.jpg); }\ndiv.main { background-image:url ( 'https://www.anothersite.com/another.png' ); }" | ||
); | ||
}); | ||
|
||
it("Http url isn't changed", function() { | ||
assertUrl("body { background-image:url(http://example.com/bg.jpg); }"); | ||
}); | ||
|
||
it("Https url isn't changed", function() { | ||
assertUrl("body { background-image:url(https://example.com/bg.jpg); }"); | ||
}); | ||
|
||
it("HTTPS url isn't changed", function() { | ||
assertUrl("body { background-image:url(HTTPS://example.com/bg.jpg); }") | ||
}); | ||
|
||
it("File url isn't changed", function() { | ||
assertUrl("body { background-image:url(file:///example.com/bg.jpg); }") | ||
}); | ||
|
||
it("Double slash url isn't changed", function() { | ||
assertUrl( | ||
"body { background-image:url(//example.com/bg.jpg); }", | ||
"body { background-image:url(\"//example.com/bg.jpg\"); }" | ||
) | ||
}); | ||
|
||
it("Image data uri url isn't changed", function() { | ||
assertUrl("body { background-image:url(data:image/png;base64,qsrwABYuwNkimqm3gAAAABJRU5ErkJggg==); }") | ||
}); | ||
|
||
it("Font data uri url isn't changed", function() { | ||
assertUrl( | ||
"body { background-image:url(data:application/x-font-woff;charset=utf-8;base64,qsrwABYuwNkimqm3gAAAABJRU5ErkJggg); }" | ||
); | ||
}); | ||
|
||
// relative urls | ||
it("Relative url", 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() { | ||
assertUrl( | ||
"body { background-image:url(c/d/bg.jpg); }", | ||
"body { background-image:url(\"https://x.y.z/a/c/d/bg.jpg\"); }" | ||
); | ||
}); | ||
it("Relative url with dot slash", function() { | ||
assertUrl( | ||
"body { background-image:url(./c/d/bg.jpg); }", | ||
"body { background-image:url(\"https://x.y.z/a/c/d/bg.jpg\"); }" | ||
); | ||
}); | ||
|
||
it("Multiple relative urls", function() { | ||
assertUrl( | ||
"body { background-image:url(bg.jpg); }\ndiv.main { background-image:url(./c/d/bg.jpg); }", | ||
"body { background-image:url(\"https://x.y.z/a/bg.jpg\"); }\ndiv.main { background-image:url(\"https://x.y.z/a/c/d/bg.jpg\"); }" | ||
); | ||
}); | ||
it("Relative url that looks like data-uri", function() { | ||
assertUrl( | ||
"body { background-image:url(data/image/png.base64); }", | ||
"body { background-image:url(\"https://x.y.z/a/data/image/png.base64\"); }" | ||
); | ||
}); | ||
|
||
// urls with hashes | ||
it("Relative url with hash are not changed", function() { | ||
assertUrl("body { background-image:url(#bg.jpg); }"); | ||
}); | ||
|
||
// rooted urls | ||
it("Rooted url", function() { | ||
assertUrl( | ||
"body { background-image:url(/bg.jpg); }", | ||
"body { background-image:url(\"https://x.y.z/bg.jpg\"); }" | ||
); | ||
}); | ||
it("Rooted url with path", function() { | ||
assertUrl( | ||
"body { background-image:url(/a/b/bg.jpg); }", | ||
"body { background-image:url(\"https://x.y.z/a/b/bg.jpg\"); }" | ||
); | ||
}); | ||
|
||
//special locations | ||
it("Location with no path, filename only", function() { | ||
assertUrl( | ||
"body { background-image:url(bg.jpg); }", | ||
"body { background-image:url(\"http://x.y.z/bg.jpg\"); }", | ||
"http://x.y.z" | ||
); | ||
}); | ||
|
||
it("Location with no path, path with filename", function() { | ||
assertUrl( | ||
"body { background-image:url(a/bg.jpg); }", | ||
"body { background-image:url(\"http://x.y.z/a/bg.jpg\"); }", | ||
"http://x.y.z" | ||
); | ||
}); | ||
it("Location with no path, rel path with filename", function() { | ||
This comment has been minimized.
Sorry, something went wrong. |
||
assertUrl( | ||
"body { background-image:url(./a/bg.jpg); }", | ||
"body { background-image:url(\"http://x.y.z/a/bg.jpg\"); }", | ||
"http://x.y.z" | ||
); | ||
}); | ||
it("Location with no path, root filename", function() { | ||
assertUrl( | ||
"body { background-image:url(/a/bg.jpg); }", | ||
"body { background-image:url(\"http://x.y.z/a/bg.jpg\"); }", | ||
"http://x.y.z" | ||
); | ||
}); | ||
}); |
removeStyleElement