mirror of
https://github.com/svg/svgo.git
synced 2025-08-01 18:46:52 +03:00
Tune plugins
This commit is contained in:
@ -48,7 +48,6 @@ plugins:
|
|||||||
- removeEmptyContainers
|
- removeEmptyContainers
|
||||||
- mergePaths
|
- mergePaths
|
||||||
- removeUnusedNS
|
- removeUnusedNS
|
||||||
- transformsWithOnePath
|
|
||||||
- sortAttrs
|
- sortAttrs
|
||||||
- removeTitle
|
- removeTitle
|
||||||
- removeDesc
|
- removeDesc
|
||||||
|
@ -6,17 +6,17 @@ exports.active = false;
|
|||||||
|
|
||||||
exports.description = 'adds attributes to an outer <svg> element';
|
exports.description = 'adds attributes to an outer <svg> element';
|
||||||
|
|
||||||
var ENOCLS = 'Error in plugin "addAttributesToSVGElement": absent parameters.\n\
|
var ENOCLS = `Error in plugin "addAttributesToSVGElement": absent parameters.
|
||||||
It should have a list of classes in "attributes" or one "attribute".\n\
|
It should have a list of classes in "attributes" or one "attribute".
|
||||||
Config example:\n\n\
|
Config example:
|
||||||
\
|
|
||||||
plugins:\n\
|
plugins:
|
||||||
- addAttributesToSVGElement:\n\
|
- addAttributesToSVGElement:
|
||||||
attribute: "mySvg"\n\n\
|
attribute: "mySvg"
|
||||||
\
|
|
||||||
plugins:\n\
|
plugins:
|
||||||
- addAttributesToSVGElement:\n\
|
- addAttributesToSVGElement:
|
||||||
attributes: ["mySvg", "size-big"]\n';
|
attributes: ["mySvg", "size-big"]`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add attributes to an outer <svg> element. Example config:
|
* Add attributes to an outer <svg> element. Example config:
|
||||||
|
@ -6,17 +6,18 @@ exports.active = false;
|
|||||||
|
|
||||||
exports.description = 'adds classnames to an outer <svg> element';
|
exports.description = 'adds classnames to an outer <svg> element';
|
||||||
|
|
||||||
var ENOCLS = 'Error in plugin "addClassesToSVGElement": absent parameters.\n\
|
var ENOCLS = `Error in plugin "addClassesToSVGElement": absent parameters.
|
||||||
It should have a list of classes in "classNames" or one "className".\n\
|
It should have a list of classes in "classNames" or one "className".
|
||||||
Config example:\n\n\
|
Config example:
|
||||||
\
|
|
||||||
plugins:\n\
|
plugins:
|
||||||
- addClassesToSVGElement:\n\
|
- addClassesToSVGElement:
|
||||||
className: "mySvg"\n\n\
|
className: "mySvg"
|
||||||
\
|
|
||||||
plugins:\n\
|
plugins:
|
||||||
- addClassesToSVGElement:\n\
|
- addClassesToSVGElement:
|
||||||
classNames: ["mySvg", "size-big"]\n';
|
classNames: ["mySvg", "size-big"]
|
||||||
|
`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add classnames to an outer <svg> element. Example config:
|
* Add classnames to an outer <svg> element. Example config:
|
||||||
|
@ -5,7 +5,7 @@ exports.type = 'perItem';
|
|||||||
exports.active = true;
|
exports.active = true;
|
||||||
|
|
||||||
exports.params = {
|
exports.params = {
|
||||||
removeAny: false
|
removeAny: true
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.description = 'removes <desc> (only non-meaningful by default)';
|
exports.description = 'removes <desc> (only non-meaningful by default)';
|
||||||
|
@ -2,13 +2,12 @@
|
|||||||
|
|
||||||
exports.type = 'perItem';
|
exports.type = 'perItem';
|
||||||
|
|
||||||
exports.active = false;
|
exports.active = true;
|
||||||
|
|
||||||
exports.description = 'removes <title> (disabled by default)';
|
exports.description = 'removes <title>';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove <title>.
|
* Remove <title>.
|
||||||
* Disabled by default cause it may be used for accessibility.
|
|
||||||
*
|
*
|
||||||
* https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title
|
* https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title
|
||||||
*
|
*
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
exports.type = 'perItem';
|
exports.type = 'perItem';
|
||||||
|
|
||||||
exports.active = false;
|
exports.active = true;
|
||||||
|
|
||||||
exports.description = 'removes viewBox attribute when possible (disabled by default)';
|
exports.description = 'removes viewBox attribute when possible';
|
||||||
|
|
||||||
var viewBoxElems = ['svg', 'pattern', 'symbol'];
|
var viewBoxElems = ['svg', 'pattern', 'symbol'];
|
||||||
|
|
||||||
|
@ -1,326 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Thanks to http://fontello.com project for sponsoring this plugin
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.type = 'full';
|
|
||||||
|
|
||||||
exports.active = false;
|
|
||||||
|
|
||||||
exports.description = 'performs a set of operations on SVG with one path inside (disabled by default)';
|
|
||||||
|
|
||||||
exports.params = {
|
|
||||||
// width and height to resize SVG and rescale inner Path
|
|
||||||
width: false,
|
|
||||||
height: false,
|
|
||||||
|
|
||||||
// scale inner Path without resizing SVG
|
|
||||||
scale: false,
|
|
||||||
|
|
||||||
// shiftX/Y inner Path
|
|
||||||
shiftX: false,
|
|
||||||
shiftY: false,
|
|
||||||
|
|
||||||
// crop SVG width along the real width of inner Path
|
|
||||||
hcrop: false,
|
|
||||||
|
|
||||||
// vertical center inner Path inside SVG height
|
|
||||||
vcenter: false,
|
|
||||||
|
|
||||||
// stringify params
|
|
||||||
floatPrecision: 3,
|
|
||||||
leadingZero: true,
|
|
||||||
negativeExtraSpace: true
|
|
||||||
};
|
|
||||||
|
|
||||||
var _path = require('./_path.js'),
|
|
||||||
relative2absolute = _path.relative2absolute,
|
|
||||||
computeCubicBoundingBox = _path.computeCubicBoundingBox,
|
|
||||||
computeQuadraticBoundingBox = _path.computeQuadraticBoundingBox,
|
|
||||||
applyTransforms = _path.applyTransforms,
|
|
||||||
js2path = _path.js2path,
|
|
||||||
path2js = _path.path2js;
|
|
||||||
|
|
||||||
exports.fn = function(data, params) {
|
|
||||||
|
|
||||||
data.content.forEach(function(item) {
|
|
||||||
|
|
||||||
// only for SVG with one Path inside
|
|
||||||
if (item.isElem('svg') &&
|
|
||||||
item.content.length === 1 &&
|
|
||||||
item.content[0].isElem('path')
|
|
||||||
) {
|
|
||||||
|
|
||||||
var svgElem = item,
|
|
||||||
pathElem = svgElem.content[0],
|
|
||||||
// get absoluted Path data
|
|
||||||
path = relative2absolute(path2js(pathElem)),
|
|
||||||
xs = [],
|
|
||||||
ys = [],
|
|
||||||
cubicСontrolPoint = [0, 0],
|
|
||||||
quadraticСontrolPoint = [0, 0],
|
|
||||||
lastPoint = [0, 0],
|
|
||||||
cubicBoundingBox,
|
|
||||||
quadraticBoundingBox,
|
|
||||||
i,
|
|
||||||
segment;
|
|
||||||
|
|
||||||
path.forEach(function(pathItem) {
|
|
||||||
|
|
||||||
// ML
|
|
||||||
if ('ML'.indexOf(pathItem.instruction) > -1) {
|
|
||||||
|
|
||||||
for (i = 0; i < pathItem.data.length; i++) {
|
|
||||||
if (i % 2 === 0) {
|
|
||||||
xs.push(pathItem.data[i]);
|
|
||||||
} else {
|
|
||||||
ys.push(pathItem.data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lastPoint = cubicСontrolPoint = quadraticСontrolPoint = pathItem.data.slice(-2);
|
|
||||||
|
|
||||||
// H
|
|
||||||
} else if (pathItem.instruction === 'H') {
|
|
||||||
|
|
||||||
pathItem.data.forEach(function(d) {
|
|
||||||
xs.push(d);
|
|
||||||
});
|
|
||||||
|
|
||||||
lastPoint[0] = cubicСontrolPoint[0] = quadraticСontrolPoint[0] = pathItem.data[pathItem.data.length - 2];
|
|
||||||
|
|
||||||
// V
|
|
||||||
} else if (pathItem.instruction === 'V') {
|
|
||||||
|
|
||||||
pathItem.data.forEach(function(d) {
|
|
||||||
ys.push(d);
|
|
||||||
});
|
|
||||||
|
|
||||||
lastPoint[1] = cubicСontrolPoint[1] = quadraticСontrolPoint[1] = pathItem.data[pathItem.data.length - 1];
|
|
||||||
|
|
||||||
// C
|
|
||||||
} else if (pathItem.instruction === 'C') {
|
|
||||||
|
|
||||||
for (i = 0; i < pathItem.data.length; i += 6) {
|
|
||||||
|
|
||||||
segment = pathItem.data.slice(i, i + 6);
|
|
||||||
|
|
||||||
cubicBoundingBox = computeCubicBoundingBox.apply(this, lastPoint.concat(segment));
|
|
||||||
|
|
||||||
xs.push(cubicBoundingBox.minx);
|
|
||||||
xs.push(cubicBoundingBox.maxx);
|
|
||||||
|
|
||||||
ys.push(cubicBoundingBox.miny);
|
|
||||||
ys.push(cubicBoundingBox.maxy);
|
|
||||||
|
|
||||||
// reflected control point for the next possible S
|
|
||||||
cubicСontrolPoint = [
|
|
||||||
2 * segment[4] - segment[2],
|
|
||||||
2 * segment[5] - segment[3]
|
|
||||||
];
|
|
||||||
|
|
||||||
lastPoint = segment.slice(-2);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// S
|
|
||||||
} else if (pathItem.instruction === 'S') {
|
|
||||||
|
|
||||||
for (i = 0; i < pathItem.data.length; i += 4) {
|
|
||||||
|
|
||||||
segment = pathItem.data.slice(i, i + 4);
|
|
||||||
|
|
||||||
cubicBoundingBox = computeCubicBoundingBox.apply(this, lastPoint.concat(cubicСontrolPoint).concat(segment));
|
|
||||||
|
|
||||||
xs.push(cubicBoundingBox.minx);
|
|
||||||
xs.push(cubicBoundingBox.maxx);
|
|
||||||
|
|
||||||
ys.push(cubicBoundingBox.miny);
|
|
||||||
ys.push(cubicBoundingBox.maxy);
|
|
||||||
|
|
||||||
// reflected control point for the next possible S
|
|
||||||
cubicСontrolPoint = [
|
|
||||||
2 * segment[2] - cubicСontrolPoint[0],
|
|
||||||
2 * segment[3] - cubicСontrolPoint[1],
|
|
||||||
];
|
|
||||||
|
|
||||||
lastPoint = segment.slice(-2);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Q
|
|
||||||
} else if (pathItem.instruction === 'Q') {
|
|
||||||
|
|
||||||
for (i = 0; i < pathItem.data.length; i += 4) {
|
|
||||||
|
|
||||||
segment = pathItem.data.slice(i, i + 4);
|
|
||||||
|
|
||||||
quadraticBoundingBox = computeQuadraticBoundingBox.apply(this, lastPoint.concat(segment));
|
|
||||||
|
|
||||||
xs.push(quadraticBoundingBox.minx);
|
|
||||||
xs.push(quadraticBoundingBox.maxx);
|
|
||||||
|
|
||||||
ys.push(quadraticBoundingBox.miny);
|
|
||||||
ys.push(quadraticBoundingBox.maxy);
|
|
||||||
|
|
||||||
// reflected control point for the next possible T
|
|
||||||
quadraticСontrolPoint = [
|
|
||||||
2 * segment[2] - segment[0],
|
|
||||||
2 * segment[3] - segment[1]
|
|
||||||
];
|
|
||||||
|
|
||||||
lastPoint = segment.slice(-2);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// S
|
|
||||||
} else if (pathItem.instruction === 'T') {
|
|
||||||
|
|
||||||
for (i = 0; i < pathItem.data.length; i += 2) {
|
|
||||||
|
|
||||||
segment = pathItem.data.slice(i, i + 2);
|
|
||||||
|
|
||||||
quadraticBoundingBox = computeQuadraticBoundingBox.apply(this, lastPoint.concat(quadraticСontrolPoint).concat(segment));
|
|
||||||
|
|
||||||
xs.push(quadraticBoundingBox.minx);
|
|
||||||
xs.push(quadraticBoundingBox.maxx);
|
|
||||||
|
|
||||||
ys.push(quadraticBoundingBox.miny);
|
|
||||||
ys.push(quadraticBoundingBox.maxy);
|
|
||||||
|
|
||||||
// reflected control point for the next possible T
|
|
||||||
quadraticСontrolPoint = [
|
|
||||||
2 * segment[0] - quadraticСontrolPoint[0],
|
|
||||||
2 * segment[1] - quadraticСontrolPoint[1]
|
|
||||||
];
|
|
||||||
|
|
||||||
lastPoint = segment.slice(-2);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
var xmin = Math.min.apply(this, xs).toFixed(params.floatPrecision),
|
|
||||||
xmax = Math.max.apply(this, xs).toFixed(params.floatPrecision),
|
|
||||||
ymin = Math.min.apply(this, ys).toFixed(params.floatPrecision),
|
|
||||||
ymax = Math.max.apply(this, ys).toFixed(params.floatPrecision),
|
|
||||||
svgWidth = +svgElem.attr('width').value,
|
|
||||||
svgHeight = +svgElem.attr('height').value,
|
|
||||||
realWidth = Math.round(xmax - xmin),
|
|
||||||
realHeight = Math.round(ymax - ymin),
|
|
||||||
transform = '',
|
|
||||||
scale;
|
|
||||||
|
|
||||||
// width & height
|
|
||||||
if (params.width && params.height) {
|
|
||||||
|
|
||||||
scale = Math.min(params.width / svgWidth, params.height / svgHeight);
|
|
||||||
|
|
||||||
realWidth = realWidth * scale;
|
|
||||||
realHeight = realHeight * scale;
|
|
||||||
|
|
||||||
svgWidth = svgElem.attr('width').value = params.width;
|
|
||||||
svgHeight = svgElem.attr('height').value = params.height;
|
|
||||||
|
|
||||||
transform += ' scale(' + scale + ')';
|
|
||||||
|
|
||||||
// width
|
|
||||||
} else if (params.width && !params.height) {
|
|
||||||
|
|
||||||
scale = params.width / svgWidth;
|
|
||||||
|
|
||||||
realWidth = realWidth * scale;
|
|
||||||
realHeight = realHeight * scale;
|
|
||||||
|
|
||||||
svgWidth = svgElem.attr('width').value = params.width;
|
|
||||||
svgHeight = svgElem.attr('height').value = svgHeight * scale;
|
|
||||||
|
|
||||||
transform += ' scale(' + scale + ')';
|
|
||||||
|
|
||||||
// height
|
|
||||||
} else if (params.height && !params.width) {
|
|
||||||
|
|
||||||
scale = params.height / svgHeight;
|
|
||||||
|
|
||||||
realWidth = realWidth * scale;
|
|
||||||
realHeight = realHeight * scale;
|
|
||||||
|
|
||||||
svgWidth = svgElem.attr('width').value = svgWidth * scale;
|
|
||||||
svgHeight = svgElem.attr('height').value = params.height;
|
|
||||||
|
|
||||||
transform += ' scale(' + scale + ')';
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// shiftX
|
|
||||||
if (params.shiftX) {
|
|
||||||
transform += ' translate(' + realWidth * params.shiftX + ', 0)';
|
|
||||||
}
|
|
||||||
|
|
||||||
// shiftY
|
|
||||||
if (params.shiftY) {
|
|
||||||
transform += ' translate(0, ' + realHeight * params.shiftY + ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
// scale
|
|
||||||
if (params.scale) {
|
|
||||||
scale = params.scale;
|
|
||||||
|
|
||||||
var shiftX = svgWidth / 2,
|
|
||||||
shiftY = svgHeight / 2;
|
|
||||||
|
|
||||||
realWidth = realWidth * scale;
|
|
||||||
realHeight = realHeight * scale;
|
|
||||||
|
|
||||||
if (params.shiftX || params.shiftY) {
|
|
||||||
transform += ' scale(' + scale + ')';
|
|
||||||
} else {
|
|
||||||
transform += ' translate(' + shiftX + ' ' + shiftY + ') scale(' + scale + ') translate(-' + shiftX + ' -' + shiftY + ')';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// hcrop
|
|
||||||
if (params.hcrop) {
|
|
||||||
transform += ' translate(' + (-xmin) + ' 0)';
|
|
||||||
|
|
||||||
svgElem.attr('width').value = realWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
// vcenter
|
|
||||||
if (params.vcenter) {
|
|
||||||
transform += ' translate(0 ' + (((svgHeight - realHeight) / 2) - ymin) + ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (transform) {
|
|
||||||
pathElem.addAttr({
|
|
||||||
name: 'transform',
|
|
||||||
prefix: '',
|
|
||||||
local: 'transform',
|
|
||||||
value: transform
|
|
||||||
});
|
|
||||||
|
|
||||||
path = applyTransforms(pathElem, pathElem.pathJS, true, params.floatPrecision);
|
|
||||||
|
|
||||||
// transformed data rounding
|
|
||||||
path.forEach(function(pathItem) {
|
|
||||||
if (pathItem.data) {
|
|
||||||
pathItem.data = pathItem.data.map(function(num) {
|
|
||||||
return +num.toFixed(params.floatPrecision);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// save new
|
|
||||||
js2path(pathElem, path, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
return data;
|
|
||||||
|
|
||||||
};
|
|
Reference in New Issue
Block a user