@emasoft/svg-matrix 1.1.0 → 1.2.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 (55) hide show
  1. package/bin/svg-matrix.js +7 -6
  2. package/bin/svgm.js +109 -40
  3. package/dist/svg-matrix.min.js +7 -7
  4. package/dist/svg-toolbox.min.js +148 -228
  5. package/dist/svgm.min.js +152 -232
  6. package/dist/version.json +5 -5
  7. package/package.json +1 -1
  8. package/scripts/postinstall.js +72 -41
  9. package/scripts/test-postinstall.js +18 -16
  10. package/scripts/version-sync.js +78 -60
  11. package/src/animation-optimization.js +190 -98
  12. package/src/animation-references.js +11 -3
  13. package/src/arc-length.js +23 -20
  14. package/src/bezier-analysis.js +9 -13
  15. package/src/bezier-intersections.js +18 -4
  16. package/src/browser-verify.js +35 -8
  17. package/src/clip-path-resolver.js +285 -114
  18. package/src/convert-path-data.js +20 -8
  19. package/src/css-specificity.js +33 -9
  20. package/src/douglas-peucker.js +272 -141
  21. package/src/geometry-to-path.js +79 -22
  22. package/src/gjk-collision.js +287 -126
  23. package/src/index.js +56 -21
  24. package/src/inkscape-support.js +122 -101
  25. package/src/logger.js +43 -27
  26. package/src/marker-resolver.js +201 -121
  27. package/src/mask-resolver.js +231 -98
  28. package/src/matrix.js +9 -5
  29. package/src/mesh-gradient.js +22 -14
  30. package/src/off-canvas-detection.js +53 -17
  31. package/src/path-optimization.js +356 -171
  32. package/src/path-simplification.js +671 -256
  33. package/src/pattern-resolver.js +1 -3
  34. package/src/polygon-clip.js +396 -78
  35. package/src/svg-boolean-ops.js +90 -23
  36. package/src/svg-collections.js +1546 -667
  37. package/src/svg-flatten.js +152 -38
  38. package/src/svg-matrix-lib.js +2 -2
  39. package/src/svg-parser.js +5 -1
  40. package/src/svg-rendering-context.js +3 -1
  41. package/src/svg-toolbox-lib.js +2 -2
  42. package/src/svg-toolbox.js +99 -457
  43. package/src/svg-validation-data.js +513 -345
  44. package/src/svg2-polyfills.js +156 -93
  45. package/src/svgm-lib.js +8 -4
  46. package/src/transform-optimization.js +168 -51
  47. package/src/transforms2d.js +73 -40
  48. package/src/transforms3d.js +34 -27
  49. package/src/use-symbol-resolver.js +175 -76
  50. package/src/vector.js +80 -44
  51. package/src/vendor/inkscape-hatch-polyfill.js +143 -108
  52. package/src/vendor/inkscape-hatch-polyfill.min.js +291 -1
  53. package/src/vendor/inkscape-mesh-polyfill.js +953 -766
  54. package/src/vendor/inkscape-mesh-polyfill.min.js +896 -1
  55. package/src/verification.js +3 -4
@@ -13,25 +13,26 @@
13
13
  * @module svg2-polyfills
14
14
  */
15
15
 
16
- import { SVGElement } from './svg-parser.js';
16
+ import { SVGElement } from "./svg-parser.js";
17
17
 
18
18
  // Environment detection
19
- const IS_NODE = typeof process !== 'undefined' && process.versions && process.versions.node;
20
- const IS_BROWSER = typeof window !== 'undefined';
19
+ const IS_NODE =
20
+ typeof process !== "undefined" && process.versions && process.versions.node;
21
+ const IS_BROWSER = typeof window !== "undefined";
21
22
 
22
23
  // Load Inkscape polyfills at module initialization (minified + full versions)
23
- let INKSCAPE_MESH_POLYFILL_MIN = '';
24
- let INKSCAPE_MESH_POLYFILL_FULL = '';
25
- let INKSCAPE_HATCH_POLYFILL_MIN = '';
26
- let INKSCAPE_HATCH_POLYFILL_FULL = '';
24
+ let INKSCAPE_MESH_POLYFILL_MIN = "";
25
+ let INKSCAPE_MESH_POLYFILL_FULL = "";
26
+ let INKSCAPE_HATCH_POLYFILL_MIN = "";
27
+ let INKSCAPE_HATCH_POLYFILL_FULL = "";
27
28
 
28
29
  // In Node.js, load polyfills from filesystem
29
30
  if (IS_NODE) {
30
31
  try {
31
32
  // Dynamic imports for Node.js-only modules
32
- const fs = await import('fs');
33
- const url = await import('url');
34
- const path = await import('path');
33
+ const fs = await import("fs");
34
+ const url = await import("url");
35
+ const path = await import("path");
35
36
 
36
37
  const __filename = url.fileURLToPath(import.meta.url);
37
38
  const __dirname = path.dirname(__filename);
@@ -39,32 +40,36 @@ if (IS_NODE) {
39
40
  // Load mesh gradient polyfills (GPLv3 by Tavmjong Bah)
40
41
  // Minified version (default, ~16KB)
41
42
  INKSCAPE_MESH_POLYFILL_MIN = fs.readFileSync(
42
- path.join(__dirname, 'vendor', 'inkscape-mesh-polyfill.min.js'),
43
- 'utf-8'
43
+ path.join(__dirname, "vendor", "inkscape-mesh-polyfill.min.js"),
44
+ "utf-8",
44
45
  );
45
46
  // Full version (~35KB, for debugging or when --no-minify-polyfills is used)
46
47
  INKSCAPE_MESH_POLYFILL_FULL = fs.readFileSync(
47
- path.join(__dirname, 'vendor', 'inkscape-mesh-polyfill.js'),
48
- 'utf-8'
48
+ path.join(__dirname, "vendor", "inkscape-mesh-polyfill.js"),
49
+ "utf-8",
49
50
  );
50
51
 
51
52
  // Load hatch polyfills (CC0/Public Domain by Valentin Ionita)
52
53
  // Minified version (default, ~5KB)
53
54
  INKSCAPE_HATCH_POLYFILL_MIN = fs.readFileSync(
54
- path.join(__dirname, 'vendor', 'inkscape-hatch-polyfill.min.js'),
55
- 'utf-8'
55
+ path.join(__dirname, "vendor", "inkscape-hatch-polyfill.min.js"),
56
+ "utf-8",
56
57
  );
57
58
  // Full version (~10KB, for debugging)
58
59
  INKSCAPE_HATCH_POLYFILL_FULL = fs.readFileSync(
59
- path.join(__dirname, 'vendor', 'inkscape-hatch-polyfill.js'),
60
- 'utf-8'
60
+ path.join(__dirname, "vendor", "inkscape-hatch-polyfill.js"),
61
+ "utf-8",
61
62
  );
62
63
  } catch (e) {
63
- throw new Error(`Failed to load SVG2 polyfill files from vendor/ directory: ${e.message}. Ensure all vendor files are present.`);
64
+ throw new Error(
65
+ `Failed to load SVG2 polyfill files from vendor/ directory: ${e.message}. Ensure all vendor files are present.`,
66
+ );
64
67
  }
65
68
  } else if (IS_BROWSER) {
66
69
  // In browser, polyfills must be set via setPolyfillContent() or loaded separately
67
- console.warn('SVG2 polyfills: Running in browser mode. Use setPolyfillContent() to provide polyfill scripts.');
70
+ console.warn(
71
+ "SVG2 polyfills: Running in browser mode. Use setPolyfillContent() to provide polyfill scripts.",
72
+ );
68
73
  }
69
74
 
70
75
  // Module-level option for minification (default: true)
@@ -75,8 +80,10 @@ let useMinifiedPolyfills = true;
75
80
  * @param {boolean} minify - True to use minified (default), false for full version
76
81
  */
77
82
  export function setPolyfillMinification(minify) {
78
- if (typeof minify !== 'boolean') {
79
- throw new Error('setPolyfillMinification: minify parameter must be a boolean');
83
+ if (typeof minify !== "boolean") {
84
+ throw new Error(
85
+ "setPolyfillMinification: minify parameter must be a boolean",
86
+ );
80
87
  }
81
88
  useMinifiedPolyfills = minify;
82
89
  }
@@ -92,32 +99,34 @@ export function setPolyfillMinification(minify) {
92
99
  */
93
100
  export function setPolyfillContent(polyfills) {
94
101
  // Validate input - polyfills must be an object with string values
95
- if (!polyfills || typeof polyfills !== 'object') {
96
- throw new Error('setPolyfillContent: polyfills parameter must be an object');
102
+ if (!polyfills || typeof polyfills !== "object") {
103
+ throw new Error(
104
+ "setPolyfillContent: polyfills parameter must be an object",
105
+ );
97
106
  }
98
107
 
99
108
  // Validate and set each polyfill if provided
100
109
  if (polyfills.meshMin !== undefined) {
101
- if (typeof polyfills.meshMin !== 'string') {
102
- throw new Error('setPolyfillContent: meshMin must be a string');
110
+ if (typeof polyfills.meshMin !== "string") {
111
+ throw new Error("setPolyfillContent: meshMin must be a string");
103
112
  }
104
113
  INKSCAPE_MESH_POLYFILL_MIN = polyfills.meshMin;
105
114
  }
106
115
  if (polyfills.meshFull !== undefined) {
107
- if (typeof polyfills.meshFull !== 'string') {
108
- throw new Error('setPolyfillContent: meshFull must be a string');
116
+ if (typeof polyfills.meshFull !== "string") {
117
+ throw new Error("setPolyfillContent: meshFull must be a string");
109
118
  }
110
119
  INKSCAPE_MESH_POLYFILL_FULL = polyfills.meshFull;
111
120
  }
112
121
  if (polyfills.hatchMin !== undefined) {
113
- if (typeof polyfills.hatchMin !== 'string') {
114
- throw new Error('setPolyfillContent: hatchMin must be a string');
122
+ if (typeof polyfills.hatchMin !== "string") {
123
+ throw new Error("setPolyfillContent: hatchMin must be a string");
115
124
  }
116
125
  INKSCAPE_HATCH_POLYFILL_MIN = polyfills.hatchMin;
117
126
  }
118
127
  if (polyfills.hatchFull !== undefined) {
119
- if (typeof polyfills.hatchFull !== 'string') {
120
- throw new Error('setPolyfillContent: hatchFull must be a string');
128
+ if (typeof polyfills.hatchFull !== "string") {
129
+ throw new Error("setPolyfillContent: hatchFull must be a string");
121
130
  }
122
131
  INKSCAPE_HATCH_POLYFILL_FULL = polyfills.hatchFull;
123
132
  }
@@ -127,10 +136,10 @@ export function setPolyfillContent(polyfills) {
127
136
  * SVG 2.0 features that can be polyfilled
128
137
  */
129
138
  export const SVG2_FEATURES = {
130
- MESH_GRADIENT: 'meshGradient',
131
- HATCH: 'hatch',
132
- CONTEXT_PAINT: 'context-paint',
133
- AUTO_START_REVERSE: 'auto-start-reverse'
139
+ MESH_GRADIENT: "meshGradient",
140
+ HATCH: "hatch",
141
+ CONTEXT_PAINT: "context-paint",
142
+ AUTO_START_REVERSE: "auto-start-reverse",
134
143
  };
135
144
 
136
145
  /**
@@ -141,15 +150,20 @@ export const SVG2_FEATURES = {
141
150
  */
142
151
  export function detectSVG2Features(doc) {
143
152
  // WHY: Validate doc is an object before attempting to traverse it
144
- if (!doc || typeof doc !== 'object') {
145
- return { meshGradients: [], hatches: [], contextPaint: false, autoStartReverse: false };
153
+ if (!doc || typeof doc !== "object") {
154
+ return {
155
+ meshGradients: [],
156
+ hatches: [],
157
+ contextPaint: false,
158
+ autoStartReverse: false,
159
+ };
146
160
  }
147
161
 
148
162
  const features = {
149
163
  meshGradients: [],
150
164
  hatches: [],
151
165
  contextPaint: false,
152
- autoStartReverse: false
166
+ autoStartReverse: false,
153
167
  };
154
168
 
155
169
  const walk = (el) => {
@@ -157,44 +171,62 @@ export function detectSVG2Features(doc) {
157
171
 
158
172
  // Check tag name for mesh gradient (case-insensitive)
159
173
  const tagName = el.tagName?.toLowerCase();
160
- if (tagName === 'meshgradient') {
161
- const id = el.getAttribute('id');
174
+ if (tagName === "meshgradient") {
175
+ const id = el.getAttribute("id");
162
176
  // WHY: Validate ID is non-empty string and not already in array to prevent duplicates
163
- if (id && typeof id === 'string' && id.trim() && !features.meshGradients.includes(id)) {
177
+ if (
178
+ id &&
179
+ typeof id === "string" &&
180
+ id.trim() &&
181
+ !features.meshGradients.includes(id)
182
+ ) {
164
183
  features.meshGradients.push(id);
165
184
  }
166
185
  }
167
186
 
168
187
  // Check for hatch element
169
- if (tagName === 'hatch') {
170
- const id = el.getAttribute('id');
188
+ if (tagName === "hatch") {
189
+ const id = el.getAttribute("id");
171
190
  // WHY: Validate ID is non-empty string and not already in array to prevent duplicates
172
- if (id && typeof id === 'string' && id.trim() && !features.hatches.includes(id)) {
191
+ if (
192
+ id &&
193
+ typeof id === "string" &&
194
+ id.trim() &&
195
+ !features.hatches.includes(id)
196
+ ) {
173
197
  features.hatches.push(id);
174
198
  }
175
199
  }
176
200
 
177
201
  // Check for context-paint in fill/stroke attributes and style attribute
178
- const fill = el.getAttribute('fill');
179
- const stroke = el.getAttribute('stroke');
180
- const style = el.getAttribute('style');
202
+ const fill = el.getAttribute("fill");
203
+ const stroke = el.getAttribute("stroke");
204
+ const style = el.getAttribute("style");
181
205
  // WHY: context-paint can appear in style attribute, not just fill/stroke attributes
182
- if (fill === 'context-fill' || fill === 'context-stroke' ||
183
- stroke === 'context-fill' || stroke === 'context-stroke' ||
184
- (style && (style.includes('context-fill') || style.includes('context-stroke')))) {
206
+ if (
207
+ fill === "context-fill" ||
208
+ fill === "context-stroke" ||
209
+ stroke === "context-fill" ||
210
+ stroke === "context-stroke" ||
211
+ (style &&
212
+ (style.includes("context-fill") || style.includes("context-stroke")))
213
+ ) {
185
214
  features.contextPaint = true;
186
215
  }
187
216
 
188
217
  // WHY: Check <style> elements for context-paint in CSS rules
189
- if (tagName === 'style' && el.textContent) {
190
- if (el.textContent.includes('context-fill') || el.textContent.includes('context-stroke')) {
218
+ if (tagName === "style" && el.textContent) {
219
+ if (
220
+ el.textContent.includes("context-fill") ||
221
+ el.textContent.includes("context-stroke")
222
+ ) {
191
223
  features.contextPaint = true;
192
224
  }
193
225
  }
194
226
 
195
227
  // Check for auto-start-reverse in markers
196
- const orient = el.getAttribute('orient');
197
- if (orient === 'auto-start-reverse') {
228
+ const orient = el.getAttribute("orient");
229
+ if (orient === "auto-start-reverse") {
198
230
  features.autoStartReverse = true;
199
231
  }
200
232
 
@@ -220,10 +252,12 @@ export function needsPolyfills(doc) {
220
252
  if (!doc) return false;
221
253
 
222
254
  const features = detectSVG2Features(doc);
223
- return features.meshGradients.length > 0 ||
224
- features.hatches.length > 0 ||
225
- features.contextPaint ||
226
- features.autoStartReverse;
255
+ return (
256
+ features.meshGradients.length > 0 ||
257
+ features.hatches.length > 0 ||
258
+ features.contextPaint ||
259
+ features.autoStartReverse
260
+ );
227
261
  }
228
262
 
229
263
  /**
@@ -242,10 +276,14 @@ export function needsPolyfills(doc) {
242
276
  */
243
277
  function generateMeshPolyfillCode() {
244
278
  // Return minified or full Inkscape mesh.js polyfill based on setting
245
- const polyfill = useMinifiedPolyfills ? INKSCAPE_MESH_POLYFILL_MIN : INKSCAPE_MESH_POLYFILL_FULL;
279
+ const polyfill = useMinifiedPolyfills
280
+ ? INKSCAPE_MESH_POLYFILL_MIN
281
+ : INKSCAPE_MESH_POLYFILL_FULL;
246
282
  // WHY: Throw error instead of silently returning empty string to prevent broken SVG output
247
- if (!polyfill || polyfill.trim() === '') {
248
- throw new Error('svg2-polyfills: Inkscape mesh polyfill not available. Ensure vendor/inkscape-mesh-polyfill files are present.');
283
+ if (!polyfill || polyfill.trim() === "") {
284
+ throw new Error(
285
+ "svg2-polyfills: Inkscape mesh polyfill not available. Ensure vendor/inkscape-mesh-polyfill files are present.",
286
+ );
249
287
  }
250
288
  return polyfill;
251
289
  }
@@ -265,10 +303,14 @@ function generateMeshPolyfillCode() {
265
303
  */
266
304
  function generateHatchPolyfillCode() {
267
305
  // Return minified or full Inkscape hatch polyfill based on setting
268
- const polyfill = useMinifiedPolyfills ? INKSCAPE_HATCH_POLYFILL_MIN : INKSCAPE_HATCH_POLYFILL_FULL;
306
+ const polyfill = useMinifiedPolyfills
307
+ ? INKSCAPE_HATCH_POLYFILL_MIN
308
+ : INKSCAPE_HATCH_POLYFILL_FULL;
269
309
  // WHY: Throw error instead of silently returning empty string to prevent broken SVG output
270
- if (!polyfill || polyfill.trim() === '') {
271
- throw new Error('svg2-polyfills: Inkscape hatch polyfill not available. Ensure vendor/inkscape-hatch-polyfill files are present.');
310
+ if (!polyfill || polyfill.trim() === "") {
311
+ throw new Error(
312
+ "svg2-polyfills: Inkscape hatch polyfill not available. Ensure vendor/inkscape-hatch-polyfill files are present.",
313
+ );
272
314
  }
273
315
  return polyfill;
274
316
  }
@@ -281,33 +323,47 @@ function generateHatchPolyfillCode() {
281
323
  */
282
324
  export function generatePolyfillScript(features) {
283
325
  // WHY: Explicit null check before typeof check prevents null passing as object
284
- if (!features || typeof features !== 'object') {
285
- throw new Error('generatePolyfillScript: features parameter must be an object');
326
+ if (!features || typeof features !== "object") {
327
+ throw new Error(
328
+ "generatePolyfillScript: features parameter must be an object",
329
+ );
286
330
  }
287
331
  if (!Array.isArray(features.meshGradients)) {
288
- throw new Error('generatePolyfillScript: features.meshGradients must be an array');
332
+ throw new Error(
333
+ "generatePolyfillScript: features.meshGradients must be an array",
334
+ );
289
335
  }
290
336
  if (!Array.isArray(features.hatches)) {
291
- throw new Error('generatePolyfillScript: features.hatches must be an array');
337
+ throw new Error(
338
+ "generatePolyfillScript: features.hatches must be an array",
339
+ );
292
340
  }
293
341
  // WHY: Validate array contents are all strings to prevent type errors
294
- if (!features.meshGradients.every(id => typeof id === 'string')) {
295
- throw new Error('generatePolyfillScript: features.meshGradients must contain only strings');
342
+ if (!features.meshGradients.every((id) => typeof id === "string")) {
343
+ throw new Error(
344
+ "generatePolyfillScript: features.meshGradients must contain only strings",
345
+ );
296
346
  }
297
- if (!features.hatches.every(id => typeof id === 'string')) {
298
- throw new Error('generatePolyfillScript: features.hatches must contain only strings');
347
+ if (!features.hatches.every((id) => typeof id === "string")) {
348
+ throw new Error(
349
+ "generatePolyfillScript: features.hatches must contain only strings",
350
+ );
299
351
  }
300
352
  // WHY: Validate boolean properties to prevent undefined/wrong type usage
301
- if (typeof features.contextPaint !== 'boolean') {
302
- throw new Error('generatePolyfillScript: features.contextPaint must be a boolean');
353
+ if (typeof features.contextPaint !== "boolean") {
354
+ throw new Error(
355
+ "generatePolyfillScript: features.contextPaint must be a boolean",
356
+ );
303
357
  }
304
- if (typeof features.autoStartReverse !== 'boolean') {
305
- throw new Error('generatePolyfillScript: features.autoStartReverse must be a boolean');
358
+ if (typeof features.autoStartReverse !== "boolean") {
359
+ throw new Error(
360
+ "generatePolyfillScript: features.autoStartReverse must be a boolean",
361
+ );
306
362
  }
307
363
 
308
364
  const parts = [];
309
365
 
310
- parts.push('/* SVG 2.0 Polyfills - Generated by svg-matrix */');
366
+ parts.push("/* SVG 2.0 Polyfills - Generated by svg-matrix */");
311
367
 
312
368
  if (features.meshGradients.length > 0) {
313
369
  parts.push(generateMeshPolyfillCode());
@@ -321,7 +377,7 @@ export function generatePolyfillScript(features) {
321
377
  return null; // Only header, no actual polyfills
322
378
  }
323
379
 
324
- return parts.join('\n');
380
+ return parts.join("\n");
325
381
  }
326
382
 
327
383
  /**
@@ -340,9 +396,11 @@ export function injectPolyfills(doc, options = {}) {
340
396
  const features = options.features || detectSVG2Features(doc);
341
397
 
342
398
  // Check if polyfills are needed
343
- if (!options.force &&
344
- features.meshGradients.length === 0 &&
345
- features.hatches.length === 0) {
399
+ if (
400
+ !options.force &&
401
+ features.meshGradients.length === 0 &&
402
+ features.hatches.length === 0
403
+ ) {
346
404
  return doc;
347
405
  }
348
406
 
@@ -357,10 +415,15 @@ export function injectPolyfills(doc, options = {}) {
357
415
  const wrappedScript = `\n// <![CDATA[\n${script}\n// ]]>\n`;
358
416
 
359
417
  // Create a proper SVGElement for the script
360
- const scriptEl = new SVGElement('script', {
361
- type: 'text/javascript',
362
- id: 'svg-matrix-polyfill'
363
- }, [], wrappedScript);
418
+ const scriptEl = new SVGElement(
419
+ "script",
420
+ {
421
+ type: "text/javascript",
422
+ id: "svg-matrix-polyfill",
423
+ },
424
+ [],
425
+ wrappedScript,
426
+ );
364
427
 
365
428
  // Insert script at beginning of SVG (after defs if present, else at start)
366
429
  if (!Array.isArray(svg.children)) {
@@ -373,7 +436,7 @@ export function injectPolyfills(doc, options = {}) {
373
436
  let insertIdx = 0;
374
437
  for (let i = 0; i < svg.children.length; i++) {
375
438
  // WHY: Optional chaining prevents errors if array contains null/undefined elements
376
- if (svg.children[i]?.tagName === 'defs') {
439
+ if (svg.children[i]?.tagName === "defs") {
377
440
  insertIdx = i + 1; // Position after this defs (don't break - continue to find last defs)
378
441
  }
379
442
  }
@@ -398,17 +461,17 @@ export function removePolyfills(doc) {
398
461
  if (!el || !el.children || !Array.isArray(el.children)) return;
399
462
 
400
463
  // Remove script elements that are svg-matrix polyfills
401
- el.children = el.children.filter(child => {
464
+ el.children = el.children.filter((child) => {
402
465
  // WHY: Optional chaining prevents errors if child is null/undefined
403
- if (child?.tagName === 'script') {
466
+ if (child?.tagName === "script") {
404
467
  // WHY: Check id attribute first (more reliable), then fallback to content check
405
- const id = child.getAttribute?.('id');
406
- if (id === 'svg-matrix-polyfill') {
468
+ const id = child.getAttribute?.("id");
469
+ if (id === "svg-matrix-polyfill") {
407
470
  return false;
408
471
  }
409
472
  // WHY: Fallback for older polyfills without id attribute
410
- const content = child.textContent || '';
411
- if (content.includes('SVG 2.0 Polyfills - Generated by svg-matrix')) {
473
+ const content = child.textContent || "";
474
+ if (content.includes("SVG 2.0 Polyfills - Generated by svg-matrix")) {
412
475
  return false;
413
476
  }
414
477
  }
package/src/svgm-lib.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * comprehensive SVG manipulation (SVGToolbox). Works in Node.js and browser.
6
6
  *
7
7
  * @module svgm-lib
8
- * @version 1.1.0
8
+ * @version 1.2.0
9
9
  * @license MIT
10
10
  *
11
11
  * @example Browser usage:
@@ -49,7 +49,7 @@ Decimal.set({ precision: 80 });
49
49
  /**
50
50
  * Library version
51
51
  */
52
- export const VERSION = "1.1.0";
52
+ export const VERSION = "1.2.0";
53
53
 
54
54
  // Export math classes
55
55
  export { Decimal, Matrix, Vector };
@@ -63,8 +63,12 @@ export * from "./svg-toolbox.js";
63
63
  export const { parseSVG, serializeSVG } = SVGParser;
64
64
 
65
65
  // Export polyfills
66
- export const { detectSVG2Features, injectPolyfills, setPolyfillMinification, setPolyfillContent } =
67
- SVG2Polyfills;
66
+ export const {
67
+ detectSVG2Features,
68
+ injectPolyfills,
69
+ setPolyfillMinification,
70
+ setPolyfillContent,
71
+ } = SVG2Polyfills;
68
72
 
69
73
  /**
70
74
  * High-level process function - load, optimize, save in one call.