Comparing version 1.0.5 to 1.1.0
@@ -0,1 +1,29 @@ | ||
### [ [>](https://github.com/svg/svgo/tree/v1.1.0) ] 1.1.0 / 16.09.2018 | ||
* Fixed `collapseGroups` plugin removing property with a child having `inherit` value. | ||
* `version` attribute value is not more being rounded. | ||
* Fixed jsAPI `clone` method with respect to the introduced CSS classes. | ||
* Fixed scaling strokes with `vector-effect="non-scaling-stroke"` (by @alexjlockwood). | ||
* Fixed passing properties from groups in `collapseGroups` plugin if child have a filter (by @stristr). | ||
* Fixed arc path commands parsing without separators after flags, effectively producing a JS error. | ||
* Fixed `viewBox` separators parsing. | ||
* Fixed `removeNonInheritableGroupAttrs` plugin to work as intended. | ||
* Fixed removing path segments without length in presence of `stroke-linecap`. | ||
* Fixed `removeUnknownsAndDefaults` plugin removing attributes from elements with `id`. | ||
* Fixed converting to large arcs from nearly straight lines curves. | ||
* Fixed `collapseGroups` plugin affecting `<switch>` and its subgroups. | ||
* Fixed `convertTransform` plugin converting to `rotate()` with wrong sign in some case. | ||
* Fixed `cleanupListOfValues` plugin not preserving non-numeric values. | ||
* Fixed `!important` being passed to attributes in `convertStyleToAttrs` plugin. | ||
* Added option `keepImportant` to `convertStyleToAttrs` plugin to preserve styles with `!important`. | ||
* `removeHiddenElems` plugin now also removes elements with `visibility="hidden"` attribute (by @mikolaj92). | ||
* Added `forceAbsolutePath` option to `convertPathData` plugin to always use absolute coordinates (by @cool). | ||
* Added `keepRoleAttr` for `removeUnknownsAndDefaults` plugin to preserve `role-` attributes (by @himedlooff). | ||
* Added `xmlns` order option in `sortAttrs` plugin (by @hellatan). | ||
* Added an option to `prefixIds` plugin to pass prefix as false or as a function that returns false (by @vzaidman). | ||
* `prefixIds` plugin now adds prefix to every class (by @vzaidman). | ||
* Updated and improved docs a bit (multiple authors). | ||
### [ [>](https://github.com/svg/svgo/tree/v1.0.5) ] 1.0.5 / 26.02.2018 | ||
* Fixed issue with prefixIDs plugin not replacing url() values correctly (by @harrisjose). | ||
### [ [>](https://github.com/svg/svgo/tree/v1.0.4) ] 1.0.4 / 30.01.2018 | ||
@@ -35,3 +63,3 @@ * Fixed bug with removing groups that are direct child of "<switch>". | ||
* `#ff0000` now converts to `red` as well as `#f00` (by @davidleston). | ||
* Added “gray” variation to colors list per CSS Color Module Level 4 (by @JoshyPHP). | ||
* Added “gray” variation to colors list per CSS Color Module Level 4 (by @ydaniv). | ||
* Fixed error on empty files. | ||
@@ -38,0 +66,0 @@ * A separator character in `removeAttrs` now can be changed per `elemSeparator` option (by @mikestreety). |
@@ -18,3 +18,3 @@ 'use strict'; | ||
csstree.walkRules(cssAst, function(node) { | ||
csstree.walk(cssAst, {visit: 'Rule', enter: function(node) { | ||
if (node.type !== 'Rule') { | ||
@@ -47,3 +47,3 @@ return; | ||
}); | ||
}); | ||
}}); | ||
@@ -70,3 +70,3 @@ return selectors; | ||
selector.atrule.expression.children.first().type === 'MediaQueryList') { | ||
var mqExpr = csstree.translate(selector.atrule.expression); | ||
var mqExpr = csstree.generate(selector.atrule.expression); | ||
mqStr = [mqName, mqExpr].join(' '); | ||
@@ -88,3 +88,3 @@ } | ||
return selectors.filter(function(selector) { | ||
var pseudoSelectorsStr = csstree.translate({ | ||
var pseudoSelectorsStr = csstree.generate({ | ||
type: 'Selector', | ||
@@ -172,3 +172,3 @@ children: new List().fromArray(selector.pseudos.map(function(pseudo) { | ||
var propertyName = declaration.property, | ||
propertyValue = csstree.translate(declaration.value), | ||
propertyValue = csstree.generate(declaration.value), | ||
propertyPriority = (declaration.important ? 'important' : ''); | ||
@@ -175,0 +175,0 @@ return { |
@@ -20,3 +20,3 @@ 'use strict'; | ||
var SVGO = module.exports = function(config) { | ||
var SVGO = function(config) { | ||
this.config = CONFIG(config); | ||
@@ -49,2 +49,5 @@ }; | ||
} | ||
if(info.path) { | ||
svgjs.path = info.path; | ||
} | ||
resolve(svgjs); | ||
@@ -82,1 +85,5 @@ } | ||
}; | ||
module.exports = SVGO; | ||
// Offer ES module interop compatibility. | ||
module.exports.default = SVGO; |
@@ -84,3 +84,3 @@ /* jshint quotmark: false */ | ||
.opt() | ||
.name('disable').title('Disable plugin by name') | ||
.name('disable').title('Disable plugin by name, "--disable={PLUGIN1,PLUGIN2}" for multiple plugins (*nix)') | ||
.long('disable') | ||
@@ -93,3 +93,3 @@ .arr() | ||
.opt() | ||
.name('enable').title('Enable plugin by name') | ||
.name('enable').title('Enable plugin by name, "--enable={PLUGIN3,PLUGIN4}" for multiple plugins (*nix)') | ||
.long('enable') | ||
@@ -96,0 +96,0 @@ .arr() |
@@ -30,3 +30,3 @@ 'use strict'; | ||
defaults = Object.assign({}, yaml.safeLoad(FS.readFileSync(__dirname + '/../../.svgo.yml', 'utf8'))); | ||
defaults.plugins = preparePluginsArray(defaults.plugins); | ||
defaults.plugins = preparePluginsArray(defaults.plugins || []); | ||
defaults = extendConfig(defaults, config); | ||
@@ -33,0 +33,0 @@ } |
@@ -16,3 +16,25 @@ 'use strict'; | ||
/** | ||
* Performs a deep clone of this object. | ||
* | ||
* @param parentNode the parentNode to assign to the cloned result | ||
*/ | ||
CSSClassList.prototype.clone = function(parentNode) { | ||
var node = this; | ||
var nodeData = {}; | ||
Object.keys(node).forEach(function(key) { | ||
if (key !== 'parentNode') { | ||
nodeData[key] = node[key]; | ||
} | ||
}); | ||
// Deep-clone node data. | ||
nodeData = JSON.parse(JSON.stringify(nodeData)); | ||
var clone = new CSSClassList(parentNode); | ||
Object.assign(clone, nodeData); | ||
return clone; | ||
}; | ||
CSSClassList.prototype.hasClass = function() { | ||
@@ -19,0 +41,0 @@ this.classAttr = { // empty class attr |
@@ -19,3 +19,25 @@ 'use strict'; | ||
/** | ||
* Performs a deep clone of this object. | ||
* | ||
* @param parentNode the parentNode to assign to the cloned result | ||
*/ | ||
CSSStyleDeclaration.prototype.clone = function(parentNode) { | ||
var node = this; | ||
var nodeData = {}; | ||
Object.keys(node).forEach(function(key) { | ||
if (key !== 'parentNode') { | ||
nodeData[key] = node[key]; | ||
} | ||
}); | ||
// Deep-clone node data. | ||
nodeData = JSON.parse(JSON.stringify(nodeData)); | ||
var clone = new CSSStyleDeclaration(parentNode); | ||
Object.assign(clone, nodeData); | ||
return clone; | ||
}; | ||
CSSStyleDeclaration.prototype.hasStyle = function() { | ||
@@ -109,4 +131,10 @@ this.addStyleHandler(); | ||
declarations.children.each(function(declaration) { | ||
var styleDeclaration = csstools.csstreeToStyleDeclaration(declaration); | ||
self.setProperty(styleDeclaration.name, styleDeclaration.value, styleDeclaration.priority); | ||
try { | ||
var styleDeclaration = csstools.csstreeToStyleDeclaration(declaration); | ||
self.setProperty(styleDeclaration.name, styleDeclaration.value, styleDeclaration.priority); | ||
} catch(styleError) { | ||
if(styleError.message !== 'Unknown node type: undefined') { | ||
self.parseError = styleError; | ||
} | ||
} | ||
}); | ||
@@ -113,0 +141,0 @@ }; |
@@ -31,3 +31,3 @@ 'use strict'; | ||
Object.keys(node).forEach(function(key) { | ||
if (key !== 'content') { | ||
if (key !== 'class' && key !== 'style' && key !== 'content') { | ||
nodeData[key] = node[key]; | ||
@@ -37,3 +37,3 @@ } | ||
// Deep-clone node data | ||
// Deep-clone node data. | ||
nodeData = JSON.parse(JSON.stringify(nodeData)); | ||
@@ -46,2 +46,8 @@ | ||
if (node.class) { | ||
clonedNode.class = node.class.clone(clonedNode); | ||
} | ||
if (node.style) { | ||
clonedNode.style = node.style.clone(clonedNode); | ||
} | ||
if (node.content) { | ||
@@ -249,3 +255,6 @@ clonedNode.content = node.content.map(function(childNode) { | ||
if (Array.isArray(name)) name.forEach(this.removeAttr, this); | ||
if (Array.isArray(name)) { | ||
name.forEach(this.removeAttr, this); | ||
return false; | ||
} | ||
@@ -252,0 +261,0 @@ if (!this.hasAttr(name)) return false; |
@@ -18,5 +18,8 @@ 'use strict'; | ||
prefix += ';base64,'; | ||
str = prefix + new Buffer(str).toString('base64'); | ||
if (Buffer.from) { | ||
str = prefix + Buffer.from(str).toString('base64'); | ||
} else { | ||
str = prefix + new Buffer(str).toString('base64'); | ||
} | ||
// URI encoded | ||
@@ -23,0 +26,0 @@ } else if (type === 'enc') { |
{ | ||
"name": "svgo", | ||
"version": "1.0.5", | ||
"version": "1.1.0", | ||
"description": "Nodejs-based tool for optimizing SVG vector graphics files", | ||
@@ -54,8 +54,8 @@ "keywords": [ | ||
"colors": "~1.1.2", | ||
"css-select": "~1.3.0-rc0", | ||
"css-select": "^2.0.0", | ||
"css-select-base-adapter": "~0.1.0", | ||
"css-tree": "1.0.0-alpha25", | ||
"css-tree": "1.0.0-alpha.28", | ||
"css-url-regex": "^1.1.0", | ||
"csso": "^3.5.0", | ||
"js-yaml": "~3.10.0", | ||
"js-yaml": "^3.12.0", | ||
"mkdirp": "~0.5.1", | ||
@@ -72,2 +72,3 @@ "object.values": "^1.0.4", | ||
"istanbul": "~0.4.5", | ||
"jshint": "~2.9.5", | ||
"mocha": "~4.0.1", | ||
@@ -74,0 +75,0 @@ "mocha-istanbul": "~0.3.0", |
'use strict'; | ||
// http://www.w3.org/TR/SVG/intro.html#Definitions | ||
// http://www.w3.org/TR/SVG11/intro.html#Definitions | ||
exports.elemsGroups = { | ||
@@ -20,3 +20,3 @@ animation: ['animate', 'animateColor', 'animateMotion', 'animateTransform', 'set'], | ||
// http://www.w3.org/TR/SVG/intro.html#Definitions | ||
// http://www.w3.org/TR/SVG11/intro.html#Definitions | ||
exports.attrsGroups = { | ||
@@ -34,3 +34,2 @@ animationAddition: ['additive', 'accumulate'], | ||
'baseline-shift', | ||
'buffered-rendering', | ||
'clip', | ||
@@ -65,3 +64,2 @@ 'clip-path', | ||
'image-rendering', | ||
'kerning', | ||
'letter-spacing', | ||
@@ -75,6 +73,5 @@ 'lighting-color', | ||
'overflow', | ||
'paint-order', | ||
'pointer-events', | ||
'shape-rendering', | ||
'solid-color', | ||
'solid-opacity', | ||
'stop-color', | ||
@@ -90,14 +87,10 @@ 'stop-opacity', | ||
'stroke-width', | ||
'paint-order', | ||
'text-anchor', | ||
'text-decoration', | ||
'text-overflow', | ||
'white-space', | ||
'text-rendering', | ||
'transform', | ||
'unicode-bidi', | ||
'vector-effect', | ||
'viewport-fill', | ||
'viewport-fill-opacity', | ||
'visibility', | ||
'white-space', | ||
'word-spacing', | ||
@@ -121,4 +114,2 @@ 'writing-mode' | ||
opacity: '1', | ||
'solid-color': '#000', | ||
'solid-opacity': '1', | ||
'stop-color': '#000', | ||
@@ -139,4 +130,2 @@ 'stop-opacity': '1', | ||
'vector-effect': 'none', | ||
'viewport-fill': 'none', | ||
'viewport-fill-opacity': '1', | ||
display: 'inline', | ||
@@ -153,3 +142,2 @@ visibility: 'visible', | ||
'image-rendering': 'auto', | ||
'buffered-rendering': 'auto', | ||
'font-style': 'normal', | ||
@@ -179,3 +167,3 @@ 'font-variant': 'normal', | ||
// http://www.w3.org/TR/SVG/eltindex.html | ||
// http://www.w3.org/TR/SVG11/eltindex.html | ||
exports.elems = { | ||
@@ -2303,6 +2291,7 @@ a: { | ||
'http://ns.adobe.com/GenericCustomNamespace/1.0/', | ||
'http://ns.adobe.com/XPath/1.0/' | ||
'http://ns.adobe.com/XPath/1.0/', | ||
'http://schemas.microsoft.com/visio/2003/SVGExtensions/' | ||
]; | ||
// http://www.w3.org/TR/SVG/linking.html#processingIRI | ||
// http://www.w3.org/TR/SVG11/linking.html#processingIRI | ||
exports.referencesProps = [ | ||
@@ -2321,3 +2310,3 @@ 'clip-path', | ||
// http://www.w3.org/TR/SVG/propidx.html | ||
// http://www.w3.org/TR/SVG11/propidx.html | ||
exports.inheritableAttrs = [ | ||
@@ -2332,2 +2321,3 @@ 'clip-rule', | ||
'direction', | ||
'dominant-baseline', | ||
'fill', | ||
@@ -2347,3 +2337,2 @@ 'fill-opacity', | ||
'image-rendering', | ||
'kerning', | ||
'letter-spacing', | ||
@@ -2354,2 +2343,3 @@ 'marker', | ||
'marker-start', | ||
'paint-order', | ||
'pointer-events', | ||
@@ -2369,3 +2359,2 @@ 'shape-rendering', | ||
'visibility', | ||
'white-space', | ||
'word-spacing', | ||
@@ -2375,3 +2364,15 @@ 'writing-mode' | ||
// http://www.w3.org/TR/SVG/single-page.html#types-ColorKeywords | ||
exports.presentationNonInheritableGroupAttrs = [ | ||
'display', | ||
'clip-path', | ||
'filter', | ||
'mask', | ||
'opacity', | ||
'text-decoration', | ||
'transform', | ||
'unicode-bidi', | ||
'visibility' | ||
]; | ||
// http://www.w3.org/TR/SVG11/single-page.html#types-ColorKeywords | ||
exports.colorsNames = { | ||
@@ -2563,5 +2564,5 @@ 'aliceblue': '#f0f8ff', | ||
// http://www.w3.org/TR/SVG/single-page.html#types-DataTypeColor | ||
// http://www.w3.org/TR/SVG11/single-page.html#types-DataTypeColor | ||
exports.colorsProps = [ | ||
'color', 'fill', 'stroke', 'stop-color', 'flood-color', 'lighting-color' | ||
]; |
/* global a2c */ | ||
'use strict'; | ||
var rNumber = String.raw`[-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?\s*`, | ||
rCommaWsp = String.raw`(?:\s,?\s*|,\s*)`, | ||
rNumberCommaWsp = `(${rNumber})` + rCommaWsp, | ||
rFlagCommaWsp = `([01])${rCommaWsp}?`, | ||
rCoordinatePair = String.raw`(${rNumber})${rCommaWsp}?(${rNumber})`, | ||
rArcSeq = (rNumberCommaWsp + '?').repeat(2) + rNumberCommaWsp + rFlagCommaWsp.repeat(2) + rCoordinatePair; | ||
var regPathInstructions = /([MmLlHhVvCcSsQqTtAaZz])\s*/, | ||
regPathData = /[-+]?(?:\d*\.\d+|\d+\.?)([eE][-+]?\d+)?/g, | ||
regCoordinateSequence = new RegExp(rNumber, 'g'), | ||
regArcArgumentSequence = new RegExp(rArcSeq, 'g'), | ||
regNumericValues = /[-+]?(\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/, | ||
@@ -56,7 +64,17 @@ transform2js = require('./_transforms').transform2js, | ||
} else { | ||
data = data.match(regPathData); | ||
/* jshint boss: true */ | ||
if (instruction == 'A' || instruction == 'a') { | ||
var newData = []; | ||
for (var args; (args = regArcArgumentSequence.exec(data));) { | ||
for (var i = 1; i < args.length; i++) { | ||
newData.push(args[i]); | ||
} | ||
} | ||
data = newData; | ||
} else { | ||
data = data.match(regCoordinateSequence); | ||
} | ||
if (!data) return; | ||
data = data.map(Number); | ||
// Subsequent moveto pairs of coordinates are threated as implicit lineto commands | ||
@@ -212,12 +230,18 @@ // http://www.w3.org/TR/SVG/paths.html#PathDataMovetoCommands | ||
if (elem.hasAttr('stroke-width')) { | ||
elem.attrs['stroke-width'].value = elem.attrs['stroke-width'].value.trim() | ||
.replace(regNumericValues, function(num) { return removeLeadingZero(num * scale) }); | ||
} else { | ||
elem.addAttr({ | ||
name: 'stroke-width', | ||
prefix: '', | ||
local: 'stroke-width', | ||
value: strokeWidth.replace(regNumericValues, function(num) { return removeLeadingZero(num * scale) }) | ||
}); | ||
if (!elem.hasAttr('vector-effect') || elem.attr('vector-effect').value !== 'non-scaling-stroke') { | ||
if (elem.hasAttr('stroke-width')) { | ||
elem.attrs['stroke-width'].value = elem.attrs['stroke-width'].value.trim() | ||
.replace(regNumericValues, function(num) { | ||
return removeLeadingZero(num * scale); | ||
}); | ||
} else { | ||
elem.addAttr({ | ||
name: 'stroke-width', | ||
prefix: '', | ||
local: 'stroke-width', | ||
value: strokeWidth.replace(regNumericValues, function(num) { | ||
return removeLeadingZero(num * scale); | ||
}) | ||
}); | ||
} | ||
} | ||
@@ -224,0 +248,0 @@ } |
@@ -118,3 +118,3 @@ 'use strict'; | ||
* Decompose matrix into simple transforms. See | ||
* http://www.maths-informatique-jeux.com/blog/frederic/?post/2013/12/01/Decomposition-of-2D-transform-matrices | ||
* http://frederic-wang.fr/decomposition-of-2d-transform-matrices.html | ||
* | ||
@@ -128,7 +128,7 @@ * @param {Object} data matrix transform object | ||
transforms = [], | ||
sx = +Math.sqrt(data[0] * data[0] + data[1] * data[1]).toFixed(params.transformPrecision), | ||
sx = +Math.hypot(data[0], data[1]).toFixed(params.transformPrecision), | ||
sy = +((data[0] * data[3] - data[1] * data[2]) / sx).toFixed(params.transformPrecision), | ||
colsSum = data[0] * data[2] + data[1] * data[3], | ||
rowsSum = data[0] * data[1] + data[2] * data[3], | ||
scaleBefore = rowsSum || +(sx == sy); | ||
scaleBefore = rowsSum != 0 || sx == sy; | ||
@@ -154,7 +154,7 @@ // [..., ..., ..., ..., tx, ty] → translate(tx, ty) | ||
if (!scaleBefore) { | ||
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]); | ||
sx = (data[0] < 0 ? -1 : 1) * Math.hypot(data[0], data[2]); | ||
sy = (data[3] < 0 ? -1 : 1) * Math.hypot(data[1], data[3]); | ||
transforms.push({ name: 'scale', data: [sx, sy] }); | ||
} | ||
var rotate = [mth.acos(data[0] / sx, floatPrecision) * (data[1] * sy < 0 ? -1 : 1)]; | ||
var rotate = [mth.acos(data[0] / sx, floatPrecision) * ((scaleBefore ? 1 : sy) * data[1] < 0 ? -1 : 1)]; | ||
@@ -266,6 +266,3 @@ if (rotate[0]) transforms.push({ name: 'rotate', data: rotate }); | ||
squareSum = m[0] * m[0] + m[1] * m[1] + lastCol, | ||
root = Math.sqrt( | ||
(Math.pow(m[0] - m[3], 2) + Math.pow(m[1] + m[2], 2)) * | ||
(Math.pow(m[0] + m[3], 2) + Math.pow(m[1] - m[2], 2)) | ||
); | ||
root = Math.hypot(m[0] - m[3], m[1] + m[2]) * Math.hypot(m[0] + m[3], m[1] - m[2]); | ||
@@ -286,3 +283,3 @@ if (!root) { // circle | ||
arc[2] = ((major ? term2 < 0 : term1 > 0) ? -1 : 1) * | ||
Math.acos((major ? term1 : term2) / Math.sqrt(term1 * term1 + term2 * term2)) * 180 / Math.PI; | ||
Math.acos((major ? term1 : term2) / Math.hypot(term1, term2)) * 180 / Math.PI; | ||
} | ||
@@ -289,0 +286,0 @@ |
@@ -99,4 +99,3 @@ 'use strict'; | ||
// if attribute value matches regNumericValues | ||
if(match){ | ||
if (match) { | ||
// round it to the fixed precision | ||
@@ -126,9 +125,8 @@ num = +(+match[1]).toFixed(params.floatPrecision), | ||
roundedListArr.push(num+units); | ||
} | ||
// if attribute value is "new"(only enable-background). | ||
else if(matchNew){ | ||
else if (matchNew) { | ||
roundedListArr.push('new'); | ||
} else { | ||
roundedListArr.push(elem); | ||
} | ||
@@ -135,0 +133,0 @@ |
@@ -43,3 +43,3 @@ 'use strict'; | ||
if (item.hasAttr('viewBox')) { | ||
var nums = item.attr('viewBox').value.split(/[ ,]/g); | ||
var nums = item.attr('viewBox').value.split(/\s,?\s*|,\s*/g); | ||
item.attr('viewBox').value = nums.map(function(value) { | ||
@@ -52,2 +52,5 @@ var num = +value; | ||
item.eachAttr(function(attr) { | ||
// The `version` attribute is a text string and cannot be rounded | ||
if (attr.name === 'version') { return } | ||
var match = attr.value.match(regNumericValues); | ||
@@ -54,0 +57,0 @@ |
@@ -45,3 +45,3 @@ 'use strict'; | ||
// non-empty elements | ||
if (item.isElem() && (!item.isElem('switch') || isFeaturedSwitch(item)) && !item.isEmpty()) { | ||
if (item.isElem() && !item.isElem('switch') && !item.isEmpty()) { | ||
item.content.forEach(function(g, i) { | ||
@@ -54,3 +54,3 @@ // non-empty groups | ||
if (inner.isElem() && !inner.hasAttr('id') && | ||
if (inner.isElem() && !inner.hasAttr('id') && !g.hasAttr('filter') && | ||
!(g.hasAttr('class') && inner.hasAttr('class')) && ( | ||
@@ -68,2 +68,4 @@ !g.hasAttr('clip-path') && !g.hasAttr('mask') || | ||
inner.attr(attr.name).value = attr.value + ' ' + inner.attr(attr.name).value; | ||
} else if (inner.hasAttr(attr.name, 'inherit')) { | ||
inner.attr(attr.name).value = attr.value; | ||
} else if ( | ||
@@ -85,4 +87,2 @@ attrsInheritable.indexOf(attr.name) < 0 && | ||
} | ||
} else if (isFeaturedSwitch(g)) { | ||
item.spliceContent(i, 1, g.content); | ||
} | ||
@@ -92,7 +92,1 @@ }); | ||
}; | ||
function isFeaturedSwitch(elem) { | ||
return elem.isElem('switch') && !elem.isEmpty() && !elem.content.some(child => | ||
child.hasAttr('systemLanguage') || child.hasAttr('requiredFeatures') || child.hasAttr('requiredExtensions') | ||
); | ||
} |
@@ -25,3 +25,4 @@ 'use strict'; | ||
leadingZero: true, | ||
negativeExtraSpace: true | ||
negativeExtraSpace: true, | ||
forceAbsolutePath: false | ||
}; | ||
@@ -39,3 +40,4 @@ | ||
arcTolerance, | ||
hasMarkerMid; | ||
hasMarkerMid, | ||
hasStrokeLinecap; | ||
@@ -71,2 +73,6 @@ /** | ||
var stroke = item.computedAttr('stroke'), | ||
strokeLinecap = item.computedAttr('stroke'); | ||
hasStrokeLinecap = stroke && stroke != 'none' && strokeLinecap && strokeLinecap != 'butt'; | ||
var data = path2js(item); | ||
@@ -589,3 +595,3 @@ | ||
// remove useless non-first path segments | ||
if (params.removeUseless) { | ||
if (params.removeUseless && !hasStrokeLinecap) { | ||
@@ -678,3 +684,3 @@ // l 0,0 / h 0 / v 0 / q 0,0 0,0 / t 0,0 / c 0,0 0,0 0,0 / s 0,0 0,0 | ||
// Convert to absolute coordinates if it's shorter. | ||
// Convert to absolute coordinates if it's shorter or forceAbsolutePath is true. | ||
// v-20 -> V0 | ||
@@ -684,2 +690,3 @@ // Don't convert if it fits following previous instruction. | ||
if ( | ||
params.forceAbsolutePath || ( | ||
absoluteDataStr.length < relativeDataStr.length && | ||
@@ -692,3 +699,3 @@ !( | ||
(data[0] < 0 || /^0\./.test(data[0]) && prev.data[prev.data.length - 1] % 1) | ||
) | ||
)) | ||
) { | ||
@@ -850,3 +857,3 @@ item.instruction = instruction.toUpperCase(); | ||
function getDistance(point1, point2) { | ||
return Math.sqrt(Math.pow(point1[0] - point2[0], 2) + Math.pow(point1[1] - point2[1], 2)); | ||
return Math.hypot(point1[0] - point2[0], point1[1] - point2[1]); | ||
} | ||
@@ -896,3 +903,4 @@ | ||
if (center && [1/4, 3/4].every(function(point) { | ||
if (center && radius < 1e15 && | ||
[1/4, 3/4].every(function(point) { | ||
return Math.abs(getDistance(getCubicBezierPoint(curve, point), center) - radius) <= tolerance; | ||
@@ -899,0 +907,0 @@ })) |
@@ -10,2 +10,6 @@ /* jshint quotmark: false */ | ||
exports.params = { | ||
keepImportant: false | ||
}; | ||
var stylingProps = require('./_collections').attrsGroups.presentation, | ||
@@ -23,3 +27,3 @@ rEscape = '\\\\(?:[0-9a-f]{1,6}\\s?|\\r\\n|.)', // Like \" or \2051. Code points consume one space. | ||
// The value. It can have strings and parentheses (see above). Fallbacks to anything in case of unexpected input. | ||
rValue = '\\s*(' + g('[^\'"();\\\\]+?', rEscape, rSingleQuotes, rQuotes, rParenthesis, '[^;]*?') + '*?' + ')', | ||
rValue = '\\s*(' + g('[^!\'"();\\\\]+?', rEscape, rSingleQuotes, rQuotes, rParenthesis, '[^;]*?') + '*?' + ')', | ||
@@ -29,4 +33,7 @@ // End of declaration. Spaces outside of capturing groups help to do natural trimming. | ||
// Important rule | ||
rImportant = '(\\s*!important(?![-(\w]))?', | ||
// Final RegExp to parse CSS declarations. | ||
regDeclarationBlock = new RegExp(rAttr + ':' + rValue + rDeclEnd, 'ig'), | ||
regDeclarationBlock = new RegExp(rAttr + ':' + rValue + rImportant + rDeclEnd, 'ig'), | ||
@@ -54,3 +61,3 @@ // Comments expression. Honors escape sequences and strings. | ||
*/ | ||
exports.fn = function(item) { | ||
exports.fn = function(item, params) { | ||
/* jshint boss: true */ | ||
@@ -72,3 +79,5 @@ | ||
for (var rule; rule = regDeclarationBlock.exec(styleValue);) { | ||
styles.push([rule[1], rule[2]]); | ||
if (!params.keepImportant || !rule[3]) { | ||
styles.push([rule[1], rule[2]]); | ||
} | ||
} | ||
@@ -75,0 +84,0 @@ |
@@ -106,3 +106,3 @@ 'use strict'; | ||
for (selector of sortedSelectors) { | ||
var selectorStr = csstree.translate(selector.item.data), | ||
var selectorStr = csstree.generate(selector.item.data), | ||
selectedEls = null; | ||
@@ -147,3 +147,3 @@ | ||
// merge declarations | ||
csstree.walkDeclarations(selector.rule, function(styleCsstreeDeclaration) { | ||
csstree.walk(selector.rule, {visit: 'Declaration', enter: function(styleCsstreeDeclaration) { | ||
@@ -160,3 +160,3 @@ // existing inline styles have higher priority | ||
selectedEl.style.setProperty(styleDeclaration.name, styleDeclaration.value, styleDeclaration.priority); | ||
}); | ||
}}); | ||
} | ||
@@ -208,3 +208,3 @@ | ||
for (var style of styles) { | ||
csstree.walkRules(style.cssAst, function(node, item, list) { | ||
csstree.walk(style.cssAst, {visit: 'Rule', enter: function(node, item, list) { | ||
// clean up <style/> atrules without any rulesets left | ||
@@ -224,3 +224,3 @@ if (node.type === 'Atrule' && | ||
} | ||
}); | ||
}}); | ||
@@ -245,3 +245,3 @@ | ||
// update existing, left over <style>s | ||
cssTools.setCssStr(style.styleEl, csstree.translate(style.cssAst)); | ||
cssTools.setCssStr(style.styleEl, csstree.generate(style.cssAst)); | ||
} | ||
@@ -248,0 +248,0 @@ |
@@ -64,4 +64,4 @@ 'use strict'; | ||
// prefixes a normal attribute value | ||
var addPrefixToAttr = function(attr) { | ||
// prefixes a class attribute value | ||
var addPrefixToClassAttr = function(attr) { | ||
if (!attrNotEmpty(attr)) { | ||
@@ -71,3 +71,3 @@ return; | ||
attr.value = addPrefix(attr.value); | ||
attr.value = attr.value.split(/\s+/).map(addPrefix).join(' '); | ||
}; | ||
@@ -81,2 +81,11 @@ | ||
attr.value = addPrefix(attr.value); | ||
}; | ||
// prefixes a href attribute value | ||
var addPrefixToHrefAttr = function(attr) { | ||
if (!attrNotEmpty(attr)) { | ||
return; | ||
} | ||
var idPrefixed = prefixId(attr.value); | ||
@@ -129,2 +138,4 @@ if (!idPrefixed) { | ||
} | ||
} else if (opts.prefix === false) { | ||
prefix = false; | ||
} else if (extra && extra.path && extra.path.length > 0) { | ||
@@ -138,2 +149,5 @@ var filename = path.basename(extra.path); | ||
addPrefix = function(name) { | ||
if(prefix === false){ | ||
return escapeIdentifierName(name); | ||
} | ||
return escapeIdentifierName(prefix + opts.delim + name); | ||
@@ -188,3 +202,3 @@ }; | ||
// update <style>s | ||
node.content[0].text = csstree.translate(cssAst); | ||
node.content[0].text = csstree.generate(cssAst); | ||
return node; | ||
@@ -201,10 +215,12 @@ } | ||
// ID | ||
addPrefixToAttr(node.attrs.id); | ||
addPrefixToIdAttr(node.attrs.id); | ||
// Class | ||
addPrefixToAttr(node.attrs.class); | ||
addPrefixToClassAttr(node.attrs.class); | ||
// href | ||
addPrefixToIdAttr(node.attrs.href); | ||
addPrefixToHrefAttr(node.attrs.href); | ||
// (xlink:)href (deprecated, must be still supported) | ||
addPrefixToIdAttr(node.attrs['xlink:href']); | ||
addPrefixToHrefAttr(node.attrs['xlink:href']); | ||
@@ -211,0 +227,0 @@ // referenceable properties |
@@ -10,2 +10,3 @@ 'use strict'; | ||
exports.params = { | ||
isHidden: true, | ||
displayNone: true, | ||
@@ -48,5 +49,11 @@ opacity0: true, | ||
*/ | ||
exports.fn = function(item, params) { | ||
exports.fn = function (item, params) { | ||
if (item.elem) { | ||
// Removes hidden elements | ||
// https://www.w3schools.com/cssref/pr_class_visibility.asp | ||
if ( | ||
params.isHidden && | ||
item.hasAttr('visibility', 'hidden') | ||
) return false; | ||
@@ -53,0 +60,0 @@ // display="none" |
@@ -11,3 +11,3 @@ 'use strict'; | ||
attrsGroups = require('./_collections').attrsGroups, | ||
excludedAttrs = ['display', 'opacity']; | ||
applyGroups = require('./_collections').presentationNonInheritableGroupAttrs; | ||
@@ -29,7 +29,4 @@ /** | ||
~attrsGroups.presentation.indexOf(attr.name) && | ||
~attrsGroups.graphicalEvent.indexOf(attr.name) && | ||
~attrsGroups.core.indexOf(attr.name) && | ||
~attrsGroups.conditionalProcessing.indexOf(attr.name) && | ||
!~excludedAttrs.indexOf(attr.name) && | ||
!~inheritableAttrs.indexOf(attr.name) | ||
!~inheritableAttrs.indexOf(attr.name) && | ||
!~applyGroups.indexOf(attr.name) | ||
) { | ||
@@ -36,0 +33,0 @@ item.removeAttr(attr.name); |
@@ -15,3 +15,4 @@ 'use strict'; | ||
keepDataAttrs: true, | ||
keepAriaAttrs: true | ||
keepAriaAttrs: true, | ||
keepRoleAttr: false | ||
}; | ||
@@ -24,3 +25,4 @@ | ||
attrsGroupsDefaults = collections.attrsGroupsDefaults, | ||
attrsInheritable = collections.inheritableAttrs; | ||
attrsInheritable = collections.inheritableAttrs, | ||
applyGroups = collections.presentationNonInheritableGroupAttrs; | ||
@@ -112,3 +114,4 @@ // collect and extend all references | ||
(!params.keepDataAttrs || attr.name.indexOf('data-') != 0) && | ||
(!params.keepAriaAttrs || attr.name.indexOf('aria-') != 0) | ||
(!params.keepAriaAttrs || attr.name.indexOf('aria-') != 0) && | ||
(!params.keepRoleAttr || attr.name != 'role') | ||
) { | ||
@@ -124,2 +127,3 @@ if ( | ||
params.defaultAttrs && | ||
!item.hasAttr('id') && | ||
elems[elem].defaults && | ||
@@ -134,3 +138,4 @@ elems[elem].defaults[attr.name] === attr.value && ( | ||
params.uselessOverrides && | ||
attr.name !== 'transform' && | ||
!item.hasAttr('id') && | ||
applyGroups.indexOf(attr.name) < 0 && | ||
attrsInheritable.indexOf(attr.name) > -1 && | ||
@@ -137,0 +142,0 @@ item.parentNode.computedAttr(attr.name, attr.value) |
@@ -33,3 +33,4 @@ 'use strict'; | ||
sorted = {}, | ||
orderlen = params.order.length + 1; | ||
orderlen = params.order.length + 1, | ||
xmlnsOrder = params.xmlnsOrder || 'front'; | ||
@@ -45,6 +46,8 @@ if (item.elem) { | ||
// xmlns attributes implicitly have the prefix xmlns | ||
if (a.prefix == 'xmlns') | ||
return -1; | ||
if (b.prefix == 'xmlns') | ||
return 1; | ||
if (xmlnsOrder == 'front') { | ||
if (a.prefix == 'xmlns') | ||
return -1; | ||
if (b.prefix == 'xmlns') | ||
return 1; | ||
} | ||
return a.prefix < b.prefix ? -1 : 1; | ||
@@ -51,0 +54,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.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) | ||
## SVGO [![NPM version](https://badge.fury.io/js/svgo.svg)](https://npmjs.org/package/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 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. | ||
SVG files, especially those exported from various editors, usually contain a lot of redundant and useless information. This can include editor metadata, comments, hidden elements, default or non-optimal values and other stuff that can be safely removed or converted without affecting the SVG rendering result. | ||
@@ -26,2 +26,3 @@ ## What it can do | ||
| [cleanupAttrs](https://github.com/svg/svgo/blob/master/plugins/cleanupAttrs.js) | cleanup attributes from newlines, trailing, and repeating spaces | | ||
| [inlineStyles](https://github.com/svg/svgo/blob/master/plugins/inlineStyles.js) | move and merge styles from `<style>` elements to element `style` attributes | | ||
| [removeDoctype](https://github.com/svg/svgo/blob/master/plugins/removeDoctype.js) | remove doctype declaration | | ||
@@ -95,4 +96,4 @@ | [removeXMLProcInst](https://github.com/svg/svgo/blob/master/plugins/removeXMLProcInst.js) | remove XML processing instructions | | ||
--config=CONFIG : Config file or JSON string to extend or replace default | ||
--disable=PLUGIN : Disable plugin by name, "--disable={PLUGIN1,PLUGIN2}" for multiple plugins | ||
--enable=PLUGIN : Enable plugin by name, "--enable={PLUGIN3,PLUGIN4}" for multiple plugins | ||
--disable=PLUGIN : Disable plugin by name, "--disable={PLUGIN1,PLUGIN2}" for multiple plugins (*nix) | ||
--enable=PLUGIN : Enable plugin by name, "--enable={PLUGIN3,PLUGIN4}" for multiple plugins (*nix) | ||
--datauri=DATAURI : Output as Data URI string (base64, URI encoded or unencoded) | ||
@@ -183,3 +184,3 @@ --multipass : Enable multipass | ||
* as a web app - [SVGOMG](https://jakearchibald.github.io/svgomg/) | ||
* as a web app – [SVGOMG](https://jakearchibald.github.io/svgomg/) | ||
* as a Nodejs module – [examples](https://github.com/svg/svgo/tree/master/examples) | ||
@@ -192,4 +193,7 @@ * as a Grunt task – [grunt-svgmin](https://github.com/sindresorhus/grunt-svgmin) | ||
* as a Telegram Bot – [svgo_bot](https://github.com/maksugr/svgo_bot) | ||
* as a PostCSS plugin - [postcss-svgo](https://github.com/ben-eb/postcss-svgo) | ||
* as an Inkscape plugin - [inkscape-svgo](https://github.com/konsumer/inkscape-svgo) | ||
* as a PostCSS plugin – [postcss-svgo](https://github.com/ben-eb/postcss-svgo) | ||
* as an Inkscape plugin – [inkscape-svgo](https://github.com/konsumer/inkscape-svgo) | ||
* as a Sketch plugin - [svgo-compressor](https://github.com/BohemianCoding/svgo-compressor) | ||
* as macOS app - [Image Shrinker](https://image-shrinker.com) | ||
* as a Rollup plugin - [rollup-plugin-svgo](https://github.com/porsager/rollup-plugin-svgo) | ||
@@ -196,0 +200,0 @@ ## License and Copyright |
@@ -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.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) | ||
## SVGO [![NPM version](https://badge.fury.io/js/svgo.svg)](https://npmjs.org/package/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 – это инструмент для оптимизации векторной графики в формате SVG, написанный на Node.js. | ||
SVG-файлы, особенно – экспортированные из различных редакторов, содержат много избыточной и бесполезной информации, комментариев, скрытых элементов, неоптимальные или стандартные значения и другой мусор, удаление которого безопасно и не влияет на конечный результат отрисовки. | ||
SVG-файлы, особенно экспортированные из редакторов, содержат много избыточной и бесполезной информации, комментариев, скрытых элементов, неоптимальные или стандартные значения и другой мусор, удаление которого безопасно и не влияет на конечный вид изображения. | ||
@@ -21,3 +21,3 @@ ## Возможности | ||
Сегодня у нас есть: | ||
Что у нас есть: | ||
@@ -27,2 +27,3 @@ | Plugin | Description | | ||
| [cleanupAttrs](https://github.com/svg/svgo/blob/master/plugins/cleanupAttrs.js) | удаление переносов строк и лишних пробелов | | ||
| [inlineStyles](https://github.com/svg/svgo/blob/master/plugins/inlineStyles.js) | перенос стилей из элементов `<style>` в атрибуты `style` | | ||
| [removeDoctype](https://github.com/svg/svgo/blob/master/plugins/removeDoctype.js) | удаление doctype | | ||
@@ -70,3 +71,3 @@ | [removeXMLProcInst](https://github.com/svg/svgo/blob/master/plugins/removeXMLProcInst.js) | удаление XML-инструкций | | ||
Хотите узнать, как это работает и как написать свой плагин? [Конечно же, да!](https://github.com/svg/svgo/blob/master/docs/how-it-works/ru.md). | ||
Хотите узнать принципы работы и как написать свой плагин? [Конечно же, да!](https://github.com/svg/svgo/blob/master/docs/how-it-works/ru.md) | ||
@@ -193,2 +194,6 @@ | ||
* как плагин PostCSS - [postcss-svgo](https://github.com/ben-eb/postcss-svgo) | ||
* как плагин для Inkscape – [inkscape-svgo](https://github.com/konsumer/inkscape-svgo) | ||
* как плагин для Sketch - [svgo-compressor](https://github.com/BohemianCoding/svgo-compressor) | ||
* в виде приложения macOS - [Image Shrinker](https://image-shrinker.com) | ||
* как плагин для Rollup - [rollup-plugin-svgo](https://github.com/porsager/rollup-plugin-svgo) | ||
@@ -195,0 +200,0 @@ ## Лицензия и копирайты |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
377560
9762
199
0
8
+ Addedcss-select@2.1.0(transitive)
+ Addedcss-tree@1.0.0-alpha.28(transitive)
+ Addedcss-what@3.4.2(transitive)
+ Addeddomutils@1.7.0(transitive)
+ Addedjs-yaml@3.14.1(transitive)
+ Addedmdn-data@1.1.4(transitive)
- Removedcss-select@1.3.0-rc0(transitive)
- Removedcss-tree@1.0.0-alpha25(transitive)
- Removedcss-what@2.1.3(transitive)
- Removeddomutils@1.5.1(transitive)
- Removedjs-yaml@3.10.0(transitive)
- Removedmdn-data@1.2.0(transitive)
Updatedcss-select@^2.0.0
Updatedcss-tree@1.0.0-alpha.28
Updatedjs-yaml@^3.12.0