diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2023-12-21 22:46:53 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2023-12-21 22:46:53 +0800 |
| commit | f06956efd2dc4bf77244a9fcce2b883a00b925af (patch) | |
| tree | 0123cb73ce67f1f4b17e1d6cbabff076ee44e31b /node_modules/svgo/lib | |
| parent | 8d980c13970c15b6d2312b6fc4ac51698dd0d220 (diff) | |
updated node modules
Diffstat (limited to 'node_modules/svgo/lib')
| -rw-r--r-- | node_modules/svgo/lib/builtin.js | 2 | ||||
| -rw-r--r-- | node_modules/svgo/lib/parser.js | 2 | ||||
| -rw-r--r-- | node_modules/svgo/lib/path.js | 10 | ||||
| -rw-r--r-- | node_modules/svgo/lib/stringifier.js | 16 | ||||
| -rw-r--r-- | node_modules/svgo/lib/style.js | 95 | ||||
| -rw-r--r-- | node_modules/svgo/lib/svgo.d.ts | 7 | ||||
| -rw-r--r-- | node_modules/svgo/lib/svgo.js | 14 | ||||
| -rw-r--r-- | node_modules/svgo/lib/svgo/coa.js | 37 | ||||
| -rw-r--r-- | node_modules/svgo/lib/svgo/plugins.js | 2 | ||||
| -rw-r--r-- | node_modules/svgo/lib/svgo/tools.js | 92 | ||||
| -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.js | 5 |
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 = { '&': '&', "'": ''', @@ -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 |
