summaryrefslogtreecommitdiff
path: root/node_modules/svgo/lib
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2023-12-21 22:46:53 +0800
committerlittleblack111 <littleblack11111@gmail.com>2023-12-21 22:46:53 +0800
commitf06956efd2dc4bf77244a9fcce2b883a00b925af (patch)
tree0123cb73ce67f1f4b17e1d6cbabff076ee44e31b /node_modules/svgo/lib
parent8d980c13970c15b6d2312b6fc4ac51698dd0d220 (diff)
updated node modules
Diffstat (limited to 'node_modules/svgo/lib')
-rw-r--r--node_modules/svgo/lib/builtin.js2
-rw-r--r--node_modules/svgo/lib/parser.js2
-rw-r--r--node_modules/svgo/lib/path.js10
-rw-r--r--node_modules/svgo/lib/stringifier.js16
-rw-r--r--node_modules/svgo/lib/style.js95
-rw-r--r--node_modules/svgo/lib/svgo.d.ts7
-rw-r--r--node_modules/svgo/lib/svgo.js14
-rw-r--r--node_modules/svgo/lib/svgo/coa.js37
-rw-r--r--node_modules/svgo/lib/svgo/plugins.js2
-rw-r--r--node_modules/svgo/lib/svgo/tools.js92
-rw-r--r--node_modules/svgo/lib/types.d.ts (renamed from node_modules/svgo/lib/types.ts)0
-rw-r--r--node_modules/svgo/lib/xast.js5
12 files changed, 222 insertions, 60 deletions
diff --git a/node_modules/svgo/lib/builtin.js b/node_modules/svgo/lib/builtin.js
index e9fada7a..28a380ec 100644
--- a/node_modules/svgo/lib/builtin.js
+++ b/node_modules/svgo/lib/builtin.js
@@ -12,6 +12,7 @@ exports.builtin = [
require('../plugins/collapseGroups.js'),
require('../plugins/convertColors.js'),
require('../plugins/convertEllipseToCircle.js'),
+ require('../plugins/convertOneStopGradients.js'),
require('../plugins/convertPathData.js'),
require('../plugins/convertShapeToPath.js'),
require('../plugins/convertStyleToAttrs.js'),
@@ -47,6 +48,7 @@ exports.builtin = [
require('../plugins/removeUselessDefs.js'),
require('../plugins/removeUselessStrokeAndFill.js'),
require('../plugins/removeViewBox.js'),
+ require('../plugins/removeXlink.js'),
require('../plugins/removeXMLNS.js'),
require('../plugins/removeXMLProcInst.js'),
require('../plugins/reusePaths.js'),
diff --git a/node_modules/svgo/lib/parser.js b/node_modules/svgo/lib/parser.js
index 8c40eda0..aeed3f09 100644
--- a/node_modules/svgo/lib/parser.js
+++ b/node_modules/svgo/lib/parser.js
@@ -15,7 +15,7 @@
// @ts-ignore sax will be replaced with something else later
const SAX = require('@trysound/sax');
-const { textElems } = require('../plugins/_collections.js');
+const { textElems } = require('../plugins/_collections');
class SvgoParserError extends Error {
/**
diff --git a/node_modules/svgo/lib/path.js b/node_modules/svgo/lib/path.js
index 5a68e8fd..1e383dd9 100644
--- a/node_modules/svgo/lib/path.js
+++ b/node_modules/svgo/lib/path.js
@@ -1,5 +1,7 @@
'use strict';
+const { removeLeadingZero } = require('./svgo/tools');
+
/**
* @typedef {import('./types').PathDataItem} PathDataItem
* @typedef {import('./types').PathDataCommand} PathDataCommand
@@ -66,7 +68,7 @@ const isDigit = (c) => {
*/
/**
- * @type {(string: string, cursor: number) => [number, number | null]}
+ * @type {(string: string, cursor: number) => [number, ?number]}
*/
const readNumber = (string, cursor) => {
let i = cursor;
@@ -141,7 +143,7 @@ const parsePathData = (string) => {
*/
const pathData = [];
/**
- * @type {null | PathDataCommand}
+ * @type {?PathDataCommand}
*/
let command = null;
let args = /** @type {number[]} */ ([]);
@@ -226,7 +228,7 @@ const parsePathData = (string) => {
// flush arguments when necessary count is reached
if (args.length === argsCount) {
pathData.push({ command, args });
- // subsequent moveto coordinates are threated as implicit lineto commands
+ // subsequent moveto coordinates are treated as implicit lineto commands
if (command === 'M') {
command = 'L';
}
@@ -249,7 +251,7 @@ const stringifyNumber = (number, precision) => {
number = Math.round(number * ratio) / ratio;
}
// remove zero whole from decimal number
- return number.toString().replace(/^0\./, '.').replace(/^-0\./, '-.');
+ return removeLeadingZero(number);
};
/**
diff --git a/node_modules/svgo/lib/stringifier.js b/node_modules/svgo/lib/stringifier.js
index 26cff6c5..e50e723c 100644
--- a/node_modules/svgo/lib/stringifier.js
+++ b/node_modules/svgo/lib/stringifier.js
@@ -12,12 +12,12 @@
* @typedef {import('./types').StringifyOptions} StringifyOptions
*/
-const { textElems } = require('../plugins/_collections.js');
+const { textElems } = require('../plugins/_collections');
/**
* @typedef {{
* indent: string,
- * textContext: null | XastElement,
+ * textContext: ?XastElement,
* indentLevel: number,
* }} State
*/
@@ -33,9 +33,7 @@ const encodeEntity = (char) => {
return entities[char];
};
-/**
- * @type {Options}
- */
+/** @type {Options} */
const defaults = {
doctypeStart: '<!DOCTYPE',
doctypeEnd: '>',
@@ -58,16 +56,14 @@ const defaults = {
indent: 4,
regEntities: /[&'"<>]/g,
regValEntities: /[&"<>]/g,
- encodeEntity: encodeEntity,
+ encodeEntity,
pretty: false,
useShortTags: true,
eol: 'lf',
finalNewline: false,
};
-/**
- * @type {Record<string, string>}
- */
+/** @type {Record<string, string>} */
const entities = {
'&': '&amp;',
"'": '&apos;',
@@ -113,7 +109,7 @@ const stringifySvg = (data, userOptions = {}) => {
config.textEnd += eol;
}
let svg = stringifyNode(data, config, state);
- if (config.finalNewline && svg.length > 0 && svg[svg.length - 1] !== '\n') {
+ if (config.finalNewline && svg.length > 0 && !svg.endsWith('\n')) {
svg += eol;
}
return svg;
diff --git a/node_modules/svgo/lib/style.js b/node_modules/svgo/lib/style.js
index eb8d93d8..29e4a538 100644
--- a/node_modules/svgo/lib/style.js
+++ b/node_modules/svgo/lib/style.js
@@ -14,8 +14,9 @@
*/
const csstree = require('css-tree');
+const csswhat = require('css-what');
const {
- // @ts-ignore not defined in @types/csso
+ // @ts-ignore internal api
syntax: { specificity },
} = require('csso');
const { visit, matches } = require('./xast.js');
@@ -47,9 +48,7 @@ const parseRule = (ruleNode, dynamic) => {
}
});
- /**
- * @type {StylesheetRule[]}
- */
+ /** @type {StylesheetRule[]} */
const rules = [];
csstree.walk(ruleNode.prelude, (node) => {
if (node.type === 'Selector') {
@@ -78,9 +77,7 @@ const parseRule = (ruleNode, dynamic) => {
* @type {(css: string, dynamic: boolean) => Array<StylesheetRule>}
*/
const parseStylesheet = (css, dynamic) => {
- /**
- * @type {Array<StylesheetRule>}
- */
+ /** @type {Array<StylesheetRule>} */
const rules = [];
const ast = csstree.parse(css, {
parseValue: false,
@@ -92,7 +89,10 @@ const parseStylesheet = (css, dynamic) => {
return csstreeWalkSkip;
}
if (cssNode.type === 'Atrule') {
- if (cssNode.name === 'keyframes') {
+ if (
+ cssNode.name === 'keyframes' ||
+ cssNode.name === '-webkit-keyframes'
+ ) {
return csstreeWalkSkip;
}
csstree.walk(cssNode, (ruleNode) => {
@@ -111,9 +111,7 @@ const parseStylesheet = (css, dynamic) => {
* @type {(css: string) => Array<StylesheetDeclaration>}
*/
const parseStyleDeclarations = (css) => {
- /**
- * @type {Array<StylesheetDeclaration>}
- */
+ /** @type {Array<StylesheetDeclaration>} */
const declarations = [];
const ast = csstree.parse(css, {
context: 'declarationList',
@@ -135,9 +133,7 @@ const parseStyleDeclarations = (css) => {
* @type {(stylesheet: Stylesheet, node: XastElement) => ComputedStyles}
*/
const computeOwnStyle = (stylesheet, node) => {
- /**
- * @type {ComputedStyles}
- */
+ /** @type {ComputedStyles} */
const computedStyle = {};
const importantStyles = new Map();
@@ -197,10 +193,12 @@ const computeOwnStyle = (stylesheet, node) => {
};
/**
- * Compares two selector specificities.
- * extracted from https://github.com/keeganstreet/specificity/blob/main/specificity.js#L211
+ * Compares selector specificities.
+ * Derived from https://github.com/keeganstreet/specificity/blob/8757133ddd2ed0163f120900047ff0f92760b536/specificity.js#L207
*
- * @type {(a: Specificity, b: Specificity) => number}
+ * @param {Specificity} a
+ * @param {Specificity} b
+ * @returns {number}
*/
const compareSpecificity = (a, b) => {
for (let i = 0; i < 4; i += 1) {
@@ -213,18 +211,15 @@ const compareSpecificity = (a, b) => {
return 0;
};
+exports.compareSpecificity = compareSpecificity;
/**
* @type {(root: XastRoot) => Stylesheet}
*/
const collectStylesheet = (root) => {
- /**
- * @type {Array<StylesheetRule>}
- */
+ /** @type {Array<StylesheetRule>} */
const rules = [];
- /**
- * @type {Map<XastElement, XastParent>}
- */
+ /** @type {Map<XastElement, XastParent>} */
const parents = new Map();
visit(root, {
element: {
@@ -282,3 +277,57 @@ const computeStyle = (stylesheet, node) => {
return computedStyles;
};
exports.computeStyle = computeStyle;
+
+/**
+ * Determines if the CSS selector includes or traverses the given attribute.
+ *
+ * Classes and IDs are generated as attribute selectors, so you can check for
+ * if a `.class` or `#id` is included by passing `name=class` or `name=id`
+ * respectively.
+ *
+ * @param {csstree.ListItem<csstree.CssNode>|string} selector
+ * @param {string} name
+ * @param {?string} value
+ * @param {boolean} traversed
+ * @returns {boolean}
+ */
+const includesAttrSelector = (
+ selector,
+ name,
+ value = null,
+ traversed = false
+) => {
+ const selectors =
+ typeof selector === 'string'
+ ? csswhat.parse(selector)
+ : csswhat.parse(csstree.generate(selector.data));
+
+ for (const subselector of selectors) {
+ const hasAttrSelector = subselector.some((segment, index) => {
+ if (traversed) {
+ if (index === subselector.length - 1) {
+ return false;
+ }
+
+ const isNextTraversal = csswhat.isTraversal(subselector[index + 1]);
+
+ if (!isNextTraversal) {
+ return false;
+ }
+ }
+
+ if (segment.type !== 'attribute' || segment.name !== name) {
+ return false;
+ }
+
+ return value == null ? true : segment.value === value;
+ });
+
+ if (hasAttrSelector) {
+ return true;
+ }
+ }
+
+ return false;
+};
+exports.includesAttrSelector = includesAttrSelector;
diff --git a/node_modules/svgo/lib/svgo.d.ts b/node_modules/svgo/lib/svgo.d.ts
index a042db6c..d98d1293 100644
--- a/node_modules/svgo/lib/svgo.d.ts
+++ b/node_modules/svgo/lib/svgo.d.ts
@@ -30,7 +30,7 @@ export type Config = {
path?: string;
/** Pass over SVGs multiple times to ensure all optimizations are applied. */
multipass?: boolean;
- /** Precision of floating point numbers. Will be passed to each plugin that suppors this param. */
+ /** Precision of floating point numbers. Will be passed to each plugin that supports this param. */
floatPrecision?: number;
/**
* Plugins configuration
@@ -63,4 +63,7 @@ export declare function loadConfig(
configFile: string,
cwd?: string
): Promise<Config>;
-export declare function loadConfig(): Promise<Config | null>;
+export declare function loadConfig(
+ configFile?: null,
+ cwd?: string
+): Promise<Config | null>;
diff --git a/node_modules/svgo/lib/svgo.js b/node_modules/svgo/lib/svgo.js
index 8c5ca130..c19c0a40 100644
--- a/node_modules/svgo/lib/svgo.js
+++ b/node_modules/svgo/lib/svgo.js
@@ -65,12 +65,20 @@ const optimize = (input, config) => {
info.multipassCount = i;
const ast = parseSvg(input, config.path);
const plugins = config.plugins || ['preset-default'];
- if (Array.isArray(plugins) === false) {
+ if (!Array.isArray(plugins)) {
throw Error(
- "Invalid plugins list. Provided 'plugins' in config should be an array."
+ 'malformed config, `plugins` property must be an array.\nSee more info here: https://github.com/svg/svgo#configuration'
+ );
+ }
+ const resolvedPlugins = plugins
+ .filter((plugin) => plugin != null)
+ .map(resolvePluginConfig);
+
+ if (resolvedPlugins.length < plugins.length) {
+ console.warn(
+ 'Warning: plugins list includes null or undefined elements, these will be ignored.'
);
}
- const resolvedPlugins = plugins.map(resolvePluginConfig);
const globalOverrides = {};
if (config.floatPrecision != null) {
globalOverrides.floatPrecision = config.floatPrecision;
diff --git a/node_modules/svgo/lib/svgo/coa.js b/node_modules/svgo/lib/svgo/coa.js
index 52d640c4..c7f2c827 100644
--- a/node_modules/svgo/lib/svgo/coa.js
+++ b/node_modules/svgo/lib/svgo/coa.js
@@ -12,6 +12,7 @@ const regSVGFile = /\.svg$/i;
/**
* Synchronously check if path is a directory. Tolerant to errors like ENOENT.
+ *
* @param {string} path
*/
function checkIsDir(path) {
@@ -276,6 +277,7 @@ async function action(args, opts, command) {
/**
* Optimize SVG files in a directory.
+ *
* @param {Object} config options
* @param {string} dir input directory
* @param {string} output output directory
@@ -292,6 +294,7 @@ function optimizeFolder(config, dir, output) {
/**
* Process given files, take only SVG.
+ *
* @param {Object} config options
* @param {string} dir input directory
* @param {Array} files list of file names in the directory
@@ -318,7 +321,8 @@ function processDirectory(config, dir, files, output) {
}
/**
- * Get svg files descriptions
+ * Get SVG files descriptions.
+ *
* @param {Object} config options
* @param {string} dir input directory
* @param {Array} files list of file names in the directory
@@ -360,6 +364,7 @@ function getFilesDescriptions(config, dir, files, output) {
/**
* Read SVG file and pass to processing.
+ *
* @param {Object} config options
* @param {string} file
* @param {string} output
@@ -375,6 +380,7 @@ function optimizeFile(config, file, output) {
/**
* Optimize SVG data.
+ *
* @param {Object} config options
* @param {string} data SVG content to optimize
* @param {string} output where to write optimized file
@@ -425,6 +431,7 @@ function processSVGData(config, info, data, output, input) {
/**
* Write result of an optimization.
+ *
* @param {string} input
* @param {string} output output file name. '-' for stdout
* @param {string} data data to write
@@ -444,7 +451,8 @@ function writeOutput(input, output, data) {
}
/**
- * Write a time taken by optimization.
+ * Write time taken to optimize.
+ *
* @param {number} time time in milliseconds.
*/
function printTimeInfo(time) {
@@ -452,26 +460,28 @@ function printTimeInfo(time) {
}
/**
- * Write optimizing information in human readable format.
+ * Write optimizing stats in a human-readable format.
+ *
* @param {number} inBytes size before optimization.
* @param {number} outBytes size after optimization.
*/
function printProfitInfo(inBytes, outBytes) {
- var profitPercents = 100 - (outBytes * 100) / inBytes;
+ const profitPercent = 100 - (outBytes * 100) / inBytes;
+ /** @type {[string, Function]} */
+ const ui = profitPercent < 0 ? ['+', colors.red] : ['-', colors.green];
console.log(
- Math.round((inBytes / 1024) * 1000) / 1000 +
- ' KiB' +
- (profitPercents < 0 ? ' + ' : ' - ') +
- colors.green(Math.abs(Math.round(profitPercents * 10) / 10) + '%') +
- ' = ' +
- Math.round((outBytes / 1024) * 1000) / 1000 +
- ' KiB'
+ Math.round((inBytes / 1024) * 1000) / 1000 + ' KiB',
+ ui[0],
+ ui[1](Math.abs(Math.round(profitPercent * 10) / 10) + '%'),
+ '=',
+ Math.round((outBytes / 1024) * 1000) / 1000 + ' KiB'
);
}
/**
* Check for errors, if it's a dir optimize the dir.
+ *
* @param {Object} config
* @param {string} input
* @param {string} output
@@ -491,6 +501,7 @@ function checkOptimizeFileError(config, input, output, error) {
/**
* Check for saving file error. If the output is a dir, then write file there.
+ *
* @param {string} input
* @param {string} output
* @param {string} data
@@ -509,9 +520,7 @@ function checkWriteFileError(input, output, data, error) {
}
}
-/**
- * Show list of available plugins with short description.
- */
+/** Show list of available plugins with short description. */
function showAvailablePlugins() {
const list = builtin
.sort((a, b) => a.name.localeCompare(b.name))
diff --git a/node_modules/svgo/lib/svgo/plugins.js b/node_modules/svgo/lib/svgo/plugins.js
index 5719d163..efeb01b1 100644
--- a/node_modules/svgo/lib/svgo/plugins.js
+++ b/node_modules/svgo/lib/svgo/plugins.js
@@ -14,7 +14,7 @@ const { visit } = require('../xast.js');
*/
const invokePlugins = (ast, info, plugins, overrides, globalOverrides) => {
for (const plugin of plugins) {
- const override = overrides == null ? null : overrides[plugin.name];
+ const override = overrides?.[plugin.name];
if (override === false) {
continue;
}
diff --git a/node_modules/svgo/lib/svgo/tools.js b/node_modules/svgo/lib/svgo/tools.js
index 43bfee95..5e6bd69c 100644
--- a/node_modules/svgo/lib/svgo/tools.js
+++ b/node_modules/svgo/lib/svgo/tools.js
@@ -1,10 +1,17 @@
'use strict';
/**
+ * @typedef {import('../../lib/types').XastElement} XastElement
* @typedef {import('../types').PathDataCommand} PathDataCommand
* @typedef {import('../types').DataUri} DataUri
*/
+const { attrsGroups, referencesProps } = require('../../plugins/_collections');
+
+const regReferencesUrl = /\burl\((["'])?#(.+?)\1\)/g;
+const regReferencesHref = /^#(.+?)$/;
+const regReferencesBegin = /(\w+)\.[a-zA-Z]/;
+
/**
* Encode plain SVG data string into Data URI string.
*
@@ -136,3 +143,88 @@ const removeLeadingZero = (num) => {
return strNum;
};
exports.removeLeadingZero = removeLeadingZero;
+
+/**
+ * If the current node contains any scripts. This does not check parents or
+ * children of the node, only the properties and attributes of the node itself.
+ *
+ * @param {XastElement} node Current node to check against.
+ * @returns {boolean} If the current node contains scripts.
+ */
+const hasScripts = (node) => {
+ if (node.name === 'script' && node.children.length !== 0) {
+ return true;
+ }
+
+ if (node.name === 'a') {
+ const hasJsLinks = Object.entries(node.attributes).some(
+ ([attrKey, attrValue]) =>
+ (attrKey === 'href' || attrKey.endsWith(':href')) &&
+ attrValue != null &&
+ attrValue.trimStart().startsWith('javascript:')
+ );
+
+ if (hasJsLinks) {
+ return true;
+ }
+ }
+
+ const eventAttrs = [
+ ...attrsGroups.animationEvent,
+ ...attrsGroups.documentEvent,
+ ...attrsGroups.documentElementEvent,
+ ...attrsGroups.globalEvent,
+ ...attrsGroups.graphicalEvent,
+ ];
+
+ return eventAttrs.some((attr) => node.attributes[attr] != null);
+};
+exports.hasScripts = hasScripts;
+
+/**
+ * For example, a string that contains one or more of following would match and
+ * return true:
+ *
+ * * `url(#gradient001)`
+ * * `url('#gradient001')`
+ *
+ * @param {string} body
+ * @returns {boolean} If the given string includes a URL reference.
+ */
+const includesUrlReference = (body) => {
+ return new RegExp(regReferencesUrl).test(body);
+};
+exports.includesUrlReference = includesUrlReference;
+
+/**
+ * @param {string} attribute
+ * @param {string} value
+ * @returns {string[]}
+ */
+const findReferences = (attribute, value) => {
+ const results = [];
+
+ if (referencesProps.includes(attribute)) {
+ const matches = value.matchAll(regReferencesUrl);
+ for (const match of matches) {
+ results.push(match[2]);
+ }
+ }
+
+ if (attribute === 'href' || attribute.endsWith(':href')) {
+ const match = regReferencesHref.exec(value);
+ if (match != null) {
+ results.push(match[1]);
+ }
+ }
+
+ if (attribute === 'begin') {
+ const match = regReferencesBegin.exec(value);
+ if (match != null) {
+ results.push(match[1]);
+ }
+ }
+
+ return results.map((body) => decodeURI(body));
+};
+exports.findReferences = findReferences;
diff --git a/node_modules/svgo/lib/types.ts b/node_modules/svgo/lib/types.d.ts
index f6260c6a..f6260c6a 100644
--- a/node_modules/svgo/lib/types.ts
+++ b/node_modules/svgo/lib/types.d.ts
diff --git a/node_modules/svgo/lib/xast.js b/node_modules/svgo/lib/xast.js
index 49edf692..7f14e2a8 100644
--- a/node_modules/svgo/lib/xast.js
+++ b/node_modules/svgo/lib/xast.js
@@ -24,7 +24,7 @@ const querySelectorAll = (node, selector) => {
exports.querySelectorAll = querySelectorAll;
/**
- * @type {(node: XastNode, selector: string) => null | XastChild}
+ * @type {(node: XastNode, selector: string) => ?XastChild}
*/
const querySelector = (node, selector) => {
return selectOne(selector, node, cssSelectOptions);
@@ -77,7 +77,8 @@ const visit = (node, visitor, parentNode) => {
exports.visit = visit;
/**
- * @type {(node: XastChild, parentNode: XastParent) => void}
+ * @param {XastChild} node
+ * @param {XastParent} parentNode
*/
const detachNodeFromParent = (node, parentNode) => {
// avoid splice to not break for loops