You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
3.7 KiB
131 lines
3.7 KiB
4 years ago
|
'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'];
|