diff options
Diffstat (limited to 'node_modules/svgo/plugins/mergePaths.js')
| -rw-r--r-- | node_modules/svgo/plugins/mergePaths.js | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/node_modules/svgo/plugins/mergePaths.js b/node_modules/svgo/plugins/mergePaths.js new file mode 100644 index 00000000..05c7ac70 --- /dev/null +++ b/node_modules/svgo/plugins/mergePaths.js @@ -0,0 +1,98 @@ +'use strict'; + +const { detachNodeFromParent } = require('../lib/xast.js'); +const { collectStylesheet, computeStyle } = require('../lib/style.js'); +const { path2js, js2path, intersects } = require('./_path.js'); + +exports.name = 'mergePaths'; +exports.description = 'merges multiple paths in one if possible'; + +/** + * Merge multiple Paths into one. + * + * @author Kir Belevich, Lev Solntsev + * + * @type {import('./plugins-types').Plugin<'mergePaths'>} + */ +exports.fn = (root, params) => { + const { + force = false, + floatPrecision, + noSpaceAfterFlags = false, // a20 60 45 0 1 30 20 → a20 60 45 0130 20 + } = params; + const stylesheet = collectStylesheet(root); + + return { + element: { + enter: (node) => { + let prevChild = null; + + for (const child of node.children) { + // skip if previous element is not path or contains animation elements + if ( + prevChild == null || + prevChild.type !== 'element' || + prevChild.name !== 'path' || + prevChild.children.length !== 0 || + prevChild.attributes.d == null + ) { + prevChild = child; + continue; + } + + // skip if element is not path or contains animation elements + if ( + child.type !== 'element' || + child.name !== 'path' || + child.children.length !== 0 || + child.attributes.d == null + ) { + prevChild = child; + continue; + } + + // preserve paths with markers + const computedStyle = computeStyle(stylesheet, child); + if ( + computedStyle['marker-start'] || + computedStyle['marker-mid'] || + computedStyle['marker-end'] + ) { + prevChild = child; + continue; + } + + const prevChildAttrs = Object.keys(prevChild.attributes); + const childAttrs = Object.keys(child.attributes); + let attributesAreEqual = prevChildAttrs.length === childAttrs.length; + for (const name of childAttrs) { + if (name !== 'd') { + if ( + prevChild.attributes[name] == null || + prevChild.attributes[name] !== child.attributes[name] + ) { + attributesAreEqual = false; + } + } + } + const prevPathJS = path2js(prevChild); + const curPathJS = path2js(child); + + if ( + attributesAreEqual && + (force || !intersects(prevPathJS, curPathJS)) + ) { + js2path(prevChild, prevPathJS.concat(curPathJS), { + floatPrecision, + noSpaceAfterFlags, + }); + detachNodeFromParent(child, node); + continue; + } + + prevChild = child; + } + }, + }, + }; +}; |
