new changes

This commit is contained in:
Niranjan
2026-04-07 05:05:28 +05:30
parent 7c070224bd
commit a18bba15f2
29975 changed files with 3247495 additions and 2761 deletions

View File

@@ -0,0 +1,106 @@
# AGENTS.md — SVGPathCommander
## Project Overview
SVGPathCommander v2.2.0 — TypeScript library for manipulating SVG `<path>` `d` attributes. Works in browser and Node.js.
## Commands
```bash
pnpm install # Install dependencies
pnpm dev # Serve docs on localhost:3000
pnpm test # Run all tests (vitest + happy-dom)
pnpm test-ui # Run tests with UI
pnpm test -- -t "Test name" # Run a single test by name
pnpm test -- class.test.ts # Run a single test file
pnpm lint # Deno lint + tsc type check
pnpm lint:ts # Deno lint only
pnpm fix:ts # Deno lint --fix
pnpm format # Deno format
pnpm build # Build with tsdown
pnpm check:ts # tsc --noEmit (type check only)
```
## Tech Stack
- **Language:** TypeScript (strict, ES2020 target, `allowImportingTsExtensions`)
- **Package manager:** pnpm (v10.33.0)
- **Build:** tsdown (ESM + UMD outputs)
- **Test:** Vitest + happy-dom (Istanbul coverage)
- **Lint/Format:** Deno (`deno lint`, `deno fmt`)
- **Dependency:** `@thednp/dommatrix` (DOMMatrix shim)
## Source Structure (`src/`)
| Directory | Purpose |
|---|---|
| `index.ts` | Main entry — exports SVGPathCommander class + all types |
| `main.ts` | SVGPathCommander class (core, chainable instance methods) |
| `types.ts` | TypeScript type definitions (PathCommand, PathSegment, PathArray, etc.) |
| `interface.ts` | Interfaces (Options, TransformObject, PathBBox, shape attrs) |
| `util.ts` | Re-export of all static methods (tree-shakeable entry) |
| `convert/` | Path format conversion (absolute, relative, curve, string) |
| `parser/` | SVG path string tokenizer/scanner |
| `process/` | Manipulation algorithms (normalize, optimize, reverse, transform, etc.) |
| `math/` | Low-level math (bezier, cubic, quad, line, arc, polygon tools) |
| `morph/` | Path morphing (equalize, split, sample, classify, match) |
| `util/` | Query helpers (bbox, length, point-at-length, intersection, etc.) |
| `options/` | Default configuration |
## Code Conventions
### Imports
- Use `.ts` extension on all imports: `import { foo } from "./bar.ts"`
- Path alias `~/*` maps to `src/` (e.g., `import SVGPathCommander from '~/index'`)
- Group imports: external libs → internal modules → types
- Use `import type` for type-only imports
### Formatting & Linting
- **No comments** unless explicitly asked
- Run `pnpm format` then `pnpm lint:ts` before committing
- Deno formatter and linter enforced (`deno fmt`, `deno lint`)
### TypeScript
- Strict mode enabled — no `any`, no implicit `any`
- `noUnusedLocals` and `noUnusedParameters` enforced
- `noImplicitReturns` enforced
- `allowImportingTsExtensions` — always include `.ts` in imports
- Use `type` aliases for unions, `interface` for object shapes
### Naming Conventions
- **Classes:** PascalCase (`SVGPathCommander`, `PathParser`)
- **Functions/Methods:** camelCase (`parsePathString`, `normalizePath`)
- **Types:** PascalCase ending in semantic suffix (`PathArray`, `NormalSegment`, `IteratorCallback`)
- **Command types:** Suffix with `Command`/`Segment` (`AbsoluteCommand`, `MSegment`)
- **Constants:** camelCase for module-level constants (`defaultOptions`, `distanceEpsilon`)
- **Test descriptions:** Start with `Test` (`Test init with no parameter`)
### Error Handling
- Throw `TypeError` with descriptive message for invalid inputs
- Use the shared `error` prefix from `~/util/error.ts`
- Validate inputs early, fail fast with clear messages
- Static methods return safe defaults for empty/invalid input (e.g., `getPathBBox('')`)
### Class Design
- Instance methods are chainable — always `return this`
- Expose functionality as both instance methods and static methods
- Use getters for computed properties (`get bbox()`, `get length()`)
- Instance options validated in constructor with fallback to `defaultOptions`
### Testing
- Tests run with happy-dom (headless browser simulation)
- Fixtures in `test/fixtures/`
- Two test files: `test/class.test.ts` (instance API), `test/static.test.ts` (static methods)
- Tests render actual SVG and verify `d` attribute output
- Use `vi.waitFor()` for async DOM queries (timeout: 200ms)
- Use `expect().to.deep.equal()` for object comparison, `expect().to.equal()` for primitives
- Coverage provider: Istanbul
## Build Outputs
| File | Description |
|---|---|
| `dist/index.min.js` | UMD bundle (minified, browser-ready, includes dommatrix) |
| `dist/index.js` | ESM bundle (tree-shakeable, neutral platform) |
| `dist/util.js` | Static methods only (tree-shakeable) |
| `dist/index.d.ts` | Type declarations |

View File

@@ -0,0 +1,25 @@
# Changelog
## [2.2.0] - 2026-04-06
### Added
- **Path intersection** — `pathsIntersection()`, `boundingBoxIntersect()`, `isPointInsideBBox()`
- **Path equalization** — `equalizePaths()`, `equalizeSegments()` for matching segment counts
- Full JSDoc coverage with `@param`, `@returns`, `@example` tags
- New demo page for path morphing
- `polyonArea` utility
- `isMultiPath()`, `isClosedPath()`, `isPolygonArray()` and `isPolylineArray` utilities
- CHANGELOG.md and AGENTS.md
### Removed
- badge workflow and script in package.json
### Fixed
- **pathToCurve** inconsistencies
- reworked all exports as named exports
### Changed
- Added a separate export for utilities in `svg-path-commander/util`
- Migrated test runner from Playwright to happy-dom
- updated tests
- tsdown bundler

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 thednp
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,315 @@
# SVGPathCommander
[![Coverage Status](https://coveralls.io/repos/github/thednp/svg-path-commander/badge.svg)](https://coveralls.io/github/thednp/svg-path-commander)
[![ci](https://github.com/thednp/svg-path-commander/actions/workflows/ci.yml/badge.svg)](https://github.com/thednp/svg-path-commander/actions/workflows/ci.yml)
[![NPM Version](https://img.shields.io/npm/v/svg-path-commander.svg)](https://www.npmjs.com/package/svg-path-commander)
[![NPM Downloads](https://img.shields.io/npm/dm/svg-path-commander.svg)](http://npm-stat.com/charts.html?svg-path-commander)
[![jsDeliver](https://img.shields.io/jsdelivr/npm/hw/svg-path-commander)](https://www.jsdelivr.com/package/npm/svg-path-commander)
![image](./docs/assets/SVGPathCommander.svg)
A modern set of Typescript tools for manipulating the `d` (description) attribute for *SVGPathElement* items. The library is implementing modern JavaScript API to produce reusable path strings with lossless quality. In addition, you also have a powerful tool to convert other SVG shapes like `<circle>` or `<rect>` to `<path>`.
While you may find familiar tools inside, this library brings ***new additions***:
* the build in `getBBox`, `getPointAtLength` and `getTotalLength` are more reliable and much more accurate than the native methods, not to mention their high [performance](https://github.com/thednp/svg-path-commander/issues/44) ratings;
* thanks to the community contributions we've implemented useful tools like `getPropertiesAtLength`, `getSegmentOfPoint` or `isPointInStroke`;
* a tool that can *reverse path draw direction* without altering path commands, even with specific shorthand path commands;
* a unique tool that can *reverse path draw direction* for path strings with only 'C' path commands;
* a new and unique tool to *apply transform functions to path commands* via the modern *DOMMatrix* API.
**The key differences with other libraries**:
* Typescript sourced with modernized codebase, all inherited codebase has been modernized as well;
* along with the modern codebase, the library also comes with strong TypeScript definitions;
* this library can create 3D to 2D projections, making your SVGs look like 3D but in the SVG coordinate system;
* you can use this library in both web apps and Node.js, you are not restricted to a single environment;
* path command transformations are all consistent with the SVG coordinates system, where others compute transform origin only for rotation transformation.
**SVGPathCommander** can use the [DOMMatrix API](https://developer.mozilla.org/en-US/docs/Web/API/DOMMatrix) for *SVGPathElement* path command transformation and implements a very fast and modernized [DOMMatrix shim](https://github.com/thednp/dommatrix).
There are a couple of good reasons for this implementation:
* *WebKitCSSMatrix* and *SVGMatrix* APIs are slowly pushed away by DOMMatrix, the green light for new and modern implementations;
* we can actually apply a [3D transformation](https://github.com/ndebeiss/svg3d) matrix to SVG path commands, by calculating a 2D projection of the actual shape in 3D coordinates;
* when most tools available will be rendered absolete, we are ready for new challenges.
This library is available on [CDN](https://www.jsdelivr.com/package/npm/svg-path-commander) and [npm](https://www.npmjs.com/package/svg-path-commander).
# Install
```
npm install svg-path-commander
# or pnpm/bun/deno add svg-path-commander
```
# CDN
Version 2.2.0+
```html
<script src="https://cdn.jsdelivr.net/npm/svg-path-commander/dist/index.min.js">
```
Versions before 2.2.0
```html
<script src="https://cdn.jsdelivr.net/npm/svg-path-commander/dist/svg-path-commander.js">
```
# Quick Guide
Flip a path on the X axis:
```js
import SVGPathCommander from 'svg-path-commander';
const path = 'M0 0L100 0L50 100';
const flippedPathString = new SVGPathCommander(path).flipX().toString();
// result => 'M0 100h100L50 0'
```
Optimize a path string by using the `round` option, to round numbers to 2 decimals and finding shorthand where possible:
```js
const optimizedPathString = new SVGPathCommander(path, {round: 2}).optimize().toString();
```
Or why not apply a **2D transformation** and even a **3D transformation**:
```js
// a transform object
const transform = {
translate: 15, // X axis translation
rotate: 15, // Z axis rotation
scale: 0.75, // uniform scale on X, Y, Z axis
skew: 15, // skew 15deg on the X axis
origin: [15, 0] // if not specified, it will use the default origin value [0, 0]
}
const transformed2DPathString = new SVGPathCommander(path).transform(transform).toString();
// apply a 3D transformation
const transform = {
translate: [15, 15, 15], // `[15, 15]` would apply a 2D translation, and only `15` for X axis translation
rotate: [15, 15, 15], // or only "15" for 2D rotation on Z axis
scale: [0.7, 0.75, 0.8], // or only "0.7" for 2D scale on all X, Y, Z axis
skew: [15, 15], // or only "15" for the X axis
origin: [15, 15, 15] // full `transform-origin` for a typical 3D transformation
}
const transformed3DPathString = new SVGPathCommander(path).transform(transform).toString();
```
Access the `bbox` instance property to apply a consistent `transform-origin`:
```js
// apply a 3D transformation with a consistent origin
const transformed3DPath = new SVGPathCommander(path);
const { cx, cy, cz } = transformed3DPath.bbox;
const transform = {
translate: [15, 15, 15], // `[15, 15]` would apply a 2D translation, and only `15` for X axis translation
rotate: [15, 15, 15], // or only "15" for 2D rotation on Z axis
scale: [0.7, 0.75, 0.8], // or only "0.7" for 2D scale on all X, Y, Z axis
skew: [15, 15], // or only "15" for the X axis
origin: [cx, cy, cz] // the origin
}
const transformed3DPathString = transformed3DPath.transform(transform).toString();
```
SVGPathCommander comes with a full range of additional static methods, here's how to normalize a path:
```js
const path = 'M0 0 H50';
const normalizedPath = SVGPathCommander.normalizePath(path);
// result => [['M', 0, 0], ['L', 50, 0]]
```
Reverse a path:
```js
const path = SVGPathCommander.parsePathString('M0 0 H50');
const reversedPath = SVGPathCommander.reversePath(path);
// result => [['M', 50, 0], ['H', 0]]
```
Export to string:
```js
const myPathString = SVGPathCommander.pathToString([['M', 0, 0], ['L', 50, 0]]);
// result => 'M0 0 L50 0'
```
Check a path string validity:
```js
SVGPathCommander.isValidPath(path);
// result => boolean
```
Check if path is a certain kind of `PathArray`:
```js
SVGPathCommander.isAbsoluteArray([['M', 0, 0], ['L', 50, 0]]);
// result => true
```
Use treeshake and create a custom function to apply a 3D transformation using static methods:
```ts
import { parsePathString, getPathBBox, transformPath, pathToString } from 'svg-path-commander';
function myTransformFn(pathInput: string | PathArray, transformObject: TransformObject) {
const path = parsePathString(pathInput);
const { cx, cy, cz } = getPathBBox(path);
return pathToString(
transformPath(path, {
...transformObject, origin: [cx, cy, cz]
})
)
}
```
In extreme cases where performance is paramount, you can consider the parent SVG `viewBox` attribute to extract a bounding box required for a consistent transform origin.
```ts
// const svgViewBox = document.getElementById('my-svg').getAttribute('viewBox');
const viewBox = '0 0 24 24';
const [x, y, width, height] = viewBox.split(/\s/).map(Number);
const origin = [
x + width / 2, // CX
y + height / 2, // CY
Math.max(width, height) + Math.min(width, height) / 2, // CZ
];
// use this origin for your shape transformation
const myNewString = new SVGPathCommander('M0 0 H50')
.transform({ rotate: [35, 0, 0], origin })
.toString();
```
Convert a shape to `<path>` and transfer all non-specific attributes
```js
const myCircle = document.getElementById('myCircle');
SVGPathCommander.shapeToPath(myCircle, true);
```
Alternatively you can create `<path>` from specific attributes:
```js
const myRectAttr = {
type: 'rect',
x: 25,
y: 25,
width: 50,
height: 50,
rx: 5
};
const myRectPath = SVGPathCommander.shapeToPath(myRectAttr);
document.getElementById('mySVG').append(myRectPath);
```
Server-side using `jsdom`:
```js
const { document } = new JSDOM(
`<html>
<head></head>
<body>
<svg id="mySVG" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect id="myRect" x="0" width="100" height="100" rx="15" />
</svg>
</body>
</html>`,
{
pretendToBeVisual: true,
}
).window;
const myRect = document.getElementById('myRect');
SVGPathCommander.shapeToPath(myRect, true, document);
```
Get the path length:
```js
const myPathLength = SVGPathCommander.getTotalLength('M0 0L50 0L25 50z');
// result => 161.80339887498948
```
Get a point along the path:
```js
const myPoint = SVGPathCommander.getPointAtLength('M0 0L50 0L25 50z', 85);
// result => {x: 34.34752415750147, y: 31.304951684997057}
```
Get the path bounding box:
```js
const myPathBBox = SVGPathCommander.getPathBBox('M0 0L50 0L25 50z');
// result => {width: 50, height: 50, x: 0, y: 0, x2: 50, y2: 50, cx: 25, cy: 25, cz: 75}
```
Find intersection points between two paths:
```js
const count = SVGPathCommander.pathsIntersection(
'M0 50C0 0,100 0,100 50',
'M50 0C100 0,100 100,50 100',
true
);
// result => 1
const points = SVGPathCommander.pathsIntersection(
'M0 50C0 0,100 0,100 50',
'M50 0C100 0,100 100,50 100',
false
);
// result => [{ x: 50, y: 25, t1: 0.5, t2: 0.5 }]
```
Equalize two paths for morphing (single subpath):
```js
const [eq1, eq2] = SVGPathCommander.equalizeSegments(
'M0 0L100 0L50 100Z',
'M0 0L100 0L100 100L0 100Z'
);
// eq1.length === eq2.length — ready for morphing
```
Equalize two paths for morphing (single or multi subpath):
```js
const [eq1, eq2] = SVGPathCommander.equalizePaths(
'M0 0L100 0L50 100Z',
'M0 0L100 0L100 100L0 100Z',
{ close: true }
);
// Both paths now have the same number of segments
```
# WIKI
For developer guidelines, and a complete list of static methods, head over to the [wiki pages](https://github.com/thednp/svg-path-commander/wiki).
# What Is It For?
* converting and optimizing *SVGPathElement* for use in third party application; our [KUTE.js](https://github.com/thednp/kute.js) animation engine is using it to process *SVGPathElement* coordinates for [SVG morphing](https://thednp.github.io/kute.js/svgMorph.html) and [SVG cubic morphing](https://thednp.github.io/kute.js/svgCubicMorph.html);
* animators that work with SVGs and need tools for performing specific path command processing;
* front-end developers looking to spice up the content by combining, splitting or transforming paths;
* font-icon creators can use it in both Node.js and web applications to process, optimize and test their creations.
# Technical Considerations
* the `optimize()` instance method will not merge path segments (for instance two or more cubic-bezier segments into one or more arc segments); however, the script will try to provide shorthand notations where possible, pick the shortest string for each segment, and generally try to deliver the best possible outcome;
* all tools processing path segments will never round float values, however `pathToString`, `optimizePath` and especially `roundPath` will always round values to the default of 4 decimals; EG: 0.56676 => 0.567, 0.50 => 0.5; you can change the default option with `SVGPathCommander.options.round = 2` or remove the value rounding all together with `SVGPathCommander.options.round = false`; you can also control this feature via instance options;
* the `getSVGMatrix` utility we developed will always compute the matrix by applying the transform functions in the following order: `translate`, `rotate`, `skew` and `scale`, which is the default composition/recomposition order specified in the W3C draft;
* all 3d transformations as well as skews will convert `A` (arc) path commands to `C` (cubic bezier) due to the lack of resources;
* most tools included with **SVGPathCommander** should work in your Node.js apps, but feel free to report any issue;
* other path commands like `R` (catmulRomBezier), `O`, `U` (ellipse and shorthand ellipse) are not present in the current draft and are not supported;
* normalization can mean many things to many people and our library is developed to convert path command values to absolute and shorthand to longhand commands to provide a solid foundation for the main processing tools of our library;
* when compared to the native methods like `SVGPathElement.getTotalLength()` or `SVGPathElement.getPointAtLength()`, the output of our static methods is within a [0.002 - 0.05] margin delta, but from our experience it's proven to be a more consistent outcome.
# Special Thanks
* Dmitry Baranovskiy for his [Raphael.js](https://dmitrybaranovskiy.github.io/raphael/)
* Vitaly Puzrin & Alex Kocharin for their [SvgPath](https://github.com/fontello/svgpath)
* Jürg Lehni & Jonathan Puckey for their [Paper.js](https://github.com/paperjs/paper.js/)
* Andrew Willems for his [awesome guide](https://stackoverflow.com/users/5218951/andrew-willems)
* Mike 'Pomax' Kamermans for his awesome [svg-path-reverse](https://github.com/Pomax/svg-path-reverse), [bezierjs](https://github.com/Pomax/bezierjs) and [bezierinfo](https://pomax.github.io/bezierinfo/)
* Nicolas Debeissat for the inspiration on [svg3d](https://github.com/ndebeiss/svg3d)
* Mike Bostock for his awesome [closestPoint](https://bl.ocks.org/mbostock/8027637)
* James Halliday for his excelent [point-at-length](https://github.com/substack/point-at-length)
* Eric Eastwood for his excelent [svg-curve-lib](https://github.com/MadLittleMods/svg-curve-lib)
* PhET Interactive Simulations for their [kite](https://github.com/phetsims/kite)
* [herrstrietzel](https://github.com/herrstrietzel) for his awesome [svg-pathdata-getbbox](https://github.com/herrstrietzel/svg-pathdata-getbbox)
* a special thanks goes to [@vltansky](https://github.com/vltansky) for fixing tree-shaking in **SVGPathCommander**!
# License
**SVGPathCommander** is released under [MIT Licence](https://github.com/thednp/svg-path-commander/blob/master/LICENSE).

View File

@@ -0,0 +1,733 @@
/*!
* SVGPathCommander v2.2.1 (http://thednp.github.io/svg-path-commander)
* Copyright 2026 © thednp
* Licensed under MIT (https://github.com/thednp/svg-path-commander/blob/master/LICENSE)
*/
import CSSMatrix from "@thednp/dommatrix";
//#region src/interface.d.ts
type SegmentProperties = {
segment: PathSegment;
index: number;
length: number;
lengthAtSegment: number;
};
type PointProperties = {
closest: {
x: number;
y: number;
};
distance: number;
segment?: SegmentProperties;
};
type LineAttr = {
type: "line";
x1: number;
y1: number;
x2: number;
y2: number;
[key: string]: string | number;
};
type PolyAttr = {
type: "polygon" | "polyline";
points: string;
[key: string]: string | number;
};
type CircleAttr = {
type: "circle";
cx: number;
cy: number;
r: number;
[key: string]: string | number;
};
type EllipseAttr = {
type: "ellipse";
cx: number;
cy: number;
rx: number;
ry?: number;
[key: string]: string | number | undefined;
};
type RectAttr = {
type: "rect";
width: number;
height: number;
x: number;
y: number;
rx?: number;
ry?: number;
[key: string]: string | number | undefined;
};
type GlyphAttr = {
type: "glyph";
d: string;
[key: string]: string | number;
};
type ShapeParams = {
line: ["x1", "y1", "x2", "y2"];
circle: ["cx", "cy", "r"];
ellipse: ["cx", "cy", "rx", "ry"];
rect: ["width", "height", "x", "y", "rx", "ry"];
polygon: ["points"];
polyline: ["points"];
glyph: ["d"];
};
type PathBBox = {
width: number;
height: number;
x: number;
y: number;
x2: number;
y2: number;
cx: number;
cy: number;
cz: number;
};
type SegmentLimits = {
min: {
x: number;
y: number;
};
max: {
x: number;
y: number;
};
};
type ParserParams = {
mx: number;
my: number;
x1: number;
y1: number;
x2: number;
y2: number;
x: number;
y: number;
qx: number | null;
qy: number | null;
};
type LengthFactory = {
length: number;
point: {
x: number;
y: number;
};
min: {
x: number;
y: number;
};
max: {
x: number;
y: number;
};
};
type Options = {
round: "off" | number;
origin: number[];
};
type PathTransform = {
s: PathSegment;
c: string;
x: number;
y: number;
};
type TransformObject = {
translate: number | number[];
rotate: number | number[];
scale: number | number[];
skew: number | number[];
origin: number[];
};
type TransformProps = keyof TransformObject;
type TransformEntries = [TransformProps, TransformObject[TransformProps]][];
//#endregion
//#region src/types.d.ts
type SpaceNumber = 0x1680 | 0x180e | 0x2000 | 0x2001 | 0x2002 | 0x2003 | 0x2004 | 0x2005 | 0x2006 | 0x2007 | 0x2008 | 0x2009 | 0x200a | 0x202f | 0x205f | 0x3000 | 0xfeff | 0x0a | 0x0d | 0x2028 | 0x2029 | 0x20 | 0x09 | 0x0b | 0x0c | 0xa0 | 0x1680;
type PathCommandNumber = 0x6d | 0x7a | 0x6c | 0x68 | 0x76 | 0x63 | 0x73 | 0x71 | 0x74 | 0x61;
type DigitNumber = 0x30 | 0x31 | 0x32 | 0x33 | 0x34 | 0x35 | 0x36 | 0x37 | 0x38 | 0x39;
type MCommand = "M";
type mCommand = "m";
type LCommand = "L";
type lCommand = "l";
type VCommand = "V";
type vCommand = "v";
type HCommand = "H";
type hCommand = "h";
type ZCommand = "Z";
type zCommand = "z";
type CCommand = "C";
type cCommand = "c";
type SCommand = "S";
type sCommand = "s";
type QCommand = "Q";
type qCommand = "q";
type TCommand = "T";
type tCommand = "t";
type ACommand = "A";
type aCommand = "a";
type AbsoluteCommand = MCommand | LCommand | VCommand | HCommand | ZCommand | CCommand | SCommand | QCommand | TCommand | ACommand;
type RelativeCommand = mCommand | lCommand | vCommand | hCommand | zCommand | cCommand | sCommand | qCommand | tCommand | aCommand;
type PathCommand = AbsoluteCommand | RelativeCommand;
type MSegment = [MCommand, number, number];
type mSegment = [mCommand, number, number];
type MoveSegment = MSegment | mSegment;
type LSegment = [LCommand, number, number];
type lSegment = [lCommand, number, number];
type LineSegment = LSegment | lSegment;
type VSegment = [VCommand, number];
type vSegment = [vCommand, number];
type VertLineSegment = vSegment | VSegment;
type HSegment = [HCommand, number];
type hSegment = [hCommand, number];
type HorLineSegment = HSegment | hSegment;
type ZSegment = [ZCommand];
type zSegment = [zCommand];
type CloseSegment = ZSegment | zSegment;
type CSegment = [CCommand, number, number, number, number, number, number];
type cSegment = [cCommand, number, number, number, number, number, number];
type CubicSegment = CSegment | cSegment;
type SSegment = [SCommand, number, number, number, number];
type sSegment = [sCommand, number, number, number, number];
type ShortCubicSegment = SSegment | sSegment;
type QSegment = [QCommand, number, number, number, number];
type qSegment = [qCommand, number, number, number, number];
type QuadSegment = QSegment | qSegment;
type TSegment = [TCommand, number, number];
type tSegment = [tCommand, number, number];
type ShortQuadSegment = TSegment | tSegment;
type ASegment = [ACommand, number, number, number, number, number, number, number];
type aSegment = [aCommand, number, number, number, number, number, number, number];
type ArcSegment = ASegment | aSegment;
type PathSegment = MoveSegment | LineSegment | VertLineSegment | HorLineSegment | CloseSegment | CubicSegment | ShortCubicSegment | QuadSegment | ShortQuadSegment | ArcSegment;
type ShortSegment = VertLineSegment | HorLineSegment | ShortCubicSegment | ShortQuadSegment | CloseSegment;
type AbsoluteSegment = MSegment | LSegment | VSegment | HSegment | CSegment | SSegment | QSegment | TSegment | ASegment | ZSegment;
type RelativeSegment = mSegment | lSegment | vSegment | hSegment | cSegment | sSegment | qSegment | tSegment | aSegment | zSegment;
type NormalSegment = MSegment | LSegment | CSegment | QSegment | ASegment | ZSegment;
type PathArray = [MSegment | mSegment, ...PathSegment[]];
type AbsoluteArray = [MSegment, ...AbsoluteSegment[]];
type RelativeArray = [MSegment, ...RelativeSegment[]];
type NormalArray = [MSegment, ...NormalSegment[]];
type CurveArray = [MSegment, ...CSegment[]];
type ClosedCurveArray = [MSegment, ...CSegment[], ZSegment];
type PolygonArray = [MSegment, ...LSegment[], ZSegment];
type PolylineArray = [MSegment, ...LSegment[]];
type MorphPathArray = PolygonArray | PolylineArray | CurveArray | ClosedCurveArray;
type ShapeTypes = SVGPolylineElement | SVGPolygonElement | SVGLineElement | SVGEllipseElement | SVGCircleElement | SVGRectElement;
type ShapeTags = "line" | "polyline" | "polygon" | "ellipse" | "circle" | "rect" | "glyph";
type ShapeOps = LineAttr | PolyAttr | PolyAttr | EllipseAttr | CircleAttr | RectAttr | GlyphAttr;
type TransformObjectValues = Partial<TransformObject> & {
origin: [number, number, number];
};
type Point = {
x: number;
y: number;
};
type PointTuple = [number, number];
type DerivedPoint = Point & {
t: number;
};
type QuadPoints = [Point, Point, Point, Point, Point, Point];
type CubicPoints = [Point, Point, Point, Point, Point, Point, Point, Point];
type DerivedQuadPoints = [DerivedPoint, DerivedPoint, DerivedPoint, DerivedPoint, DerivedPoint, DerivedPoint];
type DerivedCubicPoints = [DerivedPoint, DerivedPoint, DerivedPoint, DerivedPoint, DerivedPoint, DerivedPoint, DerivedPoint, DerivedPoint];
type QuadCoordinates = [number, number, number, number, number, number];
type CubicCoordinates = [number, number, number, number, number, number, number, number];
type ArcCoordinates = [number, number, number, number, number, number, number, number, number];
type LineCoordinates = [number, number, number, number];
type DeriveCallback = (t: number) => Point;
type IteratorCallback<T extends PathArray, K extends keyof T = number> = (segment: PathSegment & T[K], index: number, lastX: number, lastY: number) => PathSegment | T[K] | false | void | undefined;
type BBoxMaxima = [minX: number, minY: number, maxX: number, maxY: number];
type PointAtLength = {
x: number;
y: number;
t: number;
};
type IntersectionPoint = {
x: number;
y: number;
t1: number;
t2: number;
};
interface IntersectionOptions {
justCount?: boolean;
epsilon?: number;
}
interface PathEqualizationOptions {
/** @default "auto" */
mode?: "line" | "curve" | "auto";
sampleSize?: number;
roundValues?: number;
close?: boolean;
}
interface EqualizationOptions {
/** @default "auto" */
mode?: "curve" | "auto";
sampleSize?: number;
roundValues?: number;
reverse?: boolean;
close?: boolean;
target?: number;
}
type PathsEqualizationOptions = Omit<EqualizationOptions, "reverse" | "target">;
interface PathFeature {
isPoly: boolean;
path: NormalArray;
size: number;
area: number;
signedArea: number;
bbox: PathBBox;
}
//#endregion
//#region src/parser/pathParser.d.ts
/**
* The `PathParser` is used by the `parsePathString` static method
* to generate a `pathArray`.
*
* @param pathString - The SVG path string to parse
*/
declare class PathParser {
segments: PathArray | PathSegment[];
pathValue: string;
max: number;
index: number;
param: number;
segmentStart: number;
data: (string | number)[];
err: string;
constructor(pathString: string);
}
//#endregion
//#region src/morph/samplePolygon.d.ts
/**
* Samples points from a path to form a polygon approximation.
* Collects endpoints of each segment (M start + ends of L/C/etc).
*
* If `sampleSize` parameter is provided, it will return a polygon
* equivalent to the original `PathArray`.
* @param path `PolygonPathArray` or `CurvePathArray`
* @returns Array of [x, y] points
*/
declare function samplePolygon<T extends NormalArray>(path: T): PointTuple[];
//#endregion
//#region src/util/isPolylineArray.d.ts
/**
* Checks if a path is a polyline (only M, L, H, V commands).
* @param pathArray PathArray (pre-normalize if needed)
* @returns boolean
*/
declare function isPolylineArray(path: PathArray): path is PolylineArray;
//#endregion
//#region src/morph/splitCubicSegment.d.ts
/**
* Split a cubic Bézier into two cubics at parameter t [01].
*
* @param x1 - Start point X
* @param y1 - Start point Y
* @param x2 - First control point X
* @param y2 - First control point Y
* @param x3 - Second control point X
* @param y3 - Second control point Y
* @param x4 - End point X
* @param y4 - End point Y
* @param t - Parameter in range [0, 1] at which to split
* @returns Array of two cubic segments, each as [x1,y1, x2,y2, x3,y3, x4,y4]
*/
declare function splitCubicSegment(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number, t: number): [CubicCoordinates, CubicCoordinates];
//#endregion
//#region src/main.d.ts
/**
* Creates a new SVGPathCommander instance with the following properties:
* * segments: `pathArray`
* * round: number
* * origin: [number, number, number?]
*
* @class
* @author thednp <https://github.com/thednp/svg-path-commander>
* @returns a new SVGPathCommander instance
*/
declare class SVGPathCommander {
segments: PathArray;
round: number | "off";
origin: [number, number, number];
/**
* @constructor
* @param pathValue the path string
* @param config instance options
*/
constructor(pathValue: string, config?: Partial<Options>);
get bbox(): {
x: number;
y: number;
width: number;
height: number;
x2: number;
y2: number;
cx: number;
cy: number;
cz: number;
};
get length(): number;
/**
* Returns the path bounding box, equivalent to native `path.getBBox()`.
*
* @public
* @returns the pathBBox
*/
getBBox(): {
x: number;
y: number;
width: number;
height: number;
x2: number;
y2: number;
cx: number;
cy: number;
cz: number;
};
/**
* Returns the total path length, equivalent to native `path.getTotalLength()`.
*
* @public
* @returns the path total length
*/
getTotalLength(): number;
/**
* Returns an `{x,y}` point in the path stroke at a given length,
* equivalent to the native `path.getPointAtLength()`.
*
* @public
* @param length the length
* @returns the requested point
*/
getPointAtLength(length: number): {
x: number;
y: number;
};
/**
* Convert path to absolute values.
*
* @example
* ```ts
* new SVGPathCommander('M10 10l80 80').toAbsolute().toString()
* // => 'M10 10L90 90'
* ```
*
* @returns this for chaining
* @public
*/
toAbsolute(): this;
/**
* Convert path to relative values.
*
* @example
* ```ts
* new SVGPathCommander('M10 10L90 90').toRelative().toString()
* // => 'M10 10l80 80'
* ```
*
* @returns this for chaining
* @public
*/
toRelative(): this;
/**
* Convert path to cubic-bezier values. In addition, un-necessary `Z`
* segment is removed if previous segment extends to the `M` segment.
*
* @example
* ```ts
* new SVGPathCommander('M10 50q15 -25 30 0').toCurve().toString()
* // => 'M10 50C25 25 40 50 40 50'
* ```
*
* @returns this for chaining
* @public
*/
toCurve(): this;
/**
* Reverse the order of the segments and their values.
*
* @example
* ```ts
* new SVGPathCommander('M0 0L100 0L100 100L0 100Z').reverse().toString()
* // => 'M0 100L0 0L100 0L100 100Z'
* ```
*
* @param onlySubpath - option to reverse all sub-paths except first
* @returns this for chaining
* @public
*/
reverse(onlySubpath?: boolean): this;
/**
* Normalize path in 2 steps:
* * convert `pathArray`(s) to absolute values
* * convert shorthand notation to standard notation
*
* @example
* ```ts
* new SVGPathCommander('M10 90s20 -80 40 -80s20 80 40 80').normalize().toString()
* // => 'M10 90C30 90 25 10 50 10C75 10 70 90 90 90'
* ```
*
* @returns this for chaining
* @public
*/
normalize(): this;
/**
* Optimize `pathArray` values:
* * convert segments to absolute and/or relative values
* * select segments with shortest resulted string
* * round values to the specified `decimals` option value
*
* @example
* ```ts
* new SVGPathCommander('M10 10L10 10L90 90').optimize().toString()
* // => 'M10 10l0 0 80 80'
* ```
*
* @returns this for chaining
* @public
*/
optimize(): this;
/**
* Transform path using values from an `Object` defined as `transformObject`.
*
* @see TransformObject for a quick reference
*
* @param source a `transformObject` as described above
* @returns this for chaining
* @public
*/
transform(source?: Partial<TransformObject>): this;
/**
* Rotate path 180deg vertically.
*
* @example
* ```ts
* const path = new SVGPathCommander('M0 0L100 0L100 100L0 100Z')
* path.flipX().toString()
* ```
*
* @returns this for chaining
* @public
*/
flipX(): this;
/**
* Rotate path 180deg horizontally.
*
* @example
* ```ts
* const path = new SVGPathCommander('M0 0L100 0L100 100L0 100Z')
* path.flipY().toString()
* ```
*
* @returns this for chaining
* @public
*/
flipY(): this;
/**
* Export the current path to be used
* for the `d` (description) attribute.
*
* @public
* @returns the path string
*/
toString(): string;
/**
* Remove the instance.
*
* @public
* @returns void
*/
dispose(): void;
static options: Options;
static CSSMatrix: typeof CSSMatrix;
static arcTools: {
angleBetween: (v0: Point, v1: Point) => number;
arcLength: (rx: number, ry: number, theta: number) => number;
arcPoint: (cx: number, cy: number, rx: number, ry: number, alpha: number, theta: number) => PointTuple;
getArcBBox: (x1: number, y1: number, RX: number, RY: number, angle: number, LAF: number, SF: number, x: number, y: number) => [number, number, number, number];
getArcLength: (x1: number, y1: number, RX: number, RY: number, angle: number, LAF: number, SF: number, x: number, y: number) => number;
getArcProps: (x1: number, y1: number, RX: number, RY: number, angle: number, LAF: number, SF: number, x: number, y: number) => {
rx: number;
ry: number;
startAngle: number;
endAngle: number;
center: {
x: number;
y: number;
};
};
getPointAtArcLength: (x1: number, y1: number, RX: number, RY: number, angle: number, LAF: number, SF: number, x: number, y: number, distance?: number) => {
x: number;
y: number;
};
};
static bezierTools: {
bezierLength: (derivativeFn: DeriveCallback) => number;
calculateBezier: (derivativeFn: DeriveCallback, t: number) => number;
CBEZIER_MINMAX_EPSILON: number;
computeBezier: (points: DerivedQuadPoints | DerivedCubicPoints, t: number) => DerivedPoint;
Cvalues: number[];
deriveBezier: (points: QuadPoints | CubicPoints) => (DerivedQuadPoints | DerivedCubicPoints)[];
getBezierLength: (curve: CubicCoordinates | QuadCoordinates) => number;
minmaxC: ([v1, cp1, cp2, v2]: [number, number, number, number]) => PointTuple;
minmaxQ: ([v1, cp, v2]: [number, number, number]) => PointTuple;
Tvalues: number[];
};
static cubicTools: {
getCubicBBox: (x1: number, y1: number, c1x: number, c1y: number, c2x: number, c2y: number, x2: number, y2: number) => BBoxMaxima;
getCubicLength: (x1: number, y1: number, c1x: number, c1y: number, c2x: number, c2y: number, x2: number, y2: number) => number;
getPointAtCubicLength: (x1: number, y1: number, c1x: number, c1y: number, c2x: number, c2y: number, x2: number, y2: number, distance?: number) => {
x: number;
y: number;
};
getPointAtCubicSegmentLength: ([x1, y1, c1x, c1y, c2x, c2y, x2, y2]: CubicCoordinates, t: number) => {
x: number;
y: number;
};
};
static lineTools: {
getLineBBox: (x1: number, y1: number, x2: number, y2: number) => [number, number, number, number];
getLineLength: (x1: number, y1: number, x2: number, y2: number) => number;
getPointAtLineLength: (x1: number, y1: number, x2: number, y2: number, distance?: number) => {
x: number;
y: number;
};
};
static polygonTools: {
polygonArea: (polygon: PointTuple[]) => number;
polygonLength: (polygon: PointTuple[]) => number;
polygonCentroid: (polygon: PointTuple[]) => PointTuple;
};
static quadTools: {
getPointAtQuadLength: (x1: number, y1: number, cx: number, cy: number, x2: number, y2: number, distance?: number) => {
x: number;
y: number;
};
getPointAtQuadSegmentLength: ([x1, y1, cx, cy, x2, y2]: QuadCoordinates, t: number) => {
x: number;
y: number;
};
getQuadBBox: (x1: number, y1: number, cx: number, cy: number, x2: number, y2: number) => [number, number, number, number];
getQuadLength: (x1: number, y1: number, cx: number, cy: number, x2: number, y2: number) => number;
};
static pathToAbsolute: <T extends PathArray>(pathInput: string | T) => AbsoluteArray;
static pathToRelative: <T extends PathArray>(pathInput: string | T) => RelativeArray;
static pathToCurve: <T extends PathArray>(pathInput: string | T) => CurveArray;
static pathToString: <T extends PathArray>(path: T, roundOption?: number | "off") => string;
static distanceSquareRoot: (a: PointTuple, b: PointTuple) => number;
static midPoint: ([ax, ay]: PointTuple, [bx, by]: PointTuple, t: number) => PointTuple;
static rotateVector: (x: number, y: number, rad: number) => {
x: number;
y: number;
};
static roundTo: (n: number, round: number) => number;
static parsePathString: <T extends PathArray>(pathInput: string | T) => PathArray;
static finalizeSegment: (path: PathParser) => void;
static invalidPathValue: string;
static isArcCommand: (code: number) => code is 97;
static isDigit: (code: number) => code is DigitNumber;
static isDigitStart: (code: number) => code is DigitNumber | 43 | 45 | 46;
static isMoveCommand: (code: number) => code is 109 | 77;
static isPathCommand: (code: number) => code is PathCommandNumber;
static isSpace: (ch: number) => ch is SpaceNumber;
static paramsCount: {
a: number;
c: number;
h: number;
l: number;
m: number;
r: number;
q: number;
s: number;
t: number;
v: number;
z: number;
};
static paramsParser: ParserParams;
static PathParser: typeof PathParser;
static scanFlag: (path: PathParser) => void;
static scanParam: (path: PathParser) => void;
static scanSegment: (path: PathParser) => void;
static skipSpaces: (path: PathParser) => void;
static distanceEpsilon: number;
static fixPath: <T extends PathArray>(pathInput: T | string) => void;
static getClosestPoint: (pathInput: string | PathArray, point: {
x: number;
y: number;
}) => {
x: number;
y: number;
};
static getDrawDirection: (path: string | PathArray) => boolean;
static getPathArea: <T extends PathArray>(path: T) => number;
static getPathBBox: <T extends PathArray>(pathInput: T | string) => {
x: number;
y: number;
width: number;
height: number;
x2: number;
y2: number;
cx: number;
cy: number;
cz: number;
};
static getPointAtLength: <T extends PathArray>(pathInput: string | T, distance?: number) => {
x: number;
y: number;
};
static getPropertiesAtLength: <T extends PathArray>(pathInput: string | T, distance?: number) => SegmentProperties;
static getPropertiesAtPoint: <T extends PathArray>(pathInput: string | T, point: Point) => PointProperties;
static getSegmentAtLength: <T extends PathArray>(pathInput: string | T, distance?: number) => PathSegment | undefined;
static getSegmentOfPoint: <T extends PathArray>(path: string | T, point: {
x: number;
y: number;
}) => SegmentProperties | undefined;
static getTotalLength: <T extends PathArray>(pathInput: string | T) => number;
static isAbsoluteArray: (path: unknown) => path is AbsoluteArray;
static isCurveArray: (path: unknown) => path is CurveArray;
static isPolygonArray: (path: PathArray) => path is PolygonArray;
static isNormalizedArray: (path: unknown) => path is NormalArray;
static isPathArray: (path: unknown) => path is PathArray;
static isPointInStroke: <T extends PathArray>(pathInput: string | T, point: {
x: number;
y: number;
}) => boolean;
static isRelativeArray: (path: unknown) => path is RelativeArray;
static isValidPath: (pathString: string) => boolean;
static samplePolygon: typeof samplePolygon;
static shapeParams: ShapeParams;
static shapeToPath: (element: ShapeTypes | ShapeOps, replace?: boolean, ownerDocument?: Document) => SVGPathElement | false;
static shapeToPathArray: (element: ShapeTypes | ShapeOps) => false | PathArray;
static absolutizeSegment: (segment: PathSegment, index: number, lastX: number, lastY: number) => AbsoluteSegment;
static arcToCubic: (X1: number, Y1: number, RX: number, RY: number, angle: number, LAF: number, SF: number, X2: number, Y2: number, recursive?: [number, number, number, number]) => number[];
static getSVGMatrix: (transform: TransformObjectValues) => CSSMatrix;
static iterate: <T extends PathArray>(path: T, iterator: IteratorCallback<T>) => T;
static lineToCubic: (x1: number, y1: number, x2: number, y2: number) => number[];
static normalizePath: (pathInput: string | PathArray) => NormalArray;
static normalizeSegment: (segment: PathSegment, params: ParserParams) => NormalSegment;
static optimizePath: <T extends PathArray>(pathInput: T, roundOption?: number) => PathArray;
static projection2d: (m: CSSMatrix, point2D: PointTuple, origin: [number, number, number]) => PointTuple;
static quadToCubic: (x1: number, y1: number, qx: number, qy: number, x2: number, y2: number) => [number, number, number, number, number, number];
static relativizeSegment: (segment: PathSegment, index: number, lastX: number, lastY: number) => MSegment | RelativeSegment;
static reverseCurve: (path: CurveArray) => CurveArray;
static reversePath: <T extends PathArray>(pathInput: T) => T;
static roundPath: <T extends PathArray>(path: T, roundOption?: number | "off") => T;
static roundSegment: <T extends PathSegment>(segment: T, roundOption: number) => T;
static segmentToCubic: (segment: PathSegment, params: ParserParams) => MSegment | CSegment;
static shortenSegment: (segment: AbsoluteSegment, normalSegment: NormalSegment, params: ParserParams, prevCommand: PathCommand) => ShortSegment;
static splitPath: <T extends PathArray>(pathInput: T | string) => T[];
static equalizePaths: (pathInput1: string | PathArray, pathInput2: string | PathArray, initialCfg?: {}) => [MorphPathArray, MorphPathArray];
static equalizeSegments: (path1: PathArray | string, path2: PathArray | string, initialCfg?: EqualizationOptions) => [MorphPathArray, MorphPathArray];
static splitCubicSegment: typeof splitCubicSegment;
static transformPath: <T extends PathArray>(pathInput: T | string, transform?: Partial<TransformObject>) => T | AbsoluteArray;
static isPointInsideBBox: (bbox: BBoxMaxima, [x, y]: PointTuple) => boolean;
static pathsIntersection: <T extends string | PathArray>(pathInput1: T, pathInput2: T, justCount?: boolean) => number | IntersectionPoint[];
static boundingBoxIntersect: (a: BBoxMaxima, b: BBoxMaxima) => boolean;
static isMultiPath: <T extends PathArray>(path: string | T) => boolean;
static isClosedPath: <T extends PathArray>(path: T) => boolean;
static isPolylineArray: typeof isPolylineArray;
static version: string;
}
//#endregion
export { ACommand, ASegment, AbsoluteArray, AbsoluteCommand, AbsoluteSegment, ArcCoordinates, ArcSegment, BBoxMaxima, CCommand, CSegment, CircleAttr, CloseSegment, ClosedCurveArray, CubicCoordinates, CubicPoints, CubicSegment, CurveArray, DeriveCallback, DerivedCubicPoints, DerivedPoint, DerivedQuadPoints, DigitNumber, EllipseAttr, EqualizationOptions, GlyphAttr, HCommand, HSegment, HorLineSegment, IntersectionOptions, IntersectionPoint, IteratorCallback, LCommand, LSegment, LengthFactory, LineAttr, LineCoordinates, LineSegment, MCommand, MSegment, MorphPathArray, MoveSegment, NormalArray, NormalSegment, Options, ParserParams, PathArray, PathBBox, PathCommand, PathCommandNumber, PathEqualizationOptions, PathFeature, PathSegment, PathTransform, PathsEqualizationOptions, Point, PointAtLength, PointProperties, PointTuple, PolyAttr, PolygonArray, PolylineArray, QCommand, QSegment, QuadCoordinates, QuadPoints, QuadSegment, RectAttr, RelativeArray, RelativeCommand, RelativeSegment, SCommand, SSegment, SegmentLimits, SegmentProperties, ShapeOps, ShapeParams, ShapeTags, ShapeTypes, ShortCubicSegment, ShortQuadSegment, ShortSegment, SpaceNumber, TCommand, TSegment, TransformEntries, TransformObject, TransformObjectValues, TransformProps, VCommand, VSegment, VertLineSegment, ZCommand, ZSegment, aCommand, aSegment, cCommand, cSegment, SVGPathCommander as default, hCommand, hSegment, lCommand, lSegment, mCommand, mSegment, qCommand, qSegment, sCommand, sSegment, tCommand, tSegment, vCommand, vSegment, zCommand, zSegment };
//# sourceMappingURL=index.d.ts.map

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,87 @@
{
"name": "svg-path-commander",
"author": "thednp",
"license": "MIT",
"version": "2.2.1",
"description": "🛹 Modern TypeScript tools for SVG",
"homepage": "http://thednp.github.io/svg-path-commander",
"bugs": {
"url": "https://github.com/thednp/svg-path-commander/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/thednp/svg-path-commander.git"
},
"keywords": [
"svg",
"path",
"commander",
"parse",
"normalize",
"optimize",
"reverse",
"intersect",
"convert",
"absolute",
"relative",
"curve",
"transform3d",
"typescript"
],
"files": [
"dist",
"package.json",
"README.md",
"AGENTS.md",
"CHANGELOG.md",
"LICENSE"
],
"main": "./dist/index.js",
"browser": "./dist/index.min.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"sideEffects": false,
"type": "module",
"exports": {
".": "./dist/index.js",
"./util": "./dist/util.js",
"./package.json": "./package.json"
},
"devDependencies": {
"@types/node": "^25.5.2",
"@vitest/browser": "^4.1.2",
"@vitest/coverage-istanbul": "^4.1.2",
"@vitest/ui": "^4.1.2",
"happy-dom": "^20.8.9",
"playwright": "^1.59.1",
"tsdown": "0.21.7",
"typescript": "^6.0.2",
"vite": "^8.0.4",
"vite-plugin-strip-comments": "^0.0.10",
"vitest": "^4.1.2"
},
"dependencies": {
"@thednp/dommatrix": "^3.0.4"
},
"engines": {
"node": ">=16",
"pnpm": ">=8.6.0"
},
"inlinedDependencies": {
"@thednp/dommatrix": "3.0.4"
},
"scripts": {
"pre-test": "pnpm clean-coverage",
"dev": "vite serve docs --port 3000",
"test": "vitest",
"test-ui": "vitest --ui",
"clean-coverage": "rm -rf coverage .nyc_output",
"format": "deno fmt src",
"lint": "pnpm lint:ts",
"fix:ts": "deno lint --fix src",
"lint:ts": "deno lint src",
"check:ts": "tsc --noEmit",
"build": "tsdown && pnpm copy-docs",
"copy-docs": "cp dist/index.min.js docs/index.min.js && cp dist/index.min.js.map docs/index.min.js.map"
}
}