svgo
Advanced tools
Comparing version 0.6.1 to 0.6.2
### [ [>](https://github.com/svg/svgo/tree/v0.6.1) ] 0.6.1 / 21.11.2015 | ||
* Added option `--quite` to suppress output (by @phihag). | ||
* Added option `--quiet` to suppress output (by @phihag). | ||
* Removed `lib-cov` folder from the package, which was erroneously included before. | ||
@@ -4,0 +4,0 @@ * Fixed errors in “[minifyStyles](https://github.com/svg/svgo/blob/master/plugins/minifyStyles.js)” when there are `<style>` elements with `CDATA` content or without content at all. |
@@ -13,7 +13,7 @@ 'use strict'; | ||
var CONFIG = require('./svgo/config'), | ||
SVG2JS = require('./svgo/svg2js'), | ||
PLUGINS = require('./svgo/plugins'), | ||
var CONFIG = require('./svgo/config.js'), | ||
SVG2JS = require('./svgo/svg2js.js'), | ||
PLUGINS = require('./svgo/plugins.js'), | ||
JSAPI = require('./svgo/jsAPI.js'), | ||
JS2SVG = require('./svgo/js2svg'); | ||
JS2SVG = require('./svgo/js2svg.js'); | ||
@@ -27,2 +27,3 @@ var SVGO = module.exports = function(config) { | ||
SVGO.prototype.optimize = function(svgstr, callback) { | ||
if (this.config.error) return callback(this.config); | ||
@@ -55,3 +56,2 @@ var _this = this, | ||
SVGO.prototype._optimizeOnce = function(svgstr, callback) { | ||
var config = this.config; | ||
@@ -71,3 +71,2 @@ | ||
}); | ||
}; | ||
@@ -74,0 +73,0 @@ |
@@ -8,8 +8,8 @@ /* jshint quotmark: false */ | ||
PATH = require('path'), | ||
SVGO = require('../svgo'), | ||
SVGO = require('../svgo.js'), | ||
YAML = require('js-yaml'), | ||
PKG = require('../../package.json'), | ||
mkdirp = require('mkdirp'), | ||
encodeSVGDatauri = require('./tools').encodeSVGDatauri, | ||
decodeSVGDatauri = require('./tools').decodeSVGDatauri, | ||
encodeSVGDatauri = require('./tools.js').encodeSVGDatauri, | ||
decodeSVGDatauri = require('./tools.js').decodeSVGDatauri, | ||
regSVGFile = /\.svg$/; | ||
@@ -32,3 +32,6 @@ | ||
.act(function() { | ||
return PKG.version; | ||
// output the version to stdout instead of stderr if returned | ||
process.stdout.write(PKG.version + '\n'); | ||
// coa will run `.toString` on the returned value and send it to stderr | ||
return ''; | ||
}) | ||
@@ -153,3 +156,9 @@ .end() | ||
if (opts.config.charAt(0) === '{') { | ||
config = JSON.parse(opts.config); | ||
try { | ||
config = JSON.parse(opts.config); | ||
} catch (e) { | ||
console.error("Error: Couldn't parse config JSON."); | ||
console.error(String(e)); | ||
return; | ||
} | ||
@@ -298,3 +307,3 @@ // external file | ||
// stdout | ||
if (output === '-' || (input === '-' && !output)) { | ||
if (output === '-' || (!input || input === '-') && !output) { | ||
@@ -553,14 +562,12 @@ process.stdout.write(result.data + '\n'); | ||
var svgo = new SVGO(); | ||
var svgo = new SVGO(), | ||
// Flatten an array of plugins grouped per type and sort alphabetically | ||
list = Array.prototype.concat.apply([], svgo.config.plugins).sort(function(a, b) { | ||
return a.name > b.name ? 1 : -1; | ||
}); | ||
console.log('Currently available plugins:'); | ||
svgo.config.plugins.forEach(function (plugins) { | ||
plugins.forEach(function (plugin) { | ||
console.log(' [ ' + plugin.name.green + ' ] ' + plugin.description); | ||
}); | ||
list.forEach(function (plugin) { | ||
console.log(' [ ' + plugin.name.green + ' ] ' + plugin.description); | ||
}); | ||
@@ -567,0 +574,0 @@ |
@@ -18,4 +18,8 @@ 'use strict'; | ||
var defaults; | ||
config = config || {}; | ||
config = typeof config == 'object' && config || {}; | ||
if (config.plugins && !Array.isArray(config.plugins)) { | ||
return { error: 'Error: Invalid plugins list. Provided \'plugins\' in config should be an array.' }; | ||
} | ||
if (config.full) { | ||
@@ -22,0 +26,0 @@ defaults = config; |
@@ -205,3 +205,4 @@ 'use strict'; | ||
return this.config.cdataStart + | ||
return this.createIndent() + | ||
this.config.cdataStart + | ||
cdata + | ||
@@ -208,0 +209,0 @@ this.config.cdataEnd; |
@@ -25,3 +25,3 @@ 'use strict'; | ||
Object.keys(node).forEach(function(key) { | ||
if (key != 'content') { | ||
if (key !== 'content') { | ||
nodeData[key] = node[key]; | ||
@@ -76,3 +76,3 @@ } | ||
if (typeof name == 'string' && name != '') | ||
if (name && typeof name === 'string') | ||
this.elem = this.local = name; | ||
@@ -203,12 +203,12 @@ | ||
* | ||
* @param {Object} attr attribute object | ||
* @return {Object} created attribute | ||
* @param {Object} [attr={}] attribute object | ||
* @return {Object|Boolean} created attribute or false if no attr was passed in | ||
*/ | ||
JSAPI.prototype.addAttr = function(attr) { | ||
attr = attr || {}; | ||
if (!attr || | ||
(attr && attr.name === undefined) || | ||
(attr && attr.value === undefined) || | ||
(attr && attr.prefix === undefined) || | ||
(attr && attr.local === undefined) | ||
if (attr.name === undefined || | ||
attr.value === undefined || | ||
attr.prefix === undefined || | ||
attr.local === undefined | ||
) return false; | ||
@@ -215,0 +215,0 @@ |
'use strict'; | ||
var SAX = require('sax'), | ||
JSAPI = require('./jsAPI'); | ||
JSAPI = require('./jsAPI.js'), | ||
entityDeclaration = /<!ENTITY\s+(\S+)\s+(?:'([^\']+)'|"([^\"]+)")\s*>/g; | ||
@@ -12,3 +13,3 @@ var config = { | ||
xmlns: true, | ||
position: false | ||
position: true | ||
}; | ||
@@ -28,3 +29,4 @@ | ||
stack = [root], | ||
textContext = null; | ||
textContext = null, | ||
parsingError = false; | ||
@@ -47,2 +49,12 @@ function pushToContent(content) { | ||
var subsetStart = doctype.indexOf('['), | ||
entityMatch; | ||
if (subsetStart >= 0) { | ||
entityDeclaration.lastIndex = subsetStart; | ||
while ((entityMatch = entityDeclaration.exec(data)) != null) { | ||
sax.ENTITIES[entityMatch[1]] = entityMatch[2] || entityMatch[3]; | ||
} | ||
} | ||
}; | ||
@@ -137,3 +149,6 @@ | ||
callback({ error: 'Error in parsing: ' + e.message }); | ||
e.message = 'Error in parsing SVG: ' + e.message; | ||
if (e.message.indexOf('Unexpected end') < 0) { | ||
throw e; | ||
} | ||
@@ -144,7 +159,17 @@ }; | ||
if (!this.error) callback(root); | ||
if (!this.error) { | ||
callback(root); | ||
} else { | ||
callback({ error: this.error.message }); | ||
} | ||
}; | ||
sax.write(data).close(); | ||
try { | ||
sax.write(data); | ||
} catch (e) { | ||
callback({ error: e.message }); | ||
parsingError = true; | ||
} | ||
if (!parsingError) sax.close(); | ||
@@ -151,0 +176,0 @@ function trim(elem) { |
@@ -44,19 +44,24 @@ 'use strict'; | ||
exports.decodeSVGDatauri = function(str) { | ||
var regexp = /data:image\/svg\+xml(;charset=[^;,]*)?(;base64)?,(.*)/; | ||
var match = regexp.exec(str); | ||
var prefix = 'data:image/svg+xml'; | ||
// plain string | ||
if (!match) return str; | ||
var data = match[3]; | ||
// base64 | ||
if (str.substring(0, 26) === (prefix + ';base64,')) { | ||
if (match[2]) { | ||
str = new Buffer(str.substring(26), 'base64').toString('utf8'); | ||
str = new Buffer(data, 'base64').toString('utf8'); | ||
// URI encoded | ||
} else if (str.substring(0, 20) === (prefix + ',%')) { | ||
} else if (data.charAt(0) === '%') { | ||
str = decodeURIComponent(str.substring(19)); | ||
str = decodeURIComponent(data); | ||
// unencoded | ||
} else if (str.substring(0, 20) === (prefix + ',<')) { | ||
} else if (data.charAt(0) === '<') { | ||
str = str.substring(19); | ||
str = data; | ||
@@ -66,3 +71,2 @@ } | ||
return str; | ||
}; | ||
@@ -69,0 +73,0 @@ |
{ | ||
"name": "svgo", | ||
"version": "0.6.1", | ||
"version": "0.6.2", | ||
"description": "Nodejs-based tool for optimizing SVG vector graphics files", | ||
"keywords": [ "svgo", "svg", "optimize", "minify" ], | ||
"keywords": [ | ||
"svgo", | ||
"svg", | ||
"optimize", | ||
"minify" | ||
], | ||
"homepage": "https://github.com/svg/svgo", | ||
@@ -16,11 +21,14 @@ "bugs": { | ||
}, | ||
"contributors": [{ | ||
"name": "Sergey Belov", | ||
"email": "peimei@ya.ru", | ||
"url": "http://github.com/arikon" | ||
}, { | ||
"name": "Lev Solntsev", | ||
"email": "lev.sun@ya.ru", | ||
"url": "http://github.com/GreLI" | ||
}], | ||
"contributors": [ | ||
{ | ||
"name": "Sergey Belov", | ||
"email": "peimei@ya.ru", | ||
"url": "http://github.com/arikon" | ||
}, | ||
{ | ||
"name": "Lev Solntsev", | ||
"email": "lev.sun@ya.ru", | ||
"url": "http://github.com/GreLI" | ||
} | ||
], | ||
"repository": { | ||
@@ -43,16 +51,16 @@ "type": "git", | ||
"dependencies": { | ||
"sax": "~1.1.4", | ||
"sax": "~1.1.6", | ||
"coa": "~1.0.1", | ||
"js-yaml": "~3.4.3", | ||
"js-yaml": "~3.5.3", | ||
"colors": "~1.1.2", | ||
"whet.extend": "~0.9.9", | ||
"mkdirp": "~0.5.1", | ||
"csso": "~1.4.2" | ||
"csso": "~1.6.4" | ||
}, | ||
"devDependencies": { | ||
"mocha": "~2.3.4", | ||
"should": "7.1.1", | ||
"istanbul": "~0.4.0", | ||
"mocha": "~2.4.5", | ||
"should": "8.2.2", | ||
"istanbul": "~0.4.2", | ||
"mocha-istanbul": "~0.2.0", | ||
"coveralls": "~2.11.4" | ||
"coveralls": "~2.11.8" | ||
}, | ||
@@ -59,0 +67,0 @@ "engines": { |
@@ -186,6 +186,7 @@ /* global a2c */ | ||
stroke = elem.computedAttr('stroke'), | ||
id = elem.computedAttr('id'), | ||
transformPrecision = params.transformPrecision, | ||
newPoint, scale; | ||
if (stroke && stroke.value != 'none') { | ||
if (stroke && stroke != 'none') { | ||
if (!params.applyTransformsStroked || | ||
@@ -196,2 +197,14 @@ (matrix.data[0] != matrix.data[3] || matrix.data[1] != -matrix.data[2]) && | ||
// "stroke-width" should be inside the part with ID, otherwise it can be overrided in <use> | ||
if (id) { | ||
var idElem = elem, | ||
hasStrokeWidth = false; | ||
do { | ||
if (idElem.hasAttr('stroke-width')) hasStrokeWidth = true; | ||
} while (!idElem.hasAttr('id', id) && !hasStrokeWidth && (idElem = idElem.parentNode)); | ||
if (!hasStrokeWidth) return path; | ||
} | ||
scale = +Math.sqrt(matrix.data[0] * matrix.data[0] + matrix.data[1] * matrix.data[1]).toFixed(transformPrecision); | ||
@@ -214,2 +227,4 @@ | ||
} | ||
} else if (id) { // Stroke and stroke-width can be redefined with <use> | ||
return path; | ||
} | ||
@@ -216,0 +231,0 @@ |
@@ -154,8 +154,7 @@ 'use strict'; | ||
if (!scaleBefore) { | ||
sx = Math.sqrt(data[0] * data[0] + data[2] * data[2]); | ||
sy = Math.sqrt(data[1] * data[1] + data[3] * data[3]); | ||
sx = (data[0] < 0 ? -1 : 1) * Math.sqrt(data[0] * data[0] + data[2] * data[2]); | ||
sy = (data[3] < 0 ? -1 : 1) * Math.sqrt(data[1] * data[1] + data[3] * data[3]); | ||
transforms.push({ name: 'scale', data: [sx, sy] }); | ||
} | ||
var a1 = mth.acos(data[0] / sx, floatPrecision), | ||
rotate = [a1.toFixed(floatPrecision) * (data[1] < 0 ? -1 : 1)]; | ||
var rotate = [mth.acos(data[0] / sx, floatPrecision) * (data[1] * sy < 0 ? -1 : 1)]; | ||
@@ -162,0 +161,0 @@ if (rotate[0]) transforms.push({ name: 'rotate', data: rotate }); |
@@ -9,14 +9,37 @@ 'use strict'; | ||
var ENOCLS = 'Error in plugin "addClassesToSVGElement": absent parameters.\n\ | ||
It should have a list of classes in "classNames" or one "className".\n\ | ||
Config example:\n\n\ | ||
\ | ||
plugins:\n\ | ||
- addClassesToSVGElement:\n\ | ||
className: "mySvg"\n\n\ | ||
\ | ||
plugins:\n\ | ||
- addClassesToSVGElement:\n\ | ||
classNames: ["mySvg", "size-big"]\n'; | ||
/** | ||
* Add classnames to an outer <svg> element. | ||
* Add classnames to an outer <svg> element. Example config: | ||
* | ||
* plugins: | ||
* - addClassesToSVGElement: | ||
* className: 'mySvg' | ||
* | ||
* plugins: | ||
* - addClassesToSVGElement: | ||
* classNames: ['mySvg', 'size-big'] | ||
* | ||
* @author April Arcus | ||
*/ | ||
exports.fn = function(data, params) { | ||
if (!params || !(Array.isArray(params.classNames) && params.classNames.some(String) || params.className)) { | ||
console.error(ENOCLS); | ||
return data; | ||
} | ||
var classNames = params.classNames || [ params.className ]; | ||
var svg = data.content[0]; | ||
var classNames = params.classNames || [ params.className ], | ||
svg = data.content[0]; | ||
if (svg.isElem('svg')) { | ||
if (svg.hasAttr('class')) { | ||
@@ -36,3 +59,2 @@ svg.attr('class').value = | ||
} | ||
} | ||
@@ -39,0 +61,0 @@ |
@@ -61,3 +61,3 @@ 'use strict'; | ||
if (params.names2hex && val.toLowerCase() in collections.colorsNames) { | ||
val = collections.colorsNames[val]; | ||
val = collections.colorsNames[val.toLowerCase()]; | ||
} | ||
@@ -64,0 +64,0 @@ |
@@ -33,2 +33,3 @@ 'use strict'; | ||
cleanupOutData = require('../lib/svgo/tools').cleanupOutData, | ||
roundData, | ||
precision, | ||
@@ -62,2 +63,3 @@ error, | ||
error = precision !== false ? +Math.pow(.1, precision).toFixed(precision) : 1e-2; | ||
roundData = precision > 0 ? strongRound : round; | ||
if (params.makeArcs) { | ||
@@ -305,3 +307,3 @@ arcThreshold = params.makeArcs.threshold; | ||
var r = roundData([circle.radius])[0], | ||
angle = findArcAngle(sdata), | ||
angle = findArcAngle(sdata, circle), | ||
sweep = sdata[5] * sdata[0] - sdata[4] * sdata[1] > 0 ? 1 : 0, | ||
@@ -331,3 +333,3 @@ arc = { | ||
arc.data[6] = arc.coords[1] - arc.base[1]; | ||
angle += findArcAngle(prev.instruction == 'a' ? prev.sdata : prev.data); | ||
angle += findArcAngle(prev.instruction == 'a' ? prev.sdata : prev.data, relCircle); | ||
if (angle > Math.PI) arc.data[3] = 1; | ||
@@ -348,3 +350,3 @@ hasPrev = 1; | ||
if (isConvex(nextData) && isArc(nextData, relCircle)) { | ||
angle += findArcAngle(nextData); | ||
angle += findArcAngle(nextData, relCircle); | ||
if (angle - 2 * Math.PI > 1e-3) break; // more than 360° | ||
@@ -758,28 +760,25 @@ if (angle > Math.PI) arc.data[3] = 1; | ||
* @param {Array} data input data array | ||
* @param {Number} fixed number of decimals | ||
* @return {Array} output data array | ||
*/ | ||
function roundData(data) { | ||
function round(data) { | ||
for (var i = data.length; i--;) { | ||
data[i] = +data[i].toFixed(precision); | ||
} | ||
return data; | ||
function strongRound(data) { | ||
for (var i = data.length; i-- > 0;) { | ||
var rounded = +data[i].toFixed(precision - 1); | ||
data[i] = +Math.abs(rounded - data[i]).toFixed(precision) > error ? | ||
+data[i].toFixed(precision) : | ||
rounded; | ||
} | ||
return data; | ||
} | ||
function strongRound(data) { | ||
for (var i = data.length; i--;) { | ||
var rounded = +data[i].toFixed(precision - 1); | ||
data[i] = +Math.abs(rounded - data[i]).toFixed(precision) > error ? | ||
+data[i].toFixed(precision) : | ||
rounded; | ||
} | ||
return data; | ||
/** | ||
* Simple rounding function if precision is 0. | ||
* | ||
* @param {Array} data input data array | ||
* @return {Array} output data array | ||
*/ | ||
function round(data) { | ||
for (var i = data.length; i-- > 0;) { | ||
data[i] = Math.round(data[i]); | ||
} | ||
roundData = precision > 0 ? strongRound : round; // jshint ignore: line | ||
return roundData(data); | ||
return data; | ||
} | ||
@@ -924,16 +923,17 @@ | ||
/** | ||
* Finds angle of an arc formed by a curve. | ||
* | ||
* Finds angle of a curve fitting the given arc. | ||
* @param {Array} curve | ||
* @param {Object} relCircle | ||
* @return {Number} angle | ||
*/ | ||
function findArcAngle(curve) { | ||
var x1 = curve[0], | ||
y1 = curve[1], | ||
x2 = curve[2] - curve[4], | ||
y2 = curve[3] - curve[5]; | ||
function findArcAngle(curve, relCircle) { | ||
var x1 = -relCircle.center[0], | ||
y1 = -relCircle.center[1], | ||
x2 = curve[4] - relCircle.center[0], | ||
y2 = curve[5] - relCircle.center[1]; | ||
return Math.PI - Math.acos( | ||
(x1 * x2 + y1 * y2 ) / | ||
return Math.acos( | ||
(x1 * x2 + y1 * y2) / | ||
Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2)) | ||
@@ -940,0 +940,0 @@ ); |
@@ -45,3 +45,3 @@ /* jshint quotmark: false */ | ||
* ⬇ | ||
* <g fill="#000" color="#fff" slyle="-webkit-blah: blah"> | ||
* <g fill="#000" color="#fff" style="-webkit-blah: blah"> | ||
* | ||
@@ -48,0 +48,0 @@ * @param {Object} item current iteration item |
@@ -46,6 +46,7 @@ 'use strict'; | ||
if(item.isElem('style') && !item.isEmpty()) { | ||
var styleCss = item.content[0].text || item.content[0].cdata || []; | ||
var styleCss = item.content[0].text || item.content[0].cdata || [], | ||
DATA = styleCss.indexOf('>') >= 0 || styleCss.indexOf('<') >= 0 ? 'cdata' : 'text'; | ||
if(styleCss.length > 0) { | ||
var styleCssMinified = minifyCss(styleCss, svgoOptions); | ||
item.content[0].text = styleCssMinified; | ||
item.content[0][DATA] = styleCssMinified; | ||
} | ||
@@ -52,0 +53,0 @@ } |
@@ -42,5 +42,7 @@ 'use strict'; | ||
hasTransform = false, | ||
hasClip = item.hasAttr('clip-path'), | ||
hasClip = item.hasAttr('clip-path') || item.hasAttr('mask'), | ||
intersected = item.content.every(function(inner) { | ||
if (inner.isElem() && inner.hasAttr()) { | ||
// don't mess with possible styles (hack until CSS parsing is implemented) | ||
if (inner.hasAttr('class')) return false; | ||
if (!Object.keys(intersection).length) { | ||
@@ -47,0 +49,0 @@ intersection = inner.attrs; |
@@ -27,2 +27,7 @@ 'use strict'; | ||
* | ||
* > basic: remove fill attribute | ||
* --- | ||
* removeAttrs: | ||
* attrs: 'fill' | ||
* | ||
* > remove fill attribute on path element | ||
@@ -29,0 +34,0 @@ * --- |
@@ -6,3 +6,3 @@ **english** | [русский](https://github.com/svg/svgo/blob/master/README.ru.md) | ||
## SVGO [![NPM version](https://badge.fury.io/js/svgo.svg)](https://npmjs.org/package/svgo) [![Dependency Status](https://gemnasium.com/svg/svgo.png)](https://gemnasium.com/svg/svgo) [![Build Status](https://secure.travis-ci.org/svg/svgo.svg)](https://travis-ci.org/svg/svgo) [![Coverage Status](https://img.shields.io/coveralls/svg/svgo.svg)](https://coveralls.io/r/svg/svgo?branch=master) | ||
## SVGO [![NPM version](https://badge.fury.io/js/svgo.svg)](https://npmjs.org/package/svgo) [![Dependency Status](https://gemnasium.com/svg/svgo.svg)](https://gemnasium.com/svg/svgo) [![Build Status](https://secure.travis-ci.org/svg/svgo.svg)](https://travis-ci.org/svg/svgo) [![Coverage Status](https://img.shields.io/coveralls/svg/svgo.svg)](https://coveralls.io/r/svg/svgo?branch=master) | ||
@@ -14,3 +14,3 @@ **SVG O**ptimizer is a Nodejs-based tool for optimizing SVG vector graphics files. | ||
SVG files, especially exported from various editors, usually contains a lot of redundant and useless information such as editor metadata, comments, hidden elements, default or non-optimal values and other stuff that can be safely removed or converted without affecting SVG rendering result. | ||
SVG files, especially exported from various editors, usually contain a lot of redundant and useless information such as editor metadata, comments, hidden elements, default or non-optimal values and other stuff that can be safely removed or converted without affecting SVG rendering result. | ||
@@ -17,0 +17,0 @@ ## What it can do |
@@ -6,3 +6,3 @@ [english](https://github.com/svg/svgo/blob/master/README.md) | **русский** | ||
## SVGO [![NPM version](https://badge.fury.io/js/svgo.svg)](https://npmjs.org/package/svgo) [![Dependency Status](https://gemnasium.com/svg/svgo.png)](https://gemnasium.com/svg/svgo) [![Build Status](https://secure.travis-ci.org/svg/svgo.svg)](https://travis-ci.org/svg/svgo) [![Coverage Status](https://img.shields.io/coveralls/svg/svgo.svg)](https://coveralls.io/r/svg/svgo?branch=master) | ||
## SVGO [![NPM version](https://badge.fury.io/js/svgo.svg)](https://npmjs.org/package/svgo) [![Dependency Status](https://gemnasium.com/svg/svgo.svg)](https://gemnasium.com/svg/svgo) [![Build Status](https://secure.travis-ci.org/svg/svgo.svg)](https://travis-ci.org/svg/svgo) [![Coverage Status](https://img.shields.io/coveralls/svg/svgo.svg)](https://coveralls.io/r/svg/svgo?branch=master) | ||
@@ -9,0 +9,0 @@ **SVG** **O**ptimizer – это инструмент для оптимизации векторной графики в формате SVG, написанный на Node.js. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
322681
8514
+ Addedcsso@1.6.4(transitive)
+ Addedjs-yaml@3.5.5(transitive)
+ Addedsource-map@0.5.7(transitive)
- Removedcsso@1.4.4(transitive)
- Removedinherit@2.2.7(transitive)
- Removedjs-yaml@3.4.6(transitive)
Updatedcsso@~1.6.4
Updatedjs-yaml@~3.5.3
Updatedsax@~1.1.6