svg-path-commander 0.1.25 → 0.2.0-alpha3

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 (71) hide show
  1. package/README.md +5 -3
  2. package/dist/svg-path-commander.es5.js +3948 -0
  3. package/dist/svg-path-commander.es5.min.js +2 -0
  4. package/dist/svg-path-commander.esm.js +425 -404
  5. package/dist/svg-path-commander.esm.min.js +2 -2
  6. package/dist/svg-path-commander.js +1432 -1513
  7. package/dist/svg-path-commander.min.js +2 -2
  8. package/package.json +28 -12
  9. package/src/convert/pathToAbsolute.js +4 -4
  10. package/src/convert/pathToCurve.js +2 -2
  11. package/src/convert/pathToRelative.js +4 -4
  12. package/src/convert/pathToString.js +2 -2
  13. package/src/math/polygonLength.js +1 -2
  14. package/src/options/options.js +1 -1
  15. package/src/parser/error.js +2 -0
  16. package/src/parser/finalizeSegment.js +1 -1
  17. package/src/parser/paramsParser.js +1 -1
  18. package/src/parser/parsePathString.js +6 -11
  19. package/src/parser/pathParser.js +1 -1
  20. package/src/parser/scanFlag.js +3 -3
  21. package/src/parser/scanParam.js +7 -6
  22. package/src/parser/scanSegment.js +3 -2
  23. package/src/parser/skipSpaces.js +1 -1
  24. package/src/process/clonePath.js +1 -1
  25. package/src/process/fixArc.js +1 -1
  26. package/src/process/fixPath.js +2 -2
  27. package/src/process/getSVGMatrix.js +3 -2
  28. package/src/process/normalizePath.js +3 -3
  29. package/src/process/normalizeSegment.js +2 -2
  30. package/src/process/optimizePath.js +2 -2
  31. package/src/process/projection2d.js +2 -2
  32. package/src/process/reverseCurve.js +3 -3
  33. package/src/process/reversePath.js +4 -5
  34. package/src/process/roundPath.js +7 -6
  35. package/src/process/segmentToCubic.js +3 -3
  36. package/src/process/shortenSegment.js +3 -3
  37. package/src/process/splitCubic.js +1 -1
  38. package/src/process/splitPath.js +1 -1
  39. package/src/process/transformPath.js +8 -7
  40. package/src/svg-path-commander.js +60 -20
  41. package/src/util/getClosestPoint.js +1 -1
  42. package/src/util/getCubicSize.js +1 -1
  43. package/src/util/getDrawDirection.js +1 -1
  44. package/src/util/getPathArea.js +1 -1
  45. package/src/util/getPathBBox.js +2 -2
  46. package/src/util/getPathLength.js +1 -1
  47. package/src/util/getPointAtLength.js +1 -1
  48. package/src/util/getPropertiesAtLength.js +3 -3
  49. package/src/util/getPropertiesAtPoint.js +2 -2
  50. package/src/util/getSegmentAtLength.js +2 -2
  51. package/src/util/getSegmentOfPoint.js +2 -2
  52. package/src/util/getTotalLength.js +1 -1
  53. package/src/util/isAbsoluteArray.js +1 -1
  54. package/src/util/isCurveArray.js +1 -1
  55. package/src/util/isNormalizedArray.js +1 -1
  56. package/src/util/isPathArray.js +1 -1
  57. package/src/util/isPointInStroke.js +2 -2
  58. package/src/util/isRelativeArray.js +1 -1
  59. package/src/util/pathLengthFactory.js +3 -2
  60. package/src/util/segmentArcFactory.js +1 -1
  61. package/src/util/segmentCubicFactory.js +1 -1
  62. package/src/util/segmentLineFactory.js +1 -1
  63. package/src/util/segmentQuadFactory.js +1 -1
  64. package/src/util/shapeToPath.js +13 -13
  65. package/src/util/util.js +0 -2
  66. package/types/index.d.ts +1 -3
  67. package/types/more/modules.ts +0 -3
  68. package/types/more/svg.d.ts +11 -10
  69. package/types/svg-path-commander.d.ts +214 -226
  70. package/src/util/createPath.js +0 -17
  71. package/src/util/getPointAtPathLength.js +0 -15
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * SVGPathCommander v0.1.25 (http://thednp.github.io/svg-path-commander)
2
+ * SVGPathCommander v0.2.0alpha3 (http://thednp.github.io/svg-path-commander)
3
3
  * Copyright 2022 © thednp
4
4
  * Licensed under MIT (https://github.com/thednp/svg-path-commander/blob/master/LICENSE)
5
5
  */
@@ -11,9 +11,9 @@
11
11
 
12
12
  /**
13
13
  * SVGPathCommander default options
14
- * @type {SVGPathCommander.options}
14
+ * @type {SVGPath.options}
15
15
  */
16
- var defaultOptions = {
16
+ const defaultOptions = {
17
17
  origin: [0, 0, 0],
18
18
  round: 4,
19
19
  };
@@ -22,19 +22,19 @@
22
22
  * Segment params length
23
23
  * @type {Record<string, number>}
24
24
  */
25
- var paramsCount = {
25
+ const paramsCount = {
26
26
  a: 7, c: 6, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, z: 0,
27
27
  };
28
28
 
29
29
  /**
30
30
  * Breaks the parsing of a pathString once a segment is finalized.
31
31
  *
32
- * @param {SVGPathCommander.PathParser} path the `PathParser` instance
32
+ * @param {SVGPath.PathParser} path the `PathParser` instance
33
33
  */
34
34
  function finalizeSegment(path) {
35
- var pathCommand = path.pathValue[path.segmentStart];
36
- var LK = pathCommand.toLowerCase();
37
- var data = path.data;
35
+ let pathCommand = path.pathValue[path.segmentStart];
36
+ let LK = pathCommand.toLowerCase();
37
+ let { data } = path;
38
38
 
39
39
  // Process duplicated commands (without comand name)
40
40
  if (LK === 'm' && data.length > 2) {
@@ -49,7 +49,7 @@
49
49
  while (data.length >= paramsCount[LK]) {
50
50
  // path.segments.push([pathCommand].concat(data.splice(0, paramsCount[LK])));
51
51
  // @ts-ignore
52
- path.segments.push([pathCommand ].concat( data.splice(0, paramsCount[LK])));
52
+ path.segments.push([pathCommand, ...data.splice(0, paramsCount[LK])]);
53
53
  // @ts-ignore
54
54
  if (!paramsCount[LK]) {
55
55
  break;
@@ -57,17 +57,17 @@
57
57
  }
58
58
  }
59
59
 
60
- var invalidPathValue = 'Invalid path value';
60
+ const error = 'SVGPathCommander error';
61
61
 
62
62
  /**
63
63
  * Validates an A (arc-to) specific path command value.
64
64
  * Usually a `large-arc-flag` or `sweep-flag`.
65
65
  *
66
- * @param {SVGPathCommander.PathParser} path the `PathParser` instance
66
+ * @param {SVGPath.PathParser} path the `PathParser` instance
67
67
  */
68
68
  function scanFlag(path) {
69
- var index = path.index;
70
- var ch = path.pathValue.charCodeAt(index);
69
+ const { index } = path;
70
+ const ch = path.pathValue.charCodeAt(index);
71
71
 
72
72
  if (ch === 0x30/* 0 */) {
73
73
  path.param = 0;
@@ -81,7 +81,7 @@
81
81
  return;
82
82
  }
83
83
 
84
- path.err = invalidPathValue + ": invalid Arc flag \"" + ch + "\", expecting 0 or 1 at index " + index;
84
+ path.err = `${error}: invalid Arc flag "${ch}", expecting 0 or 1 at index ${index}`;
85
85
  }
86
86
 
87
87
  /**
@@ -94,26 +94,26 @@
94
94
  return (code >= 48 && code <= 57); // 0..9
95
95
  }
96
96
 
97
+ const invalidPathValue = 'Invalid path value';
98
+
97
99
  /**
98
100
  * Validates every character of the path string,
99
101
  * every path command, negative numbers or floating point numbers.
100
102
  *
101
- * @param {SVGPathCommander.PathParser} path the `PathParser` instance
103
+ * @param {SVGPath.PathParser} path the `PathParser` instance
102
104
  */
103
105
  function scanParam(path) {
104
- var max = path.max;
105
- var pathValue = path.pathValue;
106
- var start = path.index;
107
- var index = start;
108
- var zeroFirst = false;
109
- var hasCeiling = false;
110
- var hasDecimal = false;
111
- var hasDot = false;
112
- var ch;
106
+ const { max, pathValue, index: start } = path;
107
+ let index = start;
108
+ let zeroFirst = false;
109
+ let hasCeiling = false;
110
+ let hasDecimal = false;
111
+ let hasDot = false;
112
+ let ch;
113
113
 
114
114
  if (index >= max) {
115
115
  // path.err = 'SvgPath: missed param (at pos ' + index + ')';
116
- path.err = invalidPathValue + " at " + index + ": missing param " + (pathValue[index]);
116
+ path.err = `${error}: ${invalidPathValue} at index ${index}, "pathValue" is missing param`;
117
117
  return;
118
118
  }
119
119
  ch = pathValue.charCodeAt(index);
@@ -127,7 +127,7 @@
127
127
  // https://github.com/ariya/esprimas
128
128
  if (!isDigit(ch) && ch !== 0x2E/* . */) {
129
129
  // path.err = 'SvgPath: param should start with 0..9 or `.` (at pos ' + index + ')';
130
- path.err = invalidPathValue + " at index " + index + ": " + (pathValue[index]) + " is not a number";
130
+ path.err = `${error}: ${invalidPathValue} at index ${index}, "${pathValue[index]}" is not a number`;
131
131
  return;
132
132
  }
133
133
 
@@ -142,7 +142,7 @@
142
142
  if (ch && isDigit(ch)) {
143
143
  // path.err = 'SvgPath: numbers started with `0` such as `09`
144
144
  // are illegal (at pos ' + start + ')';
145
- path.err = invalidPathValue + " at index " + start + ": " + (pathValue[start]) + " illegal number";
145
+ path.err = `${error}: ${invalidPathValue} at index ${start}, "${pathValue[start]}" illegal number`;
146
146
  return;
147
147
  }
148
148
  }
@@ -166,7 +166,7 @@
166
166
 
167
167
  if (ch === 0x65/* e */ || ch === 0x45/* E */) {
168
168
  if (hasDot && !hasCeiling && !hasDecimal) {
169
- path.err = invalidPathValue + " at index " + index + ": " + (pathValue[index]) + " invalid float exponent";
169
+ path.err = `${error}: ${invalidPathValue} at index ${index}, "${pathValue[index]}" invalid float exponent`;
170
170
  return;
171
171
  }
172
172
 
@@ -182,7 +182,7 @@
182
182
  }
183
183
  } else {
184
184
  // path.err = 'SvgPath: invalid float exponent (at pos ' + index + ')';
185
- path.err = invalidPathValue + " at index " + index + ": " + (pathValue[index]) + " invalid float exponent";
185
+ path.err = `${error}: ${invalidPathValue} at index ${index}: "${pathValue[index]}" invalid float exponent`;
186
186
  return;
187
187
  }
188
188
  }
@@ -198,7 +198,7 @@
198
198
  * @returns {boolean} check result
199
199
  */
200
200
  function isSpace(ch) {
201
- var specialSpaces = [
201
+ const specialSpaces = [
202
202
  0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006,
203
203
  0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF];
204
204
  return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029) // Line terminators
@@ -212,11 +212,10 @@
212
212
  * path string every time it encounters any kind of
213
213
  * space character.
214
214
  *
215
- * @param {SVGPathCommander.PathParser} path the `PathParser` instance
215
+ * @param {SVGPath.PathParser} path the `PathParser` instance
216
216
  */
217
217
  function skipSpaces(path) {
218
- var pathValue = path.pathValue;
219
- var max = path.max;
218
+ const { pathValue, max } = path;
220
219
  while (path.index < max && isSpace(pathValue.charCodeAt(path.index))) {
221
220
  path.index += 1;
222
221
  }
@@ -277,19 +276,17 @@
277
276
  * Scans every character in the path string to determine
278
277
  * where a segment starts and where it ends.
279
278
  *
280
- * @param {SVGPathCommander.PathParser} path the `PathParser` instance
279
+ * @param {SVGPath.PathParser} path the `PathParser` instance
281
280
  */
282
281
  function scanSegment(path) {
283
- var max = path.max;
284
- var pathValue = path.pathValue;
285
- var index = path.index;
286
- var cmdCode = pathValue.charCodeAt(index);
287
- var reqParams = paramsCount[pathValue[index].toLowerCase()];
282
+ const { max, pathValue, index } = path;
283
+ const cmdCode = pathValue.charCodeAt(index);
284
+ const reqParams = paramsCount[pathValue[index].toLowerCase()];
288
285
 
289
286
  path.segmentStart = index;
290
287
 
291
288
  if (!isPathCommand(cmdCode)) {
292
- path.err = invalidPathValue + ": " + (pathValue[index]) + " not a path command";
289
+ path.err = `${error}: ${invalidPathValue} "${pathValue[index]}" is not a path command`;
293
290
  return;
294
291
  }
295
292
 
@@ -305,9 +302,9 @@
305
302
  }
306
303
 
307
304
  for (;;) {
308
- for (var i = reqParams; i > 0; i -= 1) {
309
- if (isArcCommand(cmdCode) && (i === 3 || i === 4)) { scanFlag(path); }
310
- else { scanParam(path); }
305
+ for (let i = reqParams; i > 0; i -= 1) {
306
+ if (isArcCommand(cmdCode) && (i === 3 || i === 4)) scanFlag(path);
307
+ else scanParam(path);
311
308
 
312
309
  if (path.err.length) {
313
310
  return;
@@ -339,11 +336,11 @@
339
336
  /**
340
337
  * Returns a clone of an existing `pathArray`.
341
338
  *
342
- * @param {SVGPathCommander.pathArray | SVGPathCommander.pathSegment} path the source `pathArray`
339
+ * @param {SVGPath.pathArray | SVGPath.pathSegment} path the source `pathArray`
343
340
  * @returns {any} the cloned `pathArray`
344
341
  */
345
342
  function clonePath(path) {
346
- return path.map(function (x) { return (Array.isArray(x) ? [].concat( x ) : x); });
343
+ return path.map((x) => (Array.isArray(x) ? [...x] : x));
347
344
  }
348
345
 
349
346
  /**
@@ -353,7 +350,7 @@
353
350
  * @param {string} pathString
354
351
  */
355
352
  function PathParser(pathString) {
356
- /** @type {SVGPathCommander.pathArray} */
353
+ /** @type {SVGPath.pathArray} */
357
354
  // @ts-ignore
358
355
  this.segments = [];
359
356
  /** @type {string} */
@@ -375,12 +372,12 @@
375
372
  /**
376
373
  * Iterates an array to check if it's an actual `pathArray`.
377
374
  *
378
- * @param {string | SVGPathCommander.pathArray} path the `pathArray` to be checked
375
+ * @param {string | SVGPath.pathArray} path the `pathArray` to be checked
379
376
  * @returns {boolean} iteration result
380
377
  */
381
378
  function isPathArray(path) {
382
- return Array.isArray(path) && path.every(function (seg) {
383
- var lk = seg[0].toLowerCase();
379
+ return Array.isArray(path) && path.every((seg) => {
380
+ const lk = seg[0].toLowerCase();
384
381
  return paramsCount[lk] === seg.length - 1 && 'achlmqstvz'.includes(lk);
385
382
  });
386
383
  }
@@ -389,8 +386,8 @@
389
386
  * Parses a path string value and returns an array
390
387
  * of segments we like to call `pathArray`.
391
388
  *
392
- * @param {SVGPathCommander.pathArray | string} pathInput the string to be parsed
393
- * @returns {SVGPathCommander.pathArray} the resulted `pathArray`
389
+ * @param {SVGPath.pathArray | string} pathInput the string to be parsed
390
+ * @returns {SVGPath.pathArray | string} the resulted `pathArray`
394
391
  */
395
392
  function parsePathString(pathInput) {
396
393
  if (isPathArray(pathInput)) {
@@ -399,7 +396,7 @@
399
396
  }
400
397
 
401
398
  // @ts-ignore -- pathInput is now string
402
- var path = new PathParser(pathInput);
399
+ const path = new PathParser(pathInput);
403
400
 
404
401
  skipSpaces(path);
405
402
 
@@ -407,41 +404,36 @@
407
404
  scanSegment(path);
408
405
  }
409
406
 
410
- if (path.err.length) {
411
- // @ts-ignore
412
- path.segments = [];
413
- } else if (path.segments.length) {
407
+ if (!path.err.length) {
414
408
  if (!'mM'.includes(path.segments[0][0])) {
415
- path.err = invalidPathValue + ": missing M/m";
416
- // @ts-ignore
417
- path.segments = [];
409
+ path.err = `${error}: missing M/m`;
418
410
  } else {
419
411
  path.segments[0][0] = 'M';
420
412
  }
421
413
  }
422
414
 
423
- return path.segments;
415
+ return path.err ? path.err : path.segments;
424
416
  }
425
417
 
426
418
  /**
427
419
  * Iterates an array to check if it's a `pathArray`
428
420
  * with all absolute values.
429
421
  *
430
- * @param {string | SVGPathCommander.pathArray} path the `pathArray` to be checked
422
+ * @param {string | SVGPath.pathArray} path the `pathArray` to be checked
431
423
  * @returns {boolean} iteration result
432
424
  */
433
425
  function isAbsoluteArray(path) {
434
426
  return isPathArray(path)
435
427
  // @ts-ignore -- `isPathArray` also checks if it's `Array`
436
- && path.every(function (x) { return x[0] === x[0].toUpperCase(); });
428
+ && path.every((x) => x[0] === x[0].toUpperCase());
437
429
  }
438
430
 
439
431
  /**
440
432
  * Parses a path string value or object and returns an array
441
433
  * of segments, all converted to absolute values.
442
434
  *
443
- * @param {string | SVGPathCommander.pathArray} pathInput the path string | object
444
- * @returns {SVGPathCommander.absoluteArray} the resulted `pathArray` with absolute values
435
+ * @param {string | SVGPath.pathArray} pathInput the path string | object
436
+ * @returns {SVGPath.absoluteArray} the resulted `pathArray` with absolute values
445
437
  */
446
438
  function pathToAbsolute(pathInput) {
447
439
  if (isAbsoluteArray(pathInput)) {
@@ -449,29 +441,27 @@
449
441
  return clonePath(pathInput);
450
442
  }
451
443
 
452
- var path = parsePathString(pathInput);
453
- var x = 0; var y = 0;
454
- var mx = 0; var my = 0;
444
+ const path = parsePathString(pathInput);
445
+ let x = 0; let y = 0;
446
+ let mx = 0; let my = 0;
455
447
 
456
448
  // @ts-ignore -- the `absoluteSegment[]` is for sure an `absolutePath`
457
- return path.map(function (segment) {
458
- var assign, assign$1, assign$2;
459
-
460
- var values = segment.slice(1).map(Number);
461
- var pathCommand = segment[0];
462
- /** @type {SVGPathCommander.absoluteCommand} */
449
+ return path.map((segment) => {
450
+ const values = segment.slice(1).map(Number);
451
+ const [pathCommand] = segment;
452
+ /** @type {SVGPath.absoluteCommand} */
463
453
  // @ts-ignore
464
- var absCommand = pathCommand.toUpperCase();
454
+ const absCommand = pathCommand.toUpperCase();
465
455
 
466
456
  if (pathCommand === 'M') {
467
- (assign = values, x = assign[0], y = assign[1]);
457
+ [x, y] = values;
468
458
  mx = x;
469
459
  my = y;
470
460
  return ['M', x, y];
471
461
  }
472
- /** @type {SVGPathCommander.absoluteSegment} */
462
+ /** @type {SVGPath.absoluteSegment} */
473
463
  // @ts-ignore
474
- var absoluteSegment = [];
464
+ let absoluteSegment = [];
475
465
 
476
466
  if (pathCommand !== absCommand) {
477
467
  switch (absCommand) {
@@ -489,17 +479,17 @@
489
479
  default: {
490
480
  // use brakets for `eslint: no-case-declaration`
491
481
  // https://stackoverflow.com/a/50753272/803358
492
- var absValues = values.map(function (n, j) { return n + (j % 2 ? y : x); });
482
+ const absValues = values.map((n, j) => n + (j % 2 ? y : x));
493
483
  // @ts-ignore for n, l, c, s, q, t
494
- absoluteSegment = [absCommand ].concat( absValues);
484
+ absoluteSegment = [absCommand, ...absValues];
495
485
  }
496
486
  }
497
487
  } else {
498
488
  // @ts-ignore
499
- absoluteSegment = [absCommand ].concat( values);
489
+ absoluteSegment = [absCommand, ...values];
500
490
  }
501
491
 
502
- var segLength = absoluteSegment.length;
492
+ const segLength = absoluteSegment.length;
503
493
  switch (absCommand) {
504
494
  case 'Z':
505
495
  x = mx;
@@ -507,11 +497,11 @@
507
497
  break;
508
498
  case 'H':
509
499
  // @ts-ignore
510
- (assign$1 = absoluteSegment, x = assign$1[1]);
500
+ [, x] = absoluteSegment;
511
501
  break;
512
502
  case 'V':
513
503
  // @ts-ignore
514
- (assign$2 = absoluteSegment, y = assign$2[1]);
504
+ [, y] = absoluteSegment;
515
505
  break;
516
506
  default:
517
507
  // @ts-ignore
@@ -532,21 +522,21 @@
532
522
  * Iterates an array to check if it's a `pathArray`
533
523
  * with relative values.
534
524
  *
535
- * @param {string | SVGPathCommander.pathArray} path the `pathArray` to be checked
525
+ * @param {string | SVGPath.pathArray} path the `pathArray` to be checked
536
526
  * @returns {boolean} iteration result
537
527
  */
538
528
  function isRelativeArray(path) {
539
529
  return isPathArray(path)
540
530
  // @ts-ignore -- `isPathArray` checks if it's `Array`
541
- && path.slice(1).every(function (seg) { return seg[0] === seg[0].toLowerCase(); });
531
+ && path.slice(1).every((seg) => seg[0] === seg[0].toLowerCase());
542
532
  }
543
533
 
544
534
  /**
545
535
  * Parses a path string value or object and returns an array
546
536
  * of segments, all converted to relative values.
547
537
  *
548
- * @param {string | SVGPathCommander.pathArray} pathInput the path string | object
549
- * @returns {SVGPathCommander.relativeArray} the resulted `pathArray` with relative values
538
+ * @param {string | SVGPath.pathArray} pathInput the path string | object
539
+ * @returns {SVGPath.relativeArray} the resulted `pathArray` with relative values
550
540
  */
551
541
  function pathToRelative(pathInput) {
552
542
  if (isRelativeArray(pathInput)) {
@@ -554,30 +544,28 @@
554
544
  return clonePath(pathInput);
555
545
  }
556
546
 
557
- var path = parsePathString(pathInput);
558
- var x = 0; var y = 0;
559
- var mx = 0; var my = 0;
547
+ const path = parsePathString(pathInput);
548
+ let x = 0; let y = 0;
549
+ let mx = 0; let my = 0;
560
550
 
561
551
  // @ts-ignore -- this is actually a `relativeArray`
562
- return path.map(function (segment) {
563
- var assign, assign$1;
564
-
565
- var values = segment.slice(1).map(Number);
566
- var pathCommand = segment[0];
567
- /** @type {SVGPathCommander.relativeCommand} */
552
+ return path.map((segment) => {
553
+ const values = segment.slice(1).map(Number);
554
+ const [pathCommand] = segment;
555
+ /** @type {SVGPath.relativeCommand} */
568
556
  // @ts-ignore
569
- var relativeCommand = pathCommand.toLowerCase();
557
+ const relativeCommand = pathCommand.toLowerCase();
570
558
 
571
559
  if (pathCommand === 'M') {
572
- (assign = values, x = assign[0], y = assign[1]);
560
+ [x, y] = values;
573
561
  mx = x;
574
562
  my = y;
575
563
  return ['M', x, y];
576
564
  }
577
565
 
578
- /** @type {SVGPathCommander.relativeSegment} */
566
+ /** @type {SVGPath.relativeSegment} */
579
567
  // @ts-ignore -- trust me DON'T CHANGE
580
- var relativeSegment = [];
568
+ let relativeSegment = [];
581
569
 
582
570
  if (pathCommand !== relativeCommand) {
583
571
  switch (relativeCommand) {
@@ -595,12 +583,12 @@
595
583
  default: {
596
584
  // use brakets for `eslint: no-case-declaration`
597
585
  // https://stackoverflow.com/a/50753272/803358
598
- var relValues = values.map(function (n, j) { return n - (j % 2 ? y : x); });
586
+ const relValues = values.map((n, j) => n - (j % 2 ? y : x));
599
587
  // @ts-ignore for M, L, C, S, Q, T
600
- relativeSegment = [relativeCommand ].concat( relValues);
588
+ relativeSegment = [relativeCommand, ...relValues];
601
589
 
602
590
  if (relativeCommand === 'm') {
603
- (assign$1 = values, x = assign$1[0], y = assign$1[1]);
591
+ [x, y] = values;
604
592
  mx = x;
605
593
  my = y;
606
594
  }
@@ -612,10 +600,10 @@
612
600
  my = values[1] + y;
613
601
  }
614
602
  // @ts-ignore
615
- relativeSegment = [relativeCommand ].concat( values);
603
+ relativeSegment = [relativeCommand, ...values];
616
604
  }
617
605
 
618
- var segLength = relativeSegment.length;
606
+ const segLength = relativeSegment.length;
619
607
  switch (relativeCommand) {
620
608
  case 'z':
621
609
  x = mx;
@@ -642,7 +630,7 @@
642
630
  /**
643
631
  * Splits an extended A (arc-to) segment into two cubic-bezier segments.
644
632
  *
645
- * @param {SVGPathCommander.pathArray} path the `pathArray` this segment belongs to
633
+ * @param {SVGPath.pathArray} path the `pathArray` this segment belongs to
646
634
  * @param {string[]} allPathCommands all previous path commands
647
635
  * @param {number} i the segment index
648
636
  */
@@ -650,13 +638,13 @@
650
638
  function fixArc(path, allPathCommands, i) {
651
639
  if (path[i].length > 7) {
652
640
  path[i].shift();
653
- var segment = path[i];
654
- var ni = i; // ESLint
641
+ const segment = path[i];
642
+ let ni = i; // ESLint
655
643
  while (segment.length) {
656
644
  // if created multiple C:s, their original seg is saved
657
645
  allPathCommands[i] = 'A';
658
646
  // @ts-ignore
659
- path.splice(ni += 1, 0, ['C' ].concat( segment.splice(0, 6)));
647
+ path.splice(ni += 1, 0, ['C', ...segment.splice(0, 6)]);
660
648
  }
661
649
  path.splice(i, 1);
662
650
  }
@@ -693,25 +681,24 @@
693
681
  function shorthandToCubic(x1, y1, x2, y2, prevCommand) {
694
682
  return 'CS'.includes(prevCommand)
695
683
  ? { x1: x1 * 2 - x2, y1: y1 * 2 - y2 }
696
- : { x1: x1, y1: y1 };
684
+ : { x1, y1 };
697
685
  }
698
686
 
699
687
  /**
700
688
  * Normalizes a single segment of a `pathArray` object.
701
689
  *
702
- * @param {SVGPathCommander.pathSegment} segment the segment object
690
+ * @param {SVGPath.pathSegment} segment the segment object
703
691
  * @param {any} params the coordinates of the previous segment
704
692
  * @param {string} prevCommand the path command of the previous segment
705
- * @returns {SVGPathCommander.normalSegment} the normalized segment
693
+ * @returns {SVGPath.normalSegment} the normalized segment
706
694
  */
707
695
  function normalizeSegment(segment, params, prevCommand) {
708
- var pathCommand = segment[0];
709
- var px1 = params.x1;
710
- var py1 = params.y1;
711
- var px2 = params.x2;
712
- var py2 = params.y2;
713
- var values = segment.slice(1).map(Number);
714
- var result = segment;
696
+ const [pathCommand] = segment;
697
+ const {
698
+ x1: px1, y1: py1, x2: px2, y2: py2,
699
+ } = params;
700
+ const values = segment.slice(1).map(Number);
701
+ let result = segment;
715
702
 
716
703
  if (!'TQ'.includes(pathCommand)) {
717
704
  // optional but good to be cautious
@@ -724,24 +711,19 @@
724
711
  } else if (pathCommand === 'V') {
725
712
  result = ['L', px1, segment[1]];
726
713
  } else if (pathCommand === 'S') {
727
- var ref = shorthandToCubic(px1, py1, px2, py2, prevCommand);
728
- var x1 = ref.x1;
729
- var y1 = ref.y1;
714
+ const { x1, y1 } = shorthandToCubic(px1, py1, px2, py2, prevCommand);
730
715
  params.x1 = x1;
731
716
  params.y1 = y1;
732
717
  // @ts-ignore
733
- result = ['C', x1, y1 ].concat( values);
718
+ result = ['C', x1, y1, ...values];
734
719
  } else if (pathCommand === 'T') {
735
- var ref$1 = shorthandToQuad(px1, py1, params.qx, params.qy, prevCommand);
736
- var qx = ref$1.qx;
737
- var qy = ref$1.qy;
720
+ const { qx, qy } = shorthandToQuad(px1, py1, params.qx, params.qy, prevCommand);
738
721
  params.qx = qx;
739
722
  params.qy = qy;
740
723
  // @ts-ignore
741
- result = ['Q', qx, qy ].concat( values);
724
+ result = ['Q', qx, qy, ...values];
742
725
  } else if (pathCommand === 'Q') {
743
- var nqx = values[0];
744
- var nqy = values[1];
726
+ const [nqx, nqy] = values;
745
727
  params.qx = nqx;
746
728
  params.qy = nqy;
747
729
  }
@@ -755,18 +737,18 @@
755
737
  * with all segments are in non-shorthand notation
756
738
  * with absolute values.
757
739
  *
758
- * @param {string | SVGPathCommander.pathArray} path the `pathArray` to be checked
740
+ * @param {string | SVGPath.pathArray} path the `pathArray` to be checked
759
741
  * @returns {boolean} iteration result
760
742
  */
761
743
  function isNormalizedArray(path) {
762
744
  // @ts-ignore -- `isAbsoluteArray` also checks if it's `Array`
763
- return isAbsoluteArray(path) && path.every(function (seg) { return 'ACLMQZ'.includes(seg[0]); });
745
+ return isAbsoluteArray(path) && path.every((seg) => 'ACLMQZ'.includes(seg[0]));
764
746
  }
765
747
 
766
748
  /**
767
- * @type {SVGPathCommander.parserParams}
749
+ * @type {SVGPath.parserParams}
768
750
  */
769
- var paramsParser = {
751
+ const paramsParser = {
770
752
  x1: 0, y1: 0, x2: 0, y2: 0, x: 0, y: 0, qx: null, qy: null,
771
753
  };
772
754
 
@@ -775,39 +757,37 @@
775
757
  * * convert segments to absolute values
776
758
  * * convert shorthand path commands to their non-shorthand notation
777
759
  *
778
- * @param {string | SVGPathCommander.pathArray} pathInput the string to be parsed or 'pathArray'
779
- * @returns {SVGPathCommander.normalArray} the normalized `pathArray`
760
+ * @param {string | SVGPath.pathArray} pathInput the string to be parsed or 'pathArray'
761
+ * @returns {SVGPath.normalArray} the normalized `pathArray`
780
762
  */
781
763
  function normalizePath(pathInput) {
782
- var assign;
783
-
784
764
  if (isNormalizedArray(pathInput)) {
785
765
  // @ts-ignore -- `isNormalizedArray` checks if it's `pathArray`
786
766
  return clonePath(pathInput);
787
767
  }
788
768
 
789
- /** @type {SVGPathCommander.normalArray} */
769
+ /** @type {SVGPath.normalArray} */
790
770
  // @ts-ignore -- `absoluteArray` will become a `normalArray`
791
- var path = pathToAbsolute(pathInput);
792
- var params = Object.assign({}, paramsParser);
793
- var allPathCommands = [];
794
- var ii = path.length;
795
- var pathCommand = '';
796
- var prevCommand = '';
771
+ const path = pathToAbsolute(pathInput);
772
+ const params = { ...paramsParser };
773
+ const allPathCommands = [];
774
+ const ii = path.length;
775
+ let pathCommand = '';
776
+ let prevCommand = '';
797
777
 
798
- for (var i = 0; i < ii; i += 1) {
799
- (assign = path[i], pathCommand = assign[0]);
778
+ for (let i = 0; i < ii; i += 1) {
779
+ [pathCommand] = path[i];
800
780
 
801
781
  // Save current path command
802
782
  allPathCommands[i] = pathCommand;
803
783
  // Get previous path command
804
- if (i) { prevCommand = allPathCommands[i - 1]; }
784
+ if (i) prevCommand = allPathCommands[i - 1];
805
785
  // Previous path command is used to normalizeSegment
806
786
  // @ts-ignore -- expected on normalization
807
787
  path[i] = normalizeSegment(path[i], params, prevCommand);
808
788
 
809
- var segment = path[i];
810
- var seglen = segment.length;
789
+ const segment = path[i];
790
+ const seglen = segment.length;
811
791
 
812
792
  params.x1 = +segment[seglen - 2];
813
793
  params.y1 = +segment[seglen - 1];
@@ -827,22 +807,18 @@
827
807
  * use `splitPath` first and apply this utility on each
828
808
  * sub-path separately.
829
809
  *
830
- * @param {SVGPathCommander.pathArray | string} pathInput the `pathArray` source
831
- * @return {SVGPathCommander.pathArray} a fixed `pathArray`
810
+ * @param {SVGPath.pathArray | string} pathInput the `pathArray` source
811
+ * @return {SVGPath.pathArray} a fixed `pathArray`
832
812
  */
833
813
  function fixPath(pathInput) {
834
- var pathArray = parsePathString(pathInput);
835
- var normalArray = normalizePath(pathArray);
836
- var length = pathArray.length;
837
- var isClosed = normalArray.slice(-1)[0][0] === 'Z';
838
- var segBeforeZ = isClosed ? length - 2 : length - 1;
839
-
840
- var ref = normalArray[0].slice(1);
841
- var mx = ref[0];
842
- var my = ref[1];
843
- var ref$1 = normalArray[segBeforeZ].slice(-2);
844
- var x = ref$1[0];
845
- var y = ref$1[1];
814
+ const pathArray = parsePathString(pathInput);
815
+ const normalArray = normalizePath(pathArray);
816
+ const { length } = pathArray;
817
+ const isClosed = normalArray.slice(-1)[0][0] === 'Z';
818
+ const segBeforeZ = isClosed ? length - 2 : length - 1;
819
+
820
+ const [mx, my] = normalArray[0].slice(1);
821
+ const [x, y] = normalArray[segBeforeZ].slice(-2);
846
822
 
847
823
  if (isClosed && mx === x && my === y) {
848
824
  // @ts-ignore -- `pathSegment[]` is quite a `pathArray`
@@ -855,12 +831,12 @@
855
831
  * Iterates an array to check if it's a `pathArray`
856
832
  * with all C (cubic bezier) segments.
857
833
  *
858
- * @param {string | SVGPathCommander.pathArray} path the `Array` to be checked
834
+ * @param {string | SVGPath.pathArray} path the `Array` to be checked
859
835
  * @returns {boolean} iteration result
860
836
  */
861
837
  function isCurveArray(path) {
862
838
  // @ts-ignore -- `isPathArray` also checks if it's `Array`
863
- return isPathArray(path) && path.every(function (seg) { return 'MC'.includes(seg[0]); });
839
+ return isPathArray(path) && path.every((seg) => 'MC'.includes(seg[0]));
864
840
  }
865
841
 
866
842
  /**
@@ -873,8 +849,8 @@
873
849
  * @returns {{x: number, y: number}} the rotated vector
874
850
  */
875
851
  function rotateVector(x, y, rad) {
876
- var X = x * Math.cos(rad) - y * Math.sin(rad);
877
- var Y = x * Math.sin(rad) + y * Math.cos(rad);
852
+ const X = x * Math.cos(rad) - y * Math.sin(rad);
853
+ const Y = x * Math.sin(rad) + y * Math.cos(rad);
878
854
  return { x: X, y: Y };
879
855
  }
880
856
 
@@ -897,21 +873,19 @@
897
873
  * @return {number[]} the resulting cubic-bezier segment(s)
898
874
  */
899
875
  function arcToCubic(X1, Y1, RX, RY, angle, LAF, SF, X2, Y2, recursive) {
900
- var assign;
901
-
902
- var x1 = X1; var y1 = Y1; var rx = RX; var ry = RY; var x2 = X2; var y2 = Y2;
876
+ let x1 = X1; let y1 = Y1; let rx = RX; let ry = RY; let x2 = X2; let y2 = Y2;
903
877
  // for more information of where this Math came from visit:
904
878
  // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
905
- var d120 = (Math.PI * 120) / 180;
879
+ const d120 = (Math.PI * 120) / 180;
906
880
 
907
- var rad = (Math.PI / 180) * (+angle || 0);
881
+ const rad = (Math.PI / 180) * (+angle || 0);
908
882
  /** @type {number[]} */
909
- var res = [];
910
- var xy;
911
- var f1;
912
- var f2;
913
- var cx;
914
- var cy;
883
+ let res = [];
884
+ let xy;
885
+ let f1;
886
+ let f2;
887
+ let cx;
888
+ let cy;
915
889
 
916
890
  if (!recursive) {
917
891
  xy = rotateVector(x1, y1, -rad);
@@ -921,32 +895,32 @@
921
895
  x2 = xy.x;
922
896
  y2 = xy.y;
923
897
 
924
- var x = (x1 - x2) / 2;
925
- var y = (y1 - y2) / 2;
926
- var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
898
+ const x = (x1 - x2) / 2;
899
+ const y = (y1 - y2) / 2;
900
+ let h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
927
901
  if (h > 1) {
928
902
  h = Math.sqrt(h);
929
903
  rx *= h;
930
904
  ry *= h;
931
905
  }
932
- var rx2 = rx * rx;
933
- var ry2 = ry * ry;
906
+ const rx2 = rx * rx;
907
+ const ry2 = ry * ry;
934
908
 
935
- var k = (LAF === SF ? -1 : 1)
909
+ const k = (LAF === SF ? -1 : 1)
936
910
  * Math.sqrt(Math.abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x)
937
911
  / (rx2 * y * y + ry2 * x * x)));
938
912
 
939
913
  cx = ((k * rx * y) / ry) + ((x1 + x2) / 2);
940
914
  cy = ((k * -ry * x) / rx) + ((y1 + y2) / 2);
941
915
  // eslint-disable-next-line no-bitwise -- Impossible to satisfy no-bitwise
942
- f1 = (Math.asin((((y1 - cy) / ry))) * (Math.pow( 10, 9 )) >> 0) / (Math.pow( 10, 9 ));
916
+ f1 = (Math.asin((((y1 - cy) / ry))) * (10 ** 9) >> 0) / (10 ** 9);
943
917
  // eslint-disable-next-line no-bitwise -- Impossible to satisfy no-bitwise
944
- f2 = (Math.asin((((y2 - cy) / ry))) * (Math.pow( 10, 9 )) >> 0) / (Math.pow( 10, 9 ));
918
+ f2 = (Math.asin((((y2 - cy) / ry))) * (10 ** 9) >> 0) / (10 ** 9);
945
919
 
946
920
  f1 = x1 < cx ? Math.PI - f1 : f1;
947
921
  f2 = x2 < cx ? Math.PI - f2 : f2;
948
- if (f1 < 0) { (f1 = Math.PI * 2 + f1); }
949
- if (f2 < 0) { (f2 = Math.PI * 2 + f2); }
922
+ if (f1 < 0) (f1 = Math.PI * 2 + f1);
923
+ if (f2 < 0) (f2 = Math.PI * 2 + f2);
950
924
  if (SF && f1 > f2) {
951
925
  f1 -= Math.PI * 2;
952
926
  }
@@ -954,38 +928,38 @@
954
928
  f2 -= Math.PI * 2;
955
929
  }
956
930
  } else {
957
- (assign = recursive, f1 = assign[0], f2 = assign[1], cx = assign[2], cy = assign[3]);
931
+ [f1, f2, cx, cy] = recursive;
958
932
  }
959
- var df = f2 - f1;
933
+ let df = f2 - f1;
960
934
  if (Math.abs(df) > d120) {
961
- var f2old = f2;
962
- var x2old = x2;
963
- var y2old = y2;
935
+ const f2old = f2;
936
+ const x2old = x2;
937
+ const y2old = y2;
964
938
  f2 = f1 + d120 * (SF && f2 > f1 ? 1 : -1);
965
939
  x2 = cx + rx * Math.cos(f2);
966
940
  y2 = cy + ry * Math.sin(f2);
967
941
  res = arcToCubic(x2, y2, rx, ry, angle, 0, SF, x2old, y2old, [f2, f2old, cx, cy]);
968
942
  }
969
943
  df = f2 - f1;
970
- var c1 = Math.cos(f1);
971
- var s1 = Math.sin(f1);
972
- var c2 = Math.cos(f2);
973
- var s2 = Math.sin(f2);
974
- var t = Math.tan(df / 4);
975
- var hx = (4 / 3) * rx * t;
976
- var hy = (4 / 3) * ry * t;
977
- var m1 = [x1, y1];
978
- var m2 = [x1 + hx * s1, y1 - hy * c1];
979
- var m3 = [x2 + hx * s2, y2 - hy * c2];
980
- var m4 = [x2, y2];
944
+ const c1 = Math.cos(f1);
945
+ const s1 = Math.sin(f1);
946
+ const c2 = Math.cos(f2);
947
+ const s2 = Math.sin(f2);
948
+ const t = Math.tan(df / 4);
949
+ const hx = (4 / 3) * rx * t;
950
+ const hy = (4 / 3) * ry * t;
951
+ const m1 = [x1, y1];
952
+ const m2 = [x1 + hx * s1, y1 - hy * c1];
953
+ const m3 = [x2 + hx * s2, y2 - hy * c2];
954
+ const m4 = [x2, y2];
981
955
  m2[0] = 2 * m1[0] - m2[0];
982
956
  m2[1] = 2 * m1[1] - m2[1];
983
957
  if (recursive) {
984
- return m2.concat( m3, m4, res);
958
+ return [...m2, ...m3, ...m4, ...res];
985
959
  }
986
- res = m2.concat( m3, m4, res);
987
- var newres = [];
988
- for (var i = 0, ii = res.length; i < ii; i += 1) {
960
+ res = [...m2, ...m3, ...m4, ...res];
961
+ const newres = [];
962
+ for (let i = 0, ii = res.length; i < ii; i += 1) {
989
963
  newres[i] = i % 2
990
964
  ? rotateVector(res[i - 1], res[i], rad).y
991
965
  : rotateVector(res[i], res[i + 1], rad).x;
@@ -1005,14 +979,15 @@
1005
979
  * @returns {number[]} the cubic-bezier segment
1006
980
  */
1007
981
  function quadToCubic(x1, y1, qx, qy, x2, y2) {
1008
- var r13 = 1 / 3;
1009
- var r23 = 2 / 3;
982
+ const r13 = 1 / 3;
983
+ const r23 = 2 / 3;
1010
984
  return [
1011
985
  r13 * x1 + r23 * qx, // cpx1
1012
986
  r13 * y1 + r23 * qy, // cpy1
1013
987
  r13 * x2 + r23 * qx, // cpx2
1014
988
  r13 * y2 + r23 * qy, // cpy2
1015
- x2, y2 ];
989
+ x2, y2, // x,y
990
+ ];
1016
991
  }
1017
992
 
1018
993
  /**
@@ -1025,9 +1000,7 @@
1025
1000
  * @returns {[number, number]} the midpoint coordinates
1026
1001
  */
1027
1002
  function midPoint(a, b, t) {
1028
- var ax = a[0];
1029
- var ay = a[1]; var bx = b[0];
1030
- var by = b[1];
1003
+ const [ax, ay] = a; const [bx, by] = b;
1031
1004
  return [ax + (bx - ax) * t, ay + (by - ay) * t];
1032
1005
  }
1033
1006
 
@@ -1042,12 +1015,12 @@
1042
1015
  function distanceSquareRoot(a, b) {
1043
1016
  return Math.sqrt(
1044
1017
  (a[0] - b[0]) * (a[0] - b[0])
1045
- + (a[1] - b[1]) * (a[1] - b[1])
1018
+ + (a[1] - b[1]) * (a[1] - b[1]),
1046
1019
  );
1047
1020
  }
1048
1021
 
1049
1022
  /**
1050
- * Returns the length of a line (L,V,H,Z) segment,
1023
+ * Returns the length of a line (L,V,H,Z) segment
1051
1024
  * or a point at a given length.
1052
1025
  *
1053
1026
  * @param {number} x1 the starting point X
@@ -1058,8 +1031,8 @@
1058
1031
  * @returns {{x: number, y: number} | number} the segment length or point
1059
1032
  */
1060
1033
  function segmentLineFactory(x1, y1, x2, y2, distance) {
1061
- var length = distanceSquareRoot([x1, y1], [x2, y2]);
1062
- var margin = 0.001;
1034
+ const length = distanceSquareRoot([x1, y1], [x2, y2]);
1035
+ const margin = 0.001;
1063
1036
 
1064
1037
  if (typeof distance === 'number') {
1065
1038
  if (distance < margin) {
@@ -1068,10 +1041,8 @@
1068
1041
  if (distance > length) {
1069
1042
  return { x: x2, y: y2 };
1070
1043
  }
1071
- var ref = midPoint([x1, y1], [x2, y2], distance / length);
1072
- var x = ref[0];
1073
- var y = ref[1];
1074
- return { x: x, y: y };
1044
+ const [x, y] = midPoint([x1, y1], [x2, y2], distance / length);
1045
+ return { x, y };
1075
1046
  }
1076
1047
  return length;
1077
1048
  }
@@ -1086,22 +1057,22 @@
1086
1057
  * @returns {number[]} the cubic-bezier segment
1087
1058
  */
1088
1059
  function lineToCubic(x1, y1, x2, y2) {
1089
- var t = 0.5;
1060
+ const t = 0.5;
1090
1061
  /** @type {[number, number]} */
1091
- var p0 = [x1, y1];
1062
+ const p0 = [x1, y1];
1092
1063
  /** @type {[number, number]} */
1093
- var p1 = [x2, y2];
1094
- var p2 = midPoint(p0, p1, t);
1095
- var p3 = midPoint(p1, p2, t);
1096
- var p4 = midPoint(p2, p3, t);
1097
- var p5 = midPoint(p3, p4, t);
1098
- var p6 = midPoint(p4, p5, t);
1099
- var seg1 = p0.concat( p2, p4, p6, [t]);
1064
+ const p1 = [x2, y2];
1065
+ const p2 = midPoint(p0, p1, t);
1066
+ const p3 = midPoint(p1, p2, t);
1067
+ const p4 = midPoint(p2, p3, t);
1068
+ const p5 = midPoint(p3, p4, t);
1069
+ const p6 = midPoint(p4, p5, t);
1070
+ const seg1 = [...p0, ...p2, ...p4, ...p6, t];
1100
1071
  // @ts-ignore
1101
- var cp1 = segmentLineFactory.apply(void 0, seg1);
1102
- var seg2 = p6.concat( p5, p3, p1, [0]);
1072
+ const cp1 = segmentLineFactory(...seg1);
1073
+ const seg2 = [...p6, ...p5, ...p3, ...p1, 0];
1103
1074
  // @ts-ignore
1104
- var cp2 = segmentLineFactory.apply(void 0, seg2);
1075
+ const cp2 = segmentLineFactory(...seg2);
1105
1076
 
1106
1077
  // @ts-ignore
1107
1078
  return [cp1.x, cp1.y, cp2.x, cp2.y, x2, y2];
@@ -1110,20 +1081,18 @@
1110
1081
  /**
1111
1082
  * Converts any segment to C (cubic-bezier).
1112
1083
  *
1113
- * @param {SVGPathCommander.pathSegment} segment the source segment
1114
- * @param {SVGPathCommander.parserParams} params the source segment parameters
1115
- * @returns {SVGPathCommander.cubicSegment | SVGPathCommander.MSegment} the cubic-bezier segment
1084
+ * @param {SVGPath.pathSegment} segment the source segment
1085
+ * @param {SVGPath.parserParams} params the source segment parameters
1086
+ * @returns {SVGPath.cubicSegment | SVGPath.MSegment} the cubic-bezier segment
1116
1087
  */
1117
1088
  function segmentToCubic(segment, params) {
1118
- var pathCommand = segment[0];
1119
- var values = segment.slice(1).map(function (n) { return +n; });
1120
- var x = values[0];
1121
- var y = values[1];
1122
- var args;
1123
- var px1 = params.x1;
1124
- var py1 = params.y1;
1125
- var px = params.x;
1126
- var py = params.y;
1089
+ const [pathCommand] = segment;
1090
+ const values = segment.slice(1).map((n) => +n);
1091
+ const [x, y] = values;
1092
+ let args;
1093
+ const {
1094
+ x1: px1, y1: py1, x: px, y: py,
1095
+ } = params;
1127
1096
 
1128
1097
  if (!'TQ'.includes(pathCommand)) {
1129
1098
  params.qx = null;
@@ -1136,21 +1105,21 @@
1136
1105
  params.y = y;
1137
1106
  return segment;
1138
1107
  case 'A':
1139
- args = [px1, py1 ].concat( values);
1108
+ args = [px1, py1, ...values];
1140
1109
  // @ts-ignore -- relax, the utility will return 6 numbers
1141
- return ['C' ].concat( arcToCubic.apply(void 0, args));
1110
+ return ['C', ...arcToCubic(...args)];
1142
1111
  case 'Q':
1143
1112
  params.qx = x;
1144
1113
  params.qy = y;
1145
- args = [px1, py1 ].concat( values);
1114
+ args = [px1, py1, ...values];
1146
1115
  // @ts-ignore -- also returning 6 numbers
1147
- return ['C' ].concat( quadToCubic.apply(void 0, args));
1116
+ return ['C', ...quadToCubic(...args)];
1148
1117
  case 'L':
1149
1118
  // @ts-ignore -- also returning 6 numbers
1150
- return ['C' ].concat( lineToCubic(px1, py1, x, y));
1119
+ return ['C', ...lineToCubic(px1, py1, x, y)];
1151
1120
  case 'Z':
1152
1121
  // @ts-ignore -- also returning 6 numbers
1153
- return ['C' ].concat( lineToCubic(px1, py1, px, py));
1122
+ return ['C', ...lineToCubic(px1, py1, px, py)];
1154
1123
  }
1155
1124
  // @ts-ignore -- we're switching `pathSegment` type
1156
1125
  return segment;
@@ -1163,25 +1132,23 @@
1163
1132
  * In addition, un-necessary `Z` segment is removed if previous segment
1164
1133
  * extends to the `M` segment.
1165
1134
  *
1166
- * @param {string | SVGPathCommander.pathArray} pathInput the string to be parsed or 'pathArray'
1167
- * @returns {SVGPathCommander.curveArray} the resulted `pathArray` converted to cubic-bezier
1135
+ * @param {string | SVGPath.pathArray} pathInput the string to be parsed or 'pathArray'
1136
+ * @returns {SVGPath.curveArray} the resulted `pathArray` converted to cubic-bezier
1168
1137
  */
1169
1138
  function pathToCurve(pathInput) {
1170
- var assign;
1171
-
1172
1139
  if (isCurveArray(pathInput)) {
1173
1140
  // @ts-ignore -- `isCurveArray` checks if it's `pathArray`
1174
1141
  return clonePath(pathInput);
1175
1142
  }
1176
1143
 
1177
- var path = fixPath(normalizePath(pathInput));
1178
- var params = Object.assign({}, paramsParser);
1179
- var allPathCommands = [];
1180
- var pathCommand = ''; // ts-lint
1181
- var ii = path.length;
1144
+ const path = fixPath(normalizePath(pathInput));
1145
+ const params = { ...paramsParser };
1146
+ const allPathCommands = [];
1147
+ let pathCommand = ''; // ts-lint
1148
+ let ii = path.length;
1182
1149
 
1183
- for (var i = 0; i < ii; i += 1) {
1184
- (assign = path[i], pathCommand = assign[0]);
1150
+ for (let i = 0; i < ii; i += 1) {
1151
+ [pathCommand] = path[i];
1185
1152
  allPathCommands[i] = pathCommand;
1186
1153
 
1187
1154
  path[i] = segmentToCubic(path[i], params);
@@ -1189,8 +1156,8 @@
1189
1156
  fixArc(path, allPathCommands, i);
1190
1157
  ii = path.length;
1191
1158
 
1192
- var segment = path[i];
1193
- var seglen = segment.length;
1159
+ const segment = path[i];
1160
+ const seglen = segment.length;
1194
1161
  params.x1 = +segment[seglen - 2];
1195
1162
  params.y1 = +segment[seglen - 1];
1196
1163
  params.x2 = +(segment[seglen - 4]) || params.x1;
@@ -1205,24 +1172,25 @@
1205
1172
  * Rounds the values of a `pathArray` instance to
1206
1173
  * a specified amount of decimals and returns it.
1207
1174
  *
1208
- * @param {SVGPathCommander.pathArray} path the source `pathArray`
1209
- * @param {number | boolean} roundOption the amount of decimals to round numbers to
1210
- * @returns {SVGPathCommander.pathArray} the resulted `pathArray` with rounded values
1175
+ * @param {SVGPath.pathArray} path the source `pathArray`
1176
+ * @param {number | false} roundOption the amount of decimals to round numbers to
1177
+ * @returns {SVGPath.pathArray} the resulted `pathArray` with rounded values
1211
1178
  */
1212
1179
  function roundPath(path, roundOption) {
1213
- var round = defaultOptions.round;
1214
- if (roundOption === false || round === false) { return clonePath(path); }
1215
- round = roundOption >= 1 ? roundOption : round;
1180
+ let { round } = defaultOptions;
1181
+ if (roundOption === false || round === false) return clonePath(path);
1182
+ // round = roundOption >= 1 ? roundOption : round;
1183
+ // allow for ZERO decimals
1184
+ round = roundOption >= 0 ? roundOption : round;
1216
1185
  // to round values to the power
1217
1186
  // the `round` value must be integer
1218
- // @ts-ignore
1219
- var pow = round >= 1 ? (Math.pow( 10, round )) : 1;
1187
+ const pow = round >= 1 ? (10 ** round) : 1;
1220
1188
 
1221
1189
  // @ts-ignore -- `pathSegment[]` is `pathArray`
1222
- return path.map(function (pi) {
1223
- var values = pi.slice(1).map(Number)
1224
- .map(function (n) { return (n % 1 === 0 ? n : Math.round(n * pow) / pow); });
1225
- return [pi[0] ].concat( values);
1190
+ return path.map((pi) => {
1191
+ const values = pi.slice(1).map(Number)
1192
+ .map((n) => (round ? (Math.round(n * pow) / pow) : Math.round(n)));
1193
+ return [pi[0], ...values];
1226
1194
  });
1227
1195
  }
1228
1196
 
@@ -1230,50 +1198,47 @@
1230
1198
  * Returns a valid `d` attribute string value created
1231
1199
  * by rounding values and concatenating the `pathArray` segments.
1232
1200
  *
1233
- * @param {SVGPathCommander.pathArray} path the `pathArray` object
1234
- * @param {any} round amount of decimals to round values to
1201
+ * @param {SVGPath.pathArray} path the `pathArray` object
1202
+ * @param {number | false} round amount of decimals to round values to
1235
1203
  * @returns {string} the concatenated path string
1236
1204
  */
1237
1205
  function pathToString(path, round) {
1238
1206
  return roundPath(path, round)
1239
- .map(function (x) { return x[0] + x.slice(1).join(' '); }).join('');
1207
+ .map((x) => x[0] + x.slice(1).join(' ')).join('');
1240
1208
  }
1241
1209
 
1242
1210
  /**
1243
- * Reverses all segments and their values of a `pathArray`
1244
- * and returns a new instance.
1211
+ * Reverses all segments of a `pathArray` and returns a new `pathArray` instance.
1245
1212
  *
1246
- * @param {SVGPathCommander.pathArray} pathInput the source `pathArray`
1247
- * @returns {SVGPathCommander.pathArray} the reversed `pathArray`
1213
+ * @param {SVGPath.pathArray} pathInput the source `pathArray`
1214
+ * @returns {SVGPath.pathArray} the reversed `pathArray`
1248
1215
  */
1249
1216
  function reversePath(pathInput) {
1250
- var absolutePath = pathToAbsolute(pathInput);
1251
- var isClosed = absolutePath.slice(-1)[0][0] === 'Z';
1217
+ const absolutePath = pathToAbsolute(pathInput);
1218
+ const isClosed = absolutePath.slice(-1)[0][0] === 'Z';
1252
1219
 
1253
- var reversedPath = normalizePath(absolutePath).map(function (segment, i) {
1254
- var ref = segment.slice(-2).map(Number);
1255
- var x = ref[0];
1256
- var y = ref[1];
1220
+ const reversedPath = normalizePath(absolutePath).map((segment, i) => {
1221
+ const [x, y] = segment.slice(-2).map(Number);
1257
1222
  return {
1258
1223
  seg: absolutePath[i], // absolute
1259
1224
  n: segment, // normalized
1260
1225
  c: absolutePath[i][0], // pathCommand
1261
- x: x, // x
1262
- y: y, // y
1226
+ x, // x
1227
+ y, // y
1263
1228
  };
1264
- }).map(function (seg, i, path) {
1265
- var segment = seg.seg;
1266
- var data = seg.n;
1267
- var prevSeg = i && path[i - 1];
1268
- var nextSeg = path[i + 1] && path[i + 1];
1269
- var pathCommand = seg.c;
1270
- var pLen = path.length;
1229
+ }).map((seg, i, path) => {
1230
+ const segment = seg.seg;
1231
+ const data = seg.n;
1232
+ const prevSeg = i && path[i - 1];
1233
+ const nextSeg = path[i + 1] && path[i + 1];
1234
+ const pathCommand = seg.c;
1235
+ const pLen = path.length;
1271
1236
  /** @type {number} */
1272
- var x = i ? path[i - 1].x : path[pLen - 1].x;
1273
- var y = i ? path[i - 1].y : path[pLen - 1].y;
1274
- /** @type {SVGPathCommander.pathSegment} */
1237
+ const x = i ? path[i - 1].x : path[pLen - 1].x;
1238
+ const y = i ? path[i - 1].y : path[pLen - 1].y;
1239
+ /** @type {SVGPath.pathSegment} */
1275
1240
  // @ts-ignore
1276
- var result = [];
1241
+ let result = [];
1277
1242
 
1278
1243
  switch (pathCommand) {
1279
1244
  case 'M':
@@ -1281,7 +1246,7 @@
1281
1246
  break;
1282
1247
  case 'A':
1283
1248
  // @ts-ignore -- expected on reverse
1284
- result = [pathCommand ].concat( segment.slice(1, -3), [(segment[5] === 1 ? 0 : 1)], [x], [y]);
1249
+ result = [pathCommand, ...segment.slice(1, -3), (segment[5] === 1 ? 0 : 1), x, y];
1285
1250
  break;
1286
1251
  case 'C':
1287
1252
  if (nextSeg && nextSeg.c === 'S') {
@@ -1306,7 +1271,7 @@
1306
1271
  result = ['T', x, y];
1307
1272
  } else {
1308
1273
  // @ts-ignore -- expected on reverse
1309
- result = [pathCommand ].concat( segment.slice(1, -2), [x], [y]);
1274
+ result = [pathCommand, ...segment.slice(1, -2), x, y];
1310
1275
  }
1311
1276
  break;
1312
1277
  case 'T':
@@ -1328,7 +1293,7 @@
1328
1293
  break;
1329
1294
  default:
1330
1295
  // @ts-ignore -- expected on reverse
1331
- result = [pathCommand ].concat( segment.slice(1, -2), [x], [y]);
1296
+ result = [pathCommand, ...segment.slice(1, -2), x, y];
1332
1297
  }
1333
1298
 
1334
1299
  return result;
@@ -1336,7 +1301,7 @@
1336
1301
 
1337
1302
  // @ts-ignore -- `pathSegment[]` is definitely `pathArray`
1338
1303
  return isClosed ? reversedPath.reverse()
1339
- : [reversedPath[0] ].concat( reversedPath.slice(1).reverse());
1304
+ : [reversedPath[0], ...reversedPath.slice(1).reverse()];
1340
1305
  }
1341
1306
 
1342
1307
  /**
@@ -1345,41 +1310,36 @@
1345
1310
  * In the process, values are converted to absolute
1346
1311
  * for visual consistency.
1347
1312
  *
1348
- * @param {SVGPathCommander.pathArray | string} pathInput the source `pathArray`
1313
+ * @param {SVGPath.pathArray | string} pathInput the source `pathArray`
1349
1314
  * @return {string[]} an array with all sub-path strings
1350
1315
  */
1351
1316
  function splitPath(pathInput) {
1352
1317
  return pathToString(pathToAbsolute(pathInput), 0)
1353
1318
  .replace(/(m|M)/g, '|$1')
1354
1319
  .split('|')
1355
- .map(function (s) { return s.trim(); })
1356
- .filter(function (s) { return s; });
1320
+ .map((s) => s.trim())
1321
+ .filter((s) => s);
1357
1322
  }
1358
1323
 
1359
1324
  /**
1360
1325
  * Shorten a single segment of a `pathArray` object.
1361
1326
  *
1362
- * @param {SVGPathCommander.absoluteSegment} segment the `absoluteSegment` object
1363
- * @param {SVGPathCommander.normalSegment} normalSegment the `normalSegment` object
1327
+ * @param {SVGPath.absoluteSegment} segment the `absoluteSegment` object
1328
+ * @param {SVGPath.normalSegment} normalSegment the `normalSegment` object
1364
1329
  * @param {any} params the coordinates of the previous segment
1365
1330
  * @param {string} prevCommand the path command of the previous segment
1366
- * @returns {SVGPathCommander.shortSegment | SVGPathCommander.pathSegment} the shortened segment
1331
+ * @returns {SVGPath.shortSegment | SVGPath.pathSegment} the shortened segment
1367
1332
  */
1368
1333
  function shortenSegment(segment, normalSegment, params, prevCommand) {
1369
- var pathCommand = segment[0];
1370
- var round4 = function (/** @type {number} */n) { return Math.round(n * (Math.pow( 10, 4 ))) / Math.pow( 10, 4 ); };
1371
- var segmentValues = segment.slice(1).map(function (n) { return +n; });
1372
- var normalValues = normalSegment.slice(1).map(function (n) { return +n; });
1373
- var px1 = params.x1;
1374
- var py1 = params.y1;
1375
- var px2 = params.x2;
1376
- var py2 = params.y2;
1377
- var px = params.x;
1378
- var py = params.y;
1379
- var result = segment;
1380
- var ref = normalValues.slice(-2);
1381
- var x = ref[0];
1382
- var y = ref[1];
1334
+ const [pathCommand] = segment;
1335
+ const round4 = (/** @type {number} */n) => Math.round(n * (10 ** 4)) / 10 ** 4;
1336
+ const segmentValues = segment.slice(1).map((n) => +n);
1337
+ const normalValues = normalSegment.slice(1).map((n) => +n);
1338
+ const {
1339
+ x1: px1, y1: py1, x2: px2, y2: py2, x: px, y: py,
1340
+ } = params;
1341
+ let result = segment;
1342
+ const [x, y] = normalValues.slice(-2);
1383
1343
 
1384
1344
  if (!'TQ'.includes(pathCommand)) {
1385
1345
  // optional but good to be cautious
@@ -1389,7 +1349,7 @@
1389
1349
 
1390
1350
  if (['V', 'H', 'S', 'T', 'Z'].includes(pathCommand)) {
1391
1351
  // @ts-ignore -- expected when so many types are included
1392
- result = [pathCommand ].concat( segmentValues);
1352
+ result = [pathCommand, ...segmentValues];
1393
1353
  } else if (pathCommand === 'L') {
1394
1354
  if (round4(px) === round4(x)) {
1395
1355
  result = ['V', y];
@@ -1397,20 +1357,18 @@
1397
1357
  result = ['H', x];
1398
1358
  }
1399
1359
  } else if (pathCommand === 'C') {
1400
- var x1 = normalValues[0];
1401
- var y1 = normalValues[1];
1360
+ const [x1, y1] = normalValues;
1402
1361
 
1403
1362
  if ('CS'.includes(prevCommand)
1404
1363
  && round4(x1) === round4(px1 * 2 - px2)
1405
1364
  && round4(y1) === round4(py1 * 2 - py2)) {
1406
1365
  // @ts-ignore -- the amount of numbers should suffice
1407
- result = ['S' ].concat( normalValues.slice(-4));
1366
+ result = ['S', ...normalValues.slice(-4)];
1408
1367
  }
1409
1368
  params.x1 = x1;
1410
1369
  params.y1 = y1;
1411
1370
  } else if (pathCommand === 'Q') {
1412
- var qx = normalValues[0];
1413
- var qy = normalValues[1];
1371
+ const [qx, qy] = normalValues;
1414
1372
  params.qx = qx;
1415
1373
  params.qy = qy;
1416
1374
 
@@ -1418,7 +1376,7 @@
1418
1376
  && round4(qx) === round4(px1 * 2 - px2)
1419
1377
  && round4(qy) === round4(py1 * 2 - py2)) {
1420
1378
  // @ts-ignore -- the amount of numbers should suffice
1421
- result = ['T' ].concat( normalValues.slice(-2));
1379
+ result = ['T', ...normalValues.slice(-2)];
1422
1380
  }
1423
1381
  }
1424
1382
 
@@ -1434,37 +1392,35 @@
1434
1392
  * * implement `auto` for rounding values based on pathBBox
1435
1393
  * * also revers path check if it's smaller string, maybe?
1436
1394
  *
1437
- * @param {SVGPathCommander.pathArray} pathInput a string or `pathArray`
1395
+ * @param {SVGPath.pathArray} pathInput a string or `pathArray`
1438
1396
  * @param {number | boolean} round the amount of decimals to round values to
1439
- * @returns {SVGPathCommander.pathArray} the optimized `pathArray`
1397
+ * @returns {SVGPath.pathArray} the optimized `pathArray`
1440
1398
  */
1441
1399
  function optimizePath(pathInput, round) {
1442
- var assign, assign$1, assign$2, assign$3;
1443
-
1444
- var path = pathToAbsolute(pathInput);
1445
- var normalPath = normalizePath(path);
1446
- var params = Object.assign({}, paramsParser);
1447
- var allPathCommands = [];
1448
- var ii = path.length;
1449
- var pathCommand = '';
1450
- var prevCommand = '';
1451
- var x = 0;
1452
- var y = 0;
1453
- var mx = 0;
1454
- var my = 0;
1455
-
1456
- for (var i = 0; i < ii; i += 1) {
1457
- (assign = path[i], pathCommand = assign[0]);
1400
+ const path = pathToAbsolute(pathInput);
1401
+ const normalPath = normalizePath(path);
1402
+ const params = { ...paramsParser };
1403
+ const allPathCommands = [];
1404
+ const ii = path.length;
1405
+ let pathCommand = '';
1406
+ let prevCommand = '';
1407
+ let x = 0;
1408
+ let y = 0;
1409
+ let mx = 0;
1410
+ let my = 0;
1411
+
1412
+ for (let i = 0; i < ii; i += 1) {
1413
+ [pathCommand] = path[i];
1458
1414
 
1459
1415
  // Save current path command
1460
1416
  allPathCommands[i] = pathCommand;
1461
1417
  // Get previous path command for `shortenSegment`
1462
- if (i) { prevCommand = allPathCommands[i - 1]; }
1418
+ if (i) prevCommand = allPathCommands[i - 1];
1463
1419
  // @ts-ignore -- expected when switching `pathSegment` type
1464
1420
  path[i] = shortenSegment(path[i], normalPath[i], params, prevCommand);
1465
1421
 
1466
- var segment = path[i];
1467
- var seglen = segment.length;
1422
+ const segment = path[i];
1423
+ const seglen = segment.length;
1468
1424
 
1469
1425
  // update C, S, Q, T specific params
1470
1426
  params.x1 = +segment[seglen - 2];
@@ -1480,14 +1436,14 @@
1480
1436
  break;
1481
1437
  case 'H':
1482
1438
  // @ts-ignore
1483
- (assign$1 = segment, x = assign$1[1]);
1439
+ [, x] = segment;
1484
1440
  break;
1485
1441
  case 'V':
1486
1442
  // @ts-ignore
1487
- (assign$2 = segment, y = assign$2[1]);
1443
+ [, y] = segment;
1488
1444
  break;
1489
1445
  default:
1490
- (assign$3 = segment.slice(-2).map(Number), x = assign$3[0], y = assign$3[1]);
1446
+ [x, y] = segment.slice(-2).map(Number);
1491
1447
 
1492
1448
  if (pathCommand === 'M') {
1493
1449
  mx = x;
@@ -1498,11 +1454,11 @@
1498
1454
  params.y = y;
1499
1455
  }
1500
1456
 
1501
- var absolutePath = roundPath(path, round);
1502
- var relativePath = roundPath(pathToRelative(path), round);
1457
+ const absolutePath = roundPath(path, round);
1458
+ const relativePath = roundPath(pathToRelative(path), round);
1503
1459
 
1504
1460
  // @ts-ignore - it's expected an optimized `pathArray` to contain all kinds of segments
1505
- return absolutePath.map(function (a, i) {
1461
+ return absolutePath.map((a, i) => {
1506
1462
  if (i) {
1507
1463
  return a.join('').length < relativePath[i].join('').length
1508
1464
  ? a : relativePath[i];
@@ -1516,7 +1472,7 @@
1516
1472
  *
1517
1473
  * @type {number}
1518
1474
  */
1519
- var epsilon = 1e-9;
1475
+ const epsilon = 1e-9;
1520
1476
 
1521
1477
  // DOMMatrix Static methods
1522
1478
  // * `fromFloat64Array` and `fromFloat32Array are not implemented;
@@ -1535,29 +1491,17 @@
1535
1491
  * @return {CSSMatrix} the resulted matrix.
1536
1492
  */
1537
1493
  function fromArray(array) {
1538
- var m = new CSSMatrix();
1539
- var a = Array.from(array);
1494
+ const m = new CSSMatrix();
1495
+ const a = Array.from(array);
1540
1496
 
1541
- if (!a.every(function (n) { return !Number.isNaN(n); })) {
1542
- throw TypeError(("CSSMatrix: \"" + array + "\" must only have numbers."));
1497
+ if (!a.every((n) => !Number.isNaN(n))) {
1498
+ throw TypeError(`CSSMatrix: "${array}" must only have numbers.`);
1543
1499
  }
1544
1500
  if (a.length === 16) {
1545
- var m11 = a[0];
1546
- var m12 = a[1];
1547
- var m13 = a[2];
1548
- var m14 = a[3];
1549
- var m21 = a[4];
1550
- var m22 = a[5];
1551
- var m23 = a[6];
1552
- var m24 = a[7];
1553
- var m31 = a[8];
1554
- var m32 = a[9];
1555
- var m33 = a[10];
1556
- var m34 = a[11];
1557
- var m41 = a[12];
1558
- var m42 = a[13];
1559
- var m43 = a[14];
1560
- var m44 = a[15];
1501
+ const [m11, m12, m13, m14,
1502
+ m21, m22, m23, m24,
1503
+ m31, m32, m33, m34,
1504
+ m41, m42, m43, m44] = a;
1561
1505
 
1562
1506
  m.m11 = m11;
1563
1507
  m.a = m11;
@@ -1590,12 +1534,7 @@
1590
1534
  m.m34 = m34;
1591
1535
  m.m44 = m44;
1592
1536
  } else if (a.length === 6) {
1593
- var M11 = a[0];
1594
- var M12 = a[1];
1595
- var M21 = a[2];
1596
- var M22 = a[3];
1597
- var M41 = a[4];
1598
- var M42 = a[5];
1537
+ const [M11, M12, M21, M22, M41, M42] = a;
1599
1538
 
1600
1539
  m.m11 = M11;
1601
1540
  m.a = M11;
@@ -1628,16 +1567,16 @@
1628
1567
  * @return {CSSMatrix} the resulted matrix.
1629
1568
  */
1630
1569
  function fromMatrix(m) {
1631
- var keys = Object.keys(new CSSMatrix());
1632
- if (typeof m === 'object' && keys.every(function (k) { return k in m; })) {
1570
+ const keys = Object.keys(new CSSMatrix());
1571
+ if (typeof m === 'object' && keys.every((k) => k in m)) {
1633
1572
  return fromArray(
1634
1573
  [m.m11, m.m12, m.m13, m.m14,
1635
1574
  m.m21, m.m22, m.m23, m.m24,
1636
1575
  m.m31, m.m32, m.m33, m.m34,
1637
- m.m41, m.m42, m.m43, m.m44]
1576
+ m.m41, m.m42, m.m43, m.m44],
1638
1577
  );
1639
1578
  }
1640
- throw TypeError(("CSSMatrix: \"" + m + "\" is not a DOMMatrix / CSSMatrix / JSON compatible object."));
1579
+ throw TypeError(`CSSMatrix: "${m}" is not a DOMMatrix / CSSMatrix / JSON compatible object.`);
1641
1580
  }
1642
1581
 
1643
1582
  /**
@@ -1655,11 +1594,11 @@
1655
1594
  */
1656
1595
  function fromString(source) {
1657
1596
  if (typeof source !== 'string') {
1658
- throw TypeError(("CSSMatrix: \"" + source + "\" is not a string."));
1597
+ throw TypeError(`CSSMatrix: "${source}" is not a string.`);
1659
1598
  }
1660
- var str = String(source).replace(/\s/g, '');
1661
- var m = new CSSMatrix();
1662
- var invalidStringError = "CSSMatrix: invalid transform string \"" + source + "\"";
1599
+ const str = String(source).replace(/\s/g, '');
1600
+ let m = new CSSMatrix();
1601
+ const invalidStringError = `CSSMatrix: invalid transform string "${source}"`;
1663
1602
 
1664
1603
  // const px = ['perspective'];
1665
1604
  // const length = ['translate', 'translate3d', 'translateX', 'translateY', 'translateZ'];
@@ -1667,71 +1606,66 @@
1667
1606
  // const abs = ['scale', 'scale3d', 'matrix', 'matrix3d'];
1668
1607
  // const transformFunctions = px.concat(length, deg, abs);
1669
1608
 
1670
- str.split(')').filter(function (f) { return f; }).forEach(function (tf) {
1671
- var ref = tf.split('(');
1672
- var prop = ref[0];
1673
- var value = ref[1];
1609
+ str.split(')').filter((f) => f).forEach((tf) => {
1610
+ const [prop, value] = tf.split('(');
1674
1611
 
1675
1612
  // invalidate empty string
1676
- if (!value) { throw TypeError(invalidStringError); }
1613
+ if (!value) throw TypeError(invalidStringError);
1677
1614
 
1678
- var components = value.split(',')
1679
- .map(function (n) { return (n.includes('rad') ? parseFloat(n) * (180 / Math.PI) : parseFloat(n)); });
1615
+ const components = value.split(',')
1616
+ .map((n) => (n.includes('rad') ? parseFloat(n) * (180 / Math.PI) : parseFloat(n)));
1680
1617
 
1681
- var x = components[0];
1682
- var y = components[1];
1683
- var z = components[2];
1684
- var a = components[3];
1685
- var xyz = [x, y, z];
1686
- var xyza = [x, y, z, a];
1618
+ const [x, y, z, a] = components;
1619
+ const xyz = [x, y, z];
1620
+ const xyza = [x, y, z, a];
1687
1621
 
1688
1622
  // single number value expected
1689
- if (prop === 'perspective' && x && [y, z].every(function (n) { return n === undefined; })) {
1623
+ if (prop === 'perspective' && x && [y, z].every((n) => n === undefined)) {
1690
1624
  m.m34 = -1 / x;
1691
1625
  // 6/16 number values expected
1692
1626
  } else if (prop.includes('matrix') && [6, 16].includes(components.length)
1693
- && components.every(function (n) { return !Number.isNaN(+n); })) {
1694
- var values = components.map(function (n) { return (Math.abs(n) < 1e-6 ? 0 : n); });
1627
+ && components.every((n) => !Number.isNaN(+n))) {
1628
+ const values = components.map((n) => (Math.abs(n) < 1e-6 ? 0 : n));
1695
1629
  m = m.multiply(fromArray(values));
1696
1630
  // 3 values expected
1697
- } else if (prop === 'translate3d' && xyz.every(function (n) { return !Number.isNaN(+n); })) {
1631
+ } else if (prop === 'translate3d' && xyz.every((n) => !Number.isNaN(+n))) {
1698
1632
  m = m.translate(x, y, z);
1699
1633
  // single/double number value(s) expected
1700
1634
  } else if (prop === 'translate' && x && z === undefined) {
1701
1635
  m = m.translate(x, y || 0, 0);
1702
1636
  // all 4 values expected
1703
- } else if (prop === 'rotate3d' && xyza.every(function (n) { return !Number.isNaN(+n); }) && a) {
1637
+ } else if (prop === 'rotate3d' && xyza.every((n) => !Number.isNaN(+n)) && a) {
1704
1638
  m = m.rotateAxisAngle(x, y, z, a);
1705
1639
  // single value expected
1706
- } else if (prop === 'rotate' && x && [y, z].every(function (n) { return n === undefined; })) {
1640
+ } else if (prop === 'rotate' && x && [y, z].every((n) => n === undefined)) {
1707
1641
  m = m.rotate(0, 0, x);
1708
1642
  // 4 values expected
1709
- } else if (prop === 'scale3d' && xyz.every(function (n) { return !Number.isNaN(+n); }) && xyz.some(function (n) { return n !== 1; })) {
1643
+ } else if (prop === 'scale3d' && xyz.every((n) => !Number.isNaN(+n)) && xyz.some((n) => n !== 1)) {
1710
1644
  m = m.scale(x, y, z);
1711
1645
  // single value expected
1712
1646
  } else if (prop === 'scale' && !Number.isNaN(x) && x !== 1 && z === undefined) {
1713
- var nosy = Number.isNaN(+y);
1714
- var sy = nosy ? x : y;
1647
+ const nosy = Number.isNaN(+y);
1648
+ const sy = nosy ? x : y;
1715
1649
  m = m.scale(x, sy, 1);
1716
1650
  // single/double value expected
1717
1651
  } else if (prop === 'skew' && x && z === undefined) {
1718
1652
  m = m.skewX(x);
1719
1653
  m = y ? m.skewY(y) : m;
1720
- } else if (/[XYZ]/.test(prop) && x && [y, z].every(function (n) { return n === undefined; }) // a single value expected
1721
- && ['translate', 'rotate', 'scale', 'skew'].some(function (p) { return prop.includes(p); })) {
1654
+ } else if (/[XYZ]/.test(prop) && x && [y, z].every((n) => n === undefined) // a single value expected
1655
+ && ['translate', 'rotate', 'scale', 'skew'].some((p) => prop.includes(p))) {
1722
1656
  if (['skewX', 'skewY'].includes(prop)) {
1723
1657
  // @ts-ignore unfortunately
1724
1658
  m = m[prop](x);
1725
1659
  } else {
1726
- var fn = prop.replace(/[XYZ]/, '');
1727
- var axis = prop.replace(fn, '');
1728
- var idx = ['X', 'Y', 'Z'].indexOf(axis);
1729
- var axeValues = [
1660
+ const fn = prop.replace(/[XYZ]/, '');
1661
+ const axis = prop.replace(fn, '');
1662
+ const idx = ['X', 'Y', 'Z'].indexOf(axis);
1663
+ const axeValues = [
1730
1664
  idx === 0 ? x : 0,
1731
1665
  idx === 1 ? x : 0,
1732
1666
  idx === 2 ? x : 0];
1733
1667
  // @ts-ignore unfortunately
1734
- m = m[fn].apply(m, axeValues);
1668
+ m = m[fn](...axeValues);
1735
1669
  }
1736
1670
  } else {
1737
1671
  throw TypeError(invalidStringError);
@@ -1756,7 +1690,7 @@
1756
1690
  * @return {CSSMatrix} the resulted matrix.
1757
1691
  */
1758
1692
  function Translate(x, y, z) {
1759
- var m = new CSSMatrix();
1693
+ const m = new CSSMatrix();
1760
1694
  m.m41 = x;
1761
1695
  m.e = x;
1762
1696
  m.m42 = y;
@@ -1776,22 +1710,22 @@
1776
1710
  * @return {CSSMatrix} the resulted matrix.
1777
1711
  */
1778
1712
  function Rotate(rx, ry, rz) {
1779
- var m = new CSSMatrix();
1780
- var degToRad = Math.PI / 180;
1781
- var radX = rx * degToRad;
1782
- var radY = ry * degToRad;
1783
- var radZ = rz * degToRad;
1713
+ const m = new CSSMatrix();
1714
+ const degToRad = Math.PI / 180;
1715
+ const radX = rx * degToRad;
1716
+ const radY = ry * degToRad;
1717
+ const radZ = rz * degToRad;
1784
1718
 
1785
1719
  // minus sin() because of right-handed system
1786
- var cosx = Math.cos(radX);
1787
- var sinx = -Math.sin(radX);
1788
- var cosy = Math.cos(radY);
1789
- var siny = -Math.sin(radY);
1790
- var cosz = Math.cos(radZ);
1791
- var sinz = -Math.sin(radZ);
1720
+ const cosx = Math.cos(radX);
1721
+ const sinx = -Math.sin(radX);
1722
+ const cosy = Math.cos(radY);
1723
+ const siny = -Math.sin(radY);
1724
+ const cosz = Math.cos(radZ);
1725
+ const sinz = -Math.sin(radZ);
1792
1726
 
1793
- var m11 = cosy * cosz;
1794
- var m12 = -cosy * sinz;
1727
+ const m11 = cosy * cosz;
1728
+ const m12 = -cosy * sinz;
1795
1729
 
1796
1730
  m.m11 = m11;
1797
1731
  m.a = m11;
@@ -1801,11 +1735,11 @@
1801
1735
 
1802
1736
  m.m13 = siny;
1803
1737
 
1804
- var m21 = sinx * siny * cosz + cosx * sinz;
1738
+ const m21 = sinx * siny * cosz + cosx * sinz;
1805
1739
  m.m21 = m21;
1806
1740
  m.c = m21;
1807
1741
 
1808
- var m22 = cosx * cosz - sinx * siny * sinz;
1742
+ const m22 = cosx * cosz - sinx * siny * sinz;
1809
1743
  m.m22 = m22;
1810
1744
  m.d = m22;
1811
1745
 
@@ -1831,15 +1765,15 @@
1831
1765
  * @return {CSSMatrix} the resulted matrix.
1832
1766
  */
1833
1767
  function RotateAxisAngle(x, y, z, alpha) {
1834
- var m = new CSSMatrix();
1835
- var angle = alpha * (Math.PI / 360);
1836
- var sinA = Math.sin(angle);
1837
- var cosA = Math.cos(angle);
1838
- var sinA2 = sinA * sinA;
1839
- var length = Math.sqrt(x * x + y * y + z * z);
1840
- var X = x;
1841
- var Y = y;
1842
- var Z = z;
1768
+ const m = new CSSMatrix();
1769
+ const angle = alpha * (Math.PI / 360);
1770
+ const sinA = Math.sin(angle);
1771
+ const cosA = Math.cos(angle);
1772
+ const sinA2 = sinA * sinA;
1773
+ const length = Math.sqrt(x * x + y * y + z * z);
1774
+ let X = x;
1775
+ let Y = y;
1776
+ let Z = z;
1843
1777
 
1844
1778
  if (length === 0) {
1845
1779
  // bad vector length, use something reasonable
@@ -1852,25 +1786,25 @@
1852
1786
  Z /= length;
1853
1787
  }
1854
1788
 
1855
- var x2 = X * X;
1856
- var y2 = Y * Y;
1857
- var z2 = Z * Z;
1789
+ const x2 = X * X;
1790
+ const y2 = Y * Y;
1791
+ const z2 = Z * Z;
1858
1792
 
1859
- var m11 = 1 - 2 * (y2 + z2) * sinA2;
1793
+ const m11 = 1 - 2 * (y2 + z2) * sinA2;
1860
1794
  m.m11 = m11;
1861
1795
  m.a = m11;
1862
1796
 
1863
- var m12 = 2 * (X * Y * sinA2 + Z * sinA * cosA);
1797
+ const m12 = 2 * (X * Y * sinA2 + Z * sinA * cosA);
1864
1798
  m.m12 = m12;
1865
1799
  m.b = m12;
1866
1800
 
1867
1801
  m.m13 = 2 * (X * Z * sinA2 - Y * sinA * cosA);
1868
1802
 
1869
- var m21 = 2 * (Y * X * sinA2 - Z * sinA * cosA);
1803
+ const m21 = 2 * (Y * X * sinA2 - Z * sinA * cosA);
1870
1804
  m.m21 = m21;
1871
1805
  m.c = m21;
1872
1806
 
1873
- var m22 = 1 - 2 * (z2 + x2) * sinA2;
1807
+ const m22 = 1 - 2 * (z2 + x2) * sinA2;
1874
1808
  m.m22 = m22;
1875
1809
  m.d = m22;
1876
1810
 
@@ -1895,7 +1829,7 @@
1895
1829
  * @return {CSSMatrix} the resulted matrix.
1896
1830
  */
1897
1831
  function Scale(x, y, z) {
1898
- var m = new CSSMatrix();
1832
+ const m = new CSSMatrix();
1899
1833
  m.m11 = x;
1900
1834
  m.a = x;
1901
1835
 
@@ -1916,9 +1850,9 @@
1916
1850
  * @return {CSSMatrix} the resulted matrix.
1917
1851
  */
1918
1852
  function SkewX(angle) {
1919
- var m = new CSSMatrix();
1920
- var radA = (angle * Math.PI) / 180;
1921
- var t = Math.tan(radA);
1853
+ const m = new CSSMatrix();
1854
+ const radA = (angle * Math.PI) / 180;
1855
+ const t = Math.tan(radA);
1922
1856
  m.m21 = t;
1923
1857
  m.c = t;
1924
1858
  return m;
@@ -1934,9 +1868,9 @@
1934
1868
  * @return {CSSMatrix} the resulted matrix.
1935
1869
  */
1936
1870
  function SkewY(angle) {
1937
- var m = new CSSMatrix();
1938
- var radA = (angle * Math.PI) / 180;
1939
- var t = Math.tan(radA);
1871
+ const m = new CSSMatrix();
1872
+ const radA = (angle * Math.PI) / 180;
1873
+ const t = Math.tan(radA);
1940
1874
  m.m12 = t;
1941
1875
  m.b = t;
1942
1876
  return m;
@@ -1951,31 +1885,31 @@
1951
1885
  * @return {CSSMatrix} the resulted matrix.
1952
1886
  */
1953
1887
  function Multiply(m1, m2) {
1954
- var m11 = m2.m11 * m1.m11 + m2.m12 * m1.m21 + m2.m13 * m1.m31 + m2.m14 * m1.m41;
1955
- var m12 = m2.m11 * m1.m12 + m2.m12 * m1.m22 + m2.m13 * m1.m32 + m2.m14 * m1.m42;
1956
- var m13 = m2.m11 * m1.m13 + m2.m12 * m1.m23 + m2.m13 * m1.m33 + m2.m14 * m1.m43;
1957
- var m14 = m2.m11 * m1.m14 + m2.m12 * m1.m24 + m2.m13 * m1.m34 + m2.m14 * m1.m44;
1958
-
1959
- var m21 = m2.m21 * m1.m11 + m2.m22 * m1.m21 + m2.m23 * m1.m31 + m2.m24 * m1.m41;
1960
- var m22 = m2.m21 * m1.m12 + m2.m22 * m1.m22 + m2.m23 * m1.m32 + m2.m24 * m1.m42;
1961
- var m23 = m2.m21 * m1.m13 + m2.m22 * m1.m23 + m2.m23 * m1.m33 + m2.m24 * m1.m43;
1962
- var m24 = m2.m21 * m1.m14 + m2.m22 * m1.m24 + m2.m23 * m1.m34 + m2.m24 * m1.m44;
1963
-
1964
- var m31 = m2.m31 * m1.m11 + m2.m32 * m1.m21 + m2.m33 * m1.m31 + m2.m34 * m1.m41;
1965
- var m32 = m2.m31 * m1.m12 + m2.m32 * m1.m22 + m2.m33 * m1.m32 + m2.m34 * m1.m42;
1966
- var m33 = m2.m31 * m1.m13 + m2.m32 * m1.m23 + m2.m33 * m1.m33 + m2.m34 * m1.m43;
1967
- var m34 = m2.m31 * m1.m14 + m2.m32 * m1.m24 + m2.m33 * m1.m34 + m2.m34 * m1.m44;
1968
-
1969
- var m41 = m2.m41 * m1.m11 + m2.m42 * m1.m21 + m2.m43 * m1.m31 + m2.m44 * m1.m41;
1970
- var m42 = m2.m41 * m1.m12 + m2.m42 * m1.m22 + m2.m43 * m1.m32 + m2.m44 * m1.m42;
1971
- var m43 = m2.m41 * m1.m13 + m2.m42 * m1.m23 + m2.m43 * m1.m33 + m2.m44 * m1.m43;
1972
- var m44 = m2.m41 * m1.m14 + m2.m42 * m1.m24 + m2.m43 * m1.m34 + m2.m44 * m1.m44;
1888
+ const m11 = m2.m11 * m1.m11 + m2.m12 * m1.m21 + m2.m13 * m1.m31 + m2.m14 * m1.m41;
1889
+ const m12 = m2.m11 * m1.m12 + m2.m12 * m1.m22 + m2.m13 * m1.m32 + m2.m14 * m1.m42;
1890
+ const m13 = m2.m11 * m1.m13 + m2.m12 * m1.m23 + m2.m13 * m1.m33 + m2.m14 * m1.m43;
1891
+ const m14 = m2.m11 * m1.m14 + m2.m12 * m1.m24 + m2.m13 * m1.m34 + m2.m14 * m1.m44;
1892
+
1893
+ const m21 = m2.m21 * m1.m11 + m2.m22 * m1.m21 + m2.m23 * m1.m31 + m2.m24 * m1.m41;
1894
+ const m22 = m2.m21 * m1.m12 + m2.m22 * m1.m22 + m2.m23 * m1.m32 + m2.m24 * m1.m42;
1895
+ const m23 = m2.m21 * m1.m13 + m2.m22 * m1.m23 + m2.m23 * m1.m33 + m2.m24 * m1.m43;
1896
+ const m24 = m2.m21 * m1.m14 + m2.m22 * m1.m24 + m2.m23 * m1.m34 + m2.m24 * m1.m44;
1897
+
1898
+ const m31 = m2.m31 * m1.m11 + m2.m32 * m1.m21 + m2.m33 * m1.m31 + m2.m34 * m1.m41;
1899
+ const m32 = m2.m31 * m1.m12 + m2.m32 * m1.m22 + m2.m33 * m1.m32 + m2.m34 * m1.m42;
1900
+ const m33 = m2.m31 * m1.m13 + m2.m32 * m1.m23 + m2.m33 * m1.m33 + m2.m34 * m1.m43;
1901
+ const m34 = m2.m31 * m1.m14 + m2.m32 * m1.m24 + m2.m33 * m1.m34 + m2.m34 * m1.m44;
1902
+
1903
+ const m41 = m2.m41 * m1.m11 + m2.m42 * m1.m21 + m2.m43 * m1.m31 + m2.m44 * m1.m41;
1904
+ const m42 = m2.m41 * m1.m12 + m2.m42 * m1.m22 + m2.m43 * m1.m32 + m2.m44 * m1.m42;
1905
+ const m43 = m2.m41 * m1.m13 + m2.m42 * m1.m23 + m2.m43 * m1.m33 + m2.m44 * m1.m43;
1906
+ const m44 = m2.m41 * m1.m14 + m2.m42 * m1.m24 + m2.m43 * m1.m34 + m2.m44 * m1.m44;
1973
1907
 
1974
1908
  return fromArray(
1975
1909
  [m11, m12, m13, m14,
1976
1910
  m21, m22, m23, m24,
1977
1911
  m31, m32, m33, m34,
1978
- m41, m42, m43, m44]
1912
+ m41, m42, m43, m44],
1979
1913
  );
1980
1914
  }
1981
1915
 
@@ -1988,346 +1922,347 @@
1988
1922
  * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMMatrix
1989
1923
  */
1990
1924
 
1991
- var CSSMatrix = function CSSMatrix() {
1992
- var args = [], len = arguments.length;
1993
- while ( len-- ) args[ len ] = arguments[ len ];
1994
-
1995
- var m = this;
1996
- // array 6
1997
- m.a = 1; m.b = 0;
1998
- m.c = 0; m.d = 1;
1999
- m.e = 0; m.f = 0;
2000
- // array 16
2001
- m.m11 = 1; m.m12 = 0; m.m13 = 0; m.m14 = 0;
2002
- m.m21 = 0; m.m22 = 1; m.m23 = 0; m.m24 = 0;
2003
- m.m31 = 0; m.m32 = 0; m.m33 = 1; m.m34 = 0;
2004
- m.m41 = 0; m.m42 = 0; m.m43 = 0; m.m44 = 1;
2005
-
2006
- if (args && args.length) {
2007
- var ARGS = [16, 6].some(function (l) { return l === args.length; }) ? args : args[0];
2008
-
2009
- return m.setMatrixValue(ARGS);
1925
+ class CSSMatrix {
1926
+ /**
1927
+ * @constructor
1928
+ * @param {any} args accepts all parameter configurations:
1929
+ * * valid CSS transform string,
1930
+ * * CSSMatrix/DOMMatrix instance,
1931
+ * * a 6/16 elements *Array*.
1932
+ */
1933
+ constructor(...args) {
1934
+ const m = this;
1935
+ // array 6
1936
+ m.a = 1; m.b = 0;
1937
+ m.c = 0; m.d = 1;
1938
+ m.e = 0; m.f = 0;
1939
+ // array 16
1940
+ m.m11 = 1; m.m12 = 0; m.m13 = 0; m.m14 = 0;
1941
+ m.m21 = 0; m.m22 = 1; m.m23 = 0; m.m24 = 0;
1942
+ m.m31 = 0; m.m32 = 0; m.m33 = 1; m.m34 = 0;
1943
+ m.m41 = 0; m.m42 = 0; m.m43 = 0; m.m44 = 1;
1944
+
1945
+ if (args && args.length) {
1946
+ const ARGS = [16, 6].some((l) => l === args.length) ? args : args[0];
1947
+
1948
+ return m.setMatrixValue(ARGS);
1949
+ }
1950
+ return m;
2010
1951
  }
2011
- return m;
2012
- };
2013
1952
 
2014
- var prototypeAccessors = { isIdentity: { configurable: true },is2D: { configurable: true } };
2015
-
2016
- /**
2017
- * Sets a new `Boolean` flag value for `this.isIdentity` matrix property.
2018
- *
2019
- * @param {boolean} value sets a new flag for this property
2020
- */
2021
- prototypeAccessors.isIdentity.set = function (value) {
2022
- this.isIdentity = value;
2023
- };
1953
+ /**
1954
+ * Sets a new `Boolean` flag value for `this.isIdentity` matrix property.
1955
+ *
1956
+ * @param {boolean} value sets a new flag for this property
1957
+ */
1958
+ set isIdentity(value) {
1959
+ this.isIdentity = value;
1960
+ }
2024
1961
 
2025
- /**
2026
- * A `Boolean` whose value is `true` if the matrix is the identity matrix. The identity
2027
- * matrix is one in which every value is 0 except those on the main diagonal from top-left
2028
- * to bottom-right corner (in other words, where the offsets in each direction are equal).
2029
- *
2030
- * @return {boolean} the current property value
2031
- */
2032
- prototypeAccessors.isIdentity.get = function () {
2033
- var m = this;
2034
- return (m.m11 === 1 && m.m12 === 0 && m.m13 === 0 && m.m14 === 0
2035
- && m.m21 === 0 && m.m22 === 1 && m.m23 === 0 && m.m24 === 0
2036
- && m.m31 === 0 && m.m32 === 0 && m.m33 === 1 && m.m34 === 0
2037
- && m.m41 === 0 && m.m42 === 0 && m.m43 === 0 && m.m44 === 1);
2038
- };
1962
+ /**
1963
+ * A `Boolean` whose value is `true` if the matrix is the identity matrix. The identity
1964
+ * matrix is one in which every value is 0 except those on the main diagonal from top-left
1965
+ * to bottom-right corner (in other words, where the offsets in each direction are equal).
1966
+ *
1967
+ * @return {boolean} the current property value
1968
+ */
1969
+ get isIdentity() {
1970
+ const m = this;
1971
+ return (m.m11 === 1 && m.m12 === 0 && m.m13 === 0 && m.m14 === 0
1972
+ && m.m21 === 0 && m.m22 === 1 && m.m23 === 0 && m.m24 === 0
1973
+ && m.m31 === 0 && m.m32 === 0 && m.m33 === 1 && m.m34 === 0
1974
+ && m.m41 === 0 && m.m42 === 0 && m.m43 === 0 && m.m44 === 1);
1975
+ }
2039
1976
 
2040
- /**
2041
- * A `Boolean` flag whose value is `true` if the matrix was initialized as a 2D matrix
2042
- * and `false` if the matrix is 3D.
2043
- *
2044
- * @return {boolean} the current property value
2045
- */
2046
- prototypeAccessors.is2D.get = function () {
2047
- var m = this;
2048
- return (m.m31 === 0 && m.m32 === 0 && m.m33 === 1 && m.m34 === 0 && m.m43 === 0 && m.m44 === 1);
2049
- };
1977
+ /**
1978
+ * A `Boolean` flag whose value is `true` if the matrix was initialized as a 2D matrix
1979
+ * and `false` if the matrix is 3D.
1980
+ *
1981
+ * @return {boolean} the current property value
1982
+ */
1983
+ get is2D() {
1984
+ const m = this;
1985
+ return (m.m31 === 0 && m.m32 === 0 && m.m33 === 1 && m.m34 === 0 && m.m43 === 0 && m.m44 === 1);
1986
+ }
2050
1987
 
2051
- /**
2052
- * Sets a new `Boolean` flag value for `this.is2D` matrix property.
2053
- *
2054
- * @param {boolean} value sets a new flag for this property
2055
- */
2056
- prototypeAccessors.is2D.set = function (value) {
2057
- this.is2D = value;
2058
- };
1988
+ /**
1989
+ * Sets a new `Boolean` flag value for `this.is2D` matrix property.
1990
+ *
1991
+ * @param {boolean} value sets a new flag for this property
1992
+ */
1993
+ set is2D(value) {
1994
+ this.is2D = value;
1995
+ }
2059
1996
 
2060
- /**
2061
- * The `setMatrixValue` method replaces the existing matrix with one computed
2062
- * in the browser. EG: `matrix(1,0.25,-0.25,1,0,0)`
2063
- *
2064
- * The method accepts any *Array* values, the result of
2065
- * `DOMMatrix` instance method `toFloat64Array()` / `toFloat32Array()` calls
2066
- *or `CSSMatrix` instance method `toArray()`.
2067
- *
2068
- * This method expects valid *matrix()* / *matrix3d()* string values, as well
2069
- * as other transform functions like *translateX(10px)*.
2070
- *
2071
- * @param {string | number[] | CSSMatrix | DOMMatrix} source
2072
- * @return {CSSMatrix} the matrix instance
2073
- */
2074
- CSSMatrix.prototype.setMatrixValue = function setMatrixValue (source) {
2075
- var m = this;
1997
+ /**
1998
+ * The `setMatrixValue` method replaces the existing matrix with one computed
1999
+ * in the browser. EG: `matrix(1,0.25,-0.25,1,0,0)`
2000
+ *
2001
+ * The method accepts any *Array* values, the result of
2002
+ * `DOMMatrix` instance method `toFloat64Array()` / `toFloat32Array()` calls
2003
+ * or `CSSMatrix` instance method `toArray()`.
2004
+ *
2005
+ * This method expects valid *matrix()* / *matrix3d()* string values, as well
2006
+ * as other transform functions like *translateX(10px)*.
2007
+ *
2008
+ * @param {string | number[] | CSSMatrix | DOMMatrix} source
2009
+ * @return {CSSMatrix} the matrix instance
2010
+ */
2011
+ setMatrixValue(source) {
2012
+ const m = this;
2076
2013
 
2077
- // [Arguments list | Array] come here
2078
- if ([Array, Float64Array, Float32Array].some(function (a) { return source instanceof a; })) {
2079
- return fromArray(source);
2080
- }
2081
- // CSS transform string source - TransformList
2082
- if (typeof source === 'string' && source.length && source !== 'none') {
2083
- return fromString(source);
2084
- }
2085
- // new CSSMatrix(CSSMatrix | DOMMatrix | JSON)
2086
- if (typeof source === 'object') {
2087
- return fromMatrix(source);
2014
+ // [Arguments list | Array] come here
2015
+ if ([Array, Float64Array, Float32Array].some((a) => source instanceof a)) {
2016
+ return fromArray(source);
2017
+ }
2018
+ // CSS transform string source - TransformList
2019
+ if (typeof source === 'string' && source.length && source !== 'none') {
2020
+ return fromString(source);
2021
+ }
2022
+ // new CSSMatrix(CSSMatrix | DOMMatrix | JSON)
2023
+ if (typeof source === 'object') {
2024
+ return fromMatrix(source);
2025
+ }
2026
+ return m;
2088
2027
  }
2089
- return m;
2090
- };
2091
-
2092
- /**
2093
- * Returns an *Array* containing elements which comprise the matrix.
2094
- * The method can return either the 16 elements or the 6 elements
2095
- * depending on the value of the `is2D` property.
2096
- *
2097
- * @return {number[]} an *Array* representation of the matrix
2098
- */
2099
- CSSMatrix.prototype.toArray = function toArray () {
2100
- var m = this;
2101
- var pow = (Math.pow( 10, 6 ));
2102
- var result;
2103
2028
 
2104
- if (m.is2D) {
2105
- result = [m.a, m.b, m.c, m.d, m.e, m.f];
2106
- } else {
2107
- result = [m.m11, m.m12, m.m13, m.m14,
2108
- m.m21, m.m22, m.m23, m.m24,
2109
- m.m31, m.m32, m.m33, m.m34,
2110
- m.m41, m.m42, m.m43, m.m44];
2111
- }
2112
- // clean up the numbers
2113
- // eslint-disable-next-line -- no-bitwise
2114
- return result.map(function (n) { return (Math.abs(n) < 1e-6 ? 0 : ((n * pow) >> 0) / pow); });
2115
- };
2029
+ /**
2030
+ * Returns an *Array* containing elements which comprise the matrix.
2031
+ * The method can return either the 16 elements or the 6 elements
2032
+ * depending on the value of the `is2D` property.
2033
+ *
2034
+ * @return {number[]} an *Array* representation of the matrix
2035
+ */
2036
+ toArray() {
2037
+ const m = this;
2038
+ const pow = (10 ** 6);
2039
+ let result;
2116
2040
 
2117
- /**
2118
- * Creates and returns a string representation of the matrix in `CSS` matrix syntax,
2119
- * using the appropriate `CSS` matrix notation.
2120
- *
2121
- * matrix3d *matrix3d(m11, m12, m13, m14, m21, ...)*
2122
- * matrix *matrix(a, b, c, d, e, f)*
2123
- *
2124
- * @return {string} a string representation of the matrix
2125
- */
2126
- CSSMatrix.prototype.toString = function toString () {
2127
- var m = this;
2128
- var values = m.toArray();
2129
- var type = m.is2D ? 'matrix' : 'matrix3d';
2130
- return (type + "(" + values + ")");
2131
- };
2041
+ if (m.is2D) {
2042
+ result = [m.a, m.b, m.c, m.d, m.e, m.f];
2043
+ } else {
2044
+ result = [m.m11, m.m12, m.m13, m.m14,
2045
+ m.m21, m.m22, m.m23, m.m24,
2046
+ m.m31, m.m32, m.m33, m.m34,
2047
+ m.m41, m.m42, m.m43, m.m44];
2048
+ }
2049
+ // clean up the numbers
2050
+ // eslint-disable-next-line -- no-bitwise
2051
+ return result.map((n) => (Math.abs(n) < 1e-6 ? 0 : ((n * pow) >> 0) / pow));
2052
+ }
2132
2053
 
2133
- /**
2134
- * Returns a JSON representation of the `CSSMatrix` instance, a standard *Object*
2135
- * that includes `{a,b,c,d,e,f}` and `{m11,m12,m13,..m44}` properties as well
2136
- * as the `is2D` & `isIdentity` properties.
2137
- *
2138
- * The result can also be used as a second parameter for the `fromMatrix` static method
2139
- * to load values into another matrix instance.
2140
- *
2141
- * @return {CSSMatrix.JSONMatrix} an *Object* with all matrix values.
2142
- */
2143
- CSSMatrix.prototype.toJSON = function toJSON () {
2144
- var m = this;
2145
- var is2D = m.is2D;
2146
- var isIdentity = m.isIdentity;
2147
- return Object.assign({}, m, {is2D: is2D, isIdentity: isIdentity});
2148
- };
2054
+ /**
2055
+ * Creates and returns a string representation of the matrix in `CSS` matrix syntax,
2056
+ * using the appropriate `CSS` matrix notation.
2057
+ *
2058
+ * matrix3d *matrix3d(m11, m12, m13, m14, m21, ...)*
2059
+ * matrix *matrix(a, b, c, d, e, f)*
2060
+ *
2061
+ * @return {string} a string representation of the matrix
2062
+ */
2063
+ toString() {
2064
+ const m = this;
2065
+ const values = m.toArray();
2066
+ const type = m.is2D ? 'matrix' : 'matrix3d';
2067
+ return `${type}(${values})`;
2068
+ }
2149
2069
 
2150
- /**
2151
- * The Multiply method returns a new CSSMatrix which is the result of this
2152
- * matrix multiplied by the passed matrix, with the passed matrix to the right.
2153
- * This matrix is not modified.
2154
- *
2155
- * @param {CSSMatrix | DOMMatrix | CSSMatrix.JSONMatrix} m2 CSSMatrix
2156
- * @return {CSSMatrix} The resulted matrix.
2157
- */
2158
- CSSMatrix.prototype.multiply = function multiply (m2) {
2159
- return Multiply(this, m2);
2160
- };
2070
+ /**
2071
+ * Returns a JSON representation of the `CSSMatrix` instance, a standard *Object*
2072
+ * that includes `{a,b,c,d,e,f}` and `{m11,m12,m13,..m44}` properties as well
2073
+ * as the `is2D` & `isIdentity` properties.
2074
+ *
2075
+ * The result can also be used as a second parameter for the `fromMatrix` static method
2076
+ * to load values into another matrix instance.
2077
+ *
2078
+ * @return {CSSMatrix.JSONMatrix} an *Object* with all matrix values.
2079
+ */
2080
+ toJSON() {
2081
+ const m = this;
2082
+ const { is2D, isIdentity } = m;
2083
+ return { ...m, is2D, isIdentity };
2084
+ }
2161
2085
 
2162
- /**
2163
- * The translate method returns a new matrix which is this matrix post
2164
- * multiplied by a translation matrix containing the passed values. If the z
2165
- * component is undefined, a 0 value is used in its place. This matrix is not
2166
- * modified.
2167
- *
2168
- * @param {number} x X component of the translation value.
2169
- * @param {number=} y Y component of the translation value.
2170
- * @param {number=} z Z component of the translation value.
2171
- * @return {CSSMatrix} The resulted matrix
2172
- */
2173
- CSSMatrix.prototype.translate = function translate (x, y, z) {
2174
- var X = x;
2175
- var Y = y;
2176
- var Z = z;
2177
- if (Z === undefined) { Z = 0; }
2178
- if (Y === undefined) { Y = 0; }
2179
- return Multiply(this, Translate(X, Y, Z));
2180
- };
2086
+ /**
2087
+ * The Multiply method returns a new CSSMatrix which is the result of this
2088
+ * matrix multiplied by the passed matrix, with the passed matrix to the right.
2089
+ * This matrix is not modified.
2090
+ *
2091
+ * @param {CSSMatrix | DOMMatrix | CSSMatrix.JSONMatrix} m2 CSSMatrix
2092
+ * @return {CSSMatrix} The resulted matrix.
2093
+ */
2094
+ multiply(m2) {
2095
+ return Multiply(this, m2);
2096
+ }
2181
2097
 
2182
- /**
2183
- * The scale method returns a new matrix which is this matrix post multiplied by
2184
- * a scale matrix containing the passed values. If the z component is undefined,
2185
- * a 1 value is used in its place. If the y component is undefined, the x
2186
- * component value is used in its place. This matrix is not modified.
2187
- *
2188
- * @param {number} x The X component of the scale value.
2189
- * @param {number=} y The Y component of the scale value.
2190
- * @param {number=} z The Z component of the scale value.
2191
- * @return {CSSMatrix} The resulted matrix
2192
- */
2193
- CSSMatrix.prototype.scale = function scale (x, y, z) {
2194
- var X = x;
2195
- var Y = y;
2196
- var Z = z;
2197
- if (Y === undefined) { Y = x; }
2198
- if (Z === undefined) { Z = 1; } // Z must be 1 if undefined
2098
+ /**
2099
+ * The translate method returns a new matrix which is this matrix post
2100
+ * multiplied by a translation matrix containing the passed values. If the z
2101
+ * component is undefined, a 0 value is used in its place. This matrix is not
2102
+ * modified.
2103
+ *
2104
+ * @param {number} x X component of the translation value.
2105
+ * @param {number=} y Y component of the translation value.
2106
+ * @param {number=} z Z component of the translation value.
2107
+ * @return {CSSMatrix} The resulted matrix
2108
+ */
2109
+ translate(x, y, z) {
2110
+ const X = x;
2111
+ let Y = y;
2112
+ let Z = z;
2113
+ if (Z === undefined) Z = 0;
2114
+ if (Y === undefined) Y = 0;
2115
+ return Multiply(this, Translate(X, Y, Z));
2116
+ }
2199
2117
 
2200
- return Multiply(this, Scale(X, Y, Z));
2201
- };
2118
+ /**
2119
+ * The scale method returns a new matrix which is this matrix post multiplied by
2120
+ * a scale matrix containing the passed values. If the z component is undefined,
2121
+ * a 1 value is used in its place. If the y component is undefined, the x
2122
+ * component value is used in its place. This matrix is not modified.
2123
+ *
2124
+ * @param {number} x The X component of the scale value.
2125
+ * @param {number=} y The Y component of the scale value.
2126
+ * @param {number=} z The Z component of the scale value.
2127
+ * @return {CSSMatrix} The resulted matrix
2128
+ */
2129
+ scale(x, y, z) {
2130
+ const X = x;
2131
+ let Y = y;
2132
+ let Z = z;
2133
+ if (Y === undefined) Y = x;
2134
+ if (Z === undefined) Z = 1; // Z must be 1 if undefined
2202
2135
 
2203
- /**
2204
- * The rotate method returns a new matrix which is this matrix post multiplied
2205
- * by each of 3 rotation matrices about the major axes, first X, then Y, then Z.
2206
- * If the y and z components are undefined, the x value is used to rotate the
2207
- * object about the z axis, as though the vector (0,0,x) were passed. All
2208
- * rotation values are in degrees. This matrix is not modified.
2209
- *
2210
- * @param {number} rx The X component of the rotation, or Z if Y and Z are null.
2211
- * @param {number=} ry The (optional) Y component of the rotation value.
2212
- * @param {number=} rz The (optional) Z component of the rotation value.
2213
- * @return {CSSMatrix} The resulted matrix
2214
- */
2215
- CSSMatrix.prototype.rotate = function rotate (rx, ry, rz) {
2216
- var RX = rx;
2217
- var RY = ry;
2218
- var RZ = rz;
2219
- if (RY === undefined) { RY = 0; }
2220
- if (RZ === undefined) { RZ = RX; RX = 0; }
2221
- return Multiply(this, Rotate(RX, RY, RZ));
2222
- };
2136
+ return Multiply(this, Scale(X, Y, Z));
2137
+ }
2223
2138
 
2224
- /**
2225
- * The rotateAxisAngle method returns a new matrix which is this matrix post
2226
- * multiplied by a rotation matrix with the given axis and `angle`. The right-hand
2227
- * rule is used to determine the direction of rotation. All rotation values are
2228
- * in degrees. This matrix is not modified.
2229
- *
2230
- * @param {number} x The X component of the axis vector.
2231
- * @param {number} y The Y component of the axis vector.
2232
- * @param {number} z The Z component of the axis vector.
2233
- * @param {number} angle The angle of rotation about the axis vector, in degrees.
2234
- * @return {CSSMatrix} The resulted matrix
2235
- */
2236
- CSSMatrix.prototype.rotateAxisAngle = function rotateAxisAngle (x, y, z, angle) {
2237
- if ([x, y, z, angle].some(function (n) { return Number.isNaN(n); })) {
2238
- throw new TypeError('CSSMatrix: expecting 4 values');
2139
+ /**
2140
+ * The rotate method returns a new matrix which is this matrix post multiplied
2141
+ * by each of 3 rotation matrices about the major axes, first X, then Y, then Z.
2142
+ * If the y and z components are undefined, the x value is used to rotate the
2143
+ * object about the z axis, as though the vector (0,0,x) were passed. All
2144
+ * rotation values are in degrees. This matrix is not modified.
2145
+ *
2146
+ * @param {number} rx The X component of the rotation, or Z if Y and Z are null.
2147
+ * @param {number=} ry The (optional) Y component of the rotation value.
2148
+ * @param {number=} rz The (optional) Z component of the rotation value.
2149
+ * @return {CSSMatrix} The resulted matrix
2150
+ */
2151
+ rotate(rx, ry, rz) {
2152
+ let RX = rx;
2153
+ let RY = ry;
2154
+ let RZ = rz;
2155
+ if (RY === undefined) RY = 0;
2156
+ if (RZ === undefined) { RZ = RX; RX = 0; }
2157
+ return Multiply(this, Rotate(RX, RY, RZ));
2239
2158
  }
2240
- return Multiply(this, RotateAxisAngle(x, y, z, angle));
2241
- };
2242
2159
 
2243
- /**
2244
- * Specifies a skew transformation along the `x-axis` by the given angle.
2245
- * This matrix is not modified.
2246
- *
2247
- * @param {number} angle The angle amount in degrees to skew.
2248
- * @return {CSSMatrix} The resulted matrix
2249
- */
2250
- CSSMatrix.prototype.skewX = function skewX (angle) {
2251
- return Multiply(this, SkewX(angle));
2252
- };
2160
+ /**
2161
+ * The rotateAxisAngle method returns a new matrix which is this matrix post
2162
+ * multiplied by a rotation matrix with the given axis and `angle`. The right-hand
2163
+ * rule is used to determine the direction of rotation. All rotation values are
2164
+ * in degrees. This matrix is not modified.
2165
+ *
2166
+ * @param {number} x The X component of the axis vector.
2167
+ * @param {number} y The Y component of the axis vector.
2168
+ * @param {number} z The Z component of the axis vector.
2169
+ * @param {number} angle The angle of rotation about the axis vector, in degrees.
2170
+ * @return {CSSMatrix} The resulted matrix
2171
+ */
2172
+ rotateAxisAngle(x, y, z, angle) {
2173
+ if ([x, y, z, angle].some((n) => Number.isNaN(n))) {
2174
+ throw new TypeError('CSSMatrix: expecting 4 values');
2175
+ }
2176
+ return Multiply(this, RotateAxisAngle(x, y, z, angle));
2177
+ }
2253
2178
 
2254
- /**
2255
- * Specifies a skew transformation along the `y-axis` by the given angle.
2256
- * This matrix is not modified.
2257
- *
2258
- * @param {number} angle The angle amount in degrees to skew.
2259
- * @return {CSSMatrix} The resulted matrix
2260
- */
2261
- CSSMatrix.prototype.skewY = function skewY (angle) {
2262
- return Multiply(this, SkewY(angle));
2263
- };
2179
+ /**
2180
+ * Specifies a skew transformation along the `x-axis` by the given angle.
2181
+ * This matrix is not modified.
2182
+ *
2183
+ * @param {number} angle The angle amount in degrees to skew.
2184
+ * @return {CSSMatrix} The resulted matrix
2185
+ */
2186
+ skewX(angle) {
2187
+ return Multiply(this, SkewX(angle));
2188
+ }
2264
2189
 
2265
- /**
2266
- * Transforms a specified point using the matrix, returning a new
2267
- * Tuple *Object* comprising of the transformed point.
2268
- * Neither the matrix nor the original point are altered.
2269
- *
2270
- * The method is equivalent with `transformPoint()` method
2271
- * of the `DOMMatrix` constructor.
2272
- *
2273
- * @copyright thednp © 2021
2274
- *
2275
- * @param {CSSMatrix.PointTuple | DOMPoint} v Tuple or DOMPoint
2276
- * @return {CSSMatrix.PointTuple} the resulting Tuple
2277
- */
2278
- CSSMatrix.prototype.transformPoint = function transformPoint (v) {
2279
- var M = this;
2280
- var m = Translate(v.x, v.y, v.z);
2190
+ /**
2191
+ * Specifies a skew transformation along the `y-axis` by the given angle.
2192
+ * This matrix is not modified.
2193
+ *
2194
+ * @param {number} angle The angle amount in degrees to skew.
2195
+ * @return {CSSMatrix} The resulted matrix
2196
+ */
2197
+ skewY(angle) {
2198
+ return Multiply(this, SkewY(angle));
2199
+ }
2281
2200
 
2282
- m.m44 = v.w || 1;
2283
- m = M.multiply(m);
2201
+ /**
2202
+ * Transforms a specified point using the matrix, returning a new
2203
+ * Tuple *Object* comprising of the transformed point.
2204
+ * Neither the matrix nor the original point are altered.
2205
+ *
2206
+ * The method is equivalent with `transformPoint()` method
2207
+ * of the `DOMMatrix` constructor.
2208
+ *
2209
+ * @copyright thednp © 2021
2210
+ *
2211
+ * @param {CSSMatrix.PointTuple | DOMPoint} v Tuple or DOMPoint
2212
+ * @return {CSSMatrix.PointTuple} the resulting Tuple
2213
+ */
2214
+ transformPoint(v) {
2215
+ const M = this;
2216
+ let m = Translate(v.x, v.y, v.z);
2284
2217
 
2285
- return {
2286
- x: m.m41,
2287
- y: m.m42,
2288
- z: m.m43,
2289
- w: m.m44,
2290
- };
2291
- };
2218
+ m.m44 = v.w || 1;
2219
+ m = M.multiply(m);
2292
2220
 
2293
- /**
2294
- * Transforms a specified vector using the matrix, returning a new
2295
- * {x,y,z,w} Tuple *Object* comprising the transformed vector.
2296
- * Neither the matrix nor the original vector are altered.
2297
- *
2298
- * @param {CSSMatrix.PointTuple} t Tuple with `{x,y,z,w}` components
2299
- * @return {CSSMatrix.PointTuple} the resulting Tuple
2300
- */
2301
- CSSMatrix.prototype.transform = function transform (t) {
2302
- var m = this;
2303
- var x = m.m11 * t.x + m.m12 * t.y + m.m13 * t.z + m.m14 * t.w;
2304
- var y = m.m21 * t.x + m.m22 * t.y + m.m23 * t.z + m.m24 * t.w;
2305
- var z = m.m31 * t.x + m.m32 * t.y + m.m33 * t.z + m.m34 * t.w;
2306
- var w = m.m41 * t.x + m.m42 * t.y + m.m43 * t.z + m.m44 * t.w;
2221
+ return {
2222
+ x: m.m41,
2223
+ y: m.m42,
2224
+ z: m.m43,
2225
+ w: m.m44,
2226
+ };
2227
+ }
2307
2228
 
2308
- return {
2309
- x: x / w,
2310
- y: y / w,
2311
- z: z / w,
2312
- w: w,
2313
- };
2314
- };
2229
+ /**
2230
+ * Transforms a specified vector using the matrix, returning a new
2231
+ * {x,y,z,w} Tuple *Object* comprising the transformed vector.
2232
+ * Neither the matrix nor the original vector are altered.
2233
+ *
2234
+ * @param {CSSMatrix.PointTuple} t Tuple with `{x,y,z,w}` components
2235
+ * @return {CSSMatrix.PointTuple} the resulting Tuple
2236
+ */
2237
+ transform(t) {
2238
+ const m = this;
2239
+ const x = m.m11 * t.x + m.m12 * t.y + m.m13 * t.z + m.m14 * t.w;
2240
+ const y = m.m21 * t.x + m.m22 * t.y + m.m23 * t.z + m.m24 * t.w;
2241
+ const z = m.m31 * t.x + m.m32 * t.y + m.m33 * t.z + m.m34 * t.w;
2242
+ const w = m.m41 * t.x + m.m42 * t.y + m.m43 * t.z + m.m44 * t.w;
2315
2243
 
2316
- Object.defineProperties( CSSMatrix.prototype, prototypeAccessors );
2244
+ return {
2245
+ x: x / w,
2246
+ y: y / w,
2247
+ z: z / w,
2248
+ w,
2249
+ };
2250
+ }
2251
+ }
2317
2252
 
2318
2253
  // Add Transform Functions to CSSMatrix object
2319
2254
  // without creating a TypeScript namespace.
2320
2255
  Object.assign(CSSMatrix, {
2321
- Translate: Translate,
2322
- Rotate: Rotate,
2323
- RotateAxisAngle: RotateAxisAngle,
2324
- Scale: Scale,
2325
- SkewX: SkewX,
2326
- SkewY: SkewY,
2327
- Multiply: Multiply,
2328
- fromArray: fromArray,
2329
- fromMatrix: fromMatrix,
2330
- fromString: fromString,
2256
+ Translate,
2257
+ Rotate,
2258
+ RotateAxisAngle,
2259
+ Scale,
2260
+ SkewX,
2261
+ SkewY,
2262
+ Multiply,
2263
+ fromArray,
2264
+ fromMatrix,
2265
+ fromString,
2331
2266
  });
2332
2267
 
2333
2268
  var version$1 = "0.0.24";
@@ -2338,31 +2273,31 @@
2338
2273
  * A global namespace for library version.
2339
2274
  * @type {string}
2340
2275
  */
2341
- var Version$1 = version$1;
2276
+ const Version$1 = version$1;
2342
2277
 
2343
2278
  Object.assign(CSSMatrix, { Version: Version$1 });
2344
2279
 
2345
2280
  /**
2346
2281
  * Returns a transformation matrix to apply to `<path>` elements.
2347
2282
  *
2348
- * @see SVGPathCommander.transformObject
2283
+ * @see SVGPath.transformObject
2349
2284
  *
2350
- * @param {SVGPathCommander.transformObject} transform the `transformObject`
2285
+ * @param {SVGPath.transformObject} transform the `transformObject`
2351
2286
  * @returns {CSSMatrix} a new transformation matrix
2352
2287
  */
2353
2288
  function getSVGMatrix(transform) {
2354
- var matrix = new CSSMatrix();
2355
- var origin = transform.origin;
2356
- var originX = origin[0];
2357
- var originY = origin[1];
2358
- var translate = transform.translate;
2359
- var rotate = transform.rotate;
2360
- var skew = transform.skew;
2361
- var scale = transform.scale;
2289
+ let matrix = new CSSMatrix();
2290
+ const { origin } = transform;
2291
+ // @ts-ignore -- at this point the origin is surely defined
2292
+ const [originX, originY] = origin;
2293
+ const { translate } = transform;
2294
+ const { rotate } = transform;
2295
+ const { skew } = transform;
2296
+ const { scale } = transform;
2362
2297
 
2363
2298
  // set translate
2364
- if (Array.isArray(translate) && translate.every(function (x) { return !Number.isNaN(+x); })
2365
- && translate.some(function (x) { return x !== 0; })) {
2299
+ if (Array.isArray(translate) && translate.every((x) => !Number.isNaN(+x))
2300
+ && translate.some((x) => x !== 0)) {
2366
2301
  matrix = matrix.translate(translate[0] || 0, translate[1] || 0, translate[2] || 0);
2367
2302
  } else if (typeof translate === 'number' && !Number.isNaN(+translate)) {
2368
2303
  matrix = matrix.translate(translate || 0, 0, 0);
@@ -2373,16 +2308,16 @@
2373
2308
  matrix = matrix.translate(originX, originY);
2374
2309
 
2375
2310
  // set rotation
2376
- if (Array.isArray(rotate) && rotate.every(function (x) { return !Number.isNaN(+x); })
2377
- && rotate.some(function (x) { return x !== 0; })) {
2311
+ if (Array.isArray(rotate) && rotate.every((x) => !Number.isNaN(+x))
2312
+ && rotate.some((x) => x !== 0)) {
2378
2313
  matrix = matrix.rotate(rotate[0], rotate[1], rotate[2]);
2379
2314
  } else if (typeof rotate === 'number' && !Number.isNaN(+rotate)) {
2380
2315
  matrix = matrix.rotate(0, 0, rotate);
2381
2316
  }
2382
2317
 
2383
2318
  // set skew(s)
2384
- if (Array.isArray(skew) && skew.every(function (x) { return !Number.isNaN(+x); })
2385
- && skew.some(function (x) { return x !== 0; })) {
2319
+ if (Array.isArray(skew) && skew.every((x) => !Number.isNaN(+x))
2320
+ && skew.some((x) => x !== 0)) {
2386
2321
  matrix = skew[0] ? matrix.skewX(skew[0]) : matrix;
2387
2322
  matrix = skew[1] ? matrix.skewY(skew[1]) : matrix;
2388
2323
  } else if (typeof skew === 'number' && !Number.isNaN(+skew)) {
@@ -2390,8 +2325,8 @@
2390
2325
  }
2391
2326
 
2392
2327
  // set scale
2393
- if (Array.isArray(scale) && scale.every(function (x) { return !Number.isNaN(+x); })
2394
- && scale.some(function (x) { return x !== 1; })) {
2328
+ if (Array.isArray(scale) && scale.every((x) => !Number.isNaN(+x))
2329
+ && scale.some((x) => x !== 1)) {
2395
2330
  matrix = matrix.scale(scale[0], scale[1], scale[2]);
2396
2331
  } else if (typeof scale === 'number' && !Number.isNaN(+scale)) {
2397
2332
  matrix = matrix.scale(scale || 1, scale || 1, scale || 1);
@@ -2415,49 +2350,50 @@
2415
2350
  // We consider the current ellipse as image of the unit circle
2416
2351
  // by first scale(rx,ry) and then rotate(ax) ...
2417
2352
  // So we apply ma = m x rotate(ax) x scale(rx,ry) to the unit circle.
2418
- var c = Math.cos((ax * Math.PI) / 180);
2419
- var s = Math.sin((ax * Math.PI) / 180);
2420
- var ma = [
2353
+ const c = Math.cos((ax * Math.PI) / 180);
2354
+ const s = Math.sin((ax * Math.PI) / 180);
2355
+ const ma = [
2421
2356
  rx * (m[0] * c + m[2] * s),
2422
2357
  rx * (m[1] * c + m[3] * s),
2423
2358
  ry * (-m[0] * s + m[2] * c),
2424
- ry * (-m[1] * s + m[3] * c) ];
2359
+ ry * (-m[1] * s + m[3] * c),
2360
+ ];
2425
2361
 
2426
2362
  // ma * transpose(ma) = [ J L ]
2427
2363
  // [ L K ]
2428
2364
  // L is calculated later (if the image is not a circle)
2429
- var J = ma[0] * ma[0] + ma[2] * ma[2];
2430
- var K = ma[1] * ma[1] + ma[3] * ma[3];
2365
+ const J = ma[0] * ma[0] + ma[2] * ma[2];
2366
+ const K = ma[1] * ma[1] + ma[3] * ma[3];
2431
2367
 
2432
2368
  // the discriminant of the characteristic polynomial of ma * transpose(ma)
2433
- var D = ((ma[0] - ma[3]) * (ma[0] - ma[3]) + (ma[2] + ma[1]) * (ma[2] + ma[1]))
2369
+ let D = ((ma[0] - ma[3]) * (ma[0] - ma[3]) + (ma[2] + ma[1]) * (ma[2] + ma[1]))
2434
2370
  * ((ma[0] + ma[3]) * (ma[0] + ma[3]) + (ma[2] - ma[1]) * (ma[2] - ma[1]));
2435
2371
 
2436
2372
  // the "mean eigenvalue"
2437
- var JK = (J + K) / 2;
2373
+ const JK = (J + K) / 2;
2438
2374
 
2439
2375
  // check if the image is (almost) a circle
2440
2376
  if (D < epsilon * JK) {
2441
2377
  // if it is
2442
- var rxy = Math.sqrt(JK);
2378
+ const rxy = Math.sqrt(JK);
2443
2379
 
2444
2380
  return { rx: rxy, ry: rxy, ax: 0 };
2445
2381
  }
2446
2382
 
2447
2383
  // if it is not a circle
2448
- var L = ma[0] * ma[1] + ma[2] * ma[3];
2384
+ const L = ma[0] * ma[1] + ma[2] * ma[3];
2449
2385
 
2450
2386
  D = Math.sqrt(D);
2451
2387
 
2452
2388
  // {l1,l2} = the two eigen values of ma * transpose(ma)
2453
- var l1 = JK + D / 2;
2454
- var l2 = JK - D / 2;
2389
+ const l1 = JK + D / 2;
2390
+ const l2 = JK - D / 2;
2455
2391
  // the x - axis - rotation angle is the argument of the l1 - eigenvector
2456
- var AX = (Math.abs(L) < epsilon && Math.abs(l1 - K) < epsilon) ? 90
2392
+ let AX = (Math.abs(L) < epsilon && Math.abs(l1 - K) < epsilon) ? 90
2457
2393
  : Math.atan(Math.abs(L) > Math.abs(l1 - K) ? (l1 - J) / L
2458
2394
  : ((L / (l1 - K))) * 180) / Math.PI;
2459
- var RX;
2460
- var RY;
2395
+ let RX;
2396
+ let RY;
2461
2397
 
2462
2398
  // if ax > 0 => rx = sqrt(l1), ry = sqrt(l2), else exchange axes and ax += 90
2463
2399
  if (AX >= 0) {
@@ -2483,28 +2419,26 @@
2483
2419
  * Details =>
2484
2420
  * https://stackoverflow.com/questions/23792505/predicted-rendering-of-css-3d-transformed-pixel
2485
2421
  *
2486
- * @param {SVGPathCommander.CSSMatrix} m the transformation matrix
2422
+ * @param {SVGPath.CSSMatrix} m the transformation matrix
2487
2423
  * @param {[number, number]} point2D the initial [x,y] coordinates
2488
- * @param {number[]} origin the initial [x,y] coordinates
2424
+ * @param {number[]} origin the [x,y,z] transform origin
2489
2425
  * @returns {[number, number]} the projected [x,y] coordinates
2490
2426
  */
2491
2427
  function projection2d(m, point2D, origin) {
2492
- var px = point2D[0];
2493
- var py = point2D[1];
2494
- var originX = origin[0];
2495
- var originY = origin[1];
2496
- var originZ = origin[2];
2497
- var point3D = m.transformPoint({
2428
+ const [px, py] = point2D;
2429
+ const [originX, originY, originZ] = origin;
2430
+ const point3D = m.transformPoint({
2498
2431
  x: px, y: py, z: 0, w: 1,
2499
2432
  });
2500
2433
 
2501
- var relativePositionX = point3D.x - originX;
2502
- var relativePositionY = point3D.y - originY;
2503
- var relativePositionZ = point3D.z - originZ;
2434
+ const relativePositionX = point3D.x - originX;
2435
+ const relativePositionY = point3D.y - originY;
2436
+ const relativePositionZ = point3D.z - originZ;
2504
2437
 
2505
2438
  return [
2506
2439
  relativePositionX * (Math.abs(originZ) / Math.abs(relativePositionZ)) + originX,
2507
- relativePositionY * (Math.abs(originZ) / Math.abs(relativePositionZ)) + originY ];
2440
+ relativePositionY * (Math.abs(originZ) / Math.abs(relativePositionZ)) + originY,
2441
+ ];
2508
2442
  }
2509
2443
 
2510
2444
  /**
@@ -2513,42 +2447,37 @@
2513
2447
  * Since *SVGElement* doesn't support 3D transformation, this function
2514
2448
  * creates a 2D projection of the <path> element.
2515
2449
  *
2516
- * @param {SVGPathCommander.pathArray} path the `pathArray` to apply transformation
2517
- * @param {SVGPathCommander.transformObject} transform the transform functions `Object`
2518
- * @returns {SVGPathCommander.pathArray} the resulted `pathArray`
2450
+ * @param {SVGPath.pathArray} path the `pathArray` to apply transformation
2451
+ * @param {SVGPath.transformObject} transform the transform functions `Object`
2452
+ * @returns {SVGPath.pathArray} the resulted `pathArray`
2519
2453
  */
2520
2454
  function transformPath(path, transform) {
2521
- var assign;
2522
-
2523
- var x = 0; var y = 0; var i; var j; var ii; var jj; var lx; var ly; var te;
2524
- var absolutePath = pathToAbsolute(path);
2525
- var normalizedPath = normalizePath(absolutePath);
2526
- var matrixInstance = getSVGMatrix(transform);
2527
- var transformProps = Object.keys(transform);
2528
- var origin = transform.origin;
2529
- var a = matrixInstance.a;
2530
- var b = matrixInstance.b;
2531
- var c = matrixInstance.c;
2532
- var d = matrixInstance.d;
2533
- var e = matrixInstance.e;
2534
- var f = matrixInstance.f;
2535
- var matrix2d = [a, b, c, d, e, f];
2536
- var params = Object.assign({}, paramsParser);
2455
+ let x = 0; let y = 0; let i; let j; let ii; let jj; let lx; let ly; let te;
2456
+ const absolutePath = pathToAbsolute(path);
2457
+ const normalizedPath = normalizePath(absolutePath);
2458
+ const matrixInstance = getSVGMatrix(transform);
2459
+ const transformProps = Object.keys(transform);
2460
+ const { origin } = transform;
2461
+ const {
2462
+ a, b, c, d, e, f,
2463
+ } = matrixInstance;
2464
+ const matrix2d = [a, b, c, d, e, f];
2465
+ const params = { ...paramsParser };
2537
2466
  /** @ts-ignore */
2538
- /** @type {SVGPathCommander.pathSegment} */
2467
+ /** @type {SVGPath.pathSegment} */
2539
2468
  // @ts-ignore
2540
- var segment = [];
2541
- var seglen = 0;
2542
- var pathCommand = '';
2543
- /** @type {SVGPathCommander.pathTransformList[]} */
2544
- var transformedPath = [];
2545
- var allPathCommands = []; // needed for arc to curve transformation
2469
+ let segment = [];
2470
+ let seglen = 0;
2471
+ let pathCommand = '';
2472
+ /** @type {SVGPath.pathTransformList[]} */
2473
+ let transformedPath = [];
2474
+ const allPathCommands = []; // needed for arc to curve transformation
2546
2475
 
2547
2476
  if (!matrixInstance.isIdentity) {
2548
2477
  for (i = 0, ii = absolutePath.length; i < ii; i += 1) {
2549
2478
  segment = absolutePath[i];
2550
2479
 
2551
- if (absolutePath[i]) { (assign = segment, pathCommand = assign[0]); }
2480
+ if (absolutePath[i]) [pathCommand] = segment;
2552
2481
 
2553
2482
  // REPLACE Arc path commands with Cubic Beziers
2554
2483
  // we don't have any scripting know-how on 3d ellipse transformation
@@ -2557,7 +2486,7 @@
2557
2486
 
2558
2487
  // Arcs don't work very well with 3D transformations or skews
2559
2488
  if (pathCommand === 'A' && (!matrixInstance.is2D
2560
- || !['skewX', 'skewY'].find(function (p) { return transformProps.includes(p); }))) {
2489
+ || !['skewX', 'skewY'].find((p) => transformProps.includes(p)))) {
2561
2490
  segment = segmentToCubic(normalizedPath[i], params);
2562
2491
 
2563
2492
  // @ts-ignore -- expected when switching `pathSegment` type
@@ -2579,18 +2508,16 @@
2579
2508
  params.x2 = +(segment[seglen - 4]) || params.x1;
2580
2509
  params.y2 = +(segment[seglen - 3]) || params.y1;
2581
2510
 
2582
- /** @type {SVGPathCommander.pathTransformList} */
2583
- var result = {
2511
+ /** @type {SVGPath.pathTransformList} */
2512
+ const result = {
2584
2513
  s: absolutePath[i], c: absolutePath[i][0], x: params.x1, y: params.y1,
2585
2514
  };
2586
2515
 
2587
- transformedPath = transformedPath.concat( [result]);
2516
+ transformedPath = [...transformedPath, ...[result]];
2588
2517
  }
2589
2518
 
2590
2519
  // @ts-ignore
2591
- return transformedPath.map(function (seg) {
2592
- var assign, assign$1, assign$2;
2593
-
2520
+ return transformedPath.map((seg) => {
2594
2521
  pathCommand = seg.c;
2595
2522
  segment = seg.s;
2596
2523
  switch (pathCommand) {
@@ -2603,7 +2530,7 @@
2603
2530
  }
2604
2531
 
2605
2532
  // @ts-ignore
2606
- (assign = projection2d(matrixInstance, [+segment[6], +segment[7]], origin), lx = assign[0], ly = assign[1]);
2533
+ [lx, ly] = projection2d(matrixInstance, [+segment[6], +segment[7]], origin);
2607
2534
 
2608
2535
  if ((x === lx && y === ly) || (te.rx < epsilon * te.ry) || (te.ry < epsilon * te.rx)) {
2609
2536
  segment = ['L', lx, ly];
@@ -2618,7 +2545,8 @@
2618
2545
  case 'L':
2619
2546
  case 'H':
2620
2547
  case 'V':
2621
- (assign$1 = projection2d(matrixInstance, [seg.x, seg.y], origin), lx = assign$1[0], ly = assign$1[1]);
2548
+ // @ts-ignore
2549
+ [lx, ly] = projection2d(matrixInstance, [seg.x, seg.y], origin);
2622
2550
 
2623
2551
  if (x !== lx && y !== ly) {
2624
2552
  segment = ['L', lx, ly];
@@ -2634,8 +2562,8 @@
2634
2562
  default:
2635
2563
 
2636
2564
  for (j = 1, jj = segment.length; j < jj; j += 2) {
2637
- // compute line coordinates without altering previous coordinates
2638
- (assign$2 = projection2d(matrixInstance, [+segment[j], +segment[j + 1]], origin), x = assign$2[0], y = assign$2[1]);
2565
+ // @ts-ignore compute line coordinates without altering previous coordinates
2566
+ [x, y] = projection2d(matrixInstance, [+segment[j], +segment[j + 1]], origin);
2639
2567
  segment[j] = x;
2640
2568
  segment[j + 1] = y;
2641
2569
  }
@@ -2662,21 +2590,21 @@
2662
2590
  * @returns {{x: number, y: number}} the cubic-bezier segment length
2663
2591
  */
2664
2592
  function getPointAtCubicSegmentLength(x1, y1, c1x, c1y, c2x, c2y, x2, y2, t) {
2665
- var t1 = 1 - t;
2593
+ const t1 = 1 - t;
2666
2594
  return {
2667
- x: (Math.pow( t1, 3 )) * x1
2668
- + 3 * (Math.pow( t1, 2 )) * t * c1x
2669
- + 3 * t1 * (Math.pow( t, 2 )) * c2x
2670
- + (Math.pow( t, 3 )) * x2,
2671
- y: (Math.pow( t1, 3 )) * y1
2672
- + 3 * (Math.pow( t1, 2 )) * t * c1y
2673
- + 3 * t1 * (Math.pow( t, 2 )) * c2y
2674
- + (Math.pow( t, 3 )) * y2,
2595
+ x: (t1 ** 3) * x1
2596
+ + 3 * (t1 ** 2) * t * c1x
2597
+ + 3 * t1 * (t ** 2) * c2x
2598
+ + (t ** 3) * x2,
2599
+ y: (t1 ** 3) * y1
2600
+ + 3 * (t1 ** 2) * t * c1y
2601
+ + 3 * t1 * (t ** 2) * c2y
2602
+ + (t ** 3) * y2,
2675
2603
  };
2676
2604
  }
2677
2605
 
2678
2606
  /**
2679
- * Returns the length of a C (cubic-bezier) segment,
2607
+ * Returns the length of a C (cubic-bezier) segment
2680
2608
  * or an {x,y} point at a given length.
2681
2609
  *
2682
2610
  * @param {number} x1 the starting point X
@@ -2691,31 +2619,29 @@
2691
2619
  * @returns {{x: number, y: number} | number} the segment length or point
2692
2620
  */
2693
2621
  function segmentCubicFactory(x1, y1, c1x, c1y, c2x, c2y, x2, y2, distance) {
2694
- var assign;
2695
-
2696
- var distanceIsNumber = typeof distance === 'number';
2697
- var lengthMargin = 0.001;
2698
- var x = x1; var y = y1;
2699
- var totalLength = 0;
2700
- var prev = [x1, y1, totalLength];
2622
+ const distanceIsNumber = typeof distance === 'number';
2623
+ const lengthMargin = 0.001;
2624
+ let x = x1; let y = y1;
2625
+ let totalLength = 0;
2626
+ let prev = [x1, y1, totalLength];
2701
2627
  /** @type {[number, number]} */
2702
- var cur = [x1, y1];
2703
- var t = 0;
2628
+ let cur = [x1, y1];
2629
+ let t = 0;
2704
2630
 
2705
2631
  if (distanceIsNumber && distance < lengthMargin) {
2706
- return { x: x, y: y };
2632
+ return { x, y };
2707
2633
  }
2708
2634
 
2709
- var n = 100;
2710
- for (var j = 0; j <= n; j += 1) {
2635
+ const n = 100;
2636
+ for (let j = 0; j <= n; j += 1) {
2711
2637
  t = j / n;
2712
2638
 
2713
- ((assign = getPointAtCubicSegmentLength(x1, y1, c1x, c1y, c2x, c2y, x2, y2, t), x = assign.x, y = assign.y));
2639
+ ({ x, y } = getPointAtCubicSegmentLength(x1, y1, c1x, c1y, c2x, c2y, x2, y2, t));
2714
2640
  totalLength += distanceSquareRoot(cur, [x, y]);
2715
2641
  cur = [x, y];
2716
2642
 
2717
2643
  if (distanceIsNumber && totalLength >= distance) {
2718
- var dv = (totalLength - distance) / (totalLength - prev[2]);
2644
+ const dv = (totalLength - distance) / (totalLength - prev[2]);
2719
2645
 
2720
2646
  return {
2721
2647
  x: cur[0] * (1 - dv) + prev[0] * dv,
@@ -2742,33 +2668,31 @@
2742
2668
  * @param {number} c2y the second control point Y
2743
2669
  * @param {number} x2 the ending point X
2744
2670
  * @param {number} y2 the ending point Y
2745
- * @returns {SVGPathCommander.segmentLimits} the bounding box of the cubic-bezier segment
2671
+ * @returns {SVGPath.segmentLimits} the bounding box of the cubic-bezier segment
2746
2672
  */
2747
2673
  function getCubicSize(x1, y1, c1x, c1y, c2x, c2y, x2, y2) {
2748
- var assign, assign$1, assign$2, assign$3;
2749
-
2750
- var a = (c2x - 2 * c1x + x1) - (x2 - 2 * c2x + c1x);
2751
- var b = 2 * (c1x - x1) - 2 * (c2x - c1x);
2752
- var c = x1 - c1x;
2753
- var t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 / a;
2754
- var t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 / a;
2755
- var X = [x1, x2];
2756
- var Y = [y1, y2];
2757
- var x = 0;
2758
- var y = 0;
2759
-
2760
- if (Math.abs(t1) > 1e12) { t1 = 0.5; }
2761
- if (Math.abs(t2) > 1e12) { t2 = 0.5; }
2674
+ let a = (c2x - 2 * c1x + x1) - (x2 - 2 * c2x + c1x);
2675
+ let b = 2 * (c1x - x1) - 2 * (c2x - c1x);
2676
+ let c = x1 - c1x;
2677
+ let t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 / a;
2678
+ let t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 / a;
2679
+ const X = [x1, x2];
2680
+ const Y = [y1, y2];
2681
+ let x = 0;
2682
+ let y = 0;
2683
+
2684
+ if (Math.abs(t1) > 1e12) t1 = 0.5;
2685
+ if (Math.abs(t2) > 1e12) t2 = 0.5;
2762
2686
 
2763
2687
  if (t1 > 0 && t1 < 1) {
2764
2688
  // @ts-ignore
2765
- ((assign = segmentCubicFactory(x1, y1, c1x, c1y, c2x, c2y, x2, y2, t1), x = assign.x, y = assign.y));
2689
+ ({ x, y } = segmentCubicFactory(x1, y1, c1x, c1y, c2x, c2y, x2, y2, t1));
2766
2690
  X.push(x);
2767
2691
  Y.push(y);
2768
2692
  }
2769
2693
  if (t2 > 0 && t2 < 1) {
2770
2694
  // @ts-ignore
2771
- ((assign$1 = segmentCubicFactory(x1, y1, c1x, c1y, c2x, c2y, x2, y2, t2), x = assign$1.x, y = assign$1.y));
2695
+ ({ x, y } = segmentCubicFactory(x1, y1, c1x, c1y, c2x, c2y, x2, y2, t2));
2772
2696
  X.push(x);
2773
2697
  Y.push(y);
2774
2698
  }
@@ -2777,32 +2701,32 @@
2777
2701
  c = y1 - c1y;
2778
2702
  t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 / a;
2779
2703
  t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 / a;
2780
- if (Math.abs(t1) > 1e12) { t1 = 0.5; }
2781
- if (Math.abs(t2) > 1e12) { t2 = 0.5; }
2704
+ if (Math.abs(t1) > 1e12) t1 = 0.5;
2705
+ if (Math.abs(t2) > 1e12) t2 = 0.5;
2782
2706
 
2783
2707
  if (t1 > 0 && t1 < 1) {
2784
2708
  // @ts-ignore
2785
- ((assign$2 = segmentCubicFactory(x1, y1, c1x, c1y, c2x, c2y, x2, y2, t1), x = assign$2.x, y = assign$2.y));
2709
+ ({ x, y } = segmentCubicFactory(x1, y1, c1x, c1y, c2x, c2y, x2, y2, t1));
2786
2710
  X.push(x);
2787
2711
  Y.push(y);
2788
2712
  }
2789
2713
  if (t2 > 0 && t2 < 1) {
2790
2714
  // @ts-ignore
2791
- ((assign$3 = segmentCubicFactory(x1, y1, c1x, c1y, c2x, c2y, x2, y2, t2), x = assign$3.x, y = assign$3.y));
2715
+ ({ x, y } = segmentCubicFactory(x1, y1, c1x, c1y, c2x, c2y, x2, y2, t2));
2792
2716
  X.push(x);
2793
2717
  Y.push(y);
2794
2718
  }
2795
2719
  return {
2796
- min: { x: Math.min.apply(Math, X), y: Math.min.apply(Math, Y) },
2797
- max: { x: Math.max.apply(Math, X), y: Math.max.apply(Math, Y) },
2720
+ min: { x: Math.min(...X), y: Math.min(...Y) },
2721
+ max: { x: Math.max(...X), y: Math.max(...Y) },
2798
2722
  };
2799
2723
  }
2800
2724
 
2801
2725
  /**
2802
2726
  * Returns the bounding box of a shape.
2803
2727
  *
2804
- * @param {SVGPathCommander.pathArray} path the shape `pathArray`
2805
- * @returns {SVGPathCommander.pathBBox} the length of the cubic-bezier segment
2728
+ * @param {SVGPath.pathArray} path the shape `pathArray`
2729
+ * @returns {SVGPath.pathBBox} the length of the cubic-bezier segment
2806
2730
  */
2807
2731
  function getPathBBox(path) {
2808
2732
  if (!path) {
@@ -2810,357 +2734,57 @@
2810
2734
  x: 0, y: 0, width: 0, height: 0, x2: 0, y2: 0, cx: 0, cy: 0, cz: 0,
2811
2735
  };
2812
2736
  }
2813
- var pathCurve = pathToCurve(path);
2737
+ const pathCurve = pathToCurve(path);
2814
2738
 
2815
- var x = 0; var y = 0;
2739
+ let x = 0; let y = 0;
2816
2740
  /** @type {number[]} */
2817
- var X = [];
2741
+ let X = [];
2818
2742
  /** @type {number[]} */
2819
- var Y = [];
2743
+ let Y = [];
2820
2744
 
2821
- pathCurve.forEach(function (segment) {
2822
- var ref = segment.slice(-2).map(Number);
2823
- var s1 = ref[0];
2824
- var s2 = ref[1];
2745
+ pathCurve.forEach((segment) => {
2746
+ const [s1, s2] = segment.slice(-2).map(Number);
2825
2747
  if (segment[0] === 'M') {
2826
2748
  x = s1;
2827
2749
  y = s2;
2828
2750
  X.push(s1);
2829
2751
  Y.push(s2);
2830
2752
  } else {
2831
- var sizeArgs = [x, y ].concat( segment.slice(1));
2753
+ const sizeArgs = [x, y, ...segment.slice(1)];
2832
2754
  // @ts-ignore -- this should be fine
2833
- var dim = getCubicSize.apply(void 0, sizeArgs);
2755
+ const dim = getCubicSize(...sizeArgs);
2834
2756
 
2835
- X = X.concat( [dim.min.x], [dim.max.x]);
2836
- Y = Y.concat( [dim.min.y], [dim.max.y]);
2757
+ X = [...X, ...[dim.min.x, dim.max.x]];
2758
+ Y = [...Y, ...[dim.min.y, dim.max.y]];
2837
2759
  x = s1;
2838
2760
  y = s2;
2839
2761
  }
2840
2762
  });
2841
2763
 
2842
- var xTop = Math.min.apply(Math, X);
2843
- var yTop = Math.min.apply(Math, Y);
2844
- var xBot = Math.max.apply(Math, X);
2845
- var yBot = Math.max.apply(Math, Y);
2846
- var width = xBot - xTop;
2847
- var height = yBot - yTop;
2764
+ const xTop = Math.min(...X);
2765
+ const yTop = Math.min(...Y);
2766
+ const xBot = Math.max(...X);
2767
+ const yBot = Math.max(...Y);
2768
+ const width = xBot - xTop;
2769
+ const height = yBot - yTop;
2848
2770
 
2849
2771
  // an estimted guess
2850
- var cz = Math.max(width, height) + Math.min(width, height) / 2;
2772
+ const cz = Math.max(width, height) + Math.min(width, height) / 2;
2851
2773
  return {
2852
- width: width,
2853
- height: height,
2774
+ width,
2775
+ height,
2854
2776
  x: xTop,
2855
2777
  y: yTop,
2856
2778
  x2: xBot,
2857
2779
  y2: yBot,
2858
2780
  cx: xTop + width / 2,
2859
2781
  cy: yTop + height / 2,
2860
- cz: cz,
2782
+ cz,
2861
2783
  };
2862
2784
  }
2863
2785
 
2864
2786
  /**
2865
- * Creates a new SVGPathCommander instance with the following properties:
2866
- * * segments: `pathArray`
2867
- * * round: number
2868
- * * origin: [number, number, number?]
2869
- *
2870
- * @class
2871
- * @author thednp <https://github.com/thednp/svg-path-commander>
2872
- * @returns {SVGPathCommander} a new SVGPathCommander instance
2873
- */
2874
- var SVGPathCommander = function SVGPathCommander(pathValue, config) {
2875
- var instanceOptions = config || {};
2876
-
2877
- /**
2878
- * @type {SVGPathCommander.pathArray}
2879
- */
2880
- this.segments = parsePathString(pathValue);
2881
- var BBox = getPathBBox(this.segments);
2882
- var width = BBox.width;
2883
- var height = BBox.height;
2884
- var cx = BBox.cx;
2885
- var cy = BBox.cy;
2886
- var cz = BBox.cz;
2887
-
2888
- // set instance options.round
2889
- var round = defaultOptions.round;
2890
- var origin = defaultOptions.origin;
2891
- var roundOption = instanceOptions.round;
2892
- var originOption = instanceOptions.origin;
2893
-
2894
- if (roundOption === 'auto') {
2895
- var pathScale = (("" + (Math.floor(Math.max(width, height))))).length;
2896
- round = pathScale >= 4 ? 0 : 4 - pathScale;
2897
- } else if ((Number.isInteger(roundOption) && roundOption >= 1) || roundOption === false) {
2898
- round = roundOption;
2899
- }
2900
-
2901
- // set instance options.origin
2902
- if (Array.isArray(originOption) && originOption.length >= 2) {
2903
- var ref = originOption.map(Number);
2904
- var originX = ref[0];
2905
- var originY = ref[1];
2906
- var originZ = ref[2];
2907
- origin = [
2908
- !Number.isNaN(originX) ? originX : cx,
2909
- !Number.isNaN(originY) ? originY : cy,
2910
- originZ || cz ];
2911
- } else {
2912
- origin = [cx, cy, cz];
2913
- }
2914
-
2915
- /**
2916
- * @type {number | boolean}
2917
- * @default 4
2918
- */
2919
- this.round = round;
2920
- this.origin = origin;
2921
-
2922
- return this;
2923
- };
2924
-
2925
- /**
2926
- * Convert path to absolute values
2927
- * @public
2928
- */
2929
- SVGPathCommander.prototype.toAbsolute = function toAbsolute () {
2930
- var ref = this;
2931
- var segments = ref.segments;
2932
- this.segments = pathToAbsolute(segments);
2933
- return this;
2934
- };
2935
-
2936
- /**
2937
- * Convert path to relative values
2938
- * @public
2939
- */
2940
- SVGPathCommander.prototype.toRelative = function toRelative () {
2941
- var ref = this;
2942
- var segments = ref.segments;
2943
- this.segments = pathToRelative(segments);
2944
- return this;
2945
- };
2946
-
2947
- /**
2948
- * Convert path to cubic-bezier values. In addition, un-necessary `Z`
2949
- * segment is removed if previous segment extends to the `M` segment.
2950
- *
2951
- * @public
2952
- */
2953
- SVGPathCommander.prototype.toCurve = function toCurve () {
2954
- var ref = this;
2955
- var segments = ref.segments;
2956
- this.segments = pathToCurve(segments);
2957
- return this;
2958
- };
2959
-
2960
- /**
2961
- * Reverse the order of the segments and their values.
2962
- * @param {boolean | number} onlySubpath option to reverse all sub-paths except first
2963
- * @public
2964
- */
2965
- SVGPathCommander.prototype.reverse = function reverse (onlySubpath) {
2966
- this.toAbsolute();
2967
-
2968
- var ref = this;
2969
- var segments = ref.segments;
2970
- var split = splitPath(this.toString());
2971
- var subPath = split.length > 1 ? split : 0;
2972
-
2973
- // @ts-ignore
2974
- var absoluteMultiPath = subPath && clonePath(subPath).map(function (x, i) {
2975
- if (onlySubpath) {
2976
- return i ? reversePath(x) : parsePathString(x);
2977
- }
2978
- return reversePath(x);
2979
- });
2980
-
2981
- var path = [];
2982
- if (subPath) {
2983
- path = absoluteMultiPath.flat(1);
2984
- } else {
2985
- path = onlySubpath ? segments : reversePath(segments);
2986
- }
2987
-
2988
- this.segments = clonePath(path);
2989
- return this;
2990
- };
2991
-
2992
- /**
2993
- * Normalize path in 2 steps:
2994
- * * convert `pathArray`(s) to absolute values
2995
- * * convert shorthand notation to standard notation
2996
- * @public
2997
- */
2998
- SVGPathCommander.prototype.normalize = function normalize () {
2999
- var ref = this;
3000
- var segments = ref.segments;
3001
- this.segments = normalizePath(segments);
3002
- return this;
3003
- };
3004
-
3005
- /**
3006
- * Optimize `pathArray` values:
3007
- * * convert segments to absolute and/or relative values
3008
- * * select segments with shortest resulted string
3009
- * * round values to the specified `decimals` option value
3010
- * @public
3011
- */
3012
- SVGPathCommander.prototype.optimize = function optimize () {
3013
- var ref = this;
3014
- var segments = ref.segments;
3015
-
3016
- this.segments = optimizePath(segments, this.round);
3017
- return this;
3018
- };
3019
-
3020
- /**
3021
- * Transform path using values from an `Object` defined as `transformObject`.
3022
- * @see SVGPathCommander.transformObject for a quick refference
3023
- *
3024
- * @param {SVGPathCommander.transformObject} source a `transformObject`as described above
3025
- * @public
3026
- */
3027
- SVGPathCommander.prototype.transform = function transform (source) {
3028
- if (!source || typeof source !== 'object' || (typeof source === 'object'
3029
- && !['translate', 'rotate', 'skew', 'scale'].some(function (x) { return x in source; }))) { return this; }
3030
-
3031
- /** @type {SVGPathCommander.transformObject} */
3032
- var transform = {};
3033
- Object.keys(source).forEach(function (fn) {
3034
- // @ts-ignore
3035
- transform[fn] = Array.isArray(source[fn]) ? [].concat( source[fn] ) : Number(source[fn]);
3036
- });
3037
- var ref = this;
3038
- var segments = ref.segments;
3039
-
3040
- // if origin is not specified
3041
- // it's important that we have one
3042
- var origin = transform.origin;
3043
- if (origin && origin.length >= 2) {
3044
- var ref$1 = origin.map(Number);
3045
- var originX = ref$1[0];
3046
- var originY = ref$1[1];
3047
- var originZ = ref$1[2];
3048
- var ref$2 = this.origin;
3049
- var cx = ref$2[0];
3050
- var cy = ref$2[1];
3051
- var cz = ref$2[2];
3052
- transform.origin = [
3053
- !Number.isNaN(originX) ? originX : cx,
3054
- !Number.isNaN(originY) ? originY : cy,
3055
- originZ || cz ];
3056
- } else {
3057
- // @ts-ignore
3058
- transform.origin = Object.assign({}, this.origin);
3059
- }
3060
-
3061
- this.segments = transformPath(segments, transform);
3062
- return this;
3063
- };
3064
-
3065
- /**
3066
- * Rotate path 180deg horizontally
3067
- * @public
3068
- */
3069
- SVGPathCommander.prototype.flipX = function flipX () {
3070
- this.transform({ rotate: [180, 0, 0] });
3071
- return this;
3072
- };
3073
-
3074
- /**
3075
- * Rotate path 180deg vertically
3076
- * @public
3077
- */
3078
- SVGPathCommander.prototype.flipY = function flipY () {
3079
- this.transform({ rotate: [0, 180, 0] });
3080
- return this;
3081
- };
3082
-
3083
- /**
3084
- * Export the current path to be used
3085
- * for the `d` (description) attribute.
3086
- * @public
3087
- * @return {String} the path string
3088
- */
3089
- SVGPathCommander.prototype.toString = function toString () {
3090
- return pathToString(this.segments, this.round);
3091
- };
3092
-
3093
- /**
3094
- * Returns the area of a single cubic-bezier segment.
3095
- *
3096
- * http://objectmix.com/graphics/133553-area-closed-bezier-curve.html
3097
- *
3098
- * @param {number} x1 the starting point X
3099
- * @param {number} y1 the starting point Y
3100
- * @param {number} c1x the first control point X
3101
- * @param {number} c1y the first control point Y
3102
- * @param {number} c2x the second control point X
3103
- * @param {number} c2y the second control point Y
3104
- * @param {number} x2 the ending point X
3105
- * @param {number} y2 the ending point Y
3106
- * @returns {number} the area of the cubic-bezier segment
3107
- */
3108
- function getCubicSegArea(x1, y1, c1x, c1y, c2x, c2y, x2, y2) {
3109
- return (3 * ((y2 - y1) * (c1x + c2x) - (x2 - x1) * (c1y + c2y)
3110
- + (c1y * (x1 - c2x)) - (c1x * (y1 - c2y))
3111
- + (y2 * (c2x + x1 / 3)) - (x2 * (c2y + y1 / 3)))) / 20;
3112
- }
3113
-
3114
- /**
3115
- * Returns the area of a shape.
3116
- * @author Jürg Lehni & Jonathan Puckey
3117
- *
3118
- * @see https://github.com/paperjs/paper.js/blob/develop/src/path/Path.js
3119
- *
3120
- * @param {SVGPathCommander.pathArray} path the shape `pathArray`
3121
- * @returns {number} the length of the cubic-bezier segment
3122
- */
3123
- function getPathArea(path) {
3124
- var x = 0; var y = 0; var len = 0;
3125
-
3126
- return pathToCurve(path).map(function (seg) {
3127
- var assign, assign$1;
3128
-
3129
- switch (seg[0]) {
3130
- case 'M':
3131
- (assign = seg, x = assign[1], y = assign[2]);
3132
- return 0;
3133
- default:
3134
- // @ts-ignore -- the utility will have proper amount of params
3135
- len = getCubicSegArea.apply(void 0, [ x, y ].concat( seg.slice(1) ));
3136
- // @ts-ignore -- the segment always has numbers
3137
- (assign$1 = seg.slice(-2), x = assign$1[0], y = assign$1[1]);
3138
- return len;
3139
- }
3140
- }).reduce(function (a, b) { return a + b; }, 0);
3141
- }
3142
-
3143
- /**
3144
- * Returns the shape total length, or the equivalent to `shape.getTotalLength()`.
3145
- *
3146
- * This is the `pathToCurve` version which is faster and more efficient for
3147
- * paths that are `curveArray`.
3148
- *
3149
- * @param {string | SVGPathCommander.curveArray} path the target `pathArray`
3150
- * @returns {number} the `curveArray` total length
3151
- */
3152
- function getPathLength(path) {
3153
- var totalLength = 0;
3154
- pathToCurve(path).forEach(function (s, i, curveArray) {
3155
- var args = s[0] !== 'M' ? curveArray[i - 1].slice(-2).concat( s.slice(1)) : [];
3156
- // @ts-ignore
3157
- totalLength += s[0] === 'M' ? 0 : segmentCubicFactory.apply(void 0, args);
3158
- });
3159
- return totalLength;
3160
- }
3161
-
3162
- /**
3163
- * Returns the length of a A (arc-to) segment,
2787
+ * Returns the length of an A (arc-to) segment
3164
2788
  * or an {x,y} point at a given length.
3165
2789
  *
3166
2790
  * @param {number} X1 the starting x position
@@ -3176,34 +2800,30 @@
3176
2800
  * @returns {{x: number, y: number} | number} the segment length or point
3177
2801
  */
3178
2802
  function segmentArcFactory(X1, Y1, RX, RY, angle, LAF, SF, X2, Y2, distance) {
3179
- var assign;
3180
-
3181
- var cubicSeg = arcToCubic(X1, Y1, RX, RY, angle, LAF, SF, X2, Y2);
3182
- var distanceIsNumber = typeof distance === 'number';
3183
- var ref = [X1, Y1];
3184
- var x = ref[0];
3185
- var y = ref[1];
3186
- var lengthMargin = 0.001;
3187
- var totalLength = 0;
3188
- var cubicSubseg = [];
3189
- var argsc = [];
3190
- var segLen = 0;
2803
+ const cubicSeg = arcToCubic(X1, Y1, RX, RY, angle, LAF, SF, X2, Y2);
2804
+ const distanceIsNumber = typeof distance === 'number';
2805
+ let [x, y] = [X1, Y1];
2806
+ const lengthMargin = 0.001;
2807
+ let totalLength = 0;
2808
+ let cubicSubseg = [];
2809
+ let argsc = [];
2810
+ let segLen = 0;
3191
2811
 
3192
2812
  if (distanceIsNumber && distance < lengthMargin) {
3193
- return { x: x, y: y };
2813
+ return { x, y };
3194
2814
  }
3195
2815
 
3196
- for (var i = 0, ii = cubicSeg.length; i < ii; i += 6) {
2816
+ for (let i = 0, ii = cubicSeg.length; i < ii; i += 6) {
3197
2817
  cubicSubseg = cubicSeg.slice(i, i + 6);
3198
- argsc = [x, y ].concat( cubicSubseg);
2818
+ argsc = [x, y, ...cubicSubseg];
3199
2819
  // @ts-ignore
3200
- segLen = segmentCubicFactory.apply(void 0, argsc);
2820
+ segLen = segmentCubicFactory(...argsc);
3201
2821
  if (distanceIsNumber && totalLength + segLen >= distance) {
3202
2822
  // @ts-ignore -- this is a `cubicSegment`
3203
- return segmentCubicFactory.apply(void 0, argsc.concat( [distance - totalLength] ));
2823
+ return segmentCubicFactory(...argsc, distance - totalLength);
3204
2824
  }
3205
2825
  totalLength += segLen;
3206
- (assign = cubicSubseg.slice(-2), x = assign[0], y = assign[1]);
2826
+ [x, y] = cubicSubseg.slice(-2);
3207
2827
  }
3208
2828
 
3209
2829
  if (distanceIsNumber && distance >= totalLength) {
@@ -3229,19 +2849,19 @@
3229
2849
  * @returns {{x: number, y: number}} the requested {x,y} coordinates
3230
2850
  */
3231
2851
  function getPointAtQuadSegmentLength(x1, y1, cx, cy, x2, y2, t) {
3232
- var t1 = 1 - t;
2852
+ const t1 = 1 - t;
3233
2853
  return {
3234
- x: (Math.pow( t1, 2 )) * x1
2854
+ x: (t1 ** 2) * x1
3235
2855
  + 2 * t1 * t * cx
3236
- + (Math.pow( t, 2 )) * x2,
3237
- y: (Math.pow( t1, 2 )) * y1
2856
+ + (t ** 2) * x2,
2857
+ y: (t1 ** 2) * y1
3238
2858
  + 2 * t1 * t * cy
3239
- + (Math.pow( t, 2 )) * y2,
2859
+ + (t ** 2) * y2,
3240
2860
  };
3241
2861
  }
3242
2862
 
3243
2863
  /**
3244
- * Returns the Q (quadratic-bezier) segment length,
2864
+ * Returns the Q (quadratic-bezier) segment length
3245
2865
  * or an {x,y} point at a given length.
3246
2866
  *
3247
2867
  * @param {number} x1 the starting point X
@@ -3254,31 +2874,29 @@
3254
2874
  * @returns {{x: number, y: number} | number} the segment length or point
3255
2875
  */
3256
2876
  function segmentQuadFactory(x1, y1, qx, qy, x2, y2, distance) {
3257
- var assign;
3258
-
3259
- var distanceIsNumber = typeof distance === 'number';
3260
- var lengthMargin = 0.001;
3261
- var x = x1; var y = y1;
3262
- var totalLength = 0;
3263
- var prev = [x1, y1, totalLength];
2877
+ const distanceIsNumber = typeof distance === 'number';
2878
+ const lengthMargin = 0.001;
2879
+ let x = x1; let y = y1;
2880
+ let totalLength = 0;
2881
+ let prev = [x1, y1, totalLength];
3264
2882
  /** @type {[number, number]} */
3265
- var cur = [x1, y1];
3266
- var t = 0;
2883
+ let cur = [x1, y1];
2884
+ let t = 0;
3267
2885
 
3268
2886
  if (distanceIsNumber && distance < lengthMargin) {
3269
- return { x: x, y: y };
2887
+ return { x, y };
3270
2888
  }
3271
2889
 
3272
- var n = 100;
3273
- for (var j = 0; j <= n; j += 1) {
2890
+ const n = 100;
2891
+ for (let j = 0; j <= n; j += 1) {
3274
2892
  t = j / n;
3275
2893
 
3276
- ((assign = getPointAtQuadSegmentLength(x1, y1, qx, qy, x2, y2, t), x = assign.x, y = assign.y));
2894
+ ({ x, y } = getPointAtQuadSegmentLength(x1, y1, qx, qy, x2, y2, t));
3277
2895
  totalLength += distanceSquareRoot(cur, [x, y]);
3278
2896
  cur = [x, y];
3279
2897
 
3280
2898
  if (distanceIsNumber && totalLength >= distance) {
3281
- var dv = (totalLength - distance) / (totalLength - prev[2]);
2899
+ const dv = (totalLength - distance) / (totalLength - prev[2]);
3282
2900
 
3283
2901
  return {
3284
2902
  x: cur[0] * (1 - dv) + prev[0] * dv,
@@ -3294,95 +2912,94 @@
3294
2912
  }
3295
2913
 
3296
2914
  /**
3297
- * Returns a {x,y} point at a given length of a shape or the shape total length.
2915
+ * Returns a {x,y} point at a given length
2916
+ * of a shape or the shape total length.
3298
2917
  *
3299
- * @param {string | SVGPathCommander.pathArray} pathInput the `pathArray` to look into
2918
+ * @param {string | SVGPath.pathArray} pathInput the `pathArray` to look into
3300
2919
  * @param {number=} distance the length of the shape to look at
3301
2920
  * @returns {{x: number, y: number} | number} the total length or point
3302
2921
  */
3303
2922
  function pathLengthFactory(pathInput, distance) {
3304
- var assign, assign$1, assign$2;
3305
-
3306
- var path = fixPath(normalizePath(pathInput));
3307
- var distanceIsNumber = typeof distance === 'number';
3308
- var totalLength = 0;
3309
- var isM = true;
2923
+ const path = fixPath(normalizePath(pathInput));
2924
+ const distanceIsNumber = typeof distance === 'number';
2925
+ let totalLength = 0;
2926
+ let isM = true;
3310
2927
  /** @type {number[]} */
3311
- var data = [];
3312
- var pathCommand = 'M';
3313
- var segLen = 0;
3314
- var x = 0;
3315
- var y = 0;
3316
- var mx = 0;
3317
- var my = 0;
3318
- var seg;
3319
-
3320
- for (var i = 0, ll = path.length; i < ll; i += 1) {
2928
+ let data = [];
2929
+ let pathCommand = 'M';
2930
+ let segLen = 0;
2931
+ let x = 0;
2932
+ let y = 0;
2933
+ let mx = 0;
2934
+ let my = 0;
2935
+ let seg;
2936
+
2937
+ for (let i = 0, ll = path.length; i < ll; i += 1) {
3321
2938
  seg = path[i];
3322
- (assign = seg, pathCommand = assign[0]);
2939
+ [pathCommand] = seg;
3323
2940
  isM = pathCommand === 'M';
3324
2941
  // @ts-ignore
3325
- data = !isM ? [x, y ].concat( seg.slice(1)) : data;
2942
+ data = !isM ? [x, y, ...seg.slice(1)] : data;
3326
2943
 
3327
2944
  // this segment is always ZERO
3328
2945
  if (isM) {
3329
2946
  // remember mx, my for Z
3330
2947
  // @ts-ignore
3331
- (assign$1 = seg, mx = assign$1[1], my = assign$1[2]);
2948
+ [, mx, my] = seg;
3332
2949
  if (distanceIsNumber && distance < 0.001) {
3333
2950
  return { x: mx, y: my };
3334
2951
  }
3335
2952
  } else if (pathCommand === 'L') {
3336
2953
  // @ts-ignore
3337
- segLen = segmentLineFactory.apply(void 0, data);
2954
+ segLen = segmentLineFactory(...data);
3338
2955
  if (distanceIsNumber && totalLength + segLen >= distance) {
3339
2956
  // @ts-ignore
3340
- return segmentLineFactory.apply(void 0, data.concat( [distance - totalLength] ));
2957
+ return segmentLineFactory(...data, distance - totalLength);
3341
2958
  }
3342
2959
  totalLength += segLen;
3343
2960
  } else if (pathCommand === 'A') {
3344
2961
  // @ts-ignore
3345
- segLen = segmentArcFactory.apply(void 0, data);
2962
+ segLen = segmentArcFactory(...data);
3346
2963
  if (distanceIsNumber && totalLength + segLen >= distance) {
3347
2964
  // @ts-ignore
3348
- return segmentArcFactory.apply(void 0, data.concat( [distance - totalLength] ));
2965
+ return segmentArcFactory(...data, distance - totalLength);
3349
2966
  }
3350
2967
  totalLength += segLen;
3351
2968
  } else if (pathCommand === 'C') {
3352
2969
  // @ts-ignore
3353
- segLen = segmentCubicFactory.apply(void 0, data);
2970
+ segLen = segmentCubicFactory(...data);
3354
2971
  if (distanceIsNumber && totalLength + segLen >= distance) {
3355
2972
  // @ts-ignore
3356
- return segmentCubicFactory.apply(void 0, data.concat( [distance - totalLength] ));
2973
+ return segmentCubicFactory(...data, distance - totalLength);
3357
2974
  }
3358
2975
  totalLength += segLen;
3359
2976
  } else if (pathCommand === 'Q') {
3360
2977
  // @ts-ignore
3361
- segLen = segmentQuadFactory.apply(void 0, data);
2978
+ segLen = segmentQuadFactory(...data);
3362
2979
  if (distanceIsNumber && totalLength + segLen >= distance) {
3363
2980
  // @ts-ignore
3364
- return segmentQuadFactory.apply(void 0, data.concat( [distance - totalLength] ));
2981
+ return segmentQuadFactory(...data, distance - totalLength);
3365
2982
  }
3366
2983
  totalLength += segLen;
3367
2984
  } else if (pathCommand === 'Z') {
3368
2985
  data = [x, y, mx, my];
3369
2986
  // @ts-ignore
3370
- segLen = segmentLineFactory.apply(void 0, data);
2987
+ segLen = segmentLineFactory(...data);
3371
2988
  if (distanceIsNumber && totalLength + segLen >= distance) {
3372
2989
  // @ts-ignore
3373
- return segmentLineFactory.apply(void 0, data.concat( [distance - totalLength] ));
2990
+ return segmentLineFactory(...data, distance - totalLength);
3374
2991
  }
3375
2992
  totalLength += segLen;
3376
2993
  }
3377
2994
 
3378
2995
  // @ts-ignore -- needed for the below
3379
- (assign$2 = pathCommand !== 'Z' ? seg.slice(-2) : [mx, my], x = assign$2[0], y = assign$2[1]);
2996
+ [x, y] = pathCommand !== 'Z' ? seg.slice(-2) : [mx, my];
3380
2997
  }
3381
2998
 
3382
2999
  // native `getPointAtLength` behavior when the given distance
3383
3000
  // is higher than total length
3384
3001
  if (distanceIsNumber && distance >= totalLength) {
3385
- return { x: x, y: y };
3002
+ return { x, y };
3386
3003
  }
3387
3004
 
3388
3005
  return totalLength;
@@ -3394,7 +3011,7 @@
3394
3011
  * The `normalizePath` version is lighter, faster, more efficient and more accurate
3395
3012
  * with paths that are not `curveArray`.
3396
3013
  *
3397
- * @param {string | SVGPathCommander.pathArray} pathInput the target `pathArray`
3014
+ * @param {string | SVGPath.pathArray} pathInput the target `pathArray`
3398
3015
  * @returns {number} the shape total length
3399
3016
  */
3400
3017
  function getTotalLength(pathInput) {
@@ -3402,21 +3019,10 @@
3402
3019
  return pathLengthFactory(pathInput);
3403
3020
  }
3404
3021
 
3405
- /**
3406
- * Check if a path is drawn clockwise and returns true if so,
3407
- * false otherwise.
3408
- *
3409
- * @param {SVGPathCommander.pathArray} path the path string or `pathArray`
3410
- * @returns {boolean} true when clockwise or false if not
3411
- */
3412
- function getDrawDirection(path) {
3413
- return getPathArea(pathToCurve(path)) >= 0;
3414
- }
3415
-
3416
3022
  /**
3417
3023
  * Returns [x,y] coordinates of a point at a given length of a shape.
3418
3024
  *
3419
- * @param {string | SVGPathCommander.pathArray} pathInput the `pathArray` to look into
3025
+ * @param {string | SVGPath.pathArray} pathInput the `pathArray` to look into
3420
3026
  * @param {number} distance the length of the shape to look at
3421
3027
  * @returns {{x: number, y: number}} the requested {x, y} point coordinates
3422
3028
  */
@@ -3426,49 +3032,369 @@
3426
3032
  }
3427
3033
 
3428
3034
  /**
3429
- * Returns [x,y] coordinates of a point at a given length of a shape.
3430
- * `pathToCurve` version.
3035
+ * Creates a new SVGPathCommander instance with the following properties:
3036
+ * * segments: `pathArray`
3037
+ * * round: number
3038
+ * * origin: [number, number, number?]
3039
+ *
3040
+ * @class
3041
+ * @author thednp <https://github.com/thednp/svg-path-commander>
3042
+ * @returns {SVGPathCommander} a new SVGPathCommander instance
3043
+ */
3044
+ class SVGPathCommander {
3045
+ /**
3046
+ * @constructor
3047
+ * @param {string} pathValue the path string
3048
+ * @param {any} config instance options
3049
+ */
3050
+ constructor(pathValue, config) {
3051
+ const instanceOptions = config || {};
3052
+
3053
+ const undefPath = typeof pathValue === 'undefined';
3054
+
3055
+ if (undefPath || !pathValue.length) {
3056
+ throw TypeError(`${error}: "pathValue" is ${undefPath ? 'undefined' : 'empty'}`);
3057
+ }
3058
+
3059
+ const segments = parsePathString(pathValue);
3060
+ if (typeof segments === 'string') {
3061
+ throw TypeError(segments);
3062
+ }
3063
+
3064
+ /**
3065
+ * @type {SVGPath.pathArray}
3066
+ */
3067
+ this.segments = segments;
3068
+
3069
+ const {
3070
+ width, height, cx, cy, cz,
3071
+ } = this.getBBox();
3072
+
3073
+ // set instance options.round
3074
+ let { round, origin } = defaultOptions;
3075
+ const { round: roundOption, origin: originOption } = instanceOptions;
3076
+
3077
+ if (roundOption === 'auto') {
3078
+ const pathScale = (`${Math.floor(Math.max(width, height))}`).length;
3079
+ round = pathScale >= 4 ? 0 : 4 - pathScale;
3080
+ } else if (Number.isInteger(roundOption) || roundOption === false) {
3081
+ round = roundOption;
3082
+ }
3083
+
3084
+ // set instance options.origin
3085
+ if (Array.isArray(originOption) && originOption.length >= 2) {
3086
+ const [originX, originY, originZ] = originOption.map(Number);
3087
+ origin = [
3088
+ !Number.isNaN(originX) ? originX : cx,
3089
+ !Number.isNaN(originY) ? originY : cy,
3090
+ !Number.isNaN(originZ) ? originZ : cz,
3091
+ ];
3092
+ } else {
3093
+ origin = [cx, cy, cz];
3094
+ }
3095
+
3096
+ /**
3097
+ * @type {number | false}
3098
+ */
3099
+ this.round = round;
3100
+ this.origin = origin;
3101
+
3102
+ return this;
3103
+ }
3104
+
3105
+ /**
3106
+ * Returns the path bounding box, equivalent to native `path.getBBox()`.
3107
+ * @public
3108
+ * @returns {SVGPath.pathBBox}
3109
+ */
3110
+ getBBox() {
3111
+ return getPathBBox(this.segments);
3112
+ }
3113
+
3114
+ /**
3115
+ * Returns the total path length, equivalent to native `path.getTotalLength()`.
3116
+ * @public
3117
+ * @returns {number}
3118
+ */
3119
+ getTotalLength() {
3120
+ return getTotalLength(this.segments);
3121
+ }
3122
+
3123
+ /**
3124
+ * Returns an `{x,y}` point in the path stroke at a given length,
3125
+ * equivalent to the native `path.getPointAtLength()`.
3126
+ *
3127
+ * @public
3128
+ * @param {number} length the length
3129
+ * @returns {{x: number, y:number}} the requested point
3130
+ */
3131
+ getPointAtLength(length) {
3132
+ return getPointAtLength(this.segments, length);
3133
+ }
3134
+
3135
+ /**
3136
+ * Convert path to absolute values
3137
+ * @public
3138
+ */
3139
+ toAbsolute() {
3140
+ const { segments } = this;
3141
+ this.segments = pathToAbsolute(segments);
3142
+ return this;
3143
+ }
3144
+
3145
+ /**
3146
+ * Convert path to relative values
3147
+ * @public
3148
+ */
3149
+ toRelative() {
3150
+ const { segments } = this;
3151
+ this.segments = pathToRelative(segments);
3152
+ return this;
3153
+ }
3154
+
3155
+ /**
3156
+ * Convert path to cubic-bezier values. In addition, un-necessary `Z`
3157
+ * segment is removed if previous segment extends to the `M` segment.
3158
+ *
3159
+ * @public
3160
+ */
3161
+ toCurve() {
3162
+ const { segments } = this;
3163
+ this.segments = pathToCurve(segments);
3164
+ return this;
3165
+ }
3166
+
3167
+ /**
3168
+ * Reverse the order of the segments and their values.
3169
+ * @param {boolean | number} onlySubpath option to reverse all sub-paths except first
3170
+ * @public
3171
+ */
3172
+ reverse(onlySubpath) {
3173
+ this.toAbsolute();
3174
+
3175
+ const { segments } = this;
3176
+ const split = splitPath(this.toString());
3177
+ const subPath = split.length > 1 ? split : 0;
3178
+
3179
+ // @ts-ignore
3180
+ const absoluteMultiPath = subPath && clonePath(subPath).map((x, i) => {
3181
+ if (onlySubpath) {
3182
+ return i ? reversePath(x) : parsePathString(x);
3183
+ }
3184
+ return reversePath(x);
3185
+ });
3186
+
3187
+ let path = [];
3188
+ if (subPath) {
3189
+ path = absoluteMultiPath.flat(1);
3190
+ } else {
3191
+ path = onlySubpath ? segments : reversePath(segments);
3192
+ }
3193
+
3194
+ this.segments = clonePath(path);
3195
+ return this;
3196
+ }
3197
+
3198
+ /**
3199
+ * Normalize path in 2 steps:
3200
+ * * convert `pathArray`(s) to absolute values
3201
+ * * convert shorthand notation to standard notation
3202
+ * @public
3203
+ */
3204
+ normalize() {
3205
+ const { segments } = this;
3206
+ this.segments = normalizePath(segments);
3207
+ return this;
3208
+ }
3209
+
3210
+ /**
3211
+ * Optimize `pathArray` values:
3212
+ * * convert segments to absolute and/or relative values
3213
+ * * select segments with shortest resulted string
3214
+ * * round values to the specified `decimals` option value
3215
+ * @public
3216
+ */
3217
+ optimize() {
3218
+ const { segments } = this;
3219
+
3220
+ this.segments = optimizePath(segments, this.round);
3221
+ return this;
3222
+ }
3223
+
3224
+ /**
3225
+ * Transform path using values from an `Object` defined as `transformObject`.
3226
+ * @see SVGPath.transformObject for a quick refference
3227
+ *
3228
+ * @param {SVGPath.transformObject} source a `transformObject`as described above
3229
+ * @public
3230
+ */
3231
+ transform(source) {
3232
+ if (!source || typeof source !== 'object' || (typeof source === 'object'
3233
+ && !['translate', 'rotate', 'skew', 'scale'].some((x) => x in source))) return this;
3234
+
3235
+ /** @type {SVGPath.transformObject} */
3236
+ const transform = {};
3237
+ Object.keys(source).forEach((fn) => {
3238
+ // @ts-ignore
3239
+ transform[fn] = Array.isArray(source[fn]) ? [...source[fn]] : Number(source[fn]);
3240
+ });
3241
+ const { segments } = this;
3242
+
3243
+ // if origin is not specified
3244
+ // it's important that we have one
3245
+ const [cx, cy, cz] = this.origin;
3246
+ const { origin } = transform;
3247
+
3248
+ if (Array.isArray(origin) && origin.length >= 2) {
3249
+ const [originX, originY, originZ] = origin.map(Number);
3250
+ transform.origin = [
3251
+ !Number.isNaN(originX) ? originX : cx,
3252
+ !Number.isNaN(originY) ? originY : cy,
3253
+ originZ || cz,
3254
+ ];
3255
+ } else {
3256
+ transform.origin = [cx, cy, cz];
3257
+ }
3258
+
3259
+ this.segments = transformPath(segments, transform);
3260
+ return this;
3261
+ }
3262
+
3263
+ /**
3264
+ * Rotate path 180deg horizontally
3265
+ * @public
3266
+ */
3267
+ flipX() {
3268
+ this.transform({ rotate: [180, 0, 0] });
3269
+ return this;
3270
+ }
3271
+
3272
+ /**
3273
+ * Rotate path 180deg vertically
3274
+ * @public
3275
+ */
3276
+ flipY() {
3277
+ this.transform({ rotate: [0, 180, 0] });
3278
+ return this;
3279
+ }
3280
+
3281
+ /**
3282
+ * Export the current path to be used
3283
+ * for the `d` (description) attribute.
3284
+ * @public
3285
+ * @return {String} the path string
3286
+ */
3287
+ toString() {
3288
+ return pathToString(this.segments, this.round);
3289
+ }
3290
+ }
3291
+
3292
+ /**
3293
+ * Returns the area of a single cubic-bezier segment.
3431
3294
  *
3432
- * @deprecated
3295
+ * http://objectmix.com/graphics/133553-area-closed-bezier-curve.html
3433
3296
  *
3434
- * @param {string | SVGPathCommander.pathArray} pathInput the `pathArray` to look into
3435
- * @param {number} distance the length of the shape to look at
3436
- * @returns {{x: number, y: number}} the requested {x, y} point coordinates
3297
+ * @param {number} x1 the starting point X
3298
+ * @param {number} y1 the starting point Y
3299
+ * @param {number} c1x the first control point X
3300
+ * @param {number} c1y the first control point Y
3301
+ * @param {number} c2x the second control point X
3302
+ * @param {number} c2y the second control point Y
3303
+ * @param {number} x2 the ending point X
3304
+ * @param {number} y2 the ending point Y
3305
+ * @returns {number} the area of the cubic-bezier segment
3306
+ */
3307
+ function getCubicSegArea(x1, y1, c1x, c1y, c2x, c2y, x2, y2) {
3308
+ return (3 * ((y2 - y1) * (c1x + c2x) - (x2 - x1) * (c1y + c2y)
3309
+ + (c1y * (x1 - c2x)) - (c1x * (y1 - c2y))
3310
+ + (y2 * (c2x + x1 / 3)) - (x2 * (c2y + y1 / 3)))) / 20;
3311
+ }
3312
+
3313
+ /**
3314
+ * Returns the area of a shape.
3315
+ * @author Jürg Lehni & Jonathan Puckey
3316
+ *
3317
+ * @see https://github.com/paperjs/paper.js/blob/develop/src/path/Path.js
3318
+ *
3319
+ * @param {SVGPath.pathArray} path the shape `pathArray`
3320
+ * @returns {number} the length of the cubic-bezier segment
3321
+ */
3322
+ function getPathArea(path) {
3323
+ let x = 0; let y = 0; let len = 0;
3324
+
3325
+ return pathToCurve(path).map((seg) => {
3326
+ switch (seg[0]) {
3327
+ case 'M':
3328
+ [, x, y] = seg;
3329
+ return 0;
3330
+ default:
3331
+ // @ts-ignore -- the utility will have proper amount of params
3332
+ len = getCubicSegArea(x, y, ...seg.slice(1));
3333
+ // @ts-ignore -- the segment always has numbers
3334
+ [x, y] = seg.slice(-2);
3335
+ return len;
3336
+ }
3337
+ }).reduce((a, b) => a + b, 0);
3338
+ }
3339
+
3340
+ /**
3341
+ * Returns the shape total length, or the equivalent to `shape.getTotalLength()`.
3342
+ *
3343
+ * This is the `pathToCurve` version which is faster and more efficient for
3344
+ * paths that are `curveArray`.
3345
+ *
3346
+ * @param {string | SVGPath.curveArray} path the target `pathArray`
3347
+ * @returns {number} the `curveArray` total length
3348
+ */
3349
+ function getPathLength(path) {
3350
+ let totalLength = 0;
3351
+ pathToCurve(path).forEach((s, i, curveArray) => {
3352
+ const args = s[0] !== 'M' ? [...curveArray[i - 1].slice(-2), ...s.slice(1)] : [];
3353
+ // @ts-ignore
3354
+ totalLength += s[0] === 'M' ? 0 : segmentCubicFactory(...args);
3355
+ });
3356
+ return totalLength;
3357
+ }
3358
+
3359
+ /**
3360
+ * Check if a path is drawn clockwise and returns true if so,
3361
+ * false otherwise.
3362
+ *
3363
+ * @param {SVGPath.pathArray} path the path string or `pathArray`
3364
+ * @returns {boolean} true when clockwise or false if not
3437
3365
  */
3438
- function getPointAtPathLength(pathInput, distance) {
3439
- return getPointAtLength(pathInput, distance);
3366
+ function getDrawDirection(path) {
3367
+ return getPathArea(pathToCurve(path)) >= 0;
3440
3368
  }
3441
3369
 
3442
3370
  /**
3443
3371
  * Returns the segment, its index and length as well as
3444
3372
  * the length to that segment at a given length in a path.
3445
3373
  *
3446
- * @param {string | SVGPathCommander.pathArray} pathInput target `pathArray`
3374
+ * @param {string | SVGPath.pathArray} pathInput target `pathArray`
3447
3375
  * @param {number=} distance the given length
3448
- * @returns {SVGPathCommander.segmentProperties=} the requested properties
3376
+ * @returns {SVGPath.segmentProperties=} the requested properties
3449
3377
  */
3450
3378
  function getPropertiesAtLength(pathInput, distance) {
3451
- var pathArray = parsePathString(pathInput);
3452
- var segments = [];
3379
+ const pathArray = parsePathString(pathInput);
3380
+ const segments = [];
3453
3381
 
3454
- var pathTemp = [].concat( pathArray );
3382
+ let pathTemp = [...pathArray];
3455
3383
  // @ts-ignore
3456
- var pathLength = getTotalLength(pathTemp);
3457
- var index = pathTemp.length - 1;
3458
- var lengthAtSegment = 0;
3459
- var length = 0;
3460
- /** @type {SVGPathCommander.pathSegment} */
3461
- var segment = pathArray[0];
3462
- var ref = segment.slice(-2);
3463
- var x = ref[0];
3464
- var y = ref[1];
3465
- var point = { x: x, y: y };
3384
+ let pathLength = getTotalLength(pathTemp);
3385
+ let index = pathTemp.length - 1;
3386
+ let lengthAtSegment = 0;
3387
+ let length = 0;
3388
+ /** @type {SVGPath.pathSegment} */
3389
+ let segment = pathArray[0];
3390
+ const [x, y] = segment.slice(-2);
3391
+ const point = { x, y };
3466
3392
 
3467
3393
  // If the path is empty, return 0.
3468
3394
  if (index <= 0 || !distance || !Number.isFinite(distance)) {
3469
3395
  return {
3470
3396
  // @ts-ignore
3471
- segment: segment, index: 0, length: length, point: point, lengthAtSegment: lengthAtSegment,
3397
+ segment, index: 0, length, point, lengthAtSegment,
3472
3398
  };
3473
3399
  }
3474
3400
 
@@ -3480,7 +3406,7 @@
3480
3406
  length = pathLength - lengthAtSegment;
3481
3407
  return {
3482
3408
  // @ts-ignore
3483
- segment: pathArray[index], index: index, length: length, lengthAtSegment: lengthAtSegment,
3409
+ segment: pathArray[index], index, length, lengthAtSegment,
3484
3410
  };
3485
3411
  }
3486
3412
 
@@ -3493,17 +3419,13 @@
3493
3419
  length = pathLength - lengthAtSegment;
3494
3420
  pathLength = lengthAtSegment;
3495
3421
  segments.push({
3496
- segment: segment, index: index, length: length, lengthAtSegment: lengthAtSegment,
3422
+ segment, index, length, lengthAtSegment,
3497
3423
  });
3498
3424
  index -= 1;
3499
3425
  }
3500
3426
 
3501
3427
  // @ts-ignore
3502
- return segments.find(function (ref) {
3503
- var l = ref.lengthAtSegment;
3504
-
3505
- return l <= distance;
3506
- });
3428
+ return segments.find(({ lengthAtSegment: l }) => l <= distance);
3507
3429
  }
3508
3430
 
3509
3431
  /**
@@ -3511,29 +3433,29 @@
3511
3433
  * the distance to the path stroke.
3512
3434
  * @see https://bl.ocks.org/mbostock/8027637
3513
3435
  *
3514
- * @param {string | SVGPathCommander.pathArray} pathInput target `pathArray`
3436
+ * @param {string | SVGPath.pathArray} pathInput target `pathArray`
3515
3437
  * @param {{x: number, y: number}} point the given point
3516
- * @returns {SVGPathCommander.pointProperties} the requested properties
3438
+ * @returns {SVGPath.pointProperties} the requested properties
3517
3439
  */
3518
3440
  function getPropertiesAtPoint(pathInput, point) {
3519
- var path = fixPath(parsePathString(pathInput));
3520
- var normalPath = normalizePath(path);
3521
- var pathLength = getTotalLength(path);
3441
+ const path = fixPath(parsePathString(pathInput));
3442
+ const normalPath = normalizePath(path);
3443
+ const pathLength = getTotalLength(path);
3522
3444
  /** @param {{x: number, y: number}} p */
3523
- var distanceTo = function (p) {
3524
- var dx = p.x - point.x;
3525
- var dy = p.y - point.y;
3445
+ const distanceTo = (p) => {
3446
+ const dx = p.x - point.x;
3447
+ const dy = p.y - point.y;
3526
3448
  return dx * dx + dy * dy;
3527
3449
  };
3528
- var precision = 8;
3529
- var scan = { x: 0, y: 0 };
3530
- var scanDistance = 0;
3531
- var closest = scan;
3532
- var bestLength = 0;
3533
- var bestDistance = Infinity;
3450
+ let precision = 8;
3451
+ let scan = { x: 0, y: 0 };
3452
+ let scanDistance = 0;
3453
+ let closest = scan;
3454
+ let bestLength = 0;
3455
+ let bestDistance = Infinity;
3534
3456
 
3535
3457
  // linear scan for coarse approximation
3536
- for (var scanLength = 0; scanLength <= pathLength; scanLength += precision) {
3458
+ for (let scanLength = 0; scanLength <= pathLength; scanLength += precision) {
3537
3459
  scan = getPointAtLength(normalPath, scanLength);
3538
3460
  scanDistance = distanceTo(scan);
3539
3461
  if (scanDistance < bestDistance) {
@@ -3545,12 +3467,12 @@
3545
3467
 
3546
3468
  // binary search for precise estimate
3547
3469
  precision /= 2;
3548
- var before = { x: 0, y: 0 };
3549
- var after = before;
3550
- var beforeLength = 0;
3551
- var afterLength = 0;
3552
- var beforeDistance = 0;
3553
- var afterDistance = 0;
3470
+ let before = { x: 0, y: 0 };
3471
+ let after = before;
3472
+ let beforeLength = 0;
3473
+ let afterLength = 0;
3474
+ let beforeDistance = 0;
3475
+ let afterDistance = 0;
3554
3476
 
3555
3477
  while (precision > 0.5) {
3556
3478
  beforeLength = bestLength - precision;
@@ -3572,16 +3494,16 @@
3572
3494
  }
3573
3495
  }
3574
3496
 
3575
- var segment = getPropertiesAtLength(path, bestLength);
3576
- var distance = Math.sqrt(bestDistance);
3497
+ const segment = getPropertiesAtLength(path, bestLength);
3498
+ const distance = Math.sqrt(bestDistance);
3577
3499
 
3578
- return { closest: closest, distance: distance, segment: segment };
3500
+ return { closest, distance, segment };
3579
3501
  }
3580
3502
 
3581
3503
  /**
3582
3504
  * Returns the point in path closest to a given point.
3583
3505
  *
3584
- * @param {string | SVGPathCommander.pathArray} pathInput target `pathArray`
3506
+ * @param {string | SVGPath.pathArray} pathInput target `pathArray`
3585
3507
  * @param {{x: number, y: number}} point the given point
3586
3508
  * @returns {{x: number, y: number}} the best match
3587
3509
  */
@@ -3592,39 +3514,37 @@
3592
3514
  /**
3593
3515
  * Returns the path segment which contains a given point.
3594
3516
  *
3595
- * @param {string | SVGPathCommander.pathArray} path the `pathArray` to look into
3517
+ * @param {string | SVGPath.pathArray} path the `pathArray` to look into
3596
3518
  * @param {{x: number, y: number}} point the point of the shape to look for
3597
- * @returns {SVGPathCommander.pathSegment?} the requested segment
3519
+ * @returns {SVGPath.pathSegment?} the requested segment
3598
3520
  */
3599
3521
  function getSegmentOfPoint(path, point) {
3600
- var props = getPropertiesAtPoint(path, point);
3601
- var segment = props.segment;
3522
+ const props = getPropertiesAtPoint(path, point);
3523
+ const { segment } = props;
3602
3524
  return typeof segment !== 'undefined' ? segment.segment : null;
3603
3525
  }
3604
3526
 
3605
3527
  /**
3606
3528
  * Returns the segment at a given length.
3607
- * @param {string | SVGPathCommander.pathArray} pathInput the target `pathArray`
3529
+ * @param {string | SVGPath.pathArray} pathInput the target `pathArray`
3608
3530
  * @param {number} distance the distance in path to look at
3609
- * @returns {SVGPathCommander.pathSegment?} the requested segment
3531
+ * @returns {SVGPath.pathSegment?} the requested segment
3610
3532
  */
3611
3533
  function getSegmentAtLength(pathInput, distance) {
3612
- var props = getPropertiesAtLength(pathInput, distance);
3613
- var ref = typeof props !== 'undefined' ? props : { segment: null };
3614
- var segment = ref.segment;
3534
+ const props = getPropertiesAtLength(pathInput, distance);
3535
+ const { segment } = typeof props !== 'undefined' ? props : { segment: null };
3615
3536
  return segment;
3616
3537
  }
3617
3538
 
3618
3539
  /**
3619
3540
  * Checks if a given point is in the stroke of a path.
3620
3541
  *
3621
- * @param {string | SVGPathCommander.pathArray} pathInput target path
3622
- * @param {{x: number, y: number}} point
3542
+ * @param {string | SVGPath.pathArray} pathInput target path
3543
+ * @param {{x: number, y: number}} point the given `{x,y}` point
3623
3544
  * @returns {boolean} the query result
3624
3545
  */
3625
3546
  function isPointInStroke(pathInput, point) {
3626
- var ref = getPropertiesAtPoint(pathInput, point);
3627
- var distance = ref.distance;
3547
+ const { distance } = getPropertiesAtPoint(pathInput, point);
3628
3548
  return Math.abs(distance) < 0.01;
3629
3549
  }
3630
3550
 
@@ -3640,7 +3560,7 @@
3640
3560
  return false;
3641
3561
  }
3642
3562
 
3643
- var path = new PathParser(pathString);
3563
+ const path = new PathParser(pathString);
3644
3564
 
3645
3565
  skipSpaces(path);
3646
3566
 
@@ -3655,7 +3575,7 @@
3655
3575
  * Supported shapes and their specific parameters.
3656
3576
  * @type {Object.<string, string[]>}
3657
3577
  */
3658
- var shapeParams = {
3578
+ const shapeParams = {
3659
3579
  circle: ['cx', 'cy', 'r'],
3660
3580
  ellipse: ['cx', 'cy', 'rx', 'ry'],
3661
3581
  rect: ['width', 'height', 'x', 'y', 'rx', 'ry'],
@@ -3667,94 +3587,94 @@
3667
3587
  /**
3668
3588
  * Returns a new `pathArray` from line attributes.
3669
3589
  *
3670
- * @param {SVGPathCommander.lineAttr} attr shape configuration
3671
- * @returns {SVGPathCommander.pathArray} a new line `pathArray`
3590
+ * @param {SVGPath.lineAttr} attr shape configuration
3591
+ * @returns {SVGPath.pathArray} a new line `pathArray`
3672
3592
  */
3673
3593
  function getLinePath(attr) {
3674
- var x1 = attr.x1;
3675
- var y1 = attr.y1;
3676
- var x2 = attr.x2;
3677
- var y2 = attr.y2;
3594
+ const {
3595
+ x1, y1, x2, y2,
3596
+ } = attr;
3678
3597
  return [['M', x1, y1], ['L', x2, y2]];
3679
3598
  }
3680
3599
 
3681
3600
  /**
3682
3601
  * Returns a new `pathArray` like from polyline/polygon attributes.
3683
3602
  *
3684
- * @param {SVGPathCommander.polyAttr} attr shape configuration
3685
- * @return {SVGPathCommander.pathArray} a new polygon/polyline `pathArray`
3603
+ * @param {SVGPath.polyAttr} attr shape configuration
3604
+ * @return {SVGPath.pathArray} a new polygon/polyline `pathArray`
3686
3605
  */
3687
3606
  function getPolyPath(attr) {
3688
- /** @type {SVGPathCommander.pathArray} */
3607
+ /** @type {SVGPath.pathArray} */
3689
3608
  // @ts-ignore -- it's an empty `pathArray`
3690
- var pathArray = [];
3691
- var points = attr.points.trim().split(/[\s|,]/).map(Number);
3609
+ const pathArray = [];
3610
+ const points = attr.points.trim().split(/[\s|,]/).map(Number);
3692
3611
 
3693
- var index = 0;
3612
+ let index = 0;
3694
3613
  while (index < points.length) {
3695
3614
  pathArray.push([(index ? 'L' : 'M'), (points[index]), (points[index + 1])]);
3696
3615
  index += 2;
3697
3616
  }
3698
3617
  // @ts-ignore -- it's a `pathArray`
3699
- return attr.type === 'polygon' ? pathArray.concat( [['z']]) : pathArray;
3618
+ return attr.type === 'polygon' ? [...pathArray, ['z']] : pathArray;
3700
3619
  }
3701
3620
 
3702
3621
  /**
3703
3622
  * Returns a new `pathArray` from circle attributes.
3704
3623
  *
3705
- * @param {SVGPathCommander.circleAttr} attr shape configuration
3706
- * @return {SVGPathCommander.pathArray} a circle `pathArray`
3624
+ * @param {SVGPath.circleAttr} attr shape configuration
3625
+ * @return {SVGPath.pathArray} a circle `pathArray`
3707
3626
  */
3708
3627
  function getCirclePath(attr) {
3709
- var cx = attr.cx;
3710
- var cy = attr.cy;
3711
- var r = attr.r;
3628
+ const {
3629
+ cx, cy, r,
3630
+ } = attr;
3712
3631
 
3713
3632
  return [
3714
3633
  ['M', (cx - r), cy],
3715
3634
  ['a', r, r, 0, 1, 0, (2 * r), 0],
3716
- ['a', r, r, 0, 1, 0, (-2 * r), 0] ];
3635
+ ['a', r, r, 0, 1, 0, (-2 * r), 0],
3636
+ ];
3717
3637
  }
3718
3638
 
3719
3639
  /**
3720
3640
  * Returns a new `pathArray` from ellipse attributes.
3721
3641
  *
3722
- * @param {SVGPathCommander.ellipseAttr} attr shape configuration
3723
- * @return {SVGPathCommander.pathArray} an ellipse `pathArray`
3642
+ * @param {SVGPath.ellipseAttr} attr shape configuration
3643
+ * @return {SVGPath.pathArray} an ellipse `pathArray`
3724
3644
  */
3725
3645
  function getEllipsePath(attr) {
3726
- var cx = attr.cx;
3727
- var cy = attr.cy;
3728
- var rx = attr.rx;
3729
- var ry = attr.ry;
3646
+ const {
3647
+ cx, cy, rx, ry,
3648
+ } = attr;
3730
3649
 
3731
3650
  return [
3732
3651
  ['M', (cx - rx), cy],
3733
3652
  ['a', rx, ry, 0, 1, 0, (2 * rx), 0],
3734
- ['a', rx, ry, 0, 1, 0, (-2 * rx), 0] ];
3653
+ ['a', rx, ry, 0, 1, 0, (-2 * rx), 0],
3654
+ ];
3735
3655
  }
3736
3656
 
3737
3657
  /**
3738
3658
  * Returns a new `pathArray` like from rect attributes.
3739
3659
  *
3740
- * @param {SVGPathCommander.rectAttr} attr object with properties above
3741
- * @return {SVGPathCommander.pathArray} a new `pathArray` from `<rect>` attributes
3660
+ * @param {SVGPath.rectAttr} attr object with properties above
3661
+ * @return {SVGPath.pathArray} a new `pathArray` from `<rect>` attributes
3742
3662
  */
3743
3663
  function getRectanglePath(attr) {
3744
- var x = +attr.x || 0;
3745
- var y = +attr.y || 0;
3746
- var w = +attr.width;
3747
- var h = +attr.height;
3748
- var rx = +attr.rx;
3749
- var ry = +attr.ry;
3664
+ const x = +attr.x || 0;
3665
+ const y = +attr.y || 0;
3666
+ const w = +attr.width;
3667
+ const h = +attr.height;
3668
+ let rx = +attr.rx;
3669
+ let ry = +attr.ry;
3750
3670
 
3751
3671
  // Validity checks from http://www.w3.org/TR/SVG/shapes.html#RectElement:
3752
3672
  if (rx || ry) {
3753
3673
  rx = !rx ? ry : rx;
3754
3674
  ry = !ry ? rx : ry;
3755
3675
 
3756
- if (rx * 2 > w) { rx -= (rx * 2 - w) / 2; }
3757
- if (ry * 2 > h) { ry -= (ry * 2 - h) / 2; }
3676
+ if (rx * 2 > w) rx -= (rx * 2 - w) / 2;
3677
+ if (ry * 2 > h) ry -= (ry * 2 - h) / 2;
3758
3678
 
3759
3679
  return [
3760
3680
  ['M', x + rx, y],
@@ -3765,7 +3685,8 @@
3765
3685
  ['h', -w + rx * 2],
3766
3686
  ['s', -rx, 0, -rx, -ry],
3767
3687
  ['v', -h + ry * 2],
3768
- ['s', 0, -ry, rx, -ry] ];
3688
+ ['s', 0, -ry, rx, -ry],
3689
+ ];
3769
3690
  }
3770
3691
 
3771
3692
  return [
@@ -3773,7 +3694,8 @@
3773
3694
  ['h', w],
3774
3695
  ['v', h],
3775
3696
  ['H', x],
3776
- ['Z'] ];
3697
+ ['Z'],
3698
+ ];
3777
3699
  }
3778
3700
 
3779
3701
  /**
@@ -3782,54 +3704,51 @@
3782
3704
  * is `true`, it will replace the target.
3783
3705
  *
3784
3706
  * It can also work with an options object,
3785
- * @see SVGPathCommander.shapeOps
3707
+ * @see SVGPath.shapeOps
3786
3708
  *
3787
3709
  * The newly created `<path>` element keeps all non-specific
3788
3710
  * attributes like `class`, `fill`, etc.
3789
3711
  *
3790
- * @param {SVGPathCommander.shapeTypes | SVGPathCommander.shapeOps} element target shape
3712
+ * @param {SVGPath.shapeTypes | SVGPath.shapeOps} element target shape
3791
3713
  * @param {boolean=} replace option to replace target
3792
3714
  * @return {SVGPathElement | boolean} the newly created `<path>` element
3793
3715
  */
3794
3716
  function shapeToPath(element, replace) {
3795
- var supportedShapes = Object.keys(shapeParams);
3796
- var isElement = element instanceof Element;
3717
+ const supportedShapes = Object.keys(shapeParams);
3718
+ const isElement = element instanceof Element;
3797
3719
 
3798
- if (isElement && !supportedShapes.some(function (s) { return element.tagName === s; })) {
3799
- throw TypeError(("shapeToPath: \"" + element + "\" is not SVGElement"));
3720
+ if (isElement && !supportedShapes.some((s) => element.tagName === s)) {
3721
+ throw TypeError(`shapeToPath: "${element}" is not SVGElement`);
3800
3722
  }
3801
3723
 
3802
- var path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
3724
+ const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
3803
3725
  /** @type {string} */
3804
- var type = isElement ? element.tagName : element.type;
3726
+ const type = isElement ? element.tagName : element.type;
3805
3727
  /** @type {any} disables TS checking for something that's specific to shape */
3806
- var config = {};
3728
+ const config = {};
3807
3729
  config.type = type;
3808
3730
 
3809
3731
  if (isElement) {
3810
- var shapeAttrs = shapeParams[type];
3811
- shapeAttrs.forEach(function (p) { config[p] = element.getAttribute(p); });
3732
+ const shapeAttrs = shapeParams[type];
3733
+ shapeAttrs.forEach((p) => { config[p] = element.getAttribute(p); });
3812
3734
  // set no-specific shape attributes: fill, stroke, etc
3813
- Object.values(element.attributes).forEach(function (ref) {
3814
- var name = ref.name;
3815
- var value = ref.value;
3816
-
3817
- if (!shapeAttrs.includes(name)) { path.setAttribute(name, value); }
3735
+ Object.values(element.attributes).forEach(({ name, value }) => {
3736
+ if (!shapeAttrs.includes(name)) path.setAttribute(name, value);
3818
3737
  });
3819
3738
  } else {
3820
3739
  Object.assign(config, element);
3821
3740
  }
3822
3741
 
3823
3742
  // set d
3824
- var description;
3825
- var round = defaultOptions.round;
3743
+ let description;
3744
+ const { round } = defaultOptions;
3826
3745
 
3827
- if (type === 'circle') { description = pathToString(getCirclePath(config), round); }
3828
- else if (type === 'ellipse') { description = pathToString(getEllipsePath(config), round); }
3829
- else if (['polyline', 'polygon'].includes(type)) { description = pathToString(getPolyPath(config), round); }
3830
- else if (type === 'rect') { description = pathToString(getRectanglePath(config), round); }
3831
- else if (type === 'line') { description = pathToString(getLinePath(config), round); }
3832
- else if (type === 'glyph') { description = isElement ? element.getAttribute('d') : element.type; }
3746
+ if (type === 'circle') description = pathToString(getCirclePath(config), round);
3747
+ else if (type === 'ellipse') description = pathToString(getEllipsePath(config), round);
3748
+ else if (['polyline', 'polygon'].includes(type)) description = pathToString(getPolyPath(config), round);
3749
+ else if (type === 'rect') description = pathToString(getRectanglePath(config), round);
3750
+ else if (type === 'line') description = pathToString(getLinePath(config), round);
3751
+ else if (type === 'glyph') description = isElement ? element.getAttribute('d') : element.type;
3833
3752
 
3834
3753
  // replace target element
3835
3754
  if (description) {
@@ -3844,67 +3763,67 @@
3844
3763
  }
3845
3764
 
3846
3765
  /**
3847
- * Reverses all segments and their values from a `pathArray`
3766
+ * Reverses all segments of a `pathArray`
3848
3767
  * which consists of only C (cubic-bezier) path commands.
3849
3768
  *
3850
- * @param {SVGPathCommander.curveArray} path the source `pathArray`
3851
- * @returns {SVGPathCommander.curveArray} the reversed `pathArray`
3769
+ * @param {SVGPath.curveArray} path the source `pathArray`
3770
+ * @returns {SVGPath.curveArray} the reversed `pathArray`
3852
3771
  */
3853
3772
  function reverseCurve(path) {
3854
- var rotatedCurve = path.slice(1)
3855
- .map(function (x, i, curveOnly) { return (!i
3856
- ? path[0].slice(1).concat( x.slice(1))
3857
- : curveOnly[i - 1].slice(-2).concat( x.slice(1))); })
3858
- .map(function (x) { return x.map(function (_, i) { return x[x.length - i - 2 * (1 - (i % 2))]; }); })
3773
+ const rotatedCurve = path.slice(1)
3774
+ .map((x, i, curveOnly) => (!i
3775
+ ? [...path[0].slice(1), ...x.slice(1)]
3776
+ : [...curveOnly[i - 1].slice(-2), ...x.slice(1)]))
3777
+ .map((x) => x.map((_, i) => x[x.length - i - 2 * (1 - (i % 2))]))
3859
3778
  .reverse();
3860
3779
 
3861
3780
  // @ts-ignore -- expected on reverse operations
3862
- return [['M' ].concat( rotatedCurve[0].slice(0, 2)) ].concat( rotatedCurve.map(function (x) { return ['C' ].concat( x.slice(2)); }));
3781
+ return [['M', ...rotatedCurve[0].slice(0, 2)],
3782
+ ...rotatedCurve.map((x) => ['C', ...x.slice(2)])];
3863
3783
  }
3864
3784
 
3865
3785
  /**
3866
3786
  * @interface
3867
3787
  */
3868
- var Util = {
3869
- CSSMatrix: CSSMatrix,
3870
- parsePathString: parsePathString,
3871
- isPathArray: isPathArray,
3872
- isCurveArray: isCurveArray,
3873
- isAbsoluteArray: isAbsoluteArray,
3874
- isRelativeArray: isRelativeArray,
3875
- isNormalizedArray: isNormalizedArray,
3876
- isValidPath: isValidPath,
3877
- pathToAbsolute: pathToAbsolute,
3878
- pathToRelative: pathToRelative,
3879
- pathToCurve: pathToCurve,
3880
- pathToString: pathToString,
3881
- getDrawDirection: getDrawDirection,
3882
- getPathArea: getPathArea,
3883
- getPathBBox: getPathBBox,
3884
- getTotalLength: getTotalLength,
3885
- getPathLength: getPathLength,
3886
- getPointAtLength: getPointAtLength,
3887
- getPointAtPathLength: getPointAtPathLength,
3888
- getClosestPoint: getClosestPoint,
3889
- getSegmentOfPoint: getSegmentOfPoint,
3890
- getPropertiesAtPoint: getPropertiesAtPoint,
3891
- getPropertiesAtLength: getPropertiesAtLength,
3892
- getSegmentAtLength: getSegmentAtLength,
3893
- isPointInStroke: isPointInStroke,
3894
- clonePath: clonePath,
3895
- splitPath: splitPath,
3896
- fixPath: fixPath,
3897
- roundPath: roundPath,
3898
- optimizePath: optimizePath,
3899
- reverseCurve: reverseCurve,
3900
- reversePath: reversePath,
3901
- normalizePath: normalizePath,
3902
- transformPath: transformPath,
3903
- shapeToPath: shapeToPath,
3788
+ const Util = {
3789
+ CSSMatrix,
3790
+ parsePathString,
3791
+ isPathArray,
3792
+ isCurveArray,
3793
+ isAbsoluteArray,
3794
+ isRelativeArray,
3795
+ isNormalizedArray,
3796
+ isValidPath,
3797
+ pathToAbsolute,
3798
+ pathToRelative,
3799
+ pathToCurve,
3800
+ pathToString,
3801
+ getDrawDirection,
3802
+ getPathArea,
3803
+ getPathBBox,
3804
+ getTotalLength,
3805
+ getPathLength,
3806
+ getPointAtLength,
3807
+ getClosestPoint,
3808
+ getSegmentOfPoint,
3809
+ getPropertiesAtPoint,
3810
+ getPropertiesAtLength,
3811
+ getSegmentAtLength,
3812
+ isPointInStroke,
3813
+ clonePath,
3814
+ splitPath,
3815
+ fixPath,
3816
+ roundPath,
3817
+ optimizePath,
3818
+ reverseCurve,
3819
+ reversePath,
3820
+ normalizePath,
3821
+ transformPath,
3822
+ shapeToPath,
3904
3823
  options: defaultOptions,
3905
3824
  };
3906
3825
 
3907
- var version = "0.1.25";
3826
+ var version = "0.2.0alpha3";
3908
3827
 
3909
3828
  // @ts-ignore
3910
3829
 
@@ -3912,10 +3831,10 @@
3912
3831
  * A global namespace for library version.
3913
3832
  * @type {string}
3914
3833
  */
3915
- var Version = version;
3834
+ const Version = version;
3916
3835
 
3917
3836
  // Export to global
3918
- Object.assign(SVGPathCommander, Util, { Version: Version });
3837
+ Object.assign(SVGPathCommander, Util, { Version });
3919
3838
 
3920
3839
  return SVGPathCommander;
3921
3840