svg-path-simplify 0.3.5 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +3 -76
  3. package/dist/svg-path-simplify.esm.js +5505 -4030
  4. package/dist/svg-path-simplify.esm.min.js +2 -8
  5. package/dist/svg-path-simplify.js +5506 -4029
  6. package/dist/svg-path-simplify.min.js +2 -8
  7. package/dist/svg-path-simplify.pathdata.esm.js +1154 -1042
  8. package/dist/svg-path-simplify.pathdata.esm.min.js +2 -8
  9. package/docs/api.md +127 -0
  10. package/index.html +279 -257
  11. package/package.json +1 -1
  12. package/src/constants.js +10 -1
  13. package/src/index.js +7 -1
  14. package/src/pathData_simplify_cubic.js +1 -18
  15. package/src/pathSimplify-main.js +87 -30
  16. package/src/pathSimplify-only-pathdata.js +2 -2
  17. package/src/svg-getAttributes.js +13 -0
  18. package/src/svg_flatten_transforms.js +1 -1
  19. package/src/svg_getViewbox.js +23 -11
  20. package/src/svg_rootSVG.js +9 -0
  21. package/src/svgii/convert_colors.js +145 -0
  22. package/src/svgii/convert_units.js +159 -0
  23. package/src/svgii/geometry.js +24 -4
  24. package/src/svgii/geometry_bbox.js +2 -1
  25. package/src/svgii/geometry_bbox_element.js +46 -0
  26. package/src/svgii/pathData_analyze.js +34 -14
  27. package/src/svgii/pathData_convert.js +204 -34
  28. package/src/svgii/pathData_parse.js +2 -99
  29. package/src/svgii/pathData_parse_els.js +217 -128
  30. package/src/svgii/pathData_simplify_refineCorners.js +72 -43
  31. package/src/svgii/pathData_stringify.js +6 -5
  32. package/src/svgii/pathData_toPolygon.js +3 -1
  33. package/src/svgii/pathData_transform.js +307 -0
  34. package/src/svgii/poly_normalize.js +21 -1
  35. package/src/svgii/rounding.js +36 -5
  36. package/src/svgii/svg-styles-getTransforms.js +119 -8
  37. package/src/svgii/svg-styles-to-attributes-const.js +26 -6
  38. package/src/svgii/svg_cleanup.js +540 -74
  39. package/src/svgii/svg_el_parse_style_props.js +561 -0
  40. package/src/svgii/transform_qr_decompose.js +74 -0
  41. package/src/svgii/pathData_scale.js +0 -42
  42. package/src/svgii/stringify.js +0 -103
  43. package/src/svgii/svg-styles-to-attributes.js +0 -217
@@ -1,103 +0,0 @@
1
- /**
2
- * Serialize pathData array to a minified "d" attribute string.
3
- */
4
- export function pathDataToD(pathData, optimize = 1) {
5
-
6
- let beautify = optimize>1;
7
- let minify = beautify ? false : true;
8
-
9
- // Convert first "M" to "m" if followed by "l" (when minified)
10
- if (pathData[1].type === "l" && minify) {
11
- pathData[0].type = "m";
12
- }
13
-
14
- let d = '';
15
- if(beautify) {
16
- d = `${pathData[0].type} ${pathData[0].values.join(" ")}\n`;
17
- }else{
18
- d = `${pathData[0].type}${pathData[0].values.join(" ")}`;
19
- }
20
-
21
-
22
- for (let i = 1, len = pathData.length; i < len; i++) {
23
- let com0 = pathData[i - 1];
24
- let com = pathData[i];
25
- let { type, values } = com;
26
-
27
- // Minify Arc commands (A/a) – actually sucks!
28
- if (minify && (type === 'A' || type === 'a')) {
29
- values = [
30
- values[0], values[1], values[2],
31
- `${values[3]}${values[4]}${values[5]}`,
32
- values[6]
33
- ];
34
- }
35
-
36
- // Omit type for repeated commands
37
- type = (com0.type === com.type && com.type.toLowerCase() !== 'm' && minify)
38
- ? " "
39
- : (
40
- (com0.type === "m" && com.type === "l") ||
41
- (com0.type === "M" && com.type === "l") ||
42
- (com0.type === "M" && com.type === "L")
43
- ) && minify
44
- ? " "
45
- : com.type;
46
-
47
-
48
- // concatenate subsequent floating point values
49
- if (minify) {
50
-
51
- //console.log(optimize, beautify, minify);
52
-
53
- let valsString = '';
54
- let prevWasFloat = false;
55
-
56
- for (let v = 0, l = values.length; v < l; v++) {
57
- let val = values[v];
58
- let valStr = val.toString();
59
- let isFloat = valStr.includes('.');
60
- let isSmallFloat = isFloat && Math.abs(val) < 1;
61
-
62
-
63
- // Remove leading zero from small floats *only* if the previous was also a float
64
- if (isSmallFloat && prevWasFloat) {
65
- valStr = valStr.replace(/^0\./, '.');
66
- }
67
-
68
- // Add space unless this is the first value OR previous was a small float
69
- if (v > 0 && !(prevWasFloat && isSmallFloat)) {
70
- valsString += ' ';
71
- }
72
- //console.log(isSmallFloat, prevWasFloat, valStr);
73
-
74
- valsString += valStr
75
- //.replace(/-0./g, '-.').replace(/ -./g, '-.')
76
- prevWasFloat = isSmallFloat;
77
- }
78
-
79
- //console.log('minify', valsString);
80
- d += `${type}${valsString}`;
81
-
82
- }
83
- // regular non-minified output
84
- else{
85
- if(beautify) {
86
- d += `${type} ${values.join(' ')}\n`;
87
- }else{
88
- d += `${type}${values.join(' ')}`;
89
- }
90
- }
91
- }
92
-
93
- if (minify) {
94
- d = d
95
- .replace(/ 0\./g, " .") // Space before small decimals
96
- .replace(/ -/g, "-") // Remove space before negatives
97
- .replace(/-0\./g, "-.") // Remove leading zero from negative decimals
98
- .replace(/Z/g, "z"); // Convert uppercase 'Z' to lowercase
99
- }
100
-
101
-
102
- return d;
103
- }
@@ -1,217 +0,0 @@
1
- import { getMatrix, parseCSSTransform } from './svg-styles-getTransforms';
2
- import { attLookup } from './svg-styles-to-attributes-const';
3
-
4
-
5
-
6
- export function getElementProps(el, {
7
- removeNameSpaced = true,
8
- decimals = -1
9
- } = {}) {
10
-
11
- let nodeName = el.nodeName.toLowerCase();
12
- let attProps = getElAttributes(el)
13
- let cssProps = getElStyleProps(el)
14
-
15
-
16
- // normalize transform attributes
17
- if (attProps['transform']) {
18
-
19
- let transAtt = attProps['transform']
20
- let transArr = transAtt.match(/[a-z]+\([^)]*\)/gi);
21
-
22
-
23
- //console.log(`attProps['transform']`, transAtt);
24
-
25
-
26
- let transforms = [];
27
- transArr.forEach(trans => {
28
- let [prop, vals] = trans.split(/\(|\)/).filter(Boolean)
29
- //let prop = vals[0];
30
- vals = vals.split(/,| /).filter(Boolean).map(Number)
31
- console.log('trans', prop, vals);
32
-
33
- let cssTrans = '';
34
-
35
- // rotate has origin
36
- if (prop === 'rotate' && vals.length === 3) {
37
-
38
- cssTrans = `
39
- translate(${vals[1]}px, ${vals[2]}px)
40
- rotate(${vals[0]}deg)
41
- translate(${-vals[1]}px, ${-vals[2]}px)
42
- `
43
- /*
44
- transforms.push({ prop: 'translate', values: [vals[1], vals[2]] })
45
- transforms.push({ prop: 'rotate', values: [vals[0]] })
46
- transforms.push({ prop: 'translate', values: [-vals[1], -vals[2]] })
47
- */
48
- } else {
49
- cssTrans = `
50
- ${prop}(${vals[1]}px, ${vals[2]}px)
51
- rotate(${vals[0]}deg)
52
- translate(${-vals[1]}px, ${-vals[2]}px)
53
- `
54
-
55
-
56
- //transforms.push({ prop, values: [vals[0]] })
57
- }
58
- })
59
-
60
- console.log('transforms', transforms);
61
-
62
-
63
-
64
-
65
- }
66
-
67
- // merge properties
68
- let props = {
69
- ...attProps,
70
- ...cssProps
71
- }
72
-
73
-
74
- }
75
-
76
-
77
- export function svgStylesToAttributes(el, {
78
- removeNameSpaced = true,
79
- decimals = -1
80
- } = {}) {
81
-
82
- let nodeName = el.nodeName.toLowerCase();
83
- let attProps = getElAttributes(el)
84
- let cssProps = getElStyleProps(el)
85
-
86
- // normalize transform attributes
87
- if (attProps['transform']) {
88
- console.log(`attProps['transform']`, attProps['transform']);
89
- }
90
-
91
- // merge properties
92
- let props = {
93
- ...attProps,
94
- ...cssProps
95
- }
96
-
97
- // filter out obsolete properties
98
- let propsFiltered = {}
99
-
100
- // parse CSS transforms
101
- let cssTrans = cssProps['transform']
102
-
103
- if (cssTrans) {
104
- let transStr = `${cssTrans}`
105
- let transformObj = parseCSSTransform(transStr)
106
- let matrix = getMatrix(transformObj)
107
-
108
- // apply as SVG matrix transform
109
- props['transform'] = `matrix(${Object.values(matrix).join(',')})`
110
- }
111
-
112
-
113
- // can't be replaced with attributes
114
- let cssOnlyProps = ['inline-size']
115
- let styleProps = [];
116
-
117
- for (let prop in props) {
118
-
119
- let value = props[prop];
120
-
121
- // CSS variable
122
- if (value && prop.startsWith('--') || cssOnlyProps.includes(prop) ||
123
- (!removeNameSpaced && prop.startsWith('-'))) {
124
- styleProps.push(`${prop}:${value}`)
125
- continue
126
- }
127
-
128
- // check if property is valid
129
- if (value && attLookup.atts[prop] &&
130
- (attLookup.atts[prop] === '*' ||
131
- attLookup.atts[prop].includes(nodeName) ||
132
- !removeNameSpaced && (prop.includes(':'))
133
- )
134
- ) {
135
- propsFiltered[prop] = value
136
- }
137
-
138
- // remove property
139
- el.removeAttribute(prop)
140
-
141
- }
142
-
143
- // apply filtered attributes
144
- for (let prop in propsFiltered) {
145
- let value = propsFiltered[prop]
146
- el.setAttribute(prop, value)
147
- }
148
-
149
- if (styleProps.length) {
150
- el.setAttribute('style', styleProps.join(';'));
151
- }
152
-
153
- //console.log('propsFiltered', propsFiltered);
154
-
155
- return propsFiltered;
156
-
157
- }
158
-
159
-
160
- function parseInlineStyle(styleAtt = '') {
161
-
162
- let props = {}
163
- if (!styleAtt) return props;
164
-
165
- let styleArr = styleAtt.split(';').filter(Boolean).map(prop => prop.trim());
166
- let l = styleArr.length
167
- if (!l) return props;
168
-
169
- for (let i = 0; l && i < l; i++) {
170
- let style = styleArr[i]
171
- let [prop, value] = style.split(':').filter(Boolean)
172
- props[prop] = value;
173
- //props.push(`${prop}:${value}`)
174
- }
175
-
176
- return props
177
- }
178
-
179
- export function getElStyleProps(el) {
180
- let styleAtt = el.getAttribute('style')
181
- let props = styleAtt ? parseInlineStyle(styleAtt) : {}
182
- return props
183
- }
184
-
185
- export function getElAttributes(el) {
186
- let props = {}
187
- let atts = [...el.attributes].map((att) => att.name);
188
- let l = atts.length;
189
- if (!l) return props;
190
-
191
- for (let i = 0; i < l; i++) {
192
- let att = atts[i];
193
- let value = el.getAttribute(att);
194
- props[att] = value
195
- }
196
-
197
- return props;
198
- }
199
-
200
-
201
- function getUnit(val) {
202
- return val && isNaN(val) ? val.match(/[^\d|.]+/g)[0] : '';
203
- }
204
-
205
-
206
- function roundValue(value = '', decimals = -1) {
207
- if (decimals < 0) return value;
208
- value = value.replace(/["]/g, '').trim()
209
- let valueNum = parseFloat(value);
210
- let valueHasNumber = !isNaN(valueNum);
211
- if (!valueHasNumber) return value;
212
-
213
- let unit = valueHasNumber ? getUnit(value) : '';
214
- if (valueHasNumber) value = `${valueNum.toFixed(decimals)}${unit}`;
215
- //console.log('rounded', value)
216
- return value;
217
- }