Comparing version 0.4.4 to 0.4.5
@@ -148,2 +148,8 @@ 'use strict'; | ||
// --output | ||
if (opts.output) { | ||
config = config || {}; | ||
config.output = opts.output; | ||
} | ||
// --folder | ||
@@ -374,2 +380,3 @@ if (opts.folder) { | ||
var filepath = PATH.resolve(path, file); | ||
var outfilepath = config.output ? PATH.resolve(config.output, file) : filepath; | ||
@@ -400,3 +407,3 @@ // check if file name matches *.svg | ||
FS.writeFile(filepath, result.data, 'utf8', function() { | ||
FS.writeFile(outfilepath, result.data, 'utf8', function() { | ||
@@ -411,2 +418,7 @@ UTIL.puts(file + ':'); | ||
//move on to the next file | ||
if (++i < files.length) { | ||
optimizeFile(files[i]); | ||
} | ||
}); | ||
@@ -419,7 +431,8 @@ | ||
} | ||
if (++i < files.length) { | ||
optimizeFile(files[i]); | ||
//move on to the next file | ||
else if (++i < files.length) { | ||
optimizeFile(files[i]); | ||
} | ||
} | ||
@@ -426,0 +439,0 @@ |
@@ -262,3 +262,3 @@ 'use strict'; | ||
this.config.attrStart + | ||
attr.value + | ||
String(attr.value).replace(/"/g, '"') + | ||
this.config.attrEnd; | ||
@@ -265,0 +265,0 @@ |
{ | ||
"name": "svgo", | ||
"version": "0.4.4", | ||
"version": "0.4.5", | ||
"description": "Nodejs-based tool for optimizing SVG vector graphics files", | ||
"keywords": [ "svgo", "svg", "optimize", "minify" ], | ||
"homepage": "http://svg.github.com/svgo/", | ||
"homepage": "https://github.com/svg/svgo", | ||
"bugs": { | ||
@@ -20,2 +20,6 @@ "url": "https://github.com/svg/svgo/issues", | ||
"url": "http://github.com/arikon" | ||
}, { | ||
"name": "Lev Solntsev", | ||
"email": "lev.sun@ya.ru", | ||
"url": "http://github.com/GreLI" | ||
}], | ||
@@ -43,3 +47,3 @@ "repository": { | ||
"colors": "~0.6.0", | ||
"whet.extend": "" | ||
"whet.extend": "~0.9.9" | ||
}, | ||
@@ -50,4 +54,4 @@ "devDependencies": { | ||
"istanbul": "~0.2.0", | ||
"mocha-istanbul": "", | ||
"coveralls": "" | ||
"mocha-istanbul": "~0.2.0", | ||
"coveralls": "~2.11.1" | ||
}, | ||
@@ -54,0 +58,0 @@ "engines": { |
@@ -2060,2 +2060,3 @@ 'use strict'; | ||
'http://www.inkscape.org/namespaces/inkscape', | ||
'http://www.bohemiancoding.com/sketch/ns', | ||
'http://ns.adobe.com/AdobeIllustrator/10.0/', | ||
@@ -2062,0 +2063,0 @@ 'http://ns.adobe.com/Graphs/1.0/', |
@@ -257,4 +257,4 @@ 'use strict'; | ||
newPoint = transformPoint(matrix.data, pathItem.data[0], pathItem.data[1]); | ||
pathItem.data[0] = newPoint[0]; | ||
pathItem.data[1] = newPoint[1]; | ||
pathItem.data[0] = pathItem.coords[0] = newPoint[0]; | ||
pathItem.data[1] = pathItem.coords[1] = newPoint[1]; | ||
@@ -273,2 +273,5 @@ // clear translate() data from transform matrix | ||
pathItem.coords[0] = pathItem.base[0] + pathItem.data[pathItem.data.length - 2] | ||
pathItem.coords[1] = pathItem.base[1] + pathItem.data[pathItem.data.length - 1] | ||
} | ||
@@ -275,0 +278,0 @@ |
@@ -9,3 +9,4 @@ 'use strict'; | ||
remove: true, | ||
minify: true | ||
minify: true, | ||
prefix: '' | ||
}; | ||
@@ -127,3 +128,3 @@ | ||
currentIDstring = getIDstring(currentID = generateID(currentID)); | ||
currentIDstring = getIDstring(currentID = generateID(currentID), params); | ||
IDs[k].attr('id').value = currentIDstring; | ||
@@ -195,5 +196,5 @@ | ||
*/ | ||
function getIDstring(arr) { | ||
function getIDstring(arr, params) { | ||
var str = ''; | ||
var str = params.prefix; | ||
@@ -200,0 +201,0 @@ arr.forEach(function(i) { |
@@ -16,2 +16,3 @@ 'use strict'; | ||
collapseRepeated: true, | ||
utilizeAbsolute: true, | ||
leadingZero: true, | ||
@@ -25,2 +26,5 @@ negativeExtraSpace: true | ||
applyTransforms = require('./_path.js').applyTransforms, | ||
cleanupOutData = require('../lib/svgo/tools').cleanupOutData, | ||
precision, | ||
error, | ||
hasMarkerMid; | ||
@@ -48,2 +52,4 @@ | ||
precision = params.floatPrecision; | ||
error = precision !== false ? +Math.pow(.1, precision).toFixed(precision) : 1e-2; | ||
hasMarkerMid = item.hasAttr('marker-mid'); | ||
@@ -53,6 +59,5 @@ | ||
// TODO: get rid of functions returns | ||
if (data.length) { | ||
data = convertToRelative(data); | ||
convertToRelative(data); | ||
@@ -69,2 +74,6 @@ if (params.applyTransforms) { | ||
if (params.utilizeAbsolute) { | ||
data = convertToMixed(data, params); | ||
} | ||
item.pathJS = data; | ||
@@ -88,17 +97,11 @@ | ||
var instruction, | ||
data, | ||
newPoint, | ||
point = [0, 0], | ||
var point = [0, 0], | ||
subpathPoint = [0, 0], | ||
index = 0, | ||
mM = false; | ||
path.forEach(function(item) { | ||
path.forEach(function(item, index) { | ||
instruction = item.instruction; | ||
data = item.data; | ||
var instruction = item.instruction, | ||
data = item.data; | ||
index++; | ||
// data !== !z | ||
@@ -111,3 +114,3 @@ if (data) { | ||
newPoint = data.slice(-2); | ||
var newPoint = data.slice(-2); | ||
@@ -118,3 +121,3 @@ point[0] += newPoint[0]; | ||
if (instruction === 'm') { | ||
if (index === 1) { | ||
if (index === 0) { | ||
instruction = 'M'; | ||
@@ -138,19 +141,18 @@ mM = true; | ||
// convert absolute path data coordinates to relative | ||
// if "M" was not transformed from "m" | ||
// M → m | ||
if (instruction === 'M') { | ||
if ( | ||
instruction === 'M' && | ||
(!mM || index > 0) | ||
) { | ||
if (index > 1) { | ||
instruction = 'm'; | ||
} | ||
if (index > 0) instruction = 'm'; | ||
// if "M" was not transformed from "m" | ||
if (!mM) { | ||
data[0] -= point[0]; | ||
data[1] -= point[1]; | ||
data[0] -= point[0]; | ||
data[1] -= point[1]; | ||
point[0] += data[0]; | ||
point[1] += data[1]; | ||
point[0] += data[0]; | ||
point[1] += data[1]; | ||
subpathPoint = point.slice(-2); | ||
} | ||
subpathPoint = point.slice(-2); | ||
@@ -242,2 +244,5 @@ } | ||
// store absolute coordinates for later use | ||
item.coords = point.slice(-2); | ||
} | ||
@@ -247,2 +252,3 @@ | ||
else { | ||
item.coords = subpathPoint.slice(0); | ||
point = subpathPoint; | ||
@@ -252,2 +258,4 @@ mM = false; | ||
item.base = index > 0 ? path[index - 1].coords : [0, 0]; | ||
}); | ||
@@ -268,4 +276,4 @@ | ||
var instruction, | ||
data, | ||
var relSubpoint = [0, 0], | ||
pathBase = [0, 0], | ||
prev; | ||
@@ -275,11 +283,53 @@ | ||
instruction = item.instruction; | ||
data = item.data; | ||
var instruction = item.instruction, | ||
data = item.data; | ||
if (data) { | ||
if (params.floatPrecision !== false) { | ||
data = roundData(data, params.floatPrecision); | ||
if (instruction === 's') { | ||
var sdata = [0, 0].concat(data); | ||
if (prev && 'cs'.indexOf(prev.instruction) > -1) { | ||
var pdata = prev.data, | ||
n = pdata.length; | ||
// (-x, -y) of the prev tangent point relative to the current point | ||
sdata[0] = pdata[n - 2] - pdata[n - 4]; | ||
sdata[1] = pdata[n - 1] - pdata[n - 3]; | ||
} | ||
} | ||
// Rounding relative coordinates, taking in account accummulating error | ||
// to get closer to absolute coordinates. Sum of rounded value remains same: | ||
// l .25 3 .25 2 .25 3 .25 2 -> l .3 3 .2 2 .3 3 .2 2 | ||
if (precision !== false) { | ||
if ('mltqsc'.indexOf(instruction) > -1) { | ||
for (var i = data.length; i--;) { | ||
data[i] += item.base[i % 2] - relSubpoint[i % 2]; | ||
} | ||
} else if (instruction == 'h') { | ||
data[0] += item.base[0] - relSubpoint[0]; | ||
} else if (instruction == 'v') { | ||
data[0] += item.base[1] - relSubpoint[1]; | ||
} else if (instruction == 'a') { | ||
data[5] += item.base[0] - relSubpoint[0]; | ||
data[6] += item.base[1] - relSubpoint[1]; | ||
} | ||
roundData(data); | ||
if (instruction == 'h') relSubpoint[0] += data[0]; | ||
else if (instruction == 'v') relSubpoint[1] += data[0]; | ||
else { | ||
relSubpoint[0] += data[data.length - 2]; | ||
relSubpoint[1] += data[data.length - 1]; | ||
} | ||
roundData(relSubpoint); | ||
if (instruction.toLowerCase() == 'm') { | ||
pathBase[0] = relSubpoint[0]; | ||
pathBase[1] = relSubpoint[1]; | ||
} | ||
} | ||
// convert straight curves into lines segments | ||
@@ -301,14 +351,11 @@ if (params.straightCurves) { | ||
// s | ||
else if (instruction === 's') { | ||
if ( | ||
isCurveStraightLine( | ||
[ 0, data[0], data[2] ], | ||
[ 0, data[1], data[3] ] | ||
) | ||
) { | ||
instruction = 'l'; | ||
data = data.slice(-2); | ||
} | ||
else if ( | ||
instruction === 's' && | ||
isCurveStraightLine( | ||
[ 0, sdata[0], sdata[2], sdata[4] ], | ||
[ 0, sdata[1], sdata[3], sdata[5] ] | ||
) | ||
) { | ||
instruction = 'l'; | ||
data = data.slice(-2); | ||
} | ||
@@ -382,6 +429,6 @@ | ||
instruction = 'h'; | ||
data = [data[0]]; | ||
data.pop(); | ||
} else if (data[0] === 0) { | ||
instruction = 'v'; | ||
data = [data[1]]; | ||
data.shift(); | ||
} | ||
@@ -458,3 +505,3 @@ } | ||
// m 0,0 / 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 | ||
// 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 | ||
if ( | ||
@@ -485,2 +532,8 @@ ( | ||
} else { | ||
// z resets coordinates | ||
relSubpoint[0] = pathBase[0]; | ||
relSubpoint[1] = pathBase[1]; | ||
} | ||
@@ -497,2 +550,77 @@ | ||
/** | ||
* Writes data in shortest form using absolute or relative coordinates. | ||
* | ||
* @param {Array} data input path data | ||
* @return {Boolean} output | ||
*/ | ||
function convertToMixed(path, params) { | ||
var currentPoint = [0, 0], | ||
prev = path[0]; | ||
path = path.filter(function(item, index) { | ||
if (index == 0) return true; | ||
if (!item.data) { | ||
prev = item; | ||
return true; | ||
} | ||
var instruction = item.instruction, | ||
data = item.data, | ||
adata = data && data.slice(0); | ||
if ('mltqsc'.indexOf(instruction) > -1) { | ||
for (var i = adata.length; i--;) { | ||
adata[i] += item.base[i % 2]; | ||
} | ||
} else if (instruction == 'h') { | ||
adata[0] += item.base[0]; | ||
} else if (instruction == 'v') { | ||
adata[0] += item.base[1]; | ||
} else if (instruction == 'a') { | ||
adata[5] += item.base[0]; | ||
adata[6] += item.base[1]; | ||
} | ||
roundData(adata); | ||
var absoluteDataStr = cleanupOutData(adata, params), | ||
relativeDataStr = cleanupOutData(data, params); | ||
// Convert to absolute coordinates if it's shorter. | ||
// v-20 -> V0 | ||
// Don't convert if it fits following previous instruction. | ||
// l20 30-10-50 instead of l20 30L20 30 | ||
if ( | ||
absoluteDataStr.length < relativeDataStr.length && | ||
!( | ||
params.negativeExtraSpace && instruction == prev.instruction && | ||
absoluteDataStr.length == relativeDataStr.length - 1 && | ||
(data[0] < 0 || 0 < data[0] && data[0] < 1 && prev.data[prev.data.length - 1] % 1) | ||
) | ||
) { | ||
if (instruction.toUpperCase() != prev.instruction) { | ||
item.instruction = instruction.toUpperCase(); | ||
item.data = adata; | ||
} else { | ||
prev.data = prev.data.concat(adata); | ||
return false; | ||
} | ||
} else if (instruction == prev.instruction) { | ||
prev.data = prev.data.concat(data); | ||
return false; | ||
} | ||
prev = item; | ||
return true; | ||
}); | ||
return path; | ||
} | ||
/** | ||
* Collapse repeated instructions data | ||
@@ -503,3 +631,3 @@ * | ||
*/ | ||
function collapseRepeated(path) { | ||
function collapseRepeated(path, params) { | ||
@@ -513,14 +641,20 @@ var prev; | ||
prev && | ||
item.instruction === prev.instruction | ||
item.instruction === prev.instruction && | ||
( | ||
!item.data || | ||
'hv'.indexOf(item.instruction) > -1 && (prev.data[0] >= 0) == (item.data[0] >= 0) || | ||
!params.utilizeAbsolute | ||
) | ||
) { | ||
// increase previous h or v data with current | ||
if ((item.instruction === 'h' || item.instruction === 'v') && (prev.data[0] >= 0) == (item.data[0] >= 0)) { | ||
if ('hv'.indexOf(item.instruction) > -1) { | ||
prev.data[0] += item.data[0]; | ||
// concat previous data with current if it is not z | ||
} else if (item.instruction !== 'z') { | ||
} else if (item.data) { | ||
prev.data = prev.data.concat(item.data); | ||
} | ||
// filter current item | ||
// filter out current item | ||
return false; | ||
} | ||
@@ -541,2 +675,3 @@ | ||
* in path data keeping a specified number of decimals. | ||
* Smart rounds values like 2.349 to 2.35. | ||
* | ||
@@ -547,15 +682,31 @@ * @param {Array} data input data array | ||
*/ | ||
function roundData(data, fixed) { | ||
function roundData(data) { | ||
return data.map(function(num) { | ||
return +num.toFixed(fixed); | ||
}); | ||
function round(data) { | ||
for (var i = data.length; i--;) { | ||
data[i] = +data[i].toFixed(precision) | ||
} | ||
return data; | ||
} | ||
function strongRound(data) { | ||
for (var i = data.length; i--;) { | ||
var rounded = +data[i].toFixed(precision - 1); | ||
data[i] = +Math.abs(rounded - data[i]).toFixed(precision) > error ? | ||
+data[i].toFixed(precision) : | ||
rounded; | ||
} | ||
return data; | ||
} | ||
roundData = precision > 0 ? strongRound : round; | ||
return roundData(data); | ||
} | ||
/** | ||
* Checks if curve is a straight line by calculating a polygon area. | ||
* Checks if a curve is a straight line by measuring distance | ||
* from middle points to the line formed by end points. | ||
* | ||
* @see http://www.mathopenref.com/coordpolygonarea2.html | ||
* | ||
* @param {Array} xs array of curve points x-coordinates | ||
@@ -568,15 +719,19 @@ * @param {Array} ys array of curve points y-coordinates | ||
var points = xs.length, | ||
area = 0, | ||
j = points - 1; | ||
// 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 | ||
d = 1 / (a * a + b * b); // same part for all points | ||
for (var i=0; i < points; i++) { | ||
area += (xs[j] + xs[i]) * (ys[j] - ys[i]); | ||
j = i; | ||
if (!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) | ||
return false; | ||
} | ||
if (+area.toFixed(2)) return false; | ||
return true; | ||
} |
@@ -10,2 +10,6 @@ 'use strict'; | ||
exports.params = { | ||
additionalNamespaces: [] | ||
}; | ||
/** | ||
@@ -20,2 +24,3 @@ * Remove editors namespaces, elements and attributes. | ||
* @param {Object} item current iteration item | ||
* @param {Object} params plugin params | ||
* @return {Boolean} if false, item will be filtered out | ||
@@ -25,4 +30,8 @@ * | ||
*/ | ||
exports.fn = function(item) { | ||
exports.fn = function(item, params) { | ||
if (Array.isArray(params.additionalNamespaces)) { | ||
editorNamespaces = editorNamespaces.concat(params.additionalNamespaces); | ||
} | ||
if (item.elem) { | ||
@@ -29,0 +38,0 @@ |
@@ -26,3 +26,3 @@ **english** | [русский](https://github.com/svg/svgo/blob/master/README.ru.md) | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/removeMetadata.js) ] remove `<metadata>` | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/removeTitle.js) ] remove `<title>` | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/removeTitle.js) ] remove `<title>` (disabled by default) | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/removeEditorsNSData.js) ] remove editors namespaces, elements and attributes | ||
@@ -33,10 +33,11 @@ * [ [>](https://github.com/svg/svgo/blob/master/plugins/removeEmptyAttrs.js) ] remove empty attributes | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/removeEmptyContainers.js) ] remove empty Container elements | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/removeViewBox.js) ] remove `viewBox` attribute when possible | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/removeViewBox.js) ] remove `viewBox` attribute when possible (disabled by default) | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/cleanupEnableBackground.js) ] remove or cleanup `enable-background` attribute when possible | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/convertStyleToAttrs.js) ] convert styles into attributes | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/convertColors.js) ] convert colors (from `rgb()` to `#rrggbb`, from `#rrggbb` to `#rgb`) | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/convertPathData.js) ] convert Path data to relative, convert one segment to another, trim useless delimiters and much more | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/convertPathData.js) ] convert Path data to relative or absolute whichever is shorter, convert one segment to another, trim useless delimiters, smart rounding and much more | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/convertTransform.js) ] collapse multiple transforms into one, convert matrices to the short aliases and much more | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/removeUnknownsAndDefaults.js) ] remove unknown elements content and attributes, remove attrs with default values | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/removeNonInheritableGroupAttrs.js) ] remove non-inheritable group's "presentation" attributes | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/removeUselessStrokeAndFill.js) ] remove useless stroke and fill attrs. | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/removeUnusedNS.js) ] remove unused namespaces declaration | ||
@@ -51,3 +52,4 @@ * [ [>](https://github.com/svg/svgo/blob/master/plugins/cleanupIDs.js) ] remove unused and minify used IDs | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/convertShapeToPath.js) ] convert some basic shapes to path | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/transformsWithOnePath.js) ] apply transforms, crop by real width, center vertical alignment and resize SVG with one Path inside | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/sortAttrs.js) ] sort element attributes for epic readability (disabled by default) | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/transformsWithOnePath.js) ] apply transforms, crop by real width, center vertical alignment and resize SVG with one Path inside (disabled by default) | ||
@@ -123,4 +125,9 @@ 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). | ||
* as a Gulp task – [gulp-svgmin](https://github.com/ben-eb/gulp-svgmin) | ||
* as a Mimosa module – [mimosa-minify-svg](https://github.com/dbashford/mimosa-minify-svg) | ||
* as an OSX Folder Action – [svgo-osx-folder-action](https://github.com/svg/svgo-osx-folder-action) | ||
## Donate | ||
BTC `1zVZYqRSzQ4aaL27rp3PLwFFSXpfs5H8r` | ||
## License and copyrights | ||
@@ -127,0 +134,0 @@ |
@@ -36,3 +36,3 @@ [english](https://github.com/svg/svgo/blob/master/README.md) | **русский** | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/convertColors.js) ] конвертирование цветовых значений: из `rgb()` в `#rrggbb`, из `#rrggbb` в `#rgb` | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/convertPathData.js) ] конвертирование данных Path в относительные координаты, конвертирование одних типов сегментов в другие, удаление ненужных разделителей и тому подобное | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/convertPathData.js) ] конвертирование данных Path в относительные или абсолютные координаты, смотря что короче, конвертирование одних типов сегментов в другие, удаление ненужных разделителей, умное округление и тому подобное | ||
* [ [>](https://github.com/svg/svgo/blob/master/plugins/convertTransform.js) ] схлопывание нескольких трансформаций в одну, конвертирование матриц в короткие алиасы и многое другое | ||
@@ -121,4 +121,9 @@ * [ [>](https://github.com/svg/svgo/blob/master/plugins/removeUnknownsAndDefaults.js) ] удаление неизвестных элементов, контента и атрибутов | ||
* как таск для Gulp – [gulp-svgmin](https://github.com/ben-eb/gulp-svgmin) | ||
* как таск для Mimosa – [mimosa-minify-svg](https://github.com/dbashford/mimosa-minify-svg) | ||
* как действие папки в OSX – [svgo-osx-folder-action](https://github.com/svg/svgo-osx-folder-action) | ||
## Пожертвования | ||
BTC `1zVZYqRSzQ4aaL27rp3PLwFFSXpfs5H8r` | ||
## Лицензия и копирайты | ||
@@ -125,0 +130,0 @@ |
Sorry, the diff of this file is not supported yet
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
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
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
Wildcard dependency
QualityPackage has a dependency with a floating version range. This can cause issues if the dependency publishes a new major version.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
375365
59
8379
1
0
134
8
7
Updatedwhet.extend@~0.9.9