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/plugins/convertOneStopGradients.js | |
| parent | 8d980c13970c15b6d2312b6fc4ac51698dd0d220 (diff) | |
updated node modules
Diffstat (limited to 'node_modules/svgo/plugins/convertOneStopGradients.js')
| -rw-r--r-- | node_modules/svgo/plugins/convertOneStopGradients.js | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/node_modules/svgo/plugins/convertOneStopGradients.js b/node_modules/svgo/plugins/convertOneStopGradients.js new file mode 100644 index 00000000..e5f4625d --- /dev/null +++ b/node_modules/svgo/plugins/convertOneStopGradients.js @@ -0,0 +1,168 @@ +'use strict'; + +/** + * @typedef {import('../lib/types').XastElement} XastElement + * @typedef {import('../lib/types').XastParent} XastParent + */ + +const { attrsGroupsDefaults, colorsProps } = require('./_collections'); +const { + detachNodeFromParent, + querySelectorAll, + querySelector, +} = require('../lib/xast'); +const { computeStyle, collectStylesheet } = require('../lib/style'); + +exports.name = 'convertOneStopGradients'; +exports.description = + 'converts one-stop (single color) gradients to a plain color'; + +/** + * Converts one-stop (single color) gradients to a plain color. + * + * @author Seth Falco <seth@falco.fun> + * @type {import('./plugins-types').Plugin<'convertOneStopGradients'>} + * @see https://developer.mozilla.org/docs/Web/SVG/Element/linearGradient + * @see https://developer.mozilla.org/docs/Web/SVG/Element/radialGradient + */ +exports.fn = (root) => { + const stylesheet = collectStylesheet(root); + + /** + * Parent defs that had gradients elements removed from them. + * + * @type {Set<XastElement>} + */ + const effectedDefs = new Set(); + + /** + * @type {Map<XastElement, XastParent>} + */ + const allDefs = new Map(); + + /** + * @type {Map<XastElement, XastParent>} + */ + const gradientsToDetach = new Map(); + + /** Number of references to the xlink:href attribute. */ + let xlinkHrefCount = 0; + + return { + element: { + enter: (node, parentNode) => { + if (node.attributes['xlink:href'] != null) { + xlinkHrefCount++; + } + + if (node.name === 'defs') { + allDefs.set(node, parentNode); + return; + } + + if (node.name !== 'linearGradient' && node.name !== 'radialGradient') { + return; + } + + const stops = node.children.filter((child) => { + return child.type === 'element' && child.name === 'stop'; + }); + + const href = node.attributes['xlink:href'] || node.attributes['href']; + let effectiveNode = + stops.length === 0 && href != null && href.startsWith('#') + ? querySelector(root, href) + : node; + + if (effectiveNode == null || effectiveNode.type !== 'element') { + gradientsToDetach.set(node, parentNode); + return; + } + + const effectiveStops = effectiveNode.children.filter((child) => { + return child.type === 'element' && child.name === 'stop'; + }); + + if ( + effectiveStops.length !== 1 || + effectiveStops[0].type !== 'element' + ) { + return; + } + + if (parentNode.type === 'element' && parentNode.name === 'defs') { + effectedDefs.add(parentNode); + } + + gradientsToDetach.set(node, parentNode); + + let color; + const style = computeStyle(stylesheet, effectiveStops[0])['stop-color']; + if (style != null && style.type === 'static') { + color = style.value; + } + + const selectorVal = `url(#${node.attributes.id})`; + + const selector = colorsProps + .map((attr) => `[${attr}="${selectorVal}"]`) + .join(','); + const elements = querySelectorAll(root, selector); + for (const element of elements) { + if (element.type !== 'element') { + continue; + } + + for (const attr of colorsProps) { + if (element.attributes[attr] !== selectorVal) { + continue; + } + + if (color != null) { + element.attributes[attr] = color; + } else { + delete element.attributes[attr]; + } + } + } + + const styledElements = querySelectorAll( + root, + `[style*=${selectorVal}]` + ); + for (const element of styledElements) { + if (element.type !== 'element') { + continue; + } + + element.attributes.style = element.attributes.style.replace( + selectorVal, + color || attrsGroupsDefaults.presentation['stop-color'] + ); + } + }, + + exit: (node) => { + if (node.name === 'svg') { + for (const [gradient, parent] of gradientsToDetach.entries()) { + if (gradient.attributes['xlink:href'] != null) { + xlinkHrefCount--; + } + + detachNodeFromParent(gradient, parent); + } + + if (xlinkHrefCount === 0) { + delete node.attributes['xmlns:xlink']; + } + + for (const [defs, parent] of allDefs.entries()) { + if (effectedDefs.has(defs) && defs.children.length === 0) { + detachNodeFromParent(defs, parent); + } + } + } + }, + }, + }; +}; |
