source: trip-planner-front/node_modules/svgo/plugins/removeHiddenElems.js@ ceaed42

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

initial commit

  • Property mode set to 100644
File size: 9.1 KB
Line 
1'use strict';
2
3const {
4 querySelector,
5 closestByName,
6 detachNodeFromParent,
7} = require('../lib/xast.js');
8const { collectStylesheet, computeStyle } = require('../lib/style.js');
9const { parsePathData } = require('../lib/path.js');
10
11exports.name = 'removeHiddenElems';
12exports.type = 'visitor';
13exports.active = true;
14exports.description =
15 'removes hidden elements (zero sized, with absent attributes)';
16
17/**
18 * Remove hidden elements with disabled rendering:
19 * - display="none"
20 * - opacity="0"
21 * - circle with zero radius
22 * - ellipse with zero x-axis or y-axis radius
23 * - rectangle with zero width or height
24 * - pattern with zero width or height
25 * - image with zero width or height
26 * - path with empty data
27 * - polyline with empty points
28 * - polygon with empty points
29 *
30 * @author Kir Belevich
31 *
32 * @type {import('../lib/types').Plugin<{
33 * isHidden: boolean,
34 * displayNone: boolean,
35 * opacity0: boolean,
36 * circleR0: boolean,
37 * ellipseRX0: boolean,
38 * ellipseRY0: boolean,
39 * rectWidth0: boolean,
40 * rectHeight0: boolean,
41 * patternWidth0: boolean,
42 * patternHeight0: boolean,
43 * imageWidth0: boolean,
44 * imageHeight0: boolean,
45 * pathEmptyD: boolean,
46 * polylineEmptyPoints: boolean,
47 * polygonEmptyPoints: boolean,
48 * }>}
49 */
50exports.fn = (root, params) => {
51 const {
52 isHidden = true,
53 displayNone = true,
54 opacity0 = true,
55 circleR0 = true,
56 ellipseRX0 = true,
57 ellipseRY0 = true,
58 rectWidth0 = true,
59 rectHeight0 = true,
60 patternWidth0 = true,
61 patternHeight0 = true,
62 imageWidth0 = true,
63 imageHeight0 = true,
64 pathEmptyD = true,
65 polylineEmptyPoints = true,
66 polygonEmptyPoints = true,
67 } = params;
68 const stylesheet = collectStylesheet(root);
69
70 return {
71 element: {
72 enter: (node, parentNode) => {
73 // Removes hidden elements
74 // https://www.w3schools.com/cssref/pr_class_visibility.asp
75 const computedStyle = computeStyle(stylesheet, node);
76 if (
77 isHidden &&
78 computedStyle.visibility &&
79 computedStyle.visibility.type === 'static' &&
80 computedStyle.visibility.value === 'hidden' &&
81 // keep if any descendant enables visibility
82 querySelector(node, '[visibility=visible]') == null
83 ) {
84 detachNodeFromParent(node, parentNode);
85 return;
86 }
87
88 // display="none"
89 //
90 // https://www.w3.org/TR/SVG11/painting.html#DisplayProperty
91 // "A value of display: none indicates that the given element
92 // and its children shall not be rendered directly"
93 if (
94 displayNone &&
95 computedStyle.display &&
96 computedStyle.display.type === 'static' &&
97 computedStyle.display.value === 'none' &&
98 // markers with display: none still rendered
99 node.name !== 'marker'
100 ) {
101 detachNodeFromParent(node, parentNode);
102 return;
103 }
104
105 // opacity="0"
106 //
107 // https://www.w3.org/TR/SVG11/masking.html#ObjectAndGroupOpacityProperties
108 if (
109 opacity0 &&
110 computedStyle.opacity &&
111 computedStyle.opacity.type === 'static' &&
112 computedStyle.opacity.value === '0' &&
113 // transparent element inside clipPath still affect clipped elements
114 closestByName(node, 'clipPath') == null
115 ) {
116 detachNodeFromParent(node, parentNode);
117 return;
118 }
119
120 // Circles with zero radius
121 //
122 // https://www.w3.org/TR/SVG11/shapes.html#CircleElementRAttribute
123 // "A value of zero disables rendering of the element"
124 //
125 // <circle r="0">
126 if (
127 circleR0 &&
128 node.name === 'circle' &&
129 node.children.length === 0 &&
130 node.attributes.r === '0'
131 ) {
132 detachNodeFromParent(node, parentNode);
133 return;
134 }
135
136 // Ellipse with zero x-axis radius
137 //
138 // https://www.w3.org/TR/SVG11/shapes.html#EllipseElementRXAttribute
139 // "A value of zero disables rendering of the element"
140 //
141 // <ellipse rx="0">
142 if (
143 ellipseRX0 &&
144 node.name === 'ellipse' &&
145 node.children.length === 0 &&
146 node.attributes.rx === '0'
147 ) {
148 detachNodeFromParent(node, parentNode);
149 return;
150 }
151
152 // Ellipse with zero y-axis radius
153 //
154 // https://www.w3.org/TR/SVG11/shapes.html#EllipseElementRYAttribute
155 // "A value of zero disables rendering of the element"
156 //
157 // <ellipse ry="0">
158 if (
159 ellipseRY0 &&
160 node.name === 'ellipse' &&
161 node.children.length === 0 &&
162 node.attributes.ry === '0'
163 ) {
164 detachNodeFromParent(node, parentNode);
165 return;
166 }
167
168 // Rectangle with zero width
169 //
170 // https://www.w3.org/TR/SVG11/shapes.html#RectElementWidthAttribute
171 // "A value of zero disables rendering of the element"
172 //
173 // <rect width="0">
174 if (
175 rectWidth0 &&
176 node.name === 'rect' &&
177 node.children.length === 0 &&
178 node.attributes.width === '0'
179 ) {
180 detachNodeFromParent(node, parentNode);
181 return;
182 }
183
184 // Rectangle with zero height
185 //
186 // https://www.w3.org/TR/SVG11/shapes.html#RectElementHeightAttribute
187 // "A value of zero disables rendering of the element"
188 //
189 // <rect height="0">
190 if (
191 rectHeight0 &&
192 rectWidth0 &&
193 node.name === 'rect' &&
194 node.children.length === 0 &&
195 node.attributes.height === '0'
196 ) {
197 detachNodeFromParent(node, parentNode);
198 return;
199 }
200
201 // Pattern with zero width
202 //
203 // https://www.w3.org/TR/SVG11/pservers.html#PatternElementWidthAttribute
204 // "A value of zero disables rendering of the element (i.e., no paint is applied)"
205 //
206 // <pattern width="0">
207 if (
208 patternWidth0 &&
209 node.name === 'pattern' &&
210 node.attributes.width === '0'
211 ) {
212 detachNodeFromParent(node, parentNode);
213 return;
214 }
215
216 // Pattern with zero height
217 //
218 // https://www.w3.org/TR/SVG11/pservers.html#PatternElementHeightAttribute
219 // "A value of zero disables rendering of the element (i.e., no paint is applied)"
220 //
221 // <pattern height="0">
222 if (
223 patternHeight0 &&
224 node.name === 'pattern' &&
225 node.attributes.height === '0'
226 ) {
227 detachNodeFromParent(node, parentNode);
228 return;
229 }
230
231 // Image with zero width
232 //
233 // https://www.w3.org/TR/SVG11/struct.html#ImageElementWidthAttribute
234 // "A value of zero disables rendering of the element"
235 //
236 // <image width="0">
237 if (
238 imageWidth0 &&
239 node.name === 'image' &&
240 node.attributes.width === '0'
241 ) {
242 detachNodeFromParent(node, parentNode);
243 return;
244 }
245
246 // Image with zero height
247 //
248 // https://www.w3.org/TR/SVG11/struct.html#ImageElementHeightAttribute
249 // "A value of zero disables rendering of the element"
250 //
251 // <image height="0">
252 if (
253 imageHeight0 &&
254 node.name === 'image' &&
255 node.attributes.height === '0'
256 ) {
257 detachNodeFromParent(node, parentNode);
258 return;
259 }
260
261 // Path with empty data
262 //
263 // https://www.w3.org/TR/SVG11/paths.html#DAttribute
264 //
265 // <path d=""/>
266 if (pathEmptyD && node.name === 'path') {
267 if (node.attributes.d == null) {
268 detachNodeFromParent(node, parentNode);
269 return;
270 }
271 const pathData = parsePathData(node.attributes.d);
272 if (pathData.length === 0) {
273 detachNodeFromParent(node, parentNode);
274 return;
275 }
276 // keep single point paths for markers
277 if (
278 pathData.length === 1 &&
279 computedStyle['marker-start'] == null &&
280 computedStyle['marker-end'] == null
281 ) {
282 detachNodeFromParent(node, parentNode);
283 return;
284 }
285 return;
286 }
287
288 // Polyline with empty points
289 //
290 // https://www.w3.org/TR/SVG11/shapes.html#PolylineElementPointsAttribute
291 //
292 // <polyline points="">
293 if (
294 polylineEmptyPoints &&
295 node.name === 'polyline' &&
296 node.attributes.points == null
297 ) {
298 detachNodeFromParent(node, parentNode);
299 return;
300 }
301
302 // Polygon with empty points
303 //
304 // https://www.w3.org/TR/SVG11/shapes.html#PolygonElementPointsAttribute
305 //
306 // <polygon points="">
307 if (
308 polygonEmptyPoints &&
309 node.name === 'polygon' &&
310 node.attributes.points == null
311 ) {
312 detachNodeFromParent(node, parentNode);
313 return;
314 }
315 },
316 },
317 };
318};
Note: See TracBrowser for help on using the repository browser.