source: trip-planner-front/node_modules/svgo/plugins/sortAttrs.js@ 6a3a178

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

initial commit

  • Property mode set to 100644
File size: 2.7 KB
Line 
1'use strict';
2
3exports.type = 'visitor';
4exports.name = 'sortAttrs';
5exports.active = false;
6exports.description = 'Sort element attributes for better compression';
7
8/**
9 * Sort element attributes for better compression
10 *
11 * @author Nikolay Frantsev
12 *
13 * @type {import('../lib/types').Plugin<{
14 * order?: Array<string>
15 * xmlnsOrder?: 'front' | 'alphabetical'
16 * }>}
17 */
18exports.fn = (_root, params) => {
19 const {
20 order = [
21 'id',
22 'width',
23 'height',
24 'x',
25 'x1',
26 'x2',
27 'y',
28 'y1',
29 'y2',
30 'cx',
31 'cy',
32 'r',
33 'fill',
34 'stroke',
35 'marker',
36 'd',
37 'points',
38 ],
39 xmlnsOrder = 'front',
40 } = params;
41
42 /**
43 * @type {(name: string) => number}
44 */
45 const getNsPriority = (name) => {
46 if (xmlnsOrder === 'front') {
47 // put xmlns first
48 if (name === 'xmlns') {
49 return 3;
50 }
51 // xmlns:* attributes second
52 if (name.startsWith('xmlns:')) {
53 return 2;
54 }
55 }
56 // other namespaces after and sort them alphabetically
57 if (name.includes(':')) {
58 return 1;
59 }
60 // other attributes
61 return 0;
62 };
63
64 /**
65 * @type {(a: [string, string], b: [string, string]) => number}
66 */
67 const compareAttrs = ([aName], [bName]) => {
68 // sort namespaces
69 const aPriority = getNsPriority(aName);
70 const bPriority = getNsPriority(bName);
71 const priorityNs = bPriority - aPriority;
72 if (priorityNs !== 0) {
73 return priorityNs;
74 }
75 // extract the first part from attributes
76 // for example "fill" from "fill" and "fill-opacity"
77 const [aPart] = aName.split('-');
78 const [bPart] = bName.split('-');
79 // rely on alphabetical sort when the first part is the same
80 if (aPart !== bPart) {
81 const aInOrderFlag = order.includes(aPart) ? 1 : 0;
82 const bInOrderFlag = order.includes(bPart) ? 1 : 0;
83 // sort by position in order param
84 if (aInOrderFlag === 1 && bInOrderFlag === 1) {
85 return order.indexOf(aPart) - order.indexOf(bPart);
86 }
87 // put attributes from order param before others
88 const priorityOrder = bInOrderFlag - aInOrderFlag;
89 if (priorityOrder !== 0) {
90 return priorityOrder;
91 }
92 }
93 // sort alphabetically
94 return aName < bName ? -1 : 1;
95 };
96
97 return {
98 element: {
99 enter: (node) => {
100 const attrs = Object.entries(node.attributes);
101 attrs.sort(compareAttrs);
102 /**
103 * @type {Record<string, string>}
104 */
105 const sortedAttributes = {};
106 for (const [name, value] of attrs) {
107 sortedAttributes[name] = value;
108 }
109 node.attributes = sortedAttributes;
110 },
111 },
112 };
113};
Note: See TracBrowser for help on using the repository browser.