svg-path-commander 2.1.3 → 2.1.6

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 (99) hide show
  1. package/README.md +4 -4
  2. package/dist/svg-path-commander.cjs +1 -1
  3. package/dist/svg-path-commander.cjs.map +1 -1
  4. package/dist/svg-path-commander.d.ts +755 -830
  5. package/dist/svg-path-commander.js +1 -1
  6. package/dist/svg-path-commander.js.map +1 -1
  7. package/dist/svg-path-commander.mjs +670 -395
  8. package/dist/svg-path-commander.mjs.map +1 -1
  9. package/package.json +16 -24
  10. package/.eslintrc.cjs +0 -225
  11. package/.lgtm.yml +0 -9
  12. package/.prettierrc.json +0 -15
  13. package/dts.config.ts +0 -15
  14. package/src/convert/pathToAbsolute.ts +0 -18
  15. package/src/convert/pathToCurve.ts +0 -43
  16. package/src/convert/pathToRelative.ts +0 -18
  17. package/src/convert/pathToString.ts +0 -50
  18. package/src/index.ts +0 -454
  19. package/src/interface.ts +0 -130
  20. package/src/math/arcTools.ts +0 -388
  21. package/src/math/bezier.ts +0 -261
  22. package/src/math/cubicTools.ts +0 -123
  23. package/src/math/distanceSquareRoot.ts +0 -15
  24. package/src/math/lineTools.ts +0 -61
  25. package/src/math/midPoint.ts +0 -18
  26. package/src/math/polygonTools.ts +0 -48
  27. package/src/math/quadTools.ts +0 -98
  28. package/src/math/rotateVector.ts +0 -17
  29. package/src/math/roundTo.ts +0 -7
  30. package/src/options/options.ts +0 -9
  31. package/src/parser/error.ts +0 -2
  32. package/src/parser/finalizeSegment.ts +0 -35
  33. package/src/parser/invalidPathValue.ts +0 -2
  34. package/src/parser/isArcCommand.ts +0 -11
  35. package/src/parser/isDigit.ts +0 -12
  36. package/src/parser/isDigitStart.ts +0 -14
  37. package/src/parser/isMoveCommand.ts +0 -17
  38. package/src/parser/isPathCommand.ts +0 -28
  39. package/src/parser/isSpace.ts +0 -23
  40. package/src/parser/paramsCount.ts +0 -16
  41. package/src/parser/paramsParser.ts +0 -14
  42. package/src/parser/parsePathString.ts +0 -33
  43. package/src/parser/pathParser.ts +0 -29
  44. package/src/parser/scanFlag.ts +0 -29
  45. package/src/parser/scanParam.ts +0 -102
  46. package/src/parser/scanSegment.ts +0 -84
  47. package/src/parser/skipSpaces.ts +0 -17
  48. package/src/process/absolutizeSegment.ts +0 -67
  49. package/src/process/arcToCubic.ts +0 -128
  50. package/src/process/getSVGMatrix.ts +0 -70
  51. package/src/process/iterate.ts +0 -58
  52. package/src/process/lineToCubic.ts +0 -17
  53. package/src/process/normalizePath.ts +0 -33
  54. package/src/process/normalizeSegment.ts +0 -84
  55. package/src/process/optimizePath.ts +0 -62
  56. package/src/process/projection2d.ts +0 -52
  57. package/src/process/quadToCubic.ts +0 -31
  58. package/src/process/relativizeSegment.ts +0 -63
  59. package/src/process/reverseCurve.ts +0 -24
  60. package/src/process/reversePath.ts +0 -114
  61. package/src/process/roundPath.ts +0 -33
  62. package/src/process/roundSegment.ts +0 -9
  63. package/src/process/segmentToCubic.ts +0 -48
  64. package/src/process/shortenSegment.ts +0 -71
  65. package/src/process/splitCubic.ts +0 -29
  66. package/src/process/splitPath.ts +0 -63
  67. package/src/process/transformPath.ts +0 -114
  68. package/src/types.ts +0 -228
  69. package/src/util/distanceEpsilon.ts +0 -3
  70. package/src/util/getClosestPoint.ts +0 -15
  71. package/src/util/getDrawDirection.ts +0 -16
  72. package/src/util/getPathArea.ts +0 -70
  73. package/src/util/getPathBBox.ts +0 -171
  74. package/src/util/getPointAtLength.ts +0 -110
  75. package/src/util/getPropertiesAtLength.ts +0 -67
  76. package/src/util/getPropertiesAtPoint.ts +0 -84
  77. package/src/util/getSegmentAtLength.ts +0 -15
  78. package/src/util/getSegmentOfPoint.ts +0 -18
  79. package/src/util/getTotalLength.ts +0 -133
  80. package/src/util/isAbsoluteArray.ts +0 -18
  81. package/src/util/isCurveArray.ts +0 -15
  82. package/src/util/isNormalizedArray.ts +0 -16
  83. package/src/util/isPathArray.ts +0 -24
  84. package/src/util/isPointInStroke.ts +0 -16
  85. package/src/util/isRelativeArray.ts +0 -18
  86. package/src/util/isValidPath.ts +0 -27
  87. package/src/util/shapeParams.ts +0 -16
  88. package/src/util/shapeToPath.ts +0 -86
  89. package/src/util/shapeToPathArray.ts +0 -183
  90. package/test/class.test.ts +0 -506
  91. package/test/fixtures/getMarkup.ts +0 -17
  92. package/test/fixtures/shapeObjects.ts +0 -11
  93. package/test/fixtures/shapes.js +0 -104
  94. package/test/fixtures/simpleShapes.js +0 -87
  95. package/test/static.test.ts +0 -330
  96. package/tsconfig.json +0 -34
  97. package/vite.config.mts +0 -41
  98. package/vitest.config-ui.mts +0 -31
  99. package/vitest.config.mts +0 -31
@@ -1,110 +0,0 @@
1
- import DISTANCE_EPSILON from './distanceEpsilon';
2
- import type { MSegment, PathArray, PointTuple } from '../types';
3
- import iterate from '../process/iterate';
4
- import { getLineLength, getPointAtLineLength } from '../math/lineTools';
5
- import { getArcLength, getPointAtArcLength } from '../math/arcTools';
6
- import { getCubicLength, getPointAtCubicLength } from '../math/cubicTools';
7
- import { getQuadLength, getPointAtQuadLength } from '../math/quadTools';
8
- import normalizePath from '../process/normalizePath';
9
-
10
- /**
11
- * Returns [x,y] coordinates of a point at a given length of a shape.
12
- *
13
- * @param pathInput the `pathArray` to look into
14
- * @param distance the length of the shape to look at
15
- * @returns the requested {x, y} point coordinates
16
- */
17
- const getPointAtLength = (pathInput: string | PathArray, distance?: number) => {
18
- const path = normalizePath(pathInput);
19
- let isM = false;
20
- let data = [] as number[];
21
- let pathCommand = 'M';
22
- let x = 0;
23
- let y = 0;
24
- let [mx, my] = path[0].slice(1) as PointTuple;
25
- const distanceIsNumber = typeof distance === 'number';
26
- let point = { x: mx, y: my };
27
- let length = 0;
28
- let POINT = point;
29
- let totalLength = 0;
30
-
31
- if (!distanceIsNumber || distance < DISTANCE_EPSILON) return point;
32
-
33
- // for (let i = 0; i < pathLen; i += 1) {
34
- iterate(path, (seg, _, lastX, lastY) => {
35
- [pathCommand] = seg;
36
- isM = pathCommand === 'M';
37
- data = !isM ? [lastX, lastY].concat(seg.slice(1) as number[]) : data;
38
-
39
- // this segment is always ZERO
40
- /* istanbul ignore else @preserve */
41
- if (isM) {
42
- // remember mx, my for Z
43
- [, mx, my] = seg as MSegment;
44
- point = { x: mx, y: my };
45
- length = 0;
46
- } else if (pathCommand === 'L') {
47
- point = getPointAtLineLength(data[0], data[1], data[2], data[3], distance - totalLength);
48
- length = getLineLength(data[0], data[1], data[2], data[3]);
49
- } else if (pathCommand === 'A') {
50
- point = getPointAtArcLength(
51
- data[0],
52
- data[1],
53
- data[2],
54
- data[3],
55
- data[4],
56
- data[5],
57
- data[6],
58
- data[7],
59
- data[8],
60
- distance - totalLength,
61
- );
62
- length = getArcLength(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8]);
63
- } else if (pathCommand === 'C') {
64
- point = getPointAtCubicLength(
65
- data[0],
66
- data[1],
67
- data[2],
68
- data[3],
69
- data[4],
70
- data[5],
71
- data[6],
72
- data[7],
73
- distance - totalLength,
74
- );
75
- length = getCubicLength(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
76
- } else if (pathCommand === 'Q') {
77
- point = getPointAtQuadLength(data[0], data[1], data[2], data[3], data[4], data[5], distance - totalLength);
78
- length = getQuadLength(data[0], data[1], data[2], data[3], data[4], data[5]);
79
- } else if (pathCommand === 'Z') {
80
- data = [lastX, lastY, mx, my];
81
- point = { x: mx, y: my };
82
-
83
- length = getLineLength(data[0], data[1], data[2], data[3]);
84
- }
85
-
86
- [x, y] = data.slice(-2);
87
-
88
- if (totalLength < distance) {
89
- POINT = point;
90
- } else {
91
- // totalLength >= distance
92
- // stop right here
93
- // stop iterator now!
94
- return false;
95
- }
96
-
97
- totalLength += length;
98
- return;
99
- });
100
-
101
- // native `getPointAtLength` behavior when the given distance
102
- // is higher than total length
103
- if (distance > totalLength - DISTANCE_EPSILON) {
104
- return { x, y };
105
- }
106
-
107
- return POINT;
108
- };
109
-
110
- export default getPointAtLength;
@@ -1,67 +0,0 @@
1
- import type { PathArray, PathSegment } from '../types';
2
- import type { SegmentProperties } from '../interface';
3
- import parsePathString from '../parser/parsePathString';
4
- import getTotalLength from './getTotalLength';
5
-
6
- /**
7
- * Returns the segment, its index and length as well as
8
- * the length to that segment at a given length in a path.
9
- *
10
- * @param pathInput target `pathArray`
11
- * @param distance the given length
12
- * @returns the requested properties
13
- */
14
- const getPropertiesAtLength = (pathInput: string | PathArray, distance?: number): SegmentProperties => {
15
- const pathArray = parsePathString(pathInput);
16
-
17
- let pathTemp = pathArray.slice(0) as PathArray;
18
- let pathLength = getTotalLength(pathTemp);
19
- let index = pathTemp.length - 1;
20
- let lengthAtSegment = 0;
21
- let length = 0;
22
- let segment = pathArray[0] as PathSegment;
23
-
24
- // If the path is empty, return 0.
25
- if (index <= 0 || !distance || !Number.isFinite(distance)) {
26
- return {
27
- segment,
28
- index: 0,
29
- length,
30
- lengthAtSegment,
31
- };
32
- }
33
-
34
- if (distance >= pathLength) {
35
- pathTemp = pathArray.slice(0, -1) as PathArray;
36
- lengthAtSegment = getTotalLength(pathTemp);
37
- length = pathLength - lengthAtSegment;
38
- segment = pathArray[index];
39
- return {
40
- segment,
41
- index,
42
- length,
43
- lengthAtSegment,
44
- };
45
- }
46
-
47
- const segments = [] as SegmentProperties[];
48
- while (index > 0) {
49
- segment = pathTemp[index];
50
- pathTemp = pathTemp.slice(0, -1) as PathArray;
51
- lengthAtSegment = getTotalLength(pathTemp);
52
- length = pathLength - lengthAtSegment;
53
- pathLength = lengthAtSegment;
54
-
55
- segments.push({
56
- segment,
57
- index,
58
- length,
59
- lengthAtSegment,
60
- });
61
- index -= 1;
62
- }
63
-
64
- return segments.find(({ lengthAtSegment: l }) => l <= distance) as SegmentProperties;
65
- };
66
-
67
- export default getPropertiesAtLength;
@@ -1,84 +0,0 @@
1
- import type { PathArray, Point } from '../types';
2
- import type { PointProperties } from '../interface';
3
- import getPointAtLength from './getPointAtLength';
4
- import getPropertiesAtLength from './getPropertiesAtLength';
5
- import getTotalLength from './getTotalLength';
6
- import parsePathString from '../parser/parsePathString';
7
- import normalizePath from '../process/normalizePath';
8
-
9
- /**
10
- * Returns the point and segment in path closest to a given point as well as
11
- * the distance to the path stroke.
12
- *
13
- * @see https://bl.ocks.org/mbostock/8027637
14
- *
15
- * @param pathInput target `pathArray`
16
- * @param point the given point
17
- * @returns the requested properties
18
- */
19
- const getPropertiesAtPoint = (pathInput: string | PathArray, point: Point): PointProperties => {
20
- const path = parsePathString(pathInput);
21
- const normalPath = normalizePath(path);
22
- const pathLength = getTotalLength(normalPath);
23
- const distanceTo = (p: Point) => {
24
- const dx = p.x - point.x;
25
- const dy = p.y - point.y;
26
- return dx * dx + dy * dy;
27
- };
28
- let precision = 8;
29
- let scan: Point;
30
- let closest = { x: 0, y: 0 }; // make TS happy
31
- let scanDistance = 0;
32
- let bestLength = 0;
33
- let bestDistance = Infinity;
34
-
35
- // linear scan for coarse approximation
36
- for (let scanLength = 0; scanLength <= pathLength; scanLength += precision) {
37
- scan = getPointAtLength(normalPath, scanLength);
38
- scanDistance = distanceTo(scan);
39
-
40
- if (scanDistance < bestDistance) {
41
- closest = scan;
42
- bestLength = scanLength;
43
- bestDistance = scanDistance;
44
- }
45
- }
46
-
47
- // binary search for precise estimate
48
- precision /= 2;
49
- let before: { x: number; y: number };
50
- let after: { x: number; y: number };
51
- let beforeLength = 0;
52
- let afterLength = 0;
53
- let beforeDistance = 0;
54
- let afterDistance = 0;
55
-
56
- while (precision > 0.000001) {
57
- beforeLength = bestLength - precision;
58
- before = getPointAtLength(normalPath, beforeLength);
59
- beforeDistance = distanceTo(before);
60
- afterLength = bestLength + precision;
61
- after = getPointAtLength(normalPath, afterLength);
62
- afterDistance = distanceTo(after);
63
-
64
- if (beforeLength >= 0 && beforeDistance < bestDistance) {
65
- closest = before;
66
- bestLength = beforeLength;
67
- bestDistance = beforeDistance;
68
- } else if (afterLength <= pathLength && afterDistance < bestDistance) {
69
- closest = after;
70
- bestLength = afterLength;
71
- bestDistance = afterDistance;
72
- } else {
73
- precision /= 2;
74
- }
75
- if (precision < 0.00001) break;
76
- }
77
-
78
- const segment = getPropertiesAtLength(path, bestLength);
79
- const distance = Math.sqrt(bestDistance);
80
-
81
- return { closest, distance, segment };
82
- };
83
-
84
- export default getPropertiesAtPoint;
@@ -1,15 +0,0 @@
1
- import type { PathArray, PathSegment } from '../types';
2
- import getPropertiesAtLength from './getPropertiesAtLength';
3
-
4
- /**
5
- * Returns the segment at a given length.
6
- *
7
- * @param pathInput the target `pathArray`
8
- * @param distance the distance in path to look at
9
- * @returns the requested segment
10
- */
11
- const getSegmentAtLength = (pathInput: string | PathArray, distance?: number): PathSegment | undefined => {
12
- return getPropertiesAtLength(pathInput, distance).segment;
13
- };
14
-
15
- export default getSegmentAtLength;
@@ -1,18 +0,0 @@
1
- import type { SegmentProperties } from '../interface';
2
- import type { PathArray } from '../types';
3
- import getPropertiesAtPoint from './getPropertiesAtPoint';
4
-
5
- /**
6
- * Returns the path segment which contains a given point.
7
- *
8
- * @param path the `pathArray` to look into
9
- * @param point the point of the shape to look for
10
- * @returns the requested segment
11
- */
12
- const getSegmentOfPoint = (
13
- path: string | PathArray,
14
- point: { x: number; y: number },
15
- ): SegmentProperties | undefined => {
16
- return getPropertiesAtPoint(path, point).segment;
17
- };
18
- export default getSegmentOfPoint;
@@ -1,133 +0,0 @@
1
- import type { LSegment, MSegment, PathArray, PointTuple } from '../types';
2
- import { getLineLength } from '../math/lineTools';
3
- import { getArcLength } from '../math/arcTools';
4
- import { getCubicLength } from '../math/cubicTools';
5
- import { getQuadLength } from '../math/quadTools';
6
- import iterate from '../process/iterate';
7
- import parsePathString from '../parser/parsePathString';
8
- import absolutizeSegment from '../process/absolutizeSegment';
9
-
10
- /**
11
- * Returns the shape total length, or the equivalent to `shape.getTotalLength()`.
12
- *
13
- *
14
- * @param pathInput the target `pathArray`
15
- * @returns the shape total length
16
- */
17
- const getTotalLength = (pathInput: string | PathArray) => {
18
- const path = parsePathString(pathInput);
19
- let paramX1 = 0;
20
- let paramY1 = 0;
21
- let paramX2 = 0;
22
- let paramY2 = 0;
23
- let paramQX = 0;
24
- let paramQY = 0;
25
- let pathCommand = 'M';
26
- let mx = 0;
27
- let my = 0;
28
- let totalLength = 0;
29
-
30
- iterate(path, (seg, index, lastX, lastY) => {
31
- [pathCommand] = seg;
32
- const absCommand = pathCommand.toUpperCase();
33
- const isRelative = absCommand !== pathCommand;
34
- const absoluteSegment = isRelative ? absolutizeSegment(seg, index, lastX, lastY) : (seg.slice(0) as typeof seg);
35
-
36
- const normalSegment =
37
- absCommand === 'V'
38
- ? (['L', lastX, absoluteSegment[1]] as LSegment)
39
- : absCommand === 'H'
40
- ? (['L', absoluteSegment[1], lastY] as LSegment)
41
- : absoluteSegment;
42
- [pathCommand] = normalSegment;
43
-
44
- if (!'TQ'.includes(absCommand)) {
45
- // optional but good to be cautious
46
- paramQX = 0;
47
- paramQY = 0;
48
- }
49
-
50
- // this segment is always ZERO
51
- /* istanbul ignore else @preserve */
52
- if (pathCommand === 'M') {
53
- // remember mx, my for Z
54
- [, mx, my] = normalSegment as MSegment;
55
- } else if (pathCommand === 'L') {
56
- totalLength += getLineLength(lastX, lastY, normalSegment[1] as number, normalSegment[2] as number);
57
- } else if (pathCommand === 'A') {
58
- totalLength += getArcLength(
59
- lastX,
60
- lastY,
61
- normalSegment[1] as number,
62
- normalSegment[2] as number,
63
- normalSegment[3] as number,
64
- normalSegment[4] as number,
65
- normalSegment[5] as number,
66
- normalSegment[6] as number,
67
- normalSegment[7] as number,
68
- );
69
- } else if (pathCommand === 'S') {
70
- const cp1x = paramX1 * 2 - paramX2;
71
- const cp1y = paramY1 * 2 - paramY2;
72
-
73
- totalLength += getCubicLength(
74
- lastX,
75
- lastY,
76
- cp1x,
77
- cp1y,
78
- normalSegment[1] as number,
79
- normalSegment[2] as number,
80
- normalSegment[3] as number,
81
- normalSegment[4] as number,
82
- );
83
- } else if (pathCommand === 'C') {
84
- totalLength += getCubicLength(
85
- lastX,
86
- lastY,
87
- normalSegment[1] as number,
88
- normalSegment[2] as number,
89
- normalSegment[3] as number,
90
- normalSegment[4] as number,
91
- normalSegment[5] as number,
92
- normalSegment[6] as number,
93
- );
94
- } else if (pathCommand === 'T') {
95
- paramQX = paramX1 * 2 - paramQX;
96
- paramQY = paramY1 * 2 - paramQY;
97
- totalLength += getQuadLength(
98
- lastX,
99
- lastY,
100
- paramQX,
101
- paramQY,
102
- normalSegment[1] as number,
103
- normalSegment[2] as number,
104
- );
105
- } else if (pathCommand === 'Q') {
106
- paramQX = normalSegment[1] as number;
107
- paramQY = normalSegment[2] as number;
108
- totalLength += getQuadLength(
109
- lastX,
110
- lastY,
111
- normalSegment[1] as number,
112
- normalSegment[2] as number,
113
- normalSegment[3] as number,
114
- normalSegment[4] as number,
115
- );
116
- } else if (pathCommand === 'Z') {
117
- totalLength += getLineLength(lastX, lastY, mx, my);
118
- }
119
-
120
- // update params
121
- [paramX1, paramY1] = pathCommand === 'Z' ? [mx, my] : (normalSegment.slice(-2) as PointTuple);
122
- [paramX2, paramY2] =
123
- pathCommand === 'C'
124
- ? ([normalSegment[3], normalSegment[4]] as PointTuple)
125
- : pathCommand === 'S'
126
- ? ([normalSegment[1], normalSegment[2]] as PointTuple)
127
- : [paramX1, paramY1];
128
- });
129
-
130
- return totalLength;
131
- };
132
-
133
- export default getTotalLength;
@@ -1,18 +0,0 @@
1
- import type { AbsoluteArray } from '../types';
2
- import isPathArray from './isPathArray';
3
-
4
- /**
5
- * Iterates an array to check if it's a `pathArray`
6
- * with all absolute values.
7
- *
8
- * @param path the `pathArray` to be checked
9
- * @returns iteration result
10
- */
11
- const isAbsoluteArray = (path: unknown): path is AbsoluteArray => {
12
- return (
13
- isPathArray(path) &&
14
- // `isPathArray` also checks if it's `Array`
15
- path.every(([x]) => x === x.toUpperCase())
16
- );
17
- };
18
- export default isAbsoluteArray;
@@ -1,15 +0,0 @@
1
- import { CurveArray } from '../types';
2
- import isNormalizedArray from './isNormalizedArray';
3
-
4
- /**
5
- * Iterates an array to check if it's a `pathArray`
6
- * with all C (cubic bezier) segments.
7
- *
8
- * @param path the `Array` to be checked
9
- * @returns iteration result
10
- */
11
- const isCurveArray = (path: unknown): path is CurveArray => {
12
- // `isPathArray` also checks if it's `Array`
13
- return isNormalizedArray(path) && path.every(([pc]) => 'MC'.includes(pc));
14
- };
15
- export default isCurveArray;
@@ -1,16 +0,0 @@
1
- import type { NormalArray } from '../types';
2
- import isAbsoluteArray from './isAbsoluteArray';
3
-
4
- /**
5
- * Iterates an array to check if it's a `pathArray`
6
- * with all segments are in non-shorthand notation
7
- * with absolute values.
8
- *
9
- * @param {string | SVGPath.pathArray} path the `pathArray` to be checked
10
- * @returns {boolean} iteration result
11
- */
12
- const isNormalizedArray = (path: unknown): path is NormalArray => {
13
- // `isAbsoluteArray` also checks if it's `Array`
14
- return isAbsoluteArray(path) && path.every(([pc]) => 'ACLMQZ'.includes(pc));
15
- };
16
- export default isNormalizedArray;
@@ -1,24 +0,0 @@
1
- import type { PathArray, PathSegment, RelativeCommand } from '../types';
2
- import paramsCount from '../parser/paramsCount';
3
-
4
- /**
5
- * Iterates an array to check if it's an actual `pathArray`.
6
- *
7
- * @param path the `pathArray` to be checked
8
- * @returns iteration result
9
- */
10
- const isPathArray = (path: unknown): path is PathArray => {
11
- return (
12
- Array.isArray(path) &&
13
- path.every((seg: PathSegment) => {
14
- const lk = seg[0].toLowerCase() as RelativeCommand;
15
- return (
16
- paramsCount[lk] === seg.length - 1 &&
17
- 'achlmqstvz'.includes(lk) &&
18
- (seg.slice(1) as unknown[]).every(Number.isFinite)
19
- );
20
- }) &&
21
- path.length > 0
22
- );
23
- };
24
- export default isPathArray;
@@ -1,16 +0,0 @@
1
- import type { PathArray } from '../types';
2
- import getPropertiesAtPoint from './getPropertiesAtPoint';
3
- import DISTANCE_EPSILON from './distanceEpsilon';
4
-
5
- /**
6
- * Checks if a given point is in the stroke of a path.
7
- *
8
- * @param pathInput target path
9
- * @param point the given `{x,y}` point
10
- * @returns the query result
11
- */
12
- const isPointInStroke = (pathInput: string | PathArray, point: { x: number; y: number }) => {
13
- const { distance } = getPropertiesAtPoint(pathInput, point);
14
- return Math.abs(distance) < DISTANCE_EPSILON; // 0.01 might be more permissive
15
- };
16
- export default isPointInStroke;
@@ -1,18 +0,0 @@
1
- import type { RelativeArray } from '../types';
2
- import isPathArray from './isPathArray';
3
-
4
- /**
5
- * Iterates an array to check if it's a `pathArray`
6
- * with relative values.
7
- *
8
- * @param path the `pathArray` to be checked
9
- * @returns iteration result
10
- */
11
- const isRelativeArray = (path: unknown): path is RelativeArray => {
12
- return (
13
- isPathArray(path) &&
14
- // `isPathArray` checks if it's `Array`
15
- path.slice(1).every(([pc]) => pc === pc.toLowerCase())
16
- );
17
- };
18
- export default isRelativeArray;
@@ -1,27 +0,0 @@
1
- import scanSegment from '../parser/scanSegment';
2
- import skipSpaces from '../parser/skipSpaces';
3
- import PathParser from '../parser/pathParser';
4
-
5
- /**
6
- * Parses a path string value to determine its validity
7
- * then returns true if it's valid or false otherwise.
8
- *
9
- * @param pathString the path string to be parsed
10
- * @returns the path string validity
11
- */
12
- const isValidPath = (pathString: string) => {
13
- if (typeof pathString !== 'string' || !pathString.length) {
14
- return false;
15
- }
16
-
17
- const path = new PathParser(pathString);
18
-
19
- skipSpaces(path);
20
-
21
- while (path.index < path.max && !path.err.length) {
22
- scanSegment(path);
23
- }
24
-
25
- return !path.err.length && 'mM'.includes(path.segments[0][0]);
26
- };
27
- export default isValidPath;
@@ -1,16 +0,0 @@
1
- import type { ShapeParams } from '../interface';
2
-
3
- /**
4
- * Supported shapes and their specific parameters.
5
- */
6
- const shapeParams: ShapeParams = {
7
- line: ['x1', 'y1', 'x2', 'y2'],
8
- circle: ['cx', 'cy', 'r'],
9
- ellipse: ['cx', 'cy', 'rx', 'ry'],
10
- rect: ['width', 'height', 'x', 'y', 'rx', 'ry'],
11
- polygon: ['points'],
12
- polyline: ['points'],
13
- glyph: ['d'],
14
- };
15
-
16
- export default shapeParams;
@@ -1,86 +0,0 @@
1
- import type { ShapeParams } from '../interface';
2
- import type { ShapeOps, ShapeTypes } from '../types';
3
- import pathToString from '../convert/pathToString';
4
- import defaultOptions from '../options/options';
5
- import error from '../parser/error';
6
- import isValidPath from './isValidPath';
7
- import shapeToPathArray from './shapeToPathArray';
8
- import shapeParams from './shapeParams';
9
-
10
- /**
11
- * Returns a new `<path>` element created from attributes of a `<line>`, `<polyline>`,
12
- * `<polygon>`, `<rect>`, `<ellipse>`, `<circle>` or `<glyph>`. If `replace` parameter
13
- * is `true`, it will replace the target. The default `ownerDocument` is your current
14
- * `document` browser page, if you want to use in server-side using `jsdom`, you can
15
- * pass the `jsdom` `document` to `ownDocument`.
16
- *
17
- * It can also work with an options object, see the type below
18
- *
19
- * @see ShapeOps
20
- *
21
- * The newly created `<path>` element keeps all non-specific
22
- * attributes like `class`, `fill`, etc.
23
- *
24
- * @param element target shape
25
- * @param replace option to replace target
26
- * @param ownerDocument document for create element
27
- * @return the newly created `<path>` element
28
- */
29
- const shapeToPath = (
30
- element: ShapeTypes | ShapeOps,
31
- replace?: boolean,
32
- ownerDocument?: Document,
33
- ): SVGPathElement | false => {
34
- const doc = ownerDocument || document;
35
- const win = doc.defaultView || /* istanbul ignore next */ window;
36
- const supportedShapes = Object.keys(shapeParams) as (keyof ShapeParams)[];
37
- const targetIsElement = element instanceof win.SVGElement;
38
- const tagName = targetIsElement ? element.tagName : null;
39
-
40
- if (tagName === 'path') throw TypeError(`${error}: "${tagName}" is already SVGPathElement`);
41
- if (tagName && supportedShapes.every(s => tagName !== s)) throw TypeError(`${error}: "${tagName}" is not SVGElement`);
42
-
43
- const path = doc.createElementNS('http://www.w3.org/2000/svg', 'path');
44
- const type = (targetIsElement ? tagName : element.type) as ShapeOps['type'];
45
- const shapeAttrs = shapeParams[type] as string[];
46
- const config = { type } as Record<string, string>;
47
-
48
- // set d
49
- const round = defaultOptions.round as number;
50
- const pathArray = shapeToPathArray(element, doc);
51
- const description = pathArray && pathArray.length ? pathToString(pathArray, round) : '';
52
-
53
- if (targetIsElement) {
54
- shapeAttrs.forEach(p => {
55
- config[p] = element.getAttribute(p) as string;
56
- });
57
- // set no-specific shape attributes: fill, stroke, etc
58
- Object.values(element.attributes).forEach(({ name, value }) => {
59
- if (!shapeAttrs.includes(name)) path.setAttribute(name, value);
60
- });
61
- } else {
62
- Object.assign(config, element);
63
- // set no-specific shape attributes: fill, stroke, etc
64
- Object.keys(config).forEach(k => {
65
- if (!shapeAttrs.includes(k) && k !== 'type') {
66
- path.setAttribute(
67
- k.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`),
68
- config[k],
69
- );
70
- }
71
- });
72
- }
73
-
74
- // replace target element
75
- if (isValidPath(description)) {
76
- path.setAttribute('d', description);
77
- if (replace && targetIsElement) {
78
- element.before(path, element);
79
- element.remove();
80
- }
81
- return path;
82
- }
83
- return false;
84
- };
85
-
86
- export default shapeToPath;