blob: f6a6191827d8281331a60a9980ab5468c5d821ba [file] [log] [blame]
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _postcss = require('postcss');
var _postcss2 = _interopRequireDefault(_postcss);
var _postcssValueParser = require('postcss-value-parser');
var _postcssValueParser2 = _interopRequireDefault(_postcssValueParser);
var _svgo = require('svgo');
var _svgo2 = _interopRequireDefault(_svgo);
var _isSvg = require('is-svg');
var _isSvg2 = _interopRequireDefault(_isSvg);
var _url = require('./lib/url');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const PLUGIN = 'postcss-svgo';
const dataURI = /data:image\/svg\+xml(;((charset=)?utf-8|base64))?,/i;
const dataURIBase64 = /data:image\/svg\+xml;base64,/i;
function minifyPromise(decl, getSvgo, opts) {
const promises = [];
const parsed = (0, _postcssValueParser2.default)(decl.value);
decl.value = parsed.walk(node => {
if (node.type !== 'function' || node.value.toLowerCase() !== 'url' || !node.nodes.length) {
return;
}
let { value, quote } = node.nodes[0];
let isBase64, isUriEncoded;
let svg = value.replace(dataURI, '');
if (dataURIBase64.test(value)) {
svg = Buffer.from(svg, 'base64').toString('utf8');
isBase64 = true;
} else {
let decodedUri;
try {
decodedUri = (0, _url.decode)(svg);
isUriEncoded = decodedUri !== svg;
} catch (e) {
// Swallow exception if we cannot decode the value
isUriEncoded = false;
}
if (isUriEncoded) {
svg = decodedUri;
}
if (opts.encode !== undefined) {
isUriEncoded = opts.encode;
}
}
if (!(0, _isSvg2.default)(svg)) {
return;
}
promises.push(getSvgo().optimize(svg).then(result => {
let data, optimizedValue;
if (isBase64) {
data = Buffer.from(result.data).toString('base64');
optimizedValue = 'data:image/svg+xml;base64,' + data;
} else {
data = isUriEncoded ? (0, _url.encode)(result.data) : result.data;
// Should always encode # otherwise we yield a broken SVG
// in Firefox (works in Chrome however). See this issue:
// https://github.com/cssnano/cssnano/issues/245
data = data.replace(/#/g, '%23');
optimizedValue = 'data:image/svg+xml;charset=utf-8,' + data;
quote = isUriEncoded ? '"' : '\'';
}
node.nodes[0] = Object.assign({}, node.nodes[0], {
value: optimizedValue,
quote: quote,
type: 'string',
before: '',
after: ''
});
}).catch(error => {
throw new Error(`${PLUGIN}: ${error}`);
}));
return false;
});
return Promise.all(promises).then(() => decl.value = decl.value.toString());
}
exports.default = _postcss2.default.plugin(PLUGIN, (opts = {}) => {
let svgo = null;
const getSvgo = () => {
if (!svgo) {
svgo = new _svgo2.default(opts);
}
return svgo;
};
return css => {
return new Promise((resolve, reject) => {
const svgoQueue = [];
css.walkDecls(decl => {
if (!dataURI.test(decl.value)) {
return;
}
svgoQueue.push(minifyPromise(decl, getSvgo, opts));
});
return Promise.all(svgoQueue).then(resolve, reject);
});
};
});
module.exports = exports['default'];