# svg-pathdata

> Manipulate SVG path data (path[d] attribute content) simply and efficiently.

Latest version **9.0.0** (published 2026-03-27) · MIT license · 0 weekly downloads

## Install

```sh
npm install svg-pathdata
pnpm add svg-pathdata
yarn add svg-pathdata
bun add svg-pathdata
```

## Health

**Score 60/100 (C)** — status: active.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 9.0.0 |
| Published | 2026-03-27 |
| First published | 2013-11-04 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=24.14.0 |
| Dependencies | 0 |
| Unpacked size | 670.2 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 215 |
| Author | Nicolas Froidure |
| Maintainers | nfroidure, pioug, huerlisi, narida |
| Keywords | svg, path, data, parser, encoder, transformer, reader, writer, stream, typescript |

## Links

- npm: https://www.npmjs.com/package/svg-pathdata
- Repository: https://github.com/nfroidure/svg-pathdata
- Homepage: https://github.com/nfroidure/svg-pathdata#readme
- Issues: https://github.com/nfroidure/SVGPathData/issues
- Funding: https://github.com/sponsors/nfroidure
- npm.io page: https://npm.io/package/svg-pathdata

## Alternatives

- [base64url](https://npm.io/package/base64url.md) — 6.1M weekly downloads
- [get-installed-path](https://npm.io/package/get-installed-path.md) — 502.9K weekly downloads
- [@uppy/url](https://npm.io/package/@uppy/url.md) — 185.8K weekly downloads
- [@d3fc/d3fc-shape](https://npm.io/package/@d3fc/d3fc-shape.md) — 16.2K weekly downloads
- [localizer](https://npm.io/package/localizer.md) — 226 weekly downloads

## Recent versions

- 9.0.0 (latest) — 2026-03-27
- 8.0.0 — 2025-06-16
- 7.2.0 — 2025-03-15
- 7.1.0 — 2024-08-30
- 7.0.1 — 2024-08-27
- 7.0.0 — 2024-07-29
- 6.0.3 — 2021-09-18
- 6.0.2 — 2021-09-17
- 6.0.1 — 2021-09-12
- 6.0.0 — 2021-04-02
- 5.0.5 — 2020-06-06
- 5.0.4 — 2020-02-20
- 5.0.3 — 2020-02-04
- 5.0.2 — 2018-06-05
- 5.0.1 — 2018-06-03
- … 25 more at https://npm.io/package/svg-pathdata/versions

## README

[//]: # ( )
[//]: # (This file is automatically generated by a `metapak`)
[//]: # (module. Do not change it  except between the)
[//]: # (`content:start/end` flags, your changes would)
[//]: # (be overridden.)
[//]: # ( )
# svg-pathdata
> Manipulate SVG path data (path[d] attribute content) simply and efficiently.

[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/nfroidure/svg-pathdata/blob/main/LICENSE)
[![Coverage Status](https://coveralls.io/repos/github/nfroidure/svg-pathdata/badge.svg?branch=main)](https://coveralls.io/github/nfroidure/svg-pathdata?branch=main)


[//]: # (::contents:start)

## Usage

Install the module:

```sh
npm install --save svg-pathdata
```

Then in your JavaScript files:

```js
import {
  SVGPathData,
  SVGPathDataTransformer,
  SVGPathDataEncoder,
  SVGPathDataParser,
} from 'svg-pathdata';
```

## Reading PathData

```js
const pathData = new SVGPathData(`
  M 10 10
  H 60
  V 60
  L 10 60
  Z`);

console.log(pathData.commands);

// [  {type: SVGPathData.MOVE_TO,       relative: false,  x: 10,  y: 10},
//    {type: SVGPathData.HORIZ_LINE_TO, relative: false,  x: 60},
//    {type: SVGPathData.VERT_LINE_TO,  relative: false,          y: 60},
//    {type: SVGPathData.LINE_TO,       relative: false,  x: 10,  y: 60},
//    {type: SVGPathData.CLOSE_PATH}]
```

## Reading PathData in chunks

```js
const parser = new SVGPathDataParser();

parser.parse('   '); // returns []
parser.parse('M 10'); // returns []
parser.parse(' 10'); // returns [{type: SVGPathData.MOVE_TO, relative: false, x: 10, y: 10 }]

parser.write('H 60'); // returns [{type: SVGPathData.HORIZ_LINE_TO, relative: false, x: 60 }]

parser.write('V'); // returns []
parser.write('60'); // returns [{type: SVGPathData.VERT_LINE_TO, relative: false, y: 60 }]

parser.write('L 10 60 \n  Z');
// returns [
//   {type: SVGPathData.LINE_TO, relative: false, x: 10, y: 60 },
//   {type: SVGPathData.CLOSE_PATH }]

parser.finish(); // tell parser there is no more data: will throw if there are unfinished commands.
```

## Outputting PathData

```js
const pathData = new SVGPathData(`
  M 10 10
  H 60
  V 60
  L 10 60
  Z`);
// returns "M10 10H60V60L10 60Z"

encodeSVGPath({ type: SVGPathData.MOVE_TO, relative: false, x: 10, y: 10 });
// returns "M10 10"

encodeSVGPath({ type: SVGPathData.HORIZ_LINE_TO, relative: false, x: 60 });
// returns "H60"

encodeSVGPath([
  { type: SVGPathData.VERT_LINE_TO, relative: false, y: 60 },
  { type: SVGPathData.LINE_TO, relative: false, x: 10, y: 60 },
  { type: SVGPathData.CLOSE_PATH },
]);
// returns "V60L10 60Z"
```

## Transforming PathData

This library can perform transformations on SVG paths. Here is
[an example of that kind of use](https://github.com/nfroidure/svgicons2svgfont/blob/aa6df0211419e9d61c417c63bcc353f0cb2ea0c8/src/index.js#L192).

### Transforming entire paths

```js
new SVGPathData(`
   m 10,10
   h 60
   v 60
   l 10,60
   z`)
  .toAbs()
  .encode();
// return s"M10,10 H70 V70 L80,130 Z"
```

### Transforming partial data

Here, we take SVGPathData from stdin and output it transformed to stdout.

```js
const transformingParser = new SVGPathDataParser().toAbs().scale(2, 2);
transformingParser.parse('m 0 0'); // returns [{ type: SVGPathData.MOVE_TO,       relative: false, x: 0, y: 0 }]
transformingParser.parse('l 2 3'); // returns [{ type: SVGPathData.LINE_TO,       relative: false, x: 4, y: 6 }]
```

## Supported transformations

You can find all supported transformations in
[src/SVGPathDataTransformer.ts](https://github.com/nfroidure/SVGPathData/blob/master/src/SVGPathDataTransformer.ts#L47).
Additionally, you can create your own by writing a function with the following
signature:

```js
type TransformFunction = (command: SVGCommand) => SVGCommand | SVGCommand[];

function SET_X_TO(xValue = 10) {
  return function(command) {
    command.x = xValue; // transform command objects and return them
    return command;
  };
};

// Synchronous usage
new SVGPathData('...')
  .transform(SET_X_TO(25))
  .encode();

// Chunk usage
new SVGPathDataParser().transform(SET_X_TO(25));
```

## Contributing

Clone this project, run:

```sh
npm install; npm test
```

[//]: # (::contents:end)

# API
## Functions

<dl>
<dt><a href="#annotateArcCommand">annotateArcCommand()</a></dt>
<dd><p><a href="https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes">https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes</a>
Fixes rX and rY.
Ensures lArcFlag and sweepFlag are 0 or 1
Adds center coordinates: command.cX, command.cY (relative or absolute, depending on command.relative)
Adds start and end arc parameters (in degrees): command.phi1, command.phi2; phi1 &lt; phi2 iff. c.sweepFlag == true</p>
</dd>
<dt><a href="#intersectionUnitCircleLine">intersectionUnitCircleLine()</a></dt>
<dd><p>Solves a quadratic system of equations of the form
     a * x + b * y = c
     x² + y² = 1
This can be understood as the intersection of the unit circle with a line.
     =&gt; y = (c - a x) / b
     =&gt; x² + (c - a x)² / b² = 1
     =&gt; x² b² + c² - 2 c a x + a² x² = b²
     =&gt; (a² + b²) x² - 2 a c x + (c² - b²) = 0</p>
</dd>
<dt><a href="#arePointsCollinear">arePointsCollinear(p1, p2, p3)</a> ⇒</dt>
<dd><p>Determines if three points are collinear (lie on the same straight line)
and the middle point is on the line segment between the first and third points</p>
</dd>
<dt><a href="#createEllipse">createEllipse()</a></dt>
<dd><p>Creates an ellipse path centered at (cx,cy) with radii rx and ry</p>
</dd>
<dt><a href="#createRect">createRect()</a></dt>
<dd><p>Creates a rectangle path with optional rounded corners</p>
</dd>
<dt><a href="#createPolyline">createPolyline()</a></dt>
<dd><p>Creates a polyline from an array of coordinates [x1,y1,x2,y2,...]</p>
</dd>
<dt><a href="#createPolygon">createPolygon()</a></dt>
<dd><p>Creates a closed polygon from an array of coordinates</p>
</dd>
<dt><a href="#REMOVE_COLLINEAR">REMOVE_COLLINEAR(commands)</a> ⇒</dt>
<dd><p>Process a path and remove collinear points</p>
</dd>
<dt><a href="#REVERSE_PATH">REVERSE_PATH(commands, preserveSubpathOrder)</a> ⇒</dt>
<dd><p>Reverses the order of path commands to go from end to start
IMPORTANT: This function expects absolute commands as input.
It doesn&#39;t convert relative to absolute - use SVGPathDataTransformer.TO_ABS() first if needed.</p>
</dd>
</dl>

<a name="annotateArcCommand"></a>

## annotateArcCommand()
https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
Fixes rX and rY.
Ensures lArcFlag and sweepFlag are 0 or 1
Adds center coordinates: command.cX, command.cY (relative or absolute, depending on command.relative)
Adds start and end arc parameters (in degrees): command.phi1, command.phi2; phi1 < phi2 iff. c.sweepFlag == true

**Kind**: global function  
<a name="intersectionUnitCircleLine"></a>

## intersectionUnitCircleLine()
Solves a quadratic system of equations of the form
     a * x + b * y = c
     x² + y² = 1
This can be understood as the intersection of the unit circle with a line.
     => y = (c - a x) / b
     => x² + (c - a x)² / b² = 1
     => x² b² + c² - 2 c a x + a² x² = b²
     => (a² + b²) x² - 2 a c x + (c² - b²) = 0

**Kind**: global function  
<a name="arePointsCollinear"></a>

## arePointsCollinear(p1, p2, p3) ⇒
Determines if three points are collinear (lie on the same straight line)
and the middle point is on the line segment between the first and third points

**Kind**: global function  
**Returns**: true if the points are collinear and p2 is on the segment p1-p3  

| Param | Description |
| --- | --- |
| p1 | First point [x, y] |
| p2 | Middle point that might be removed |
| p3 | Last point [x, y] |

<a name="createEllipse"></a>

## createEllipse()
Creates an ellipse path centered at (cx,cy) with radii rx and ry

**Kind**: global function  
<a name="createRect"></a>

## createRect()
Creates a rectangle path with optional rounded corners

**Kind**: global function  
<a name="createPolyline"></a>

## createPolyline()
Creates a polyline from an array of coordinates [x1,y1,x2,y2,...]

**Kind**: global function  
<a name="createPolygon"></a>

## createPolygon()
Creates a closed polygon from an array of coordinates

**Kind**: global function  
<a name="REMOVE_COLLINEAR"></a>

## REMOVE\_COLLINEAR(commands) ⇒
Process a path and remove collinear points

**Kind**: global function  
**Returns**: New array with collinear points removed  

| Param | Description |
| --- | --- |
| commands | Array of SVG path commands to process (must be absolute) |

<a name="REVERSE_PATH"></a>

## REVERSE\_PATH(commands, preserveSubpathOrder) ⇒
Reverses the order of path commands to go from end to start
IMPORTANT: This function expects absolute commands as input.
It doesn't convert relative to absolute - use SVGPathDataTransformer.TO_ABS() first if needed.

**Kind**: global function  
**Returns**: New SVG commands in reverse order with absolute coordinates  

| Param | Description |
| --- | --- |
| commands | SVG path commands in absolute form to reverse |
| preserveSubpathOrder | If true, keeps subpaths in their original order |


# Authors
- [Nicolas Froidure](https://insertafter.com/en/index.html)
- [Anders Kaseorg](mailto:andersk@mit.edu)

# License
[MIT](https://github.com/nfroidure/svg-pathdata/blob/main/LICENSE)

---
_Source: https://npm.io/package/svg-pathdata · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
