123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- 'use strict';
- const { detachNodeFromParent } = require('../lib/xast.js');
- const { collectStylesheet, computeStyle } = require('../lib/style.js');
- const { path2js, js2path, intersects } = require('./_path.js');
- exports.type = 'visitor';
- exports.name = 'mergePaths';
- exports.active = true;
- exports.description = 'merges multiple paths in one if possible';
- /**
- * Merge multiple Paths into one.
- *
- * @author Kir Belevich, Lev Solntsev
- *
- * @type {import('../lib/types').Plugin<{
- * force?: boolean,
- * floatPrecision?: number,
- * noSpaceAfterFlags?: boolean
- * }>}
- */
- 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;
- }
- },
- },
- };
- };
|