svg-path-simplify 0.0.7 → 0.0.8

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.
@@ -0,0 +1,239 @@
1
+ //import { pathDataToAbsoluteOrRelative, pathDataToLonghands, cubicToArc } from './pathData_convert.js';
2
+ import { parsePathDataString, parsePathDataNormalized, stringifyPathData } from './pathData_parse.js';
3
+
4
+ export function shapeElToPath(el){
5
+
6
+ let nodeName = el.nodeName.toLowerCase();
7
+ if(nodeName==='path')return el;
8
+
9
+ let pathData = getPathDataFromEl(el);
10
+ let d = pathData.map(com=>{return `${com.type} ${com.values} `}).join(' ')
11
+ let attributes = [...el.attributes].map(att=>att.name);
12
+
13
+ let pathN = document.createElementNS('http://www.w3.org/2000/svg', 'path');
14
+ pathN.setAttribute('d', d );
15
+
16
+ let exclude = ['x', 'y', 'cx', 'cy', 'dx', 'dy', 'r', 'rx', 'ry', 'width', 'height', 'points']
17
+
18
+ attributes.forEach(att=>{
19
+ if(!exclude.includes(att)){
20
+ let val = el.getAttribute(att);
21
+ pathN.setAttribute(att, val)
22
+ }
23
+ })
24
+
25
+ //el.replaceWith(pathN)
26
+ return pathN
27
+
28
+ }
29
+
30
+
31
+ // retrieve pathdata from svg geometry elements
32
+ export function getPathDataFromEl(el, stringify=false) {
33
+
34
+ let pathData = [];
35
+ let type = el.nodeName;
36
+ let atts, attNames, d, x, y, width, height, r, rx, ry, cx, cy, x1, x2, y1, y2;
37
+
38
+ // convert relative or absolute units
39
+ const svgElUnitsToPixel = (el, decimals = 9) => {
40
+ //console.log(this);
41
+ const svg = el.nodeName !== "svg" ? el.closest("svg") : el;
42
+
43
+ // convert real life units to pixels
44
+ const translateUnitToPixel = (value) => {
45
+
46
+ if (value === null) {
47
+ return 0
48
+ }
49
+ //default dpi = 96
50
+ let dpi = 96;
51
+ let unit = value.match(/([a-z]+)/gi);
52
+ unit = unit ? unit[0] : "";
53
+ let val = parseFloat(value);
54
+ let rat;
55
+
56
+ // no unit - already pixes/user unit
57
+ if (!unit) {
58
+ return val;
59
+ }
60
+
61
+ switch (unit) {
62
+ case "in":
63
+ rat = dpi;
64
+ break;
65
+ case "pt":
66
+ rat = (1 / 72) * 96;
67
+ break;
68
+ case "cm":
69
+ rat = (1 / 2.54) * 96;
70
+ break;
71
+ case "mm":
72
+ rat = ((1 / 2.54) * 96) / 10;
73
+ break;
74
+ // just a default approximation
75
+ case "em":
76
+ case "rem":
77
+ rat = 16;
78
+ break;
79
+ default:
80
+ rat = 1;
81
+ }
82
+ let valuePx = val * rat;
83
+ return +valuePx.toFixed(decimals);
84
+ };
85
+
86
+ // svg width and height attributes
87
+ let width = svg.getAttribute("width");
88
+ width = width ? translateUnitToPixel(width) : 300;
89
+ let height = svg.getAttribute("height");
90
+ height = width ? translateUnitToPixel(height) : 150;
91
+
92
+ //prefer viewBox values
93
+ let vB = svg.getAttribute("viewBox");
94
+ vB = vB
95
+ ? vB
96
+ .replace(/,/g, " ")
97
+ .split(" ")
98
+ .filter(Boolean)
99
+ .map((val) => {
100
+ return +val;
101
+ })
102
+ : [];
103
+
104
+ let w = vB.length ? vB[2] : width;
105
+ let h = vB.length ? vB[3] : height;
106
+ let scaleX = w / 100;
107
+ let scaleY = h / 100;
108
+ let scalRoot = Math.sqrt((Math.pow(scaleX, 2) + Math.pow(scaleY, 2)) / 2);
109
+
110
+ let attsH = ["x", "width", "x1", "x2", "rx", "cx", "r"];
111
+ let attsV = ["y", "height", "y1", "y2", "ry", "cy"];
112
+
113
+
114
+ let atts = el.getAttributeNames();
115
+ atts.forEach((att) => {
116
+ let val = el.getAttribute(att);
117
+ let valAbs = val;
118
+ if (attsH.includes(att) || attsV.includes(att)) {
119
+ let scale = attsH.includes(att) ? scaleX : scaleY;
120
+ scale = att === "r" && w != h ? scalRoot : scale;
121
+ let unit = val.match(/([a-z|%]+)/gi);
122
+ unit = unit ? unit[0] : "";
123
+ if (val.includes("%")) {
124
+ valAbs = parseFloat(val) * scale;
125
+ }
126
+ //absolute units
127
+ else {
128
+ valAbs = translateUnitToPixel(val);
129
+ }
130
+ el.setAttribute(att, +valAbs);
131
+ }
132
+ });
133
+ }
134
+
135
+ svgElUnitsToPixel(el)
136
+
137
+ const getAtts = (attNames) => {
138
+ atts = {}
139
+ attNames.forEach(att => {
140
+ atts[att] = +el.getAttribute(att)
141
+ })
142
+ return atts
143
+ }
144
+
145
+ switch (type) {
146
+ case 'path':
147
+ d = el.getAttribute("d");
148
+ pathData = parsePathDataNormalized(d);
149
+ break;
150
+
151
+ case 'rect':
152
+ attNames = ['x', 'y', 'width', 'height', 'rx', 'ry'];
153
+ ({ x, y, width, height, rx, ry } = getAtts(attNames));
154
+
155
+
156
+ if (!rx && !ry) {
157
+ pathData = [
158
+ { type: "M", values: [x, y] },
159
+ { type: "L", values: [x + width, y] },
160
+ { type: "L", values: [x + width, y + height] },
161
+ { type: "L", values: [x, y + height] },
162
+ { type: "Z", values: [] }
163
+ ];
164
+ } else {
165
+
166
+ if (rx > width / 2) {
167
+ rx = width / 2;
168
+ }
169
+ if (ry > height / 2) {
170
+ ry = height / 2;
171
+ }
172
+ pathData = [
173
+ { type: "M", values: [x + rx, y] },
174
+ { type: "L", values: [x + width - rx, y] },
175
+ { type: "A", values: [rx, ry, 0, 0, 1, x + width, y + ry] },
176
+ { type: "L", values: [x + width, y + height - ry] },
177
+ { type: "A", values: [rx, ry, 0, 0, 1, x + width - rx, y + height] },
178
+ { type: "L", values: [x + rx, y + height] },
179
+ { type: "A", values: [rx, ry, 0, 0, 1, x, y + height - ry] },
180
+ { type: "L", values: [x, y + ry] },
181
+ { type: "A", values: [rx, ry, 0, 0, 1, x + rx, y] },
182
+ { type: "Z", values: [] }
183
+ ];
184
+ }
185
+ break;
186
+
187
+ case 'circle':
188
+ case 'ellipse':
189
+
190
+ attNames = ['cx', 'cy', 'rx', 'ry', 'r'];
191
+ ({ cx, cy, r, rx, ry } = getAtts(attNames));
192
+
193
+ if (type === 'circle') {
194
+ r = r;
195
+ rx = r
196
+ ry = r
197
+ } else {
198
+ rx = rx ? rx : r;
199
+ ry = ry ? ry : r;
200
+ }
201
+
202
+ pathData = [
203
+ { type: "M", values: [cx + rx, cy] },
204
+ { type: "A", values: [rx, ry, 0, 1, 1, cx - rx, cy] },
205
+ { type: "A", values: [rx, ry, 0, 1, 1, cx + rx, cy] },
206
+ ];
207
+
208
+ break;
209
+ case 'line':
210
+ attNames = ['x1', 'y1', 'x2', 'y2'];
211
+ ({ x1, y1, x2, y2 } = getAtts(attNames));
212
+ pathData = [
213
+ { type: "M", values: [x1, y1] },
214
+ { type: "L", values: [x2, y2] }
215
+ ];
216
+ break;
217
+ case 'polygon':
218
+ case 'polyline':
219
+
220
+ let points = el.getAttribute('points').replaceAll(',', ' ').split(' ').filter(Boolean)
221
+
222
+ for (let i = 0; i < points.length; i += 2) {
223
+ pathData.push({
224
+ type: (i === 0 ? "M" : "L"),
225
+ values: [+points[i], +points[i + 1]]
226
+ });
227
+ }
228
+ if (type === 'polygon') {
229
+ pathData.push({
230
+ type: "Z",
231
+ values: []
232
+ });
233
+ }
234
+ break;
235
+ }
236
+
237
+ return stringify ? stringifyPathData(pathData): pathData;
238
+
239
+ };
@@ -1,5 +1,6 @@
1
- import { checkBezierFlatness, getDistAv, getSquareDistance } from "./geometry.js";
1
+ import { getDistAv, getSquareDistance } from "./geometry.js";
2
2
  import { getPolygonArea } from "./geometry_area.js";
3
+ import { checkBezierFlatness, commandIsFlat } from "./geometry_flatness.js";
3
4
  import { renderPoint } from "./visualize.js";
4
5
 
5
6
  export function pathDataRemoveColinear(pathData, tolerance = 1, flatBezierToLinetos = true) {
@@ -50,6 +51,7 @@ export function pathDataRemoveColinear(pathData, tolerance = 1, flatBezierToLine
50
51
  //let areaBez = getPolygonArea([p0, ...cpts, p], true)
51
52
 
52
53
  isFlatBez = checkBezierFlatness(p0, cpts, p)
54
+ //isFlatBez = commandIsFlat([p0, ...cpts, p]).flat
53
55
  // console.log();
54
56
 
55
57
  //isFlatBez = areaBez < distMax * 0.25
@@ -0,0 +1,20 @@
1
+ export function removeOrphanedM(pathData) {
2
+
3
+ for (let i = 0, l = pathData.length; i < l; i++) {
4
+ let com = pathData[i];
5
+ if (!com) continue;
6
+ let { type = null, values = [] } = com;
7
+ let comN = pathData[i + 1] ? pathData[i + 1] : null;
8
+ if ((type === 'M' || type === 'm')) {
9
+
10
+ if (!comN || (comN && (comN.type === 'Z' || comN.type === 'z'))) {
11
+ pathData[i] = null
12
+ pathData[i + 1] = null
13
+ }
14
+ }
15
+ }
16
+
17
+ pathData = pathData.filter(Boolean);
18
+ return pathData;
19
+
20
+ }
@@ -1,4 +1,5 @@
1
1
 
2
+ /*
2
3
  // remove zero-length segments introduced by rounding
3
4
  export function removeZeroLengthLinetos_post(pathData) {
4
5
  let pathDataOpt = []
@@ -13,6 +14,7 @@ export function removeZeroLengthLinetos_post(pathData) {
13
14
  })
14
15
  return pathDataOpt
15
16
  }
17
+ */
16
18
 
17
19
  export function removeZeroLengthLinetos(pathData) {
18
20
 
@@ -26,14 +28,22 @@ export function removeZeroLengthLinetos(pathData) {
26
28
  let com = pathData[c];
27
29
  let { type, values } = com;
28
30
 
29
- let valsL = values.slice(-2);
30
- p = { x: valsL[0], y: valsL[1] };
31
+ let valsLen = values.length;
32
+ //let valsL = values.slice(-2);
33
+ //p = { x: valsL[0], y: valsL[1] };
34
+ p = { x: values[valsLen-2], y: values[valsLen-1] };
31
35
 
32
36
  // skip lineto
33
37
  if (type === 'L' && p.x === p0.x && p.y === p0.y) {
34
38
  continue
35
39
  }
36
40
 
41
+ // skip minified zero length
42
+ if (type === 'l' || type === 'v' || type === 'h') {
43
+ let noLength = type === 'l' ? (values.join('') === '00') : values[0] === 0;
44
+ if(noLength) continue
45
+ }
46
+
37
47
  pathDataN.push(com)
38
48
  p0 = p;
39
49
  }
@@ -1,10 +1,12 @@
1
1
  import { splitSubpaths, addExtemesToCommand } from './pathData_split.js';
2
- import { getComThresh, commandIsFlat, getPathDataVertices, getSquareDistance } from './geometry.js';
2
+ import { getComThresh, getPathDataVertices, getSquareDistance } from './geometry.js';
3
3
  import { getPolyBBox } from './geometry_bbox.js';
4
4
 
5
5
 
6
6
  import { renderPoint, renderPath } from './visualize.js';
7
7
  import { getPolygonArea } from './geometry_area.js';
8
+ import { checkBezierFlatness, commandIsFlat } from "./geometry_flatness.js";
9
+
8
10
 
9
11
 
10
12
  export function pathDataToTopLeft(pathData) {
@@ -2,6 +2,7 @@ import { pointAtT, svgArcToCenterParam, getBezierExtremeT } from "./geometry";
2
2
  import { renderPoint, renderPath } from "./visualize";
3
3
 
4
4
 
5
+
5
6
  /**
6
7
  * split segments into chunks to
7
8
  * prevent simplification across
@@ -11,7 +11,7 @@ export function detectAccuracy(pathData) {
11
11
 
12
12
  // Reference first MoveTo command (M)
13
13
  let M = { x: pathData[0].values[0], y: pathData[0].values[1] };
14
- let p0 = M
14
+ let p0 = M
15
15
  let p = M
16
16
  pathData[0].decimals = 0
17
17
  let lastDec = 0;
@@ -29,34 +29,40 @@ export function detectAccuracy(pathData) {
29
29
  let { type, values } = com;
30
30
 
31
31
  let lastVals = values.length ? values.slice(-2) : [M.x, M.y];
32
- p={x:lastVals[0], y:lastVals[1]}
32
+ p = { x: lastVals[0], y: lastVals[1] }
33
33
 
34
34
  // use existing averave dimension value or calculate
35
- let dimA = com.dimA ? +com.dimA.toFixed(8) : type!=='M' ? +getDistAv(p0, p).toFixed(8) : 0
35
+ let dimA = com.dimA ? +com.dimA.toFixed(8) : type !== 'M' ? +getDistAv(p0, p).toFixed(8) : 0
36
36
  //let dimA = +getDistAv(p0, p).toFixed(8)
37
37
  //console.log('dimA', dimA, com.dimA, type);
38
38
 
39
- if(dimA) dims.add(dimA);
39
+ if (dimA) dims.add(dimA);
40
+
41
+ if (dimA && dimA < minDim) minDim = dimA;
42
+ if (dimA && dimA > maxDim) maxDim = dimA;
40
43
 
41
- if(dimA && dimA<minDim) minDim = dimA;
42
- if(dimA && dimA>maxDim) maxDim = dimA;
43
-
44
44
 
45
- if(type==='M'){
46
- M=p;
45
+ if (type === 'M') {
46
+ M = p;
47
47
  }
48
48
  p0 = p;
49
49
  }
50
50
 
51
51
 
52
52
  let dim_min = Array.from(dims).sort()
53
- let sliceIdx = Math.ceil(dim_min.length/8);
54
- dim_min = dim_min.slice(0, sliceIdx );
55
53
 
56
- let dimVal = dim_min.reduce((a,b)=>a+b, 0) / sliceIdx;
54
+ /*
55
+ let minVal = dim_min.length > 15 ?
56
+ (dim_min[0] + dim_min[2]) / 2 :
57
+ dim_min[0];
58
+ */
59
+
60
+ let sliceIdx = Math.ceil(dim_min.length / 10);
61
+ dim_min = dim_min.slice(0, sliceIdx);
62
+ let minVal = dim_min.reduce((a, b) => a + b, 0) / sliceIdx;
57
63
 
58
- let threshold = 50
59
- let decimalsAuto = dimVal > threshold ? 0 : Math.floor(threshold / dimVal).toString().length
64
+ let threshold = 40
65
+ let decimalsAuto = minVal > threshold*1.5 ? 0 : Math.floor(threshold / minVal).toString().length
60
66
 
61
67
  // clamp
62
68
  return Math.min(Math.max(0, decimalsAuto), 8)
@@ -145,16 +151,16 @@ export function roundPathData(pathData, decimals = -1) {
145
151
  let hasDecimal = decimals == 'auto' && pathData[0].hasOwnProperty('decimals') ? true : false;
146
152
  //console.log('decimals', decimals, hasDecimal);
147
153
 
148
- for(let c=0, len=pathData.length; c<len; c++){
149
- let com=pathData[c];
150
- let {type, values} = com
154
+ for (let c = 0, len = pathData.length; c < len; c++) {
155
+ let com = pathData[c];
156
+ let { type, values } = com
151
157
 
152
- if (decimals >-1 || hasDecimal) {
158
+ if (decimals > -1 || hasDecimal) {
153
159
  decimals = hasDecimal ? com.decimals : decimals;
154
160
 
155
161
 
156
162
  //console.log('decimals', type, decimals);
157
- pathData[c].values = com.values.map(val=>{return val ? +val.toFixed(decimals) : val });
163
+ pathData[c].values = com.values.map(val => { return val ? +val.toFixed(decimals) : val });
158
164
 
159
165
  }
160
166
  };
@@ -0,0 +1,173 @@
1
+ import { getCombinedByDominant } from "../pathData_simplify_cubic_extrapolate";
2
+ import { getDistAv, interpolate } from "./geometry";
3
+ import { getPathArea } from "./geometry_area";
4
+ import { getPathDataBBox } from "./geometry_bbox";
5
+ import { renderPoint } from "./visualize";
6
+
7
+ export function refineAdjacentExtremes(pathData, {
8
+ threshold = null, tolerance = 1
9
+ } = {}) {
10
+
11
+ //dimA = dimA ? dimA :
12
+ if (!threshold) {
13
+ let bb = getPathDataBBox(pathData);
14
+ threshold = (bb.width + bb.height) / 2 * 0.05
15
+ //console.log('new threshold', threshold);
16
+ }
17
+
18
+ let l = pathData.length
19
+
20
+ for (let i = 0; i < l; i++) {
21
+ let com = pathData[i];
22
+ let { type, values, extreme, corner=false, dimA, p0, p } = com;
23
+ let comN = pathData[i + 1] ? pathData[i + 1] : null;
24
+
25
+
26
+ // adjacent
27
+ //&& comN.extreme
28
+ if (comN && type === 'C' && comN.type === 'C' && extreme && !corner) {
29
+
30
+ // check dist
31
+ let diff = getDistAv(p, comN.p)
32
+ let isCose = diff < threshold;
33
+
34
+
35
+ if (isCose) {
36
+ //renderPoint(markers, comN.p, 'cyan', '1%', '0.5')
37
+ //console.log(comN);
38
+ //console.log(diff, threshold);
39
+
40
+ let dx1 = (com.cp1.x - comN.p0.x)
41
+ let dy1 = (com.cp1.y - comN.p0.y)
42
+
43
+ let horizontal = Math.abs(dy1) < Math.abs(dx1);
44
+
45
+ let pN = comN.p;
46
+ let ptI;
47
+ let t = 1;
48
+
49
+ if (comN.extreme) {
50
+
51
+ // extend cp2
52
+ if (horizontal) {
53
+ t = Math.abs(Math.abs(comN.cp2.x - comN.p.x) / Math.abs(com.cp2.x - com.p.x))
54
+ //console.log('t', t);
55
+ ptI = interpolate(comN.p, com.cp2, 1 + t)
56
+ com.cp2.x = ptI.x
57
+ //renderPoint(markers, com.cp2, 'cyan', '1%', '0.5')
58
+ //renderPoint(markers, ptI, 'orange', '1%', '0.5')
59
+ }
60
+ else {
61
+ //renderPoint(markers, comN.p0, 'cyan', '1%', '0.5')
62
+ t = Math.abs(Math.abs(comN.cp2.y - comN.p.y) / Math.abs(com.cp2.y - com.p.y))
63
+ ptI = interpolate(comN.p, com.cp2, 1 + t)
64
+ com.cp2.y = ptI.y
65
+ }
66
+
67
+ //merge commands
68
+ pathData[i + 1].values = [com.cp1.x, com.cp1.y, com.cp2.x, com.cp2.y, pN.x, pN.y]
69
+ pathData[i + 1].cp1 = com.cp1
70
+ pathData[i + 1].cp2 = com.cp2
71
+ pathData[i + 1].p0 = com.p0
72
+ pathData[i + 1].p = pN
73
+ pathData[i + 1].extreme = true
74
+
75
+ // nullify 1st
76
+ pathData[i] = null;
77
+ continue
78
+
79
+ }
80
+
81
+ // extend fist command
82
+ else {
83
+
84
+ let comN2 = pathData[i + 2] ? pathData[i + 2] : null;
85
+ if (!comN2 && comN2.type !== 'C') continue
86
+
87
+ //continue
88
+
89
+ // extrapolate
90
+ let comEx = getCombinedByDominant(comN, comN2, threshold, tolerance, false)
91
+ //console.log('comEx', comEx);
92
+
93
+ if (comEx.length === 1) {
94
+ pathData[i + 1] = null;
95
+
96
+ comEx = comEx[0]
97
+
98
+ pathData[i + 2].values = [comEx.cp1.x, comEx.cp1.y, comEx.cp2.x, comEx.cp2.y, comEx.p.x, comEx.p.y]
99
+ pathData[i + 2].cp1 = comEx.cp1
100
+ pathData[i + 2].cp2 = comEx.cp2
101
+ pathData[i + 2].p0 = comEx.p0
102
+ pathData[i + 2].p = comEx.p
103
+ pathData[i + 2].extreme = comEx.extreme
104
+
105
+ i++
106
+ continue
107
+ }
108
+
109
+ }
110
+
111
+ }
112
+ }
113
+ }
114
+
115
+ // remove commands
116
+ pathData = pathData.filter(Boolean)
117
+ l = pathData.length
118
+
119
+
120
+
121
+ /**
122
+ * refine closing commands
123
+ */
124
+
125
+ let closed = pathData[l - 1].type.toLowerCase() === 'z';
126
+ let lastIdx = closed ? l - 2 : l - 1;
127
+ let lastCom = pathData[lastIdx];
128
+ let penultimateCom = pathData[lastIdx - 1] || null;
129
+ let M = { x: pathData[0].values[0], y: pathData[0].values[1] }
130
+
131
+ let dec = 8
132
+ let lastVals = lastCom.values.slice(-2);
133
+ let isClosingTo = +lastVals[0].toFixed(dec) === +M.x.toFixed(dec) && +lastVals[1].toFixed(dec) === +M.y.toFixed(dec)
134
+ let fistExt = pathData[1].type === 'C' && pathData[1].extreme ? pathData[1] : null;
135
+
136
+
137
+ //renderPoint(markers, M, 'blue')
138
+ //renderPoint(markers, fistExt.cp1, 'blue')
139
+ //renderPoint(markers, fistExt.p0, 'blue')
140
+
141
+
142
+
143
+ let diff = getDistAv(lastCom.p0, lastCom.p)
144
+ let isCose = diff < threshold;
145
+
146
+
147
+ if (penultimateCom && penultimateCom.type === 'C' && isCose && isClosingTo && fistExt) {
148
+
149
+ let dx1 = Math.abs(fistExt.cp1.x - M.x)
150
+ let dy1 = Math.abs(fistExt.cp1.y - M.y)
151
+
152
+ let horizontal = dy1 < dx1;
153
+ //console.log(dx1, dx2);
154
+ //console.log('isCose', isCose, diff, dimA);
155
+
156
+ let comEx = getCombinedByDominant(penultimateCom, lastCom, threshold, tolerance, false)
157
+ console.log('comEx', comEx);
158
+
159
+ if (comEx.length === 1) {
160
+ pathData[lastIdx - 1] = comEx[0];
161
+ pathData[lastIdx] = null;
162
+ pathData = pathData.filter(Boolean)
163
+ }
164
+
165
+
166
+ }
167
+
168
+
169
+ //console.log('pathData ex', pathData);
170
+
171
+ return pathData
172
+
173
+ }
@@ -1,3 +1,6 @@
1
+
2
+
3
+
1
4
  export function removeEmptySVGEls(svg) {
2
5
  let els = svg.querySelectorAll('g, defs');
3
6
  els.forEach(el => {
@@ -22,7 +25,7 @@ export function cleanUpSVG(svgMarkup, {
22
25
  .querySelector("svg");
23
26
 
24
27
 
25
- let allowed=['viewBox', 'xmlns', 'width', 'height', 'id', 'class'];
28
+ let allowed=['viewBox', 'xmlns', 'width', 'height', 'id', 'class', 'fill', 'stroke', 'stroke-width'];
26
29
  removeExcludedAttribues(svg, allowed)
27
30
 
28
31
  let removeEls = ['metadata', 'script']
package/testSVG.js ADDED
@@ -0,0 +1,39 @@
1
+ // add suport for DOM manipulations
2
+ import { DOMParser, parseHTML } from 'linkedom';
3
+ //import { XMLSerializerPoly, DOMParserPoly } from 'svg-path-simplify/dom_polyfills.js';
4
+ import { svgPathSimplify } from 'svg-path-simplify';
5
+
6
+
7
+
8
+
9
+ let svgMarkup =
10
+ `<?xml version="1.0" encoding="utf-8"?>
11
+ <!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
12
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
13
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="100px"
14
+ height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
15
+ <g id="garamond">
16
+ <path id="path1" d="M16.2 125.7 L16.2 125.7 Q12.1 125.7 8.4 123.8 Q4.6 122 2.3 119.1 Q0 116.2 0.2 113.1 L0.2 113.1 L0.4 112.6 Q2.2 111.2 5 109.3 Q7.8 107.4 11.4 105.1 Q15 102.8 19.1 100.4 L19.1 100.4 L19.2 99.5 Q16.8 98.1 15.5 94.7 Q14.1 91.3 14.1 86.7 L14.1 86.7 Q14.1 81.1 16 75.5 Q17.9 70 21.1 65.5 Q24.2 61 28.1 58.3 Q32 55.6 35.9 55.6 L35.9 55.6 L46.1 57.2 L47.2 54.7 L47.7 54.6 L50.8 56.1 L51.6 57 Q49.2 61.4 47.6 65.1 Q45.9 68.9 45 72 Q44 75.1 43.7 77.8 L43.7 77.8 Q43.4 80.3 43.2 83.7 Q43 87.1 42.8 90.6 Q42.6 94.2 42.5 97.1 Q42.3 100.1 42.1 101.6 L42.1 101.6 Q41.7 105.1 40 108.5 Q38.2 112 35.6 115.1 Q32.9 118.2 29.7 120.6 Q26.5 123 23 124.3 Q19.5 125.7 16.2 125.7 ZM19.5 119.9 L19.5 119.9 Q25.9 119.9 30.4 115.3 Q34.9 110.7 35.9 102.7 L35.9 102.7 L38.4 82 L37.6 81.8 Q34.5 87.5 32.3 91 Q30 94.6 28 96.8 Q25.9 99 23.5 100.8 L23.5 100.8 Q20.4 103.1 16.8 105.3 Q13.2 107.6 10.7 109.4 Q8.1 111.3 8.1 112.3 L8.1 112.3 Q8.1 114 9.9 115.8 Q11.6 117.5 14.3 118.7 Q16.9 119.9 19.5 119.9 ZM24.8 92.9 L24.8 92.9 Q26.3 92.9 29 89.4 Q31.6 86 35.2 79.5 Q38.7 73.1 42.9 64.1 L42.9 64.1 Q40.9 63.1 39.1 62.4 Q37.2 61.7 35.7 61.3 Q34.1 61 32.8 61 L32.8 61 Q29.8 61 27.1 64 Q24.4 67.1 22.7 71.9 Q21 76.7 21 82 L21 82 Q21 86.3 22.2 89.6 Q23.3 92.9 24.8 92.9 Z "/>
17
+ </g>
18
+ </svg>`
19
+
20
+
21
+ /*
22
+ */
23
+ let document = new DOMParser().parseFromString(svgMarkup, 'image/svg+xml');
24
+ let svg = document.querySelector('svg');
25
+ let path = svg.querySelector('path');
26
+ let d = path.getAttribute('d')
27
+
28
+ let markup = document.toString()
29
+ markup = new XMLSerializer().serializeToString(svg)
30
+
31
+ console.log(markup);
32
+
33
+ /*
34
+ // try to simplify
35
+ let svgOpt = svgPathSimplify(svgMarkup);
36
+
37
+ // simplified pathData
38
+ console.log(svgOpt)
39
+ */