1
0
mirror of https://github.com/svg/svgo.git synced 2025-08-09 02:22:08 +03:00
This commit is contained in:
Yoshiya Hinosawa
2015-06-09 13:59:52 +09:00
parent 7bba483b36
commit 3f8e6fd15c
15 changed files with 75 additions and 52 deletions

View File

@@ -11,6 +11,7 @@
"curly": false,
"camelcase": true,
"eqeqeq": false,
"-W041": false,
"forin": false,
"immed": true,
"multistr": true,

View File

@@ -8,4 +8,7 @@ branches:
only:
- master
before_install:
- npm install -g jshint
script: make travis

View File

@@ -13,7 +13,7 @@ coveralls: lib-cov
@cat lcov.info | ./node_modules/.bin/coveralls
@rm -rf lib-cov lcov.info
travis: test coveralls
travis: jshint test coveralls
jshint:
@jshint --show-non-errors .

View File

@@ -1,3 +1,4 @@
/* jshint quotmark: false */
'use strict';
require('colors');

View File

@@ -8,7 +8,7 @@ var JSAPI = module.exports = function(data, parentNode) {
Object.defineProperty(this, 'parentNode', {
writable: true,
value: parentNode
})
});
}
};
@@ -105,7 +105,7 @@ JSAPI.prototype.renameElem = function(name) {
if (!Array.isArray(insertion))
insertion = Array.apply(null, arguments).slice(2);
insertion.forEach(function(inner) { inner.parentNode = this }, this);
insertion.forEach(function(inner) { inner.parentNode = this; }, this);
return this.content.splice.apply(this.content, [start, n].concat(insertion));
@@ -157,6 +157,7 @@ JSAPI.prototype.renameElem = function(name) {
* @return {Object|Undefined}
*/
JSAPI.prototype.computedAttr = function(name, val) {
/* jshint eqnull: true */
if (!arguments.length) return;
for (var elem = this; elem && (!elem.hasAttr(name) || !elem.attr(name).value); elem = elem.parentNode);

View File

@@ -176,7 +176,7 @@ exports.applyTransforms = function(elem, path, params) {
// gradiends or clip-path which are also subjects to transform.
if (!elem.hasAttr('transform') ||
elem.someAttr(function(attr) {
return ~referencesProps.indexOf(attr.name) && ~attr.value.indexOf('url(')
return ~referencesProps.indexOf(attr.name) && ~attr.value.indexOf('url(');
}))
return path;
@@ -198,13 +198,13 @@ exports.applyTransforms = function(elem, path, params) {
if (elem.hasAttr('stroke-width')) {
elem.attrs['stroke-width'].value = elem.attrs['stroke-width'].value.trim()
.replace(regNumericValues, function(num) { return removeLeadingZero(num * scale) });
.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) })
value: strokeWidth.replace(regNumericValues, function(num) { return removeLeadingZero(num * scale); })
});
}
}
@@ -544,7 +544,7 @@ function collapseRepeated(data) {
data: prev.data.concat(item.data),
coords: item.coords,
base: prev.base
}
};
} else {
prev.data = item.data;
prev.coords = item.coords;
@@ -649,6 +649,8 @@ exports.intersects = function(path1, path2) {
};
function processSimplex(simplex, direction) {
/* jshint -W004 */
// we only need to handle to 1-simplex and 2-simplex
if (simplex.length == 2) { // 1-simplex
var a = simplex[1],
@@ -744,27 +746,27 @@ function gatherPoints(points, item, index, path) {
break;
case 'C':
// Approximate quibic Bezier curve with middle points between control points
addPoint(subPath, [.5 * (basePoint[0] + data[0]), .5 * (basePoint[1] + data[1])]);
addPoint(subPath, [.5 * (data[0] + data[2]), .5 * (data[1] + data[3])]);
addPoint(subPath, [.5 * (data[2] + data[4]), .5 * (data[3] + data[5])]);
addPoint(subPath, [0.5 * (basePoint[0] + data[0]), 0.5 * (basePoint[1] + data[1])]);
addPoint(subPath, [0.5 * (data[0] + data[2]), 0.5 * (data[1] + data[3])]);
addPoint(subPath, [0.5 * (data[2] + data[4]), 0.5 * (data[3] + data[5])]);
prevCtrlPoint = [data[4] - data[2], data[5] - data[3]]; // Save control point for shorthand
break;
case 'S':
if (prev.instruction == 'C' && prev.instruction == 'S') {
addPoint(subPath, [basePoint[0] + .5 * prevCtrlPoint[0], basePoint[1] + .5 * prevCtrlPoint[1]]);
addPoint(subPath, [basePoint[0] + 0.5 * prevCtrlPoint[0], basePoint[1] + 0.5 * prevCtrlPoint[1]]);
ctrlPoint = [basePoint[0] + prevCtrlPoint[0], basePoint[1] + prevCtrlPoint[1]];
}
addPoint(subPath, [.5 * (ctrlPoint[0] + data[0]), .5 * (ctrlPoint[1]+ data[1])]);
addPoint(subPath, [.5 * (data[0] + data[2]), .5 * (data[1] + data[3])]);
addPoint(subPath, [0.5 * (ctrlPoint[0] + data[0]), 0.5 * (ctrlPoint[1]+ data[1])]);
addPoint(subPath, [0.5 * (data[0] + data[2]), 0.5 * (data[1] + data[3])]);
prevCtrlPoint = [data[2] - data[0], data[3] - data[1]];
break;
case 'A':
// Convert the arc to bezier curves and use the same approximation
var curves = a2c.apply(0, basePoint.concat(data));
for (var cData; (cData = curves.splice(0,6).map(toAbsolute)).length;) {
addPoint(subPath, [.5 * (basePoint[0] + cData[0]), .5 * (basePoint[1] + cData[1])]);
addPoint(subPath, [.5 * (cData[0] + cData[2]), .5 * (cData[1] + cData[3])]);
addPoint(subPath, [.5 * (cData[2] + cData[4]), .5 * (cData[3] + cData[5])]);
addPoint(subPath, [0.5 * (basePoint[0] + cData[0]), 0.5 * (basePoint[1] + cData[1])]);
addPoint(subPath, [0.5 * (cData[0] + cData[2]), 0.5 * (cData[1] + cData[3])]);
addPoint(subPath, [0.5 * (cData[2] + cData[4]), 0.5 * (cData[3] + cData[5])]);
if (curves.length) addPoint(subPath, basePoint = cData.slice(-2));
}
break;
@@ -773,7 +775,7 @@ function gatherPoints(points, item, index, path) {
if (data && data.length >= 2) addPoint(subPath, data.slice(-2));
return points;
function toAbsolute(n, i) { return n + basePoint[i % 2] }
function toAbsolute(n, i) { return n + basePoint[i % 2]; }
// Writes data about the extreme points on each axle
function addPoint(path, point) {
@@ -825,7 +827,7 @@ function convexHull(points) {
var upper = [],
maxY = points.length - 1,
top = 0;
for (var i = points.length; i--;) {
for (i = points.length; i--;) {
while (upper.length >= 2 && cross(upper[upper.length - 2], upper[upper.length - 1], points[i]) <= 0) {
upper.pop();
}
@@ -851,21 +853,25 @@ function convexHull(points) {
}
function cross(o, a, b) {
return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0])
return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
}
/* Based on code from Snap.svg (Apache 2 license). http://snapsvg.io/
* Thanks to Dmitry Baranovskiy for his great work!
*/
function a2c(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
function a2c(x1, y1, rx, ry, angle, largeArcFlag, sweepFlag, x2, y2, recursive) {
// for more information of where this Math came from visit:
// http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
var _120 = Math.PI * 120 / 180,
rad = Math.PI / 180 * (+angle || 0),
res = [],
rotateX = function(x, y, rad) { return x * Math.cos(rad) - y * Math.sin(rad) },
rotateY = function(x, y, rad) { return x * Math.sin(rad) + y * Math.cos(rad) };
rotateX = function(x, y, rad) { return x * Math.cos(rad) - y * Math.sin(rad); },
rotateY = function(x, y, rad) { return x * Math.sin(rad) + y * Math.cos(rad); },
cx,
cy,
f1,
f2;
if (!recursive) {
x1 = rotateX(x1, y1, -rad);
y1 = rotateY(x1, y1, -rad);
@@ -881,21 +887,23 @@ function a2c(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursiv
}
var rx2 = rx * rx,
ry2 = ry * ry,
k = (large_arc_flag == sweep_flag ? -1 : 1) *
Math.sqrt(Math.abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))),
cx = k * rx * y / ry + (x1 + x2) / 2,
cy = k * -ry * x / rx + (y1 + y2) / 2,
f1 = Math.asin(((y1 - cy) / ry).toFixed(9)),
k = (largeArcFlag == sweepFlag ? -1 : 1) *
Math.sqrt(Math.abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x)));
cx = k * rx * y / ry + (x1 + x2) / 2;
cy = k * -ry * x / rx + (y1 + y2) / 2;
f1 = Math.asin(((y1 - cy) / ry).toFixed(9));
f2 = Math.asin(((y2 - cy) / ry).toFixed(9));
f1 = x1 < cx ? Math.PI - f1 : f1;
f2 = x2 < cx ? Math.PI - f2 : f2;
f1 < 0 && (f1 = Math.PI * 2 + f1);
f2 < 0 && (f2 = Math.PI * 2 + f2);
if (sweep_flag && f1 > f2) {
if (sweepFlag && f1 > f2) {
f1 = f1 - Math.PI * 2;
}
if (!sweep_flag && f2 > f1) {
if (!sweepFlag && f2 > f1) {
f2 = f2 - Math.PI * 2;
}
} else {
@@ -909,10 +917,10 @@ function a2c(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursiv
var f2old = f2,
x2old = x2,
y2old = y2;
f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
f2 = f1 + _120 * (sweepFlag && f2 > f1 ? 1 : -1);
x2 = cx + rx * Math.cos(f2);
y2 = cy + ry * Math.sin(f2);
res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);
res = a2c(x2, y2, rx, ry, angle, 0, sweepFlag, x2old, y2old, [f2, f2old, cx, cy]);
}
df = f2 - f1;
var c1 = Math.cos(f1),

View File

@@ -61,7 +61,7 @@ exports.transformsMultiply = function(transforms) {
data: transforms.reduce(function(a, b) {
return multiplyTransformMatrices(a, b);
})
}
};
return transforms;
@@ -149,7 +149,6 @@ exports.matrixToTransform = function(transform, params) {
transforms.push({ name: 'scale', data: [sx, sy] });
}
var a1 = mth.acos(data[0] / sx, floatPrecision),
a2 = mth.asin(data[1] / (rowsSum ? sx : sy), floatPrecision),
rotate = [a1.toFixed(floatPrecision) * (data[1] < 0 ? -1 : 1)];
if (rotate[0]) transforms.push({ name: 'rotate', data: rotate });
@@ -157,7 +156,7 @@ exports.matrixToTransform = function(transform, params) {
if (rowsSum && colsSum) transforms.push({
name: 'skewX',
data: [mth.atan(colsSum / (sx * sx), floatPrecision)]
})
});
// rotate(a, cx, cy) can consume translate() within optional arguments cx, cy (rotation point)
if (rotate[0] && (data[4] || data[5])) {
@@ -226,7 +225,7 @@ function transformToMatrix(transform) {
return matrix;
};
}
/**
* Applies transformation to an arc. To do so, we represent ellipse as a matrix, multiply it

View File

@@ -13,8 +13,8 @@ exports.description = 'Add classnames to an outer <svg> element.';
*/
exports.fn = function(data, params) {
var classNames = params.classNames || [ params.className ]
var svg = data.content[0]
var classNames = params.classNames || [ params.className ];
var svg = data.content[0];
if (svg.isElem('svg')) {

View File

@@ -61,7 +61,7 @@ exports.fn = function(item) {
}
// collapse groups without attributes
if (!g.hasAttr() && !g.content.some(function(item) { return item.isElem(animationElems) })) {
if (!g.hasAttr() && !g.content.some(function(item) { return item.isElem(animationElems); })) {
item.spliceContent(i, 1, g.content);
}
}

View File

@@ -107,5 +107,5 @@ exports.fn = function(item, params) {
* @author Jed Schmidt
*/
function rgb2hex(rgb) {
return '#' + ("00000" + (rgb[0] << 16 | rgb[1] << 8 | rgb[2]).toString(16)).slice(-6).toUpperCase();
return '#' + ('00000' + (rgb[0] << 16 | rgb[1] << 8 | rgb[2]).toString(16)).slice(-6).toUpperCase();
}

View File

@@ -51,7 +51,7 @@ exports.fn = function(item, params) {
if (item.isElem(pathElems) && item.hasAttr('d')) {
precision = params.floatPrecision;
error = precision !== false ? +Math.pow(.1, precision).toFixed(precision) : 1e-2;
error = precision !== false ? +Math.pow(0.1, precision).toFixed(precision) : 1e-2;
hasMarkerMid = item.hasAttr('marker-mid');
var data = path2js(item);
@@ -263,8 +263,10 @@ function filters(path, params) {
if (data) {
var sdata;
if (instruction === 's') {
var sdata = [0, 0].concat(data);
sdata = [0, 0].concat(data);
if ('cs'.indexOf(prev.instruction) > -1) {
var pdata = prev.data,
@@ -639,9 +641,15 @@ function roundData(data) {
return data;
}
roundData = precision > 0 ? strongRound : round;
if (precision > 0) {
return roundData(data);
return strongRound(data);
} else {
return round(data);
}
}

View File

@@ -10,7 +10,7 @@ var EXTEND = require('whet.extend'),
stylingProps = require('./_collections').stylingProps,
rEscape = '\\\\(?:[0-9a-f]{1,6}\\s?|\\r\\n|.)', // Like \" or \2051. Code points consume one space.
rAttr = '\\s*(' + g('[^:;\\\\]', rEscape) + '*?)\\s*', // attribute name like fill
rSingleQuotes = "'(?:[^'\\n\\r\\\\]|" + rEscape + ")*?(?:'|$)", // string in single quotes: 'smth'
rSingleQuotes = '\'(?:[^\'\\n\\r\\\\]|' + rEscape + ')*?(?:\'|$)', // string in single quotes: 'smth'
rQuotes = '"(?:[^"\\n\\r\\\\]|' + rEscape + ')*?(?:"|$)', // string in double quotes: "smth"
rQuotedString = new RegExp('^' + g(rSingleQuotes, rQuotes) + '$'),
@@ -49,6 +49,7 @@ var EXTEND = require('whet.extend'),
* @author Kir Belevich
*/
exports.fn = function(item) {
/* jshint boss: true */
if (item.elem && item.hasAttr('style')) {
// ['opacity: 1', 'color: #000']
@@ -60,7 +61,7 @@ exports.fn = function(item) {
styleValue = styleValue.replace(regStripComments, function(match) {
return match[0] == '/' ? '' :
match[0] == '\\' && /[-g-z]/i.test(match[1]) ? match[1] : match;
})
});
regDeclarationBlock.lastIndex = 0;
for (var rule; rule = regDeclarationBlock.exec(styleValue);) {
@@ -98,7 +99,7 @@ exports.fn = function(item) {
if (styles.length) {
item.attr('style').value = styles
.map(function(declaration) { return declaration.join(':') })
.map(function(declaration) { return declaration.join(':'); })
.join(';');
} else {
item.removeAttr('style');

View File

@@ -108,6 +108,7 @@ function convertTransform(item, attrName, params) {
* @return {Array} output array
*/
function definePrecision(data, params) {
/* jshint validthis: true */
var matrixData = data.reduce(getMatrixData, []),
significantDigits = params.transformPrecision;
@@ -343,7 +344,7 @@ function round(data) {
* @return {Array} output data array
*/
function smartRound(precision, data) {
for (var i = data.length, tolerance = Math.pow(.1, precision); i--;) {
for (var i = data.length, tolerance = Math.pow(0.1, precision); i--;) {
var rounded = +data[i].toFixed(precision - 1);
data[i] = +Math.abs(rounded - data[i]).toFixed(precision) >= tolerance ?
+data[i].toFixed(precision) :

View File

@@ -37,7 +37,7 @@ exports.fn = function(item) {
item.hasAttr('transform') &&
!item.isEmpty() &&
!item.someAttr(function(attr) {
return ~referencesProps.indexOf(attr.name) && ~attr.value.indexOf('url(')
return ~referencesProps.indexOf(attr.name) && ~attr.value.indexOf('url(');
}) &&
item.content.every(function(inner) {
return inner.isElem(pathElems);

View File

@@ -1,4 +1,4 @@
"use strict";
'use strict';
exports.type = 'perItem';