source: trip-planner-front/node_modules/svgo/plugins/moveElemsAttrsToGroup.js@ 6fe77af

Last change on this file since 6fe77af was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 3.7 KB
Line 
1'use strict';
2
3const { visit } = require('../lib/xast.js');
4const { inheritableAttrs, pathElems } = require('./_collections.js');
5
6exports.type = 'visitor';
7exports.name = 'moveElemsAttrsToGroup';
8exports.active = true;
9exports.description = 'Move common attributes of group children to the group';
10
11/**
12 * Move common attributes of group children to the group
13 *
14 * @example
15 * <g attr1="val1">
16 * <g attr2="val2">
17 * text
18 * </g>
19 * <circle attr2="val2" attr3="val3"/>
20 * </g>
21 * ⬇
22 * <g attr1="val1" attr2="val2">
23 * <g>
24 * text
25 * </g>
26 * <circle attr3="val3"/>
27 * </g>
28 *
29 * @author Kir Belevich
30 *
31 * @type {import('../lib/types').Plugin<void>}
32 */
33exports.fn = (root) => {
34 // find if any style element is present
35 let deoptimizedWithStyles = false;
36 visit(root, {
37 element: {
38 enter: (node) => {
39 if (node.name === 'style') {
40 deoptimizedWithStyles = true;
41 }
42 },
43 },
44 });
45
46 return {
47 element: {
48 exit: (node) => {
49 // process only groups with more than 1 children
50 if (node.name !== 'g' || node.children.length <= 1) {
51 return;
52 }
53
54 // deoptimize the plugin when style elements are present
55 // selectors may rely on id, classes or tag names
56 if (deoptimizedWithStyles) {
57 return;
58 }
59
60 /**
61 * find common attributes in group children
62 * @type {Map<string, string>}
63 */
64 const commonAttributes = new Map();
65 let initial = true;
66 let everyChildIsPath = true;
67 for (const child of node.children) {
68 if (child.type === 'element') {
69 if (pathElems.includes(child.name) === false) {
70 everyChildIsPath = false;
71 }
72 if (initial) {
73 initial = false;
74 // collect all inheritable attributes from first child element
75 for (const [name, value] of Object.entries(child.attributes)) {
76 // consider only inheritable attributes
77 if (inheritableAttrs.includes(name)) {
78 commonAttributes.set(name, value);
79 }
80 }
81 } else {
82 // exclude uncommon attributes from initial list
83 for (const [name, value] of commonAttributes) {
84 if (child.attributes[name] !== value) {
85 commonAttributes.delete(name);
86 }
87 }
88 }
89 }
90 }
91
92 // preserve transform on children when group has clip-path or mask
93 if (
94 node.attributes['clip-path'] != null ||
95 node.attributes.mask != null
96 ) {
97 commonAttributes.delete('transform');
98 }
99
100 // preserve transform when all children are paths
101 // so the transform could be applied to path data by other plugins
102 if (everyChildIsPath) {
103 commonAttributes.delete('transform');
104 }
105
106 // add common children attributes to group
107 for (const [name, value] of commonAttributes) {
108 if (name === 'transform') {
109 if (node.attributes.transform != null) {
110 node.attributes.transform = `${node.attributes.transform} ${value}`;
111 } else {
112 node.attributes.transform = value;
113 }
114 } else {
115 node.attributes[name] = value;
116 }
117 }
118
119 // delete common attributes from children
120 for (const child of node.children) {
121 if (child.type === 'element') {
122 for (const [name] of commonAttributes) {
123 delete child.attributes[name];
124 }
125 }
126 }
127 },
128 },
129 };
130};
Note: See TracBrowser for help on using the repository browser.