Socket
Socket
Sign inDemoInstall

svgo

Package Overview
Dependencies
21
Maintainers
2
Versions
102
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.5.6 to 0.6.0

lib-cov/svgo.js

12

CHANGELOG.md

@@ -0,1 +1,13 @@

### [ [>](https://github.com/svg/svgo/tree/v0.6.0) ] 0.6.0 / 08.11.2015
* New optimization: circular curves now being converted to arcs. A notable improvement for circles within paths.
* New plugin “[minifyStyles](https://github.com/svg/svgo/blob/master/plugins/minifyStyles.js)” which minifies `<style>` elments content with CSSO by @strarsis (svgo still doesn't understand its content)
* New plugin “[removeStyleElement](https://github.com/svg/svgo/blob/master/plugins/removeStyleElement.js)” (disabled by default) by @betsydupuis.
* Fixed issues wuth parsing numbers with exponent fraction (could happen with high precision >= 7).
* Fixed rounding error due to incorrect preserving of precision in transformations.
* Fixed shortand curve distortion due to converted previous curve to not a curve.
* Fixed interoperability issue with `precision` cli-option and `full` config.
* Fixed an error produced by “[removeUnknownsAndDefaults](https://github.com/svg/svgo/blob/master/plugins/removeUnknownsAndDefaults.js)” by @thiakil
* Another Inkscape prefix namespace is being removed.
* Fixed an issue in [moveElemsAttrsToGroup“](https://github.com/svg/svgo/blob/master/plugins/moveElemsAttrsToGroup“.js)” with transforms moved around `clip-path`.
### [ [>](https://github.com/svg/svgo/tree/v0.5.6) ] 0.5.6 / 13.08.2015

@@ -2,0 +14,0 @@ * Fixed paths removing.

12

lib/svgo/coa.js

@@ -180,3 +180,3 @@ /* jshint quotmark: false */

if (opts.disable) {
config = changePluginsState(opts.disable, false, config);
changePluginsState(opts.disable, false, config);
}

@@ -186,3 +186,3 @@

if (opts.enable) {
config = changePluginsState(opts.enable, true, config);
changePluginsState(opts.enable, true, config);
}

@@ -354,3 +354,3 @@

// extend config
if (config && config.plugins) {
if (config.plugins) {

@@ -371,5 +371,5 @@ names.forEach(function(name) {

// if there are such plugin name
// if there is such a plugin name
if (key === name) {
// do not replace plugin's params with true
// don't replace plugin's params with true
if (typeof plugin[key] !== 'object' || !state) {

@@ -404,3 +404,3 @@ plugin[key] = state;

config = { plugins: [] };
config.plugins = [];

@@ -407,0 +407,0 @@ names.forEach(function(name) {

@@ -18,35 +18,27 @@ 'use strict';

var defaults;
config = config || {};
if (config && config.full) {
if (config.full) {
defaults = config;
if (defaults.plugins) {
if (Array.isArray(defaults.plugins)) {
defaults.plugins = preparePluginsArray(defaults.plugins);
defaults.plugins = optimizePluginsArray(defaults.plugins);
}
defaults.multipass = config.multipass;
} else {
defaults = EXTEND({}, yaml.safeLoad(FS.readFileSync(__dirname + '/../../.svgo.yml', 'utf8')));
defaults.plugins = preparePluginsArray(defaults.plugins);
defaults = extendConfig(defaults, config);
}
if (config) {
defaults = extendConfig(defaults, config);
defaults.multipass = config.multipass;
if ('floatPrecision' in config) {
defaults.plugins.forEach(function(plugin) {
if (plugin.params && ('floatPrecision' in plugin.params)) {
plugin.params.floatPrecision = config.floatPrecision;
}
});
if ('floatPrecision' in config && Array.isArray(defaults.plugins)) {
defaults.plugins.forEach(function(plugin) {
if (plugin.params && ('floatPrecision' in plugin.params)) {
// Don't touch default plugin params
plugin.params = EXTEND({}, plugin.params, { floatPrecision: config.floatPrecision });
}
}
});
}
if (Array.isArray(defaults.plugins)) {
defaults.plugins = optimizePluginsArray(defaults.plugins);
}

@@ -167,2 +159,4 @@

defaults.multipass = config.multipass;
// svg2js

@@ -207,21 +201,11 @@ if (config.svg2js) {

plugins = plugins.map(function(item) {
return [item];
});
plugins = plugins.filter(function(item) {
if (prev && item[0].type === prev[0].type) {
prev.push(item[0]);
return false;
return plugins.reduce(function(plugins, item) {
if (prev && item.type == prev[0].type) {
prev.push(item);
} else {
plugins.push(prev = [item]);
}
return plugins;
}, []);
prev = item;
return true;
});
return plugins;
}

@@ -90,2 +90,9 @@ 'use strict';

// remove floating-point numbers leading zeros
// 0.5 → .5
// -0.5 → -.5
if (params.leadingZero) {
item = removeLeadingZero(item);
}
// no extra space in front of negative number or

@@ -96,3 +103,3 @@ // in front of a floating number if a previous number is floating too

(item < 0 ||
(item > 0 && item < 1 && prev % 1 !== 0)
(/^\./.test(item) && prev % 1 !== 0)
)

@@ -106,9 +113,2 @@ ) {

// remove floating-point numbers leading zeros
// 0.5 → .5
// -0.5 → -.5
if (params.leadingZero) {
item = removeLeadingZero(item);
}
str += delimiter + item;

@@ -115,0 +115,0 @@

{
"name": "svgo",
"version": "0.5.6",
"version": "0.6.0",
"description": "Nodejs-based tool for optimizing SVG vector graphics files",

@@ -42,13 +42,14 @@ "keywords": [ "svgo", "svg", "optimize", "minify" ],

"dependencies": {
"sax": "~1.1.1",
"sax": "~1.1.4",
"coa": "~1.0.1",
"js-yaml": "~3.3.1",
"js-yaml": "~3.4.3",
"colors": "~1.1.2",
"whet.extend": "~0.9.9",
"mkdirp": "~0.5.1"
"mkdirp": "~0.5.1",
"csso": "~1.4.1"
},
"devDependencies": {
"mocha": "~2.2.5",
"should": "7.0.3",
"istanbul": "~0.3.17",
"mocha": "~2.3.3",
"should": "7.1.1",
"istanbul": "~0.4.0",
"mocha-istanbul": "~0.2.0",

@@ -55,0 +56,0 @@ "coveralls": "~2.11.4"

@@ -2270,2 +2270,3 @@ 'use strict';

'http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd',
'http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd',
'http://www.inkscape.org/namespaces/inkscape',

@@ -2272,0 +2273,0 @@ 'http://www.bohemiancoding.com/sketch/ns',

@@ -39,4 +39,4 @@ 'use strict';

currentIDstring,
IDs = {},
referencesIDs = {},
IDs = Object.create(null),
referencesIDs = Object.create(null),
idPrefix = 'id-', // prefix IDs so that values like '__proto__' don't break the work

@@ -53,3 +53,3 @@ hasStyleOrScript = false;

for (var i = 0; i < items.content.length; i++) {
for (var i = 0; i < items.content.length && !hasStyleOrScript; i++) {

@@ -62,54 +62,54 @@ var item = items.content[i],

hasStyleOrScript = true;
continue;
}
// …and don't remove any ID if yes
if (!hasStyleOrScript) {
if (item.isElem()) {
if (item.isElem()) {
item.eachAttr(function(attr) {
// save IDs
if (attr.name === 'id') {
if (idPrefix + attr.value in IDs) {
item.removeAttr('id');
} else {
IDs[idPrefix + attr.value] = item;
}
item.eachAttr(function(attr) {
var key;
// save IDs
if (attr.name === 'id') {
key = idPrefix + attr.value;
if (key in IDs) {
item.removeAttr('id');
} else {
IDs[key] = item;
}
}
// save IDs url() references
else if (referencesProps.indexOf(attr.name) > -1) {
match = attr.value.match(regReferencesUrl);
// save IDs url() references
else if (referencesProps.indexOf(attr.name) > -1) {
match = attr.value.match(regReferencesUrl);
if (match) {
if (referencesIDs[idPrefix + match[2]]) {
referencesIDs[idPrefix + match[2]].push(attr);
} else {
referencesIDs[idPrefix + match[2]] = [attr];
}
if (match) {
key = idPrefix + match[2];
if (referencesIDs[key]) {
referencesIDs[key].push(attr);
} else {
referencesIDs[key] = [attr];
}
}
}
// save IDs href references
else if (
attr.name === 'xlink:href' && (match = attr.value.match(regReferencesHref)) ||
attr.name === 'begin' && (match = attr.value.match(regReferencesBegin))
) {
if (referencesIDs[idPrefix + match[1]]) {
referencesIDs[idPrefix + match[1]].push(attr);
} else {
referencesIDs[idPrefix + match[1]] = [attr];
}
// save IDs href references
else if (
attr.name === 'xlink:href' && (match = attr.value.match(regReferencesHref)) ||
attr.name === 'begin' && (match = attr.value.match(regReferencesBegin))
) {
key = idPrefix + match[1];
if (referencesIDs[key]) {
referencesIDs[key].push(attr);
} else {
referencesIDs[key] = [attr];
}
});
}
});
}
}
// go deeper
if (item.content) {
monkeys(item);
}
// go deeper
if (item.content) {
monkeys(item);
}
}

@@ -123,36 +123,35 @@

if (!hasStyleOrScript) {
if (hasStyleOrScript) {
return data;
}
for (var k in referencesIDs) {
if (IDs[k]) {
for (var k in referencesIDs) {
if (IDs[k]) {
// replace referenced IDs with the minified ones
if (params.minify) {
// replace referenced IDs with the minified ones
if (params.minify) {
currentIDstring = getIDstring(currentID = generateID(currentID), params);
IDs[k].attr('id').value = currentIDstring;
currentIDstring = getIDstring(currentID = generateID(currentID), params);
IDs[k].attr('id').value = currentIDstring;
referencesIDs[k].forEach(function(attr) {
k = k.replace(idPrefix, '');
attr.value = attr.value
.replace('#' + k, '#' + currentIDstring)
.replace(k + '.', currentIDstring + '.');
});
referencesIDs[k].forEach(function(attr) {
k = k.replace(idPrefix, '');
attr.value = attr.value
.replace('#' + k, '#' + currentIDstring)
.replace(k + '.', currentIDstring + '.');
});
}
}
// don't remove referenced IDs
delete IDs[idPrefix + k];
// don't remove referenced IDs
delete IDs[idPrefix + k];
}
}
}
// remove non-referenced IDs attributes from elements
if (params.remove) {
// remove non-referenced IDs attributes from elements
if (params.remove) {
for(var ID in IDs) {
IDs[ID].removeAttr('id');
}
for(var ID in IDs) {
IDs[ID].removeAttr('id');
}

@@ -159,0 +158,0 @@

@@ -21,3 +21,3 @@ 'use strict';

cm: 96/2.54,
mm: 9600/2.54,
mm: 96/25.4,
in: 96,

@@ -24,0 +24,0 @@ pt: 4/3,

@@ -20,3 +20,3 @@ 'use strict';

cm: 96/2.54,
mm: 9600/2.54,
mm: 96/25.4,
in: 96,

@@ -23,0 +23,0 @@ pt: 4/3,

@@ -12,2 +12,6 @@ 'use strict';

applyTransformsStroked: true,
makeArcs: {
threshold: 2.5, // coefficient of rounding error
tolerance: 0.5 // percentage of radius
},
straightCurves: true,

@@ -32,2 +36,4 @@ lineShorthands: true,

error,
arcThreshold,
arcTolerance,
hasMarkerMid;

@@ -57,2 +63,6 @@

error = precision !== false ? +Math.pow(.1, precision).toFixed(precision) : 1e-2;
if (params.makeArcs) {
arcThreshold = params.makeArcs.threshold;
arcTolerance = params.makeArcs.tolerance;
}
hasMarkerMid = item.hasAttr('marker-mid');

@@ -258,14 +268,17 @@

var relSubpoint = [0, 0],
var stringify = data2Path.bind(null, params),
relSubpoint = [0, 0],
pathBase = [0, 0],
prev = {};
path = path.filter(function(item, index) {
path = path.filter(function(item, index, path) {
var instruction = item.instruction,
data = item.data;
data = item.data,
next = path[index + 1];
if (data) {
var sdata;
var sdata = data,
circle;

@@ -286,2 +299,107 @@ if (instruction === 's') {

// convert curves to arcs if possible
if (
params.makeArcs &&
(instruction == 'c' || instruction == 's') &&
isConvex(sdata) &&
(circle = findCircle(sdata))
) {
var r = roundData([circle.radius])[0],
angle = findArcAngle(sdata),
sweep = sdata[5] * sdata[0] - sdata[4] * sdata[1] > 0 ? 1 : 0,
arc = {
instruction: 'a',
data: [r, r, 0, 0, sweep, sdata[4], sdata[5]],
coords: item.coords.slice(),
base: item.base
},
output = [arc],
// relative coordinates to adjust the found circle
relCenter = [circle.center[0] - sdata[4], circle.center[1] - sdata[5]],
relCircle = { center: relCenter, radius: circle.radius },
arcCurves = [item],
hasPrev = 0,
suffix = '',
nextLonghand;
if (
prev.instruction == 'c' && isConvex(prev.data) && isArcPrev(prev.data, circle) ||
prev.instruction == 'a' && prev.sdata && isArcPrev(prev.sdata, circle)
) {
arcCurves.unshift(prev);
arc.base = prev.base;
arc.data[5] = arc.coords[0] - arc.base[0];
arc.data[6] = arc.coords[1] - arc.base[1];
angle += findArcAngle(prev.instruction == 'a' ? prev.sdata : prev.data);
if (angle > Math.PI) arc.data[3] = 1;
hasPrev = 1;
}
// check if next curves are fitting the arc
for (var j = index; (next = path[++j]) && ~'cs'.indexOf(next.instruction);) {
var nextData = next.data;
if (next.instruction == 's') {
nextLonghand = makeLonghand({instruction: 's', data: next.data.slice() },
path[j - 1].data);
nextData = nextLonghand.data;
nextLonghand.data = nextData.slice(0, 2);
suffix = stringify([nextLonghand]);
}
if (isConvex(nextData) && isArc(nextData, relCircle)) {
angle += findArcAngle(nextData);
if (angle - 2 * Math.PI > 1e-3) break; // more than 360°
if (angle > Math.PI) arc.data[3] = 1;
arcCurves.push(next);
if (2 * Math.PI - angle > 1e-3) { // less than 360°
arc.coords = next.coords;
arc.data[5] = arc.coords[0] - arc.base[0];
arc.data[6] = arc.coords[1] - arc.base[1];
} else {
// full circle, make a half-circle arc and add a second one
arc.data[5] = 2 * (relCircle.center[0] - nextData[4]);
arc.data[6] = 2 * (relCircle.center[1] - nextData[5]);
arc.coords = [arc.base[0] + arc.data[5], arc.base[1] + arc.data[6]];
arc = {
instruction: 'a',
data: [r, r, 0, 0, sweep,
next.coords[0] - arc.coords[0], next.coords[1] - arc.coords[1]],
coords: next.coords,
base: arc.coords
};
output.push(arc);
j++;
break;
}
relCenter[0] -= nextData[4];
relCenter[1] -= nextData[5];
} else break;
}
if ((stringify(output) + suffix).length < stringify(arcCurves).length) {
if (path[j] && path[j].instruction == 's') {
makeLonghand(path[j], path[j - 1].data);
}
if (hasPrev) {
var prevArc = output.shift();
roundData(prevArc.data);
relSubpoint[0] += prevArc.data[5] - prev.data[prev.data.length - 2];
relSubpoint[1] += prevArc.data[6] - prev.data[prev.data.length - 1];
prev.instruction = 'a';
prev.data = prevArc.data;
item.base = prev.coords = prevArc.coords;
}
arc = output.shift();
if (arcCurves.length == 1) {
item.sdata = sdata.slice(); // preserve curve data for future checks
} else if (arcCurves.length - 1 - hasPrev > 0) {
// filter out consumed next items
path.splice.apply(path, [index + 1, arcCurves.length - 1 - hasPrev].concat(output));
}
if (!arc) return false;
instruction = 'a';
data = arc.data;
item.coords = arc.coords;
}
}
// Rounding relative coordinates, taking in account accummulating error

@@ -322,10 +440,10 @@ // to get closer to absolute coordinates. Sum of rounded value remains same:

// c
if (
instruction === 'c' &&
isCurveStraightLine(
[ 0, data[0], data[2], data[4] ],
[ 0, data[1], data[3], data[5] ]
)
isCurveStraightLine(data) ||
instruction === 's' &&
isCurveStraightLine(sdata)
) {
if (next && next.instruction == 's')
makeLonghand(next, data); // fix up next curve
instruction = 'l';

@@ -335,10 +453,8 @@ data = data.slice(-2);

// s
else if (
instruction === 's' &&
isCurveStraightLine(
[ 0, sdata[0], sdata[2], sdata[4] ],
[ 0, sdata[1], sdata[3], sdata[5] ]
)
instruction === 'q' &&
isCurveStraightLine(data)
) {
if (next && next.instruction == 't')
makeLonghand(next, data); // fix up next curve
instruction = 'l';

@@ -348,16 +464,7 @@ data = data.slice(-2);

// q
else if (
instruction === 'q' &&
isCurveStraightLine(
[ 0, data[0], data[2] ],
[ 0, data[1], data[3] ]
)
instruction === 't' &&
prev.instruction !== 'q' &&
prev.instruction !== 't'
) {
// save the original one for the future potential q + t conversion
item.original = {
instruction: instruction,
data: data
};
instruction = 'l';

@@ -367,30 +474,2 @@ data = data.slice(-2);

else if (instruction === 't') {
// q (original) + t
if (
prev.original &&
prev.original.instruction === 'q'
) {
if (isCurveStraightLine(
[ prev.original.data[0], prev.original.data[2], data[0] ],
[ prev.original.data[1], prev.original.data[3], data[1] ]
)) {
instruction = 'l';
data = data.slice(-2);
} else {
prev.instruction = 'q';
prev.data = prev.original.data;
}
}
// [^qt] + t
else if ('qt'.indexOf(prev.instruction) < 0) {
instruction = 'l';
data = data.slice(-2);
}
}
// a
else if (

@@ -438,3 +517,2 @@ instruction === 'a' &&

prev.coords = item.coords;
if (prev.original) prev.original = null;
path[index] = prev;

@@ -609,3 +687,3 @@ return false;

absoluteDataStr.length == relativeDataStr.length - 1 &&
(data[0] < 0 || 0 < data[0] && data[0] < 1 && prev.data[prev.data.length - 1] % 1)
(data[0] < 0 || /^0\./.test(data[0]) && prev.data[prev.data.length - 1] % 1)
)

@@ -628,2 +706,55 @@ ) {

/**
* Checks if curve is convex. Control points of such a curve must form
* a convex quadrilateral with diagonals crosspoint inside of it.
*
* @param {Array} data input path data
* @return {Boolean} output
*/
function isConvex(data) {
var center = getIntersection([0, 0, data[2], data[3], data[0], data[1], data[4], data[5]]);
return center &&
(data[2] < center[0] == center[0] < 0) &&
(data[3] < center[1] == center[1] < 0) &&
(data[4] < center[0] == center[0] < data[0]) &&
(data[5] < center[1] == center[1] < data[1]);
}
/**
* Computes lines equations by two points and returns their intersection point.
*
* @param {Array} coords 8 numbers for 4 pairs of coordinates (x,y)
* @return {Array|undefined} output coordinate of lines' crosspoint
*/
function getIntersection(coords) {
// Prev line equation parameters.
var a1 = coords[1] - coords[3], // y1 - y2
b1 = coords[2] - coords[0], // x2 - x1
c1 = coords[0] * coords[3] - coords[2] * coords[1], // x1 * y2 - x2 * y1
// Next line equation parameters
a2 = coords[5] - coords[7], // y1 - y2
b2 = coords[6] - coords[4], // x2 - x1
c2 = coords[4] * coords[7] - coords[5] * coords[6], // x1 * y2 - x2 * y1
denom = (a1 * b2 - a2 * b1);
if (!denom) return; // parallel lines havn't an intersection
var cross = [
(b1 * c2 - b2 * c1) / denom,
(a1 * c2 - a2 * c1) / -denom
];
if (
!isNaN(cross[0]) && !isNaN(cross[1]) &&
isFinite(cross[0]) && isFinite(cross[1])
) {
return cross;
}
}
/**
* Decrease accuracy of floating-point numbers

@@ -671,16 +802,15 @@ * in path data keeping a specified number of decimals.

function isCurveStraightLine(xs, ys) {
function isCurveStraightLine(data) {
// Get line equation a·x + b·y + c = 0 coefficients a, b, c by start and end points.
var i = xs.length - 1,
a = ys[0] - ys[i], // y1 − y2
b = xs[i] - xs[0], // x2 − x1
c = xs[0] * ys[i] - xs[i] * ys[0], // x1·y2 − x2·y1
// Get line equation a·x + b·y + c = 0 coefficients a, b (c = 0) by start and end points.
var i = data.length - 2,
a = -data[i + 1], // y1 − y2 (y1 = 0)
b = data[i], // x2 − x1 (x1 = 0)
d = 1 / (a * a + b * b); // same part for all points
if (!isFinite(d)) return false; // curve that ends at start point isn't the case
if (i <= 1 || !isFinite(d)) return false; // curve that ends at start point isn't the case
// Distance from point (x0, y0) to the line is sqrt((c − a·x0 − b·y0)² / (a² + b²))
while (--i) {
if (Math.sqrt(Math.pow(c - a * xs[i] - b * ys[i], 2) * d) > error)
while ((i -= 2) >= 0) {
if (Math.sqrt(Math.pow(a * data[i] + b * data[i + 1], 2) * d) > error)
return false;

@@ -692,1 +822,141 @@ }

}
/**
* Converts next curve from shorthand to full form using the current curve data.
*
* @param {Object} item curve to convert
* @param {Array} data current curve data
*/
function makeLonghand(item, data) {
switch (item.instruction) {
case 's': item.instruction = 'c'; break;
case 't': item.instruction = 'q'; break;
}
item.data.unshift(data[data.length - 2] - data[data.length - 4], data[data.length - 1] - data[data.length - 3]);
return item;
}
/**
* Returns distance between two points
*
* @param {Array} point1 first point coordinates
* @param {Array} point2 second point coordinates
* @return {Number} distance
*/
function getDistance(point1, point2) {
return Math.sqrt(Math.pow(point1[0] - point2[0], 2) + Math.pow(point1[1] - point2[1], 2));
}
/**
* Returns coordinates of the curve point corresponding to the certain t
* a·(1 - t)³·p1 + b·(1 - t)²·t·p2 + c·(1 - t)·t²·p3 + d·t³·p4,
* where pN are control points and p1 is zero due to relative coordinates.
*
* @param {Array} curve array of curve points coordinates
* @param {Number} t parametric position from 0 to 1
* @return {Array} Point coordinates
*/
function getCubicBezierPoint(curve, t) {
var sqrT = t * t,
cubT = sqrT * t,
mt = 1 - t,
sqrMt = mt * mt;
return [
3 * sqrMt * t * curve[0] + 3 * mt * sqrT * curve[2] + cubT * curve[4],
3 * sqrMt * t * curve[1] + 3 * mt * sqrT * curve[3] + cubT * curve[5]
];
}
/**
* Finds circle by 3 points of the curve and checks if the curve fits the found circle.
*
* @param {Array} curve
* @return {Object|undefined} circle
*/
function findCircle(curve) {
var midPoint = getCubicBezierPoint(curve, 1/2),
m1 = [midPoint[0] / 2, midPoint[1] / 2],
m2 = [(midPoint[0] + curve[4]) / 2, (midPoint[1] + curve[5]) / 2],
center = getIntersection([
m1[0], m1[1],
m1[0] + m1[1], m1[1] - m1[0],
m2[0], m2[1],
m2[0] + (m2[1] - midPoint[1]), m2[1] - (m2[0] - midPoint[0])
]),
radius = center && getDistance([0, 0], center),
tolerance = Math.min(arcThreshold * error, arcTolerance * radius / 100);
if (center && [1/4, 3/4].every(function(point) {
return Math.abs(getDistance(getCubicBezierPoint(curve, point), center) - radius) <= tolerance;
}))
return { center: center, radius: radius};
}
/**
* Checks if a curve fits the given circe.
*
* @param {Object} circle
* @param {Array} curve
* @return {Boolean}
*/
function isArc(curve, circle) {
var tolerance = Math.min(arcThreshold * error, arcTolerance * circle.radius / 100);
return [0, 1/4, 1/2, 3/4, 1].every(function(point) {
return Math.abs(getDistance(getCubicBezierPoint(curve, point), circle.center) - circle.radius) <= tolerance;
});
}
/**
* Checks if a previos curve fits the given circe.
*
* @param {Object} circle
* @param {Array} curve
* @return {Boolean}
*/
function isArcPrev(curve, circle) {
return isArc(curve, {
center: [circle.center[0] + curve[4], circle.center[1] + curve[5]],
radius: circle.radius
});
}
/**
* Finds angle of an arc formed by a curve.
*
* @param {Array} curve
* @return {Number} angle
*/
function findArcAngle(curve) {
var x1 = curve[0],
y1 = curve[1],
x2 = curve[2] - curve[4],
y2 = curve[3] - curve[5];
return Math.PI - Math.acos(
(x1 * x2 + y1 * y2 ) /
Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))
);
}
/**
* Converts given path data to string.
*
* @param {Object} params
* @param {Array} pathData
* @return {String}
*/
function data2Path(params, pathData) {
return pathData.reduce(function(pathString, item) {
return pathString += item.instruction + (item.data ? cleanupOutData(roundData(item.data.slice()), params) : '');
}, '');
}

@@ -90,5 +90,2 @@ 'use strict';

var closePath = item.isElem('polygon') &&
(item.computedAttr('id') || (item.computedAttr('stroke') || 'none') != 'none');
item.addAttr({

@@ -98,3 +95,3 @@ name: 'd',

'L' + coords.slice(2).join(' ') +
(closePath ? 'z' : ''),
(item.isElem('polygon') ? 'z' : ''),
prefix: '',

@@ -101,0 +98,0 @@ local: 'd'

@@ -25,2 +25,3 @@ 'use strict';

var cleanupOutData = require('../lib/svgo/tools').cleanupOutData,
EXTEND = require('whet.extend'),
transform2js = require('./_transforms.js').transform2js,

@@ -79,3 +80,3 @@ transformsMultiply = require('./_transforms.js').transformsMultiply,

var data = transform2js(item.attr(attrName).value);
definePrecision(data, params);
params = definePrecision(data, params);

@@ -89,5 +90,3 @@ if (params.collapseIntoOne && data.length > 1) {

} else {
data.forEach(function(transform) {
transform = roundTransform(transform, params);
});
data.forEach(roundTransform);
}

@@ -122,2 +121,5 @@

// Clone params so it don't affect other elements transformations.
params = EXTEND({}, params);
// Limit transform precision with matrix one. Calculating with larger precision doesn't add any value.

@@ -137,5 +139,7 @@ if (matrixData.length) {

floatRound = params.floatPrecision >= 1 ? smartRound.bind(this, params.floatPrecision) : round;
degRound = params.degPrecision >= 1 ? smartRound.bind(this, params.degPrecision) : round;
floatRound = params.floatPrecision >= 1 ? smartRound.bind(this, params.floatPrecision) : round;
transformRound = params.transformPrecision >= 1 ? smartRound.bind(this, params.transformPrecision) : round;
return params;
}

@@ -188,11 +192,5 @@

transform = roundTransform(transform, params);
// fixed-point numbers
// 12.754997 → 12.755
if (params.transformPrecision !== false) {
transform.data = transform.data.map(function(num) {
return +num.toFixed(params.transformPrecision);
});
}
roundTransform(transform);

@@ -307,3 +305,3 @@ // convert long translate transform notation to the shorts one

transformJS.forEach(function(transform) {
transform = roundTransform(transform, params);
roundTransform(transform);
transformString += (transformString && ' ') + transform.name + '(' + cleanupOutData(transform.data, params) + ')';

@@ -310,0 +308,0 @@ });

@@ -42,2 +42,3 @@ 'use strict';

hasTransform = false,
hasClip = item.hasAttr('clip-path'),
intersected = item.content.every(function(inner) {

@@ -66,3 +67,3 @@ if (inner.isElem() && inner.hasAttr()) {

if (!allPath || name !== 'transform') {
if (!allPath && !hasClip || name !== 'transform') {

@@ -69,0 +70,0 @@ g.removeAttr(name);

@@ -77,3 +77,4 @@ 'use strict';

!item.isEmpty() &&
elems[elem].content
elems[elem] && //make sure we know of this element before checking its children
elem !== 'foreignObject'//Don't check foreignObject
) {

@@ -83,4 +84,13 @@ item.content.forEach(function(content, i) {

content.isElem() &&
!content.prefix &&
elems[elem].content.indexOf(content.elem) === -1
!content.prefix &&
(
(
elems[elem].content && // Do we have a record of its permitted content?
elems[elem].content.indexOf(content.elem) === -1
) ||
(
!elems[elem].content && // we dont know about its permitted content
!elems[content.elem] // check that we know about the element at all
)
)
) {

@@ -93,3 +103,3 @@ item.content.splice(i, 1);

// remove element's unknown attrs and attrs with default values
if (elems[elem].attrs) {
if (elems[elem] && elems[elem].attrs) {

@@ -96,0 +106,0 @@ item.eachAttr(function(attr) {

@@ -36,2 +36,3 @@ **english** | [русский](https://github.com/svg/svgo/blob/master/README.ru.md)

* [ [ cleanUpEnableBackground](https://github.com/svg/svgo/blob/master/plugins/cleanupEnableBackground.js) ] remove or cleanup `enable-background` attribute when possible
* [ [ minifyStyles](https://github.com/svg/svgo/blob/master/plugins/minifyStyles.js) ] minify `<style>` elements content with [CSSO](https://github.com/css/csso)
* [ [ convertStyleToAttrs](https://github.com/svg/svgo/blob/master/plugins/convertStyleToAttrs.js) ] convert styles into attributes

@@ -58,2 +59,3 @@ * [ [ convertColors](https://github.com/svg/svgo/blob/master/plugins/convertColors.js) ] convert colors (from `rgb()` to `#rrggbb`, from `#rrggbb` to `#rgb`)

* [ [ addClassesToSVGElement](https://github.com/svg/svgo/blob/master/plugins/addClassesToSVGElement.js) ] add classnames to an outer `<svg>` element (disabled by default)
* [ [ removeStyleElement](https://github.com/svg/svgo/blob/master/plugins/removeStyleElement.js) ] remove `<style>` elements (disabled by default)

@@ -60,0 +62,0 @@ Want to know how it works and how to write your own plugin? [Of course you want to](https://github.com/svg/svgo/blob/master/docs/how-it-works/en.md).

@@ -36,2 +36,3 @@ [english](https://github.com/svg/svgo/blob/master/README.md) | **русский**

* [ [ cleanupEnableBackground](https://github.com/svg/svgo/blob/master/plugins/cleanupEnableBackground.js) ] удаление или оптимизация атрибута `enable-background`, когда это возможно
* [ [ minifyStyles](https://github.com/svg/svgo/blob/master/plugins/minifyStyles.js) ] уменьшает содержимое элементов `<style>` с помощью [CSSO](https://github.com/css/csso).
* [ [ convertStyleToAttrs](https://github.com/svg/svgo/blob/master/plugins/convertStyleToAttrs.js) ] конвертирование стилей в атрибуте `style` в отдельные svg-атрибуты

@@ -58,2 +59,3 @@ * [ [ convertColors](https://github.com/svg/svgo/blob/master/plugins/convertColors.js) ] конвертирование цветовых значений: из `rgb()` в `#rrggbb`, из `#rrggbb` в `#rgb`

* [ [ addClassesToSVGElement](https://github.com/svg/svgo/blob/master/plugins/addClassesToSVGElement.js) ] добавляет имена классов корневому элементу `<svg>` (выключено по умолчанию)
* [ [ removeStyleElement](https://github.com/svg/svgo/blob/master/plugins/removeStyleElement.js) ] удаляет элементы `<style>` (выключено по умолчанию)

@@ -86,3 +88,3 @@ Хотите узнать, как это работает и как написать свой плагин? [Конечно же, да!](https://github.com/svg/svgo/blob/master/docs/how-it-works/ru.md).

--pretty : Удобочитаемое форматирование SVG
--show-plugins : доступные плагины
--show-plugins : Доступные плагины

@@ -89,0 +91,0 @@ Аргументы:

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc