{"id":15570245,"url":"https://github.com/nfroidure/svg-pathdata","last_synced_at":"2025-10-19T20:06:04.675Z","repository":{"id":11583630,"uuid":"14073538","full_name":"nfroidure/svg-pathdata","owner":"nfroidure","description":"Parse SVG PathDatas","archived":false,"fork":false,"pushed_at":"2025-03-27T09:13:13.000Z","size":1110,"stargazers_count":193,"open_issues_count":8,"forks_count":19,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-03-30T19:36:46.460Z","etag":null,"topics":["javascript","svg","svg-path"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nfroidure.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["nfroidure"]}},"created_at":"2013-11-02T19:35:50.000Z","updated_at":"2025-03-27T11:35:54.000Z","dependencies_parsed_at":"2023-01-13T16:34:28.344Z","dependency_job_id":"67d79445-a5b7-429e-b7d7-7ca8ca25d698","html_url":"https://github.com/nfroidure/svg-pathdata","commit_stats":{"total_commits":198,"total_committers":12,"mean_commits":16.5,"dds":0.595959595959596,"last_synced_commit":"50ad245add4253b09e56852069dd240a338d0e78"},"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nfroidure%2Fsvg-pathdata","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nfroidure%2Fsvg-pathdata/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nfroidure%2Fsvg-pathdata/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nfroidure%2Fsvg-pathdata/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nfroidure","download_url":"https://codeload.github.com/nfroidure/svg-pathdata/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247399871,"owners_count":20932876,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","svg","svg-path"],"created_at":"2024-10-02T17:41:46.232Z","updated_at":"2025-10-19T20:06:04.650Z","avatar_url":"https://github.com/nfroidure.png","language":"TypeScript","readme":"[//]: # ( )\n[//]: # (This file is automatically generated by a `metapak`)\n[//]: # (module. Do not change it  except between the)\n[//]: # (`content:start/end` flags, your changes would)\n[//]: # (be overridden.)\n[//]: # ( )\n# svg-pathdata\n\u003e Manipulate SVG path data (path[d] attribute content) simply and efficiently.\n\n[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/nfroidure/svg-pathdata/blob/main/LICENSE)\n[![Coverage Status](https://coveralls.io/repos/github/nfroidure/svg-pathdata/badge.svg?branch=main)](https://coveralls.io/github/nfroidure/svg-pathdata?branch=main)\n\n\n[//]: # (::contents:start)\n\n## Usage\n\nInstall the module:\n\n```sh\nnpm install --save svg-pathdata\n```\n\nThen in your JavaScript files:\n\n```js\nimport {\n  SVGPathData,\n  SVGPathDataTransformer,\n  SVGPathDataEncoder,\n  SVGPathDataParser,\n} from 'svg-pathdata';\n```\n\n## Reading PathData\n\n```js\nconst pathData = new SVGPathData(`\n  M 10 10\n  H 60\n  V 60\n  L 10 60\n  Z`);\n\nconsole.log(pathData.commands);\n\n// [  {type: SVGPathData.MOVE_TO,       relative: false,  x: 10,  y: 10},\n//    {type: SVGPathData.HORIZ_LINE_TO, relative: false,  x: 60},\n//    {type: SVGPathData.VERT_LINE_TO,  relative: false,          y: 60},\n//    {type: SVGPathData.LINE_TO,       relative: false,  x: 10,  y: 60},\n//    {type: SVGPathData.CLOSE_PATH}]\n```\n\n## Reading PathData in chunks\n\n```js\nconst parser = new SVGPathDataParser();\n\nparser.parse('   '); // returns []\nparser.parse('M 10'); // returns []\nparser.parse(' 10'); // returns [{type: SVGPathData.MOVE_TO, relative: false, x: 10, y: 10 }]\n\nparser.write('H 60'); // returns [{type: SVGPathData.HORIZ_LINE_TO, relative: false, x: 60 }]\n\nparser.write('V'); // returns []\nparser.write('60'); // returns [{type: SVGPathData.VERT_LINE_TO, relative: false, y: 60 }]\n\nparser.write('L 10 60 \\n  Z');\n// returns [\n//   {type: SVGPathData.LINE_TO, relative: false, x: 10, y: 60 },\n//   {type: SVGPathData.CLOSE_PATH }]\n\nparser.finish(); // tell parser there is no more data: will throw if there are unfinished commands.\n```\n\n## Outputting PathData\n\n```js\nconst pathData = new SVGPathData(`\n  M 10 10\n  H 60\n  V 60\n  L 10 60\n  Z`);\n// returns \"M10 10H60V60L10 60Z\"\n\nencodeSVGPath({ type: SVGPathData.MOVE_TO, relative: false, x: 10, y: 10 });\n// returns \"M10 10\"\n\nencodeSVGPath({ type: SVGPathData.HORIZ_LINE_TO, relative: false, x: 60 });\n// returns \"H60\"\n\nencodeSVGPath([\n  { type: SVGPathData.VERT_LINE_TO, relative: false, y: 60 },\n  { type: SVGPathData.LINE_TO, relative: false, x: 10, y: 60 },\n  { type: SVGPathData.CLOSE_PATH },\n]);\n// returns \"V60L10 60Z\"\n```\n\n## Transforming PathData\n\nThis library can perform transformations on SVG paths. Here is\n[an example of that kind of use](https://github.com/nfroidure/svgicons2svgfont/blob/aa6df0211419e9d61c417c63bcc353f0cb2ea0c8/src/index.js#L192).\n\n### Transforming entire paths\n\n```js\nnew SVGPathData(`\n   m 10,10\n   h 60\n   v 60\n   l 10,60\n   z`)\n  .toAbs()\n  .encode();\n// return s\"M10,10 H70 V70 L80,130 Z\"\n```\n\n### Transforming partial data\n\nHere, we take SVGPathData from stdin and output it transformed to stdout.\n\n```js\nconst transformingParser = new SVGPathDataParser().toAbs().scale(2, 2);\ntransformingParser.parse('m 0 0'); // returns [{ type: SVGPathData.MOVE_TO,       relative: false, x: 0, y: 0 }]\ntransformingParser.parse('l 2 3'); // returns [{ type: SVGPathData.LINE_TO,       relative: false, x: 4, y: 6 }]\n```\n\n## Supported transformations\n\nYou can find all supported transformations in\n[src/SVGPathDataTransformer.ts](https://github.com/nfroidure/SVGPathData/blob/master/src/SVGPathDataTransformer.ts#L47).\nAdditionally, you can create your own by writing a function with the following\nsignature:\n\n```js\ntype TransformFunction = (command: SVGCommand) =\u003e SVGCommand | SVGCommand[];\n\nfunction SET_X_TO(xValue = 10) {\n  return function(command) {\n    command.x = xValue; // transform command objects and return them\n    return command;\n  };\n};\n\n// Synchronous usage\nnew SVGPathData('...')\n  .transform(SET_X_TO(25))\n  .encode();\n\n// Chunk usage\nnew SVGPathDataParser().transform(SET_X_TO(25));\n```\n\n## Contributing\n\nClone this project, run:\n\n```sh\nnpm install; npm test\n```\n\n[//]: # (::contents:end)\n\n# API\n## Functions\n\n\u003cdl\u003e\n\u003cdt\u003e\u003ca href=\"#annotateArcCommand\"\u003eannotateArcCommand()\u003c/a\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003e\u003ca href=\"https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes\"\u003ehttps://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes\u003c/a\u003e\nFixes rX and rY.\nEnsures lArcFlag and sweepFlag are 0 or 1\nAdds center coordinates: command.cX, command.cY (relative or absolute, depending on command.relative)\nAdds start and end arc parameters (in degrees): command.phi1, command.phi2; phi1 \u0026lt; phi2 iff. c.sweepFlag == true\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#intersectionUnitCircleLine\"\u003eintersectionUnitCircleLine()\u003c/a\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eSolves a quadratic system of equations of the form\n     a * x + b * y = c\n     x² + y² = 1\nThis can be understood as the intersection of the unit circle with a line.\n     =\u0026gt; y = (c - a x) / b\n     =\u0026gt; x² + (c - a x)² / b² = 1\n     =\u0026gt; x² b² + c² - 2 c a x + a² x² = b²\n     =\u0026gt; (a² + b²) x² - 2 a c x + (c² - b²) = 0\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#arePointsCollinear\"\u003earePointsCollinear(p1, p2, p3)\u003c/a\u003e ⇒\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eDetermines if three points are collinear (lie on the same straight line)\nand the middle point is on the line segment between the first and third points\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#createEllipse\"\u003ecreateEllipse()\u003c/a\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eCreates an ellipse path centered at (cx,cy) with radii rx and ry\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#createRect\"\u003ecreateRect()\u003c/a\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eCreates a rectangle path with optional rounded corners\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#createPolyline\"\u003ecreatePolyline()\u003c/a\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eCreates a polyline from an array of coordinates [x1,y1,x2,y2,...]\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#createPolygon\"\u003ecreatePolygon()\u003c/a\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eCreates a closed polygon from an array of coordinates\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#REMOVE_COLLINEAR\"\u003eREMOVE_COLLINEAR(commands)\u003c/a\u003e ⇒\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eProcess a path and remove collinear points\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#REVERSE_PATH\"\u003eREVERSE_PATH(commands, preserveSubpathOrder)\u003c/a\u003e ⇒\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eReverses the order of path commands to go from end to start\nIMPORTANT: This function expects absolute commands as input.\nIt doesn\u0026#39;t convert relative to absolute - use SVGPathDataTransformer.TO_ABS() first if needed.\u003c/p\u003e\n\u003c/dd\u003e\n\u003c/dl\u003e\n\n\u003ca name=\"annotateArcCommand\"\u003e\u003c/a\u003e\n\n## annotateArcCommand()\nhttps://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes\nFixes rX and rY.\nEnsures lArcFlag and sweepFlag are 0 or 1\nAdds center coordinates: command.cX, command.cY (relative or absolute, depending on command.relative)\nAdds start and end arc parameters (in degrees): command.phi1, command.phi2; phi1 \u003c phi2 iff. c.sweepFlag == true\n\n**Kind**: global function  \n\u003ca name=\"intersectionUnitCircleLine\"\u003e\u003c/a\u003e\n\n## intersectionUnitCircleLine()\nSolves a quadratic system of equations of the form\n     a * x + b * y = c\n     x² + y² = 1\nThis can be understood as the intersection of the unit circle with a line.\n     =\u003e y = (c - a x) / b\n     =\u003e x² + (c - a x)² / b² = 1\n     =\u003e x² b² + c² - 2 c a x + a² x² = b²\n     =\u003e (a² + b²) x² - 2 a c x + (c² - b²) = 0\n\n**Kind**: global function  \n\u003ca name=\"arePointsCollinear\"\u003e\u003c/a\u003e\n\n## arePointsCollinear(p1, p2, p3) ⇒\nDetermines if three points are collinear (lie on the same straight line)\nand the middle point is on the line segment between the first and third points\n\n**Kind**: global function  \n**Returns**: true if the points are collinear and p2 is on the segment p1-p3  \n\n| Param | Description |\n| --- | --- |\n| p1 | First point [x, y] |\n| p2 | Middle point that might be removed |\n| p3 | Last point [x, y] |\n\n\u003ca name=\"createEllipse\"\u003e\u003c/a\u003e\n\n## createEllipse()\nCreates an ellipse path centered at (cx,cy) with radii rx and ry\n\n**Kind**: global function  \n\u003ca name=\"createRect\"\u003e\u003c/a\u003e\n\n## createRect()\nCreates a rectangle path with optional rounded corners\n\n**Kind**: global function  \n\u003ca name=\"createPolyline\"\u003e\u003c/a\u003e\n\n## createPolyline()\nCreates a polyline from an array of coordinates [x1,y1,x2,y2,...]\n\n**Kind**: global function  \n\u003ca name=\"createPolygon\"\u003e\u003c/a\u003e\n\n## createPolygon()\nCreates a closed polygon from an array of coordinates\n\n**Kind**: global function  \n\u003ca name=\"REMOVE_COLLINEAR\"\u003e\u003c/a\u003e\n\n## REMOVE\\_COLLINEAR(commands) ⇒\nProcess a path and remove collinear points\n\n**Kind**: global function  \n**Returns**: New array with collinear points removed  \n\n| Param | Description |\n| --- | --- |\n| commands | Array of SVG path commands to process (must be absolute) |\n\n\u003ca name=\"REVERSE_PATH\"\u003e\u003c/a\u003e\n\n## REVERSE\\_PATH(commands, preserveSubpathOrder) ⇒\nReverses the order of path commands to go from end to start\nIMPORTANT: This function expects absolute commands as input.\nIt doesn't convert relative to absolute - use SVGPathDataTransformer.TO_ABS() first if needed.\n\n**Kind**: global function  \n**Returns**: New SVG commands in reverse order with absolute coordinates  \n\n| Param | Description |\n| --- | --- |\n| commands | SVG path commands in absolute form to reverse |\n| preserveSubpathOrder | If true, keeps subpaths in their original order |\n\n\n# Authors\n- [Nicolas Froidure](https://insertafter.com/en/index.html)\n- [Anders Kaseorg](mailto:andersk@mit.edu)\n\n# License\n[MIT](https://github.com/nfroidure/svg-pathdata/blob/main/LICENSE)\n","funding_links":["https://github.com/sponsors/nfroidure"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnfroidure%2Fsvg-pathdata","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnfroidure%2Fsvg-pathdata","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnfroidure%2Fsvg-pathdata/lists"}