@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
package/src/logger.js CHANGED
@@ -34,14 +34,14 @@
34
34
  // Why: Only appendFileSync is needed - we use sync writes in flush() for reliability
35
35
  // during shutdown or before critical operations. Async writes were considered but
36
36
  // the complexity of handling async flush during process exit wasn't worth it.
37
- import { appendFileSync } from 'fs';
37
+ import { appendFileSync } from "fs";
38
38
 
39
39
  // ============================================================================
40
40
  // CONSTANTS
41
41
  // ============================================================================
42
42
  // Why: Centralize configuration values to make tuning easier
43
- const LOG_BUFFER_SIZE = 100; // Flush after this many messages
44
- const LOG_FLUSH_INTERVAL_MS = 5000; // Auto-flush every 5 seconds
43
+ const LOG_BUFFER_SIZE = 100; // Flush after this many messages
44
+ const LOG_FLUSH_INTERVAL_MS = 5000; // Auto-flush every 5 seconds
45
45
 
46
46
  // ============================================================================
47
47
  // LOG LEVELS
@@ -125,8 +125,8 @@ export const Logger = {
125
125
  */
126
126
  _safeStringify(value) {
127
127
  // Why: Handle null/undefined explicitly to show their actual type
128
- if (value === null) return 'null';
129
- if (value === undefined) return 'undefined';
128
+ if (value === null) return "null";
129
+ if (value === undefined) return "undefined";
130
130
 
131
131
  // Why: Error objects should include stack traces for debugging
132
132
  if (value instanceof Error) {
@@ -134,7 +134,7 @@ export const Logger = {
134
134
  }
135
135
 
136
136
  // Why: For primitives, use String() for simple conversion
137
- if (typeof value !== 'object') {
137
+ if (typeof value !== "object") {
138
138
  return String(value);
139
139
  }
140
140
 
@@ -143,9 +143,9 @@ export const Logger = {
143
143
  const seen = new WeakSet();
144
144
  return JSON.stringify(value, (key, val) => {
145
145
  // Why: Handle circular references by replacing with placeholder
146
- if (typeof val === 'object' && val !== null) {
146
+ if (typeof val === "object" && val !== null) {
147
147
  if (seen.has(val)) {
148
- return '[Circular]';
148
+ return "[Circular]";
149
149
  }
150
150
  seen.add(val);
151
151
  }
@@ -168,8 +168,8 @@ export const Logger = {
168
168
  */
169
169
  _format(level, message) {
170
170
  // Why: Validate parameters to prevent crashes from invalid inputs
171
- if (typeof level !== 'string' || !level) {
172
- throw new Error('Logger._format: level must be a non-empty string');
171
+ if (typeof level !== "string" || !level) {
172
+ throw new Error("Logger._format: level must be a non-empty string");
173
173
  }
174
174
  // Why: Use safe stringify to handle all message types including errors and objects
175
175
  const messageStr = this._safeStringify(message);
@@ -219,7 +219,7 @@ export const Logger = {
219
219
  try {
220
220
  // Why sync here: flush() is called when reliability matters more
221
221
  // than performance (shutdown, before risky operation)
222
- const content = this._buffer.join('\n') + '\n';
222
+ const content = this._buffer.join("\n") + "\n";
223
223
  appendFileSync(this.logToFile, content);
224
224
  this._buffer = [];
225
225
  } catch {
@@ -240,9 +240,11 @@ export const Logger = {
240
240
  // Why: Check level FIRST - avoid performance cost of validation when logging is disabled
241
241
  if (this.level < LogLevel.ERROR) return;
242
242
 
243
- const formatted = this._format('ERROR', message);
243
+ const formatted = this._format("ERROR", message);
244
244
  // Why: Safely stringify args to handle objects, errors, and circular refs
245
- const argsStr = args.length ? ' ' + args.map(a => this._safeStringify(a)).join(' ') : '';
245
+ const argsStr = args.length
246
+ ? " " + args.map((a) => this._safeStringify(a)).join(" ")
247
+ : "";
246
248
  console.error(formatted, ...args);
247
249
  this._bufferWrite(formatted + argsStr);
248
250
  // Why: Errors are important enough to flush immediately
@@ -258,9 +260,11 @@ export const Logger = {
258
260
  // Why: Check level FIRST - avoid performance cost when logging is disabled
259
261
  if (this.level < LogLevel.WARN) return;
260
262
 
261
- const formatted = this._format('WARN', message);
263
+ const formatted = this._format("WARN", message);
262
264
  // Why: Safely stringify args to handle objects, errors, and circular refs
263
- const argsStr = args.length ? ' ' + args.map(a => this._safeStringify(a)).join(' ') : '';
265
+ const argsStr = args.length
266
+ ? " " + args.map((a) => this._safeStringify(a)).join(" ")
267
+ : "";
264
268
  console.warn(formatted, ...args);
265
269
  this._bufferWrite(formatted + argsStr);
266
270
  },
@@ -274,9 +278,11 @@ export const Logger = {
274
278
  // Why: Check level FIRST - avoid performance cost when logging is disabled
275
279
  if (this.level < LogLevel.INFO) return;
276
280
 
277
- const formatted = this._format('INFO', message);
281
+ const formatted = this._format("INFO", message);
278
282
  // Why: Safely stringify args to handle objects, errors, and circular refs
279
- const argsStr = args.length ? ' ' + args.map(a => this._safeStringify(a)).join(' ') : '';
283
+ const argsStr = args.length
284
+ ? " " + args.map((a) => this._safeStringify(a)).join(" ")
285
+ : "";
280
286
  console.log(formatted, ...args);
281
287
  this._bufferWrite(formatted + argsStr);
282
288
  },
@@ -290,9 +296,11 @@ export const Logger = {
290
296
  // Why: Check level FIRST - avoid performance cost when logging is disabled
291
297
  if (this.level < LogLevel.DEBUG) return;
292
298
 
293
- const formatted = this._format('DEBUG', message);
299
+ const formatted = this._format("DEBUG", message);
294
300
  // Why: Safely stringify args to handle objects, errors, and circular refs
295
- const argsStr = args.length ? ' ' + args.map(a => this._safeStringify(a)).join(' ') : '';
301
+ const argsStr = args.length
302
+ ? " " + args.map((a) => this._safeStringify(a)).join(" ")
303
+ : "";
296
304
  console.log(formatted, ...args);
297
305
  this._bufferWrite(formatted + argsStr);
298
306
  },
@@ -319,12 +327,16 @@ export const Logger = {
319
327
  */
320
328
  export function setLogLevel(level) {
321
329
  // Why: Validate level is a number to catch type errors
322
- if (typeof level !== 'number' || !Number.isFinite(level)) {
323
- throw new Error(`setLogLevel: level must be a finite number, got ${typeof level}`);
330
+ if (typeof level !== "number" || !Number.isFinite(level)) {
331
+ throw new Error(
332
+ `setLogLevel: level must be a finite number, got ${typeof level}`,
333
+ );
324
334
  }
325
335
  // Why: Validate level is within valid range to catch typos
326
336
  if (level < LogLevel.SILENT || level > LogLevel.DEBUG) {
327
- throw new Error(`Invalid log level: ${level}. Use LogLevel.SILENT (0) through LogLevel.DEBUG (4)`);
337
+ throw new Error(
338
+ `Invalid log level: ${level}. Use LogLevel.SILENT (0) through LogLevel.DEBUG (4)`,
339
+ );
328
340
  }
329
341
  Logger.level = level;
330
342
  }
@@ -347,16 +359,20 @@ export function getLogLevel() {
347
359
  */
348
360
  export function enableFileLogging(filePath, withTimestamps = true) {
349
361
  // Why: Validate filePath type to catch type errors
350
- if (typeof filePath !== 'string') {
351
- throw new Error(`enableFileLogging: filePath must be a string, got ${typeof filePath}`);
362
+ if (typeof filePath !== "string") {
363
+ throw new Error(
364
+ `enableFileLogging: filePath must be a string, got ${typeof filePath}`,
365
+ );
352
366
  }
353
367
  // Why: Don't accept empty/null paths - would cause confusing errors later
354
368
  if (!filePath) {
355
- throw new Error('File path required for enableFileLogging()');
369
+ throw new Error("File path required for enableFileLogging()");
356
370
  }
357
371
  // Why: Validate withTimestamps type to catch type errors
358
- if (typeof withTimestamps !== 'boolean') {
359
- throw new Error(`enableFileLogging: withTimestamps must be a boolean, got ${typeof withTimestamps}`);
372
+ if (typeof withTimestamps !== "boolean") {
373
+ throw new Error(
374
+ `enableFileLogging: withTimestamps must be a boolean, got ${typeof withTimestamps}`,
375
+ );
360
376
  }
361
377
  Logger.logToFile = filePath;
362
378
  Logger.timestamps = withTimestamps;