Skip to content

Commit 64bf99a

Browse files
authored
Merge pull request #102 from peergradeio/option-strip-out-xml-declaration
Add `stripdeclarations` option
2 parents b392b01 + 5b68171 commit 64bf99a

5 files changed

Lines changed: 92 additions & 10 deletions

File tree

README.md

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33

44
A webpack loader which loads SVG file as utf-8 encoded DataUrl string.
55

6-
Existing [`url-loader`](https://github.com/webpack-contrib/url-loader) always does Base64 encoding for data-uri. As SVG content is a human-readable xml string, using base64 encoding is not mandatory. Instead, one may only escape [unsafe characters](http://www.ietf.org/rfc/rfc1738.txt) and replace `"` with `'` as described [in this article](http://codepen.io/Tigt/post/optimizing-svgs-in-data-uris).
6+
Existing [`url-loader`](https://github.com/webpack-contrib/url-loader) always does Base64 encoding for data-uri. As SVG content is a human-readable xml string, using base64 encoding is not mandatory. Instead, one may only escape [unsafe characters](http://www.ietf.org/rfc/rfc1738.txt) and replace `"` with `'` as described [in this article](http://codepen.io/Tigt/post/optimizing-svgs-in-data-uris).
77

8-
There are some benefits for choosing utf-8 encoding over base64.
9-
1. Resulting string is shorter (can be ~2 times shorter for 2K-sized icons);
10-
2. Resulting string will be compressed better when using gzip compression;
8+
There are some benefits for choosing utf-8 encoding over base64.
9+
1. Resulting string is shorter (can be ~2 times shorter for 2K-sized icons);
10+
2. Resulting string will be compressed better when using gzip compression;
1111
3. Browser parses utf-8 encoded string faster than its base64 equivalent.
1212

1313
## Supported parameters
@@ -23,8 +23,8 @@ Passing this parameter (or setting to `true`) tells to loader *not to include* r
2323

2424
### `limit`
2525

26-
If given will tell the loader not to encode the source file if its content is greater than this limit.
27-
Defaults to no limit.
26+
If given will tell the loader not to encode the source file if its content is greater than this limit.
27+
Defaults to no limit.
2828
If the file is greater than the limit the [`file-loader`](https://github.com/webpack-contrib/file-loader) is used and all query parameters are passed to it.
2929

3030
``` javascript
@@ -36,6 +36,15 @@ require('svg-url-loader?prefix=img/!./file.svg');
3636
// They are passed to the file-loader if used.
3737
```
3838

39+
### `stripdeclarations`
40+
41+
If given will tell the loader to strip out any XML declaration, e.g. `<?xml version="1.0" encoding="UTF-8"?>` at the beginning of imported SVGs.
42+
Internet Explorer (tested in Edge 14) cannot handle XML declarations in CSS data URLs (`content: url("data:image/svg...")`).
43+
44+
``` javascript
45+
require('svg-url-loader?stripdeclarations!./file.svg');
46+
```
47+
3948
## Usage
4049

4150
[Documentation: Loaders](https://webpack.js.org/concepts/loaders/)

index.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@ module.exports = function(content) {
88
this.cacheable && this.cacheable();
99

1010
var query = loaderUtils.getOptions(this);
11-
11+
1212
var limit = query.limit ? parseInt(query.limit, 10) : 0;
13-
14-
if(limit <= 0 || content.length < limit) {
13+
14+
if (limit <= 0 || content.length < limit) {
1515
content = content.toString('utf8');
16+
17+
if (query.stripdeclarations) {
18+
content = content.replace(/^\s*<\?xml [^>]*>\s*/i, "");
19+
}
20+
1621
content = content.replace(/"/g, "'");
1722
content = content.replace(/\s+/g, " ");
1823
content = content.replace(/[{}\|\\\^~\[\]`"<>#%]/g, function(match) {
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
var icon = require('./images/icon-with-declaration.svg');
2+
module.exports = icon;
Lines changed: 7 additions & 0 deletions
Loading

test/loader.spec.js

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ var webpack = require('webpack');
66

77
describe('svg-url-loader', function() {
88
'use strict';
9-
9+
1010
this.timeout(10000);
1111

1212
var outputDir = path.resolve(__dirname, './output'),
@@ -85,6 +85,65 @@ describe('svg-url-loader', function() {
8585
});
8686

8787

88+
describe('"stripdeclarations" option', function () {
89+
it('if turned off - should do nothing to an SVG that has an XML declaration', function(done) {
90+
var config = assign({}, globalConfig, {
91+
entry: './test/input/icon-with-declaration.js'
92+
});
93+
config.module.rules[0].use[0].options.stripdeclarations = false;
94+
95+
webpack(config, function(err) {
96+
expect(err).to.be(null);
97+
fs.readFile(getBundleFile(), function(err, data) {
98+
expect(err).to.be(null);
99+
var encoded = (0,eval)(data.toString());
100+
expect(encoded.indexOf("%3C?xml version='1.0' encoding='UTF-8'?%3E")).to.be.greaterThan(-1);
101+
return done();
102+
});
103+
});
104+
});
105+
106+
it('if turned on - should do nothing to an SVG that doesn\'t have an XML declaration', function(done) {
107+
var config = assign({}, globalConfig, {
108+
entry: './test/input/icon.js'
109+
});
110+
config.module.rules[0].use[0].options.stripdeclarations = true;
111+
112+
webpack(config, function(err) {
113+
expect(err).to.be(null);
114+
fs.readFile(getBundleFile(), function(err, data) {
115+
expect(err).to.be(null);
116+
var encoded = (0,eval)(data.toString());
117+
expect(encoded.indexOf('"')).to.be(0);
118+
expect(encoded.lastIndexOf('"')).to.be(encoded.length - 1);
119+
expect(encoded.indexOf('data:image/svg+xml,%3Csvg')).to.be(1);
120+
return done();
121+
});
122+
});
123+
});
124+
125+
126+
it('if turned on - should remove XML declaration from a file that has one', function(done) {
127+
var config = assign({}, globalConfig, {
128+
entry: './test/input/icon-with-declaration.js'
129+
});
130+
config.module.rules[0].use[0].options.stripdeclarations = true;
131+
132+
webpack(config, function(err) {
133+
expect(err).to.be(null);
134+
fs.readFile(getBundleFile(), function(err, data) {
135+
expect(err).to.be(null);
136+
var encoded = (0,eval)(data.toString());
137+
expect(encoded.indexOf('%3C?xml version="1.0" encoding="UTF-8"?%3E')).to.be(-1);
138+
expect(encoded.indexOf('data:image/svg+xml,%3Csvg')).to.be(1);
139+
return done();
140+
});
141+
});
142+
});
143+
});
144+
145+
146+
88147
describe('"limit" option and "url.dataUrlLimit" configuration', function () {
89148
it('should fall back to file-loader if the content of SVG file is longer than "limit" query parameter', function(done) {
90149
var config = assign({}, globalConfig, {

0 commit comments

Comments
 (0)