| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 | 
							- 'use strict';
 
- const { visit } = require('../lib/xast.js');
 
- const { inheritableAttrs, pathElems } = require('./_collections.js');
 
- exports.type = 'visitor';
 
- exports.name = 'moveElemsAttrsToGroup';
 
- exports.active = true;
 
- exports.description = 'Move common attributes of group children to the group';
 
- /**
 
-  * Move common attributes of group children to the group
 
-  *
 
-  * @example
 
-  * <g attr1="val1">
 
-  *     <g attr2="val2">
 
-  *         text
 
-  *     </g>
 
-  *     <circle attr2="val2" attr3="val3"/>
 
-  * </g>
 
-  *              ⬇
 
-  * <g attr1="val1" attr2="val2">
 
-  *     <g>
 
-  *         text
 
-  *     </g>
 
-  *    <circle attr3="val3"/>
 
-  * </g>
 
-  *
 
-  * @author Kir Belevich
 
-  *
 
-  * @type {import('../lib/types').Plugin<void>}
 
-  */
 
- exports.fn = (root) => {
 
-   // find if any style element is present
 
-   let deoptimizedWithStyles = false;
 
-   visit(root, {
 
-     element: {
 
-       enter: (node) => {
 
-         if (node.name === 'style') {
 
-           deoptimizedWithStyles = true;
 
-         }
 
-       },
 
-     },
 
-   });
 
-   return {
 
-     element: {
 
-       exit: (node) => {
 
-         // process only groups with more than 1 children
 
-         if (node.name !== 'g' || node.children.length <= 1) {
 
-           return;
 
-         }
 
-         // deoptimize the plugin when style elements are present
 
-         // selectors may rely on id, classes or tag names
 
-         if (deoptimizedWithStyles) {
 
-           return;
 
-         }
 
-         /**
 
-          * find common attributes in group children
 
-          * @type {Map<string, string>}
 
-          */
 
-         const commonAttributes = new Map();
 
-         let initial = true;
 
-         let everyChildIsPath = true;
 
-         for (const child of node.children) {
 
-           if (child.type === 'element') {
 
-             if (pathElems.includes(child.name) === false) {
 
-               everyChildIsPath = false;
 
-             }
 
-             if (initial) {
 
-               initial = false;
 
-               // collect all inheritable attributes from first child element
 
-               for (const [name, value] of Object.entries(child.attributes)) {
 
-                 // consider only inheritable attributes
 
-                 if (inheritableAttrs.includes(name)) {
 
-                   commonAttributes.set(name, value);
 
-                 }
 
-               }
 
-             } else {
 
-               // exclude uncommon attributes from initial list
 
-               for (const [name, value] of commonAttributes) {
 
-                 if (child.attributes[name] !== value) {
 
-                   commonAttributes.delete(name);
 
-                 }
 
-               }
 
-             }
 
-           }
 
-         }
 
-         // preserve transform on children when group has clip-path or mask
 
-         if (
 
-           node.attributes['clip-path'] != null ||
 
-           node.attributes.mask != null
 
-         ) {
 
-           commonAttributes.delete('transform');
 
-         }
 
-         // preserve transform when all children are paths
 
-         // so the transform could be applied to path data by other plugins
 
-         if (everyChildIsPath) {
 
-           commonAttributes.delete('transform');
 
-         }
 
-         // add common children attributes to group
 
-         for (const [name, value] of commonAttributes) {
 
-           if (name === 'transform') {
 
-             if (node.attributes.transform != null) {
 
-               node.attributes.transform = `${node.attributes.transform} ${value}`;
 
-             } else {
 
-               node.attributes.transform = value;
 
-             }
 
-           } else {
 
-             node.attributes[name] = value;
 
-           }
 
-         }
 
-         // delete common attributes from children
 
-         for (const child of node.children) {
 
-           if (child.type === 'element') {
 
-             for (const [name] of commonAttributes) {
 
-               delete child.attributes[name];
 
-             }
 
-           }
 
-         }
 
-       },
 
-     },
 
-   };
 
- };
 
 
  |