fix: wrap all CSS data urls in quotes

This ensures that if SVG is used as a background, it doesn't get corrupted.

Fixes #97
Fixes #96
This commit is contained in:
Remy Sharp 2016-05-22 14:45:52 +01:00
parent cc9cc826ec
commit 253a3173cd
13 changed files with 47 additions and 15 deletions

View File

@ -10,12 +10,13 @@ var debug = require('debug')('inliner');
function getImages(root, css) {
var inliner = this;
var singleURLMatch = /url\(\s*(?:['"]*)(?!['"]*data:)(.*?)(?:['"]*)\s*\)/;
var singleURLMatch = /url\(\s*(['"]*)(?!['"]*data:)(.*?)(['"]*)\s*\)/;
var matches = css.match(match) || [];
var images = matches.map(function eachURL(url) {
var source = url.match(singleURLMatch)[1];
var match = url.match(singleURLMatch);
var source = match[2];
return {
source: source,
source: match.input,
resolved: inliner.resolve(root, source),
};
});
@ -26,9 +27,7 @@ function getImages(root, css) {
return Promise.all(images.map(function map(url) {
return inliner.image(url.resolved).then(function then(dataURL) {
inliner.jobs.done.images();
css = css.replace(new RegExp(url.source, 'g'), function replace() {
return dataURL;
});
css = replace(css, url.source, 'url("' + dataURL + '")');
return css;
});
})).then(function then() {
@ -36,6 +35,10 @@ function getImages(root, css) {
});
}
function replace(body, source, target) {
return body.split(source).join(target);
}
function getImports(root, css) {
// change to a string in case the CSS is a buffer, which is the case
// when we're reading off the local file system

View File

@ -12,4 +12,4 @@ function resolve(inliner, todo, $) {
$(style).text(css);
});
});
}
}

11
test/fixtures/circle.svg vendored Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="210px" height="210px" viewBox="0 0 210 210" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 3.7.2 (28276) - http://www.bohemiancoding.com/sketch -->
<title>circle</title>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="circle" transform="translate(5.000000, 5.000000)" stroke="#0000FF" stroke-width="10" fill="#FF0000">
<circle id="Oval" cx="100" cy="100" r="100"></circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 626 B

View File

@ -1 +1 @@
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <meta charset="UTF-8"> <title>App</title> <style>p{ font-size:10px;background:url('data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=') repeat;}p:before{ content:'<';color:blue;}</style> </head> <body> body </body> </html>
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <meta charset="UTF-8"> <title>App</title> <style>p{ font-size:10px;background:url("data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=") repeat;}p:before{ content:'<';color:blue;}</style> </head> <body> body </body> </html>

View File

@ -1 +1 @@
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>External script + css</title> <style>p{ font-size:10px;background:url('data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=') repeat;}p:before{ content:'<';color:blue;}</style> <script src="http://localhost:54321/script.min.js"></script> <script>function doit(o){var r="remy",e=o.bar="sharp";return r+e.split("").reverse().join("")}console.log(doit(window));</script> </head> <body> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>External script + css</title> <style>p{ font-size:10px;background:url("data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=") repeat;}p:before{ content:'<';color:blue;}</style> <script src="http://localhost:54321/script.min.js"></script> <script>function doit(o){var r="remy",e=o.bar="sharp";return r+e.split("").reverse().join("")}console.log(doit(window));</script> </head> <body> </body> </html>

View File

@ -1 +1 @@
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>inline style</title> <style> p{ font-size:10px;background:url('data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=') repeat;}p:before{ content:'<';color:blue;} p{ font-size:10px;background:url('data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=') repeat;}p:before{ content:'<';color:blue;} p{ font-size:10px;background:url('data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=') repeat;}p:before{ content:'<';color:blue;} @media screen and orientation:landscape{p{ font-size:10px;background:url('data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=') repeat;}p:before{ content:'<';color:blue;}}</style> </head> <body> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>inline style</title> <style> p{ font-size:10px;background:url("data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=") repeat;}p:before{ content:'<';color:blue;} p{ font-size:10px;background:url("data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=") repeat;}p:before{ content:'<';color:blue;} p{ font-size:10px;background:url("data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=") repeat;}p:before{ content:'<';color:blue;} @media screen and orientation:landscape{p{ font-size:10px;background:url("data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=") repeat;}p:before{ content:'<';color:blue;}}</style> </head> <body> </body> </html>

View File

@ -1 +1 @@
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>css image</title> <style> body{ background:black;}#image{ background:url(data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=) repeat;height:400px;width:400px;}#image{ background:url( "data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=" ) repeat;}p:before{ content:'<';color:blue;}</style> </head> <body> <div id="image"></div> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>css image</title> <style> body{ background:black;}#image{ background:url("data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=") repeat;height:400px;width:400px;}#image{ background:url("data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=") repeat;}p:before{ content:'<';color:blue;}</style> </head> <body> <div id="image"></div> </body> </html>

View File

@ -1 +1 @@
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>css image in style attr</title> </head> <body> <div style="background:url(data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=) repeat;"></div> <div style="background:url( &apos;data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=&apos; ) repeat;"></div> <div style="background:url(data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=) repeat;"></div> <div style="background:url(&apos;data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=&apos;) repeat;"></div> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>css image in style attr</title> </head> <body> <div style="background:url(&quot;data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=&quot;) repeat;"></div> <div style="background:url(&quot;data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=&quot;) repeat;"></div> <div style="background:url(&quot;data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=&quot;) repeat;"></div> <div style="background:url(&quot;data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=&quot;) repeat;"></div> </body> </html>

View File

@ -10,4 +10,4 @@
<div style="background: url(http://localhost:54321/1x1.gif) repeat;"></div>
<div style="background: url('http://localhost:54321/1x1.gif') repeat;"></div>
</body>
</html>
</html>

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>full combo</title> <style>p{ font-size:10px;background:url('data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=') repeat;}p:before{ content:'<';color:blue;}</style> <style> p{ font-size:10px;background:url('data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=') repeat;}p:before{ content:'<';color:blue;}body{ font-family:sans-serif;}#icon{ height:48px;width:48px;background:url(data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=) no-repeat;background-size:cover;}</style> </head> <body> <script>function doit(o){var r="remy",e=o.bar="sharp";return r+e.split("").reverse().join("")}console.log(doit(window));</script> <script>console.log("Hello world");</script> <img src="data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=" title="White 1x1"> <div id="icon"></div> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>full combo</title> <style>p{ font-size:10px;background:url("data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=") repeat;}p:before{ content:'<';color:blue;}</style> <style> p{ font-size:10px;background:url("data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=") repeat;}p:before{ content:'<';color:blue;}body{ font-family:sans-serif;}#icon{ height:48px;width:48px;background:url("data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=") no-repeat;background-size:cover;}</style> </head> <body> <script>function doit(o){var r="remy",e=o.bar="sharp";return r+e.split("").reverse().join("")}console.log(doit(window));</script> <script>console.log("Hello world");</script> <img src="data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=" title="White 1x1"> <div id="icon"></div> </body> </html>

1
test/fixtures/svg-bg.result.html vendored Normal file
View File

@ -0,0 +1 @@
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>circle.svg bg</title> <style> .homescreen{ background:url("data:image/svg+xml;utf8,%3Csvg width=%22210%22 height=%22210%22 viewBox=%220 0 210 210%22 xmlns=%22http://www.w3.org/2000/svg%22%3E%3Ctitle%3Ecircle%3C/title%3E%3Ccircle cx=%22100%22 cy=%22100%22 r=%22100%22 transform=%22translate(5 5)%22 stroke=%22#00F%22 stroke-width=%2210%22 fill=%22#F00%22 fill-rule=%22evenodd%22/%3E%3C/svg%3E") no-repeat;height:210px;}</style> </head> <body> <div class="homescreen"></div> </body> </html>

17
test/fixtures/svg-bg.src.html vendored Normal file
View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>circle.svg bg</title>
<style>
.homescreen {
background: url(circle.svg) no-repeat;
height: 210px;
}
</style>
</head>
<body>
<div class="homescreen"></div>
</body>
</html>