-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
cleanupListOfValues.js
145 lines (125 loc) · 3.76 KB
/
cleanupListOfValues.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import { removeLeadingZero } from '../lib/svgo/tools.js';
export const name = 'cleanupListOfValues';
export const description = 'rounds list of values to the fixed precision';
const regNumericValues =
/^([-+]?\d*\.?\d+([eE][-+]?\d+)?)(px|pt|pc|mm|cm|m|in|ft|em|ex|%)?$/;
const regSeparator = /\s+,?\s*|,\s*/;
const absoluteLengths = {
// relative to px
cm: 96 / 2.54,
mm: 96 / 25.4,
in: 96,
pt: 4 / 3,
pc: 16,
px: 1,
};
/**
* Round list of values to the fixed precision.
*
* @example
* <svg viewBox="0 0 200.28423 200.28423" enable-background="new 0 0 200.28423 200.28423">
* ⬇
* <svg viewBox="0 0 200.284 200.284" enable-background="new 0 0 200.284 200.284">
*
* <polygon points="208.250977 77.1308594 223.069336 ... "/>
* ⬇
* <polygon points="208.251 77.131 223.069 ... "/>
*
* @author kiyopikko
*
* @type {import('./plugins-types.js').Plugin<'cleanupListOfValues'>}
*/
export const fn = (_root, params) => {
const {
floatPrecision = 3,
leadingZero = true,
defaultPx = true,
convertToPx = true,
} = params;
/**
* @type {(lists: string) => string}
*/
const roundValues = (lists) => {
const roundedList = [];
for (const elem of lists.split(regSeparator)) {
const match = elem.match(regNumericValues);
const matchNew = elem.match(/new/);
// if attribute value matches regNumericValues
if (match) {
// round it to the fixed precision
let num = Number(Number(match[1]).toFixed(floatPrecision));
/**
* @type {any}
*/
let matchedUnit = match[3] || '';
/**
* @type{'' | keyof typeof absoluteLengths}
*/
let units = matchedUnit;
// convert absolute values to pixels
if (convertToPx && units && units in absoluteLengths) {
const pxNum = Number(
(absoluteLengths[units] * Number(match[1])).toFixed(floatPrecision),
);
if (pxNum.toString().length < match[0].length) {
num = pxNum;
units = 'px';
}
}
// and remove leading zero
let str;
if (leadingZero) {
str = removeLeadingZero(num);
} else {
str = num.toString();
}
// remove default 'px' units
if (defaultPx && units === 'px') {
units = '';
}
roundedList.push(str + units);
}
// if attribute value is "new"(only enable-background).
else if (matchNew) {
roundedList.push('new');
} else if (elem) {
roundedList.push(elem);
}
}
return roundedList.join(' ');
};
return {
element: {
enter: (node) => {
if (node.attributes.points != null) {
node.attributes.points = roundValues(node.attributes.points);
}
if (node.attributes['enable-background'] != null) {
node.attributes['enable-background'] = roundValues(
node.attributes['enable-background'],
);
}
if (node.attributes.viewBox != null) {
node.attributes.viewBox = roundValues(node.attributes.viewBox);
}
if (node.attributes['stroke-dasharray'] != null) {
node.attributes['stroke-dasharray'] = roundValues(
node.attributes['stroke-dasharray'],
);
}
if (node.attributes.dx != null) {
node.attributes.dx = roundValues(node.attributes.dx);
}
if (node.attributes.dy != null) {
node.attributes.dy = roundValues(node.attributes.dy);
}
if (node.attributes.x != null) {
node.attributes.x = roundValues(node.attributes.x);
}
if (node.attributes.y != null) {
node.attributes.y = roundValues(node.attributes.y);
}
},
},
};
};