{"id":13580643,"url":"https://github.com/thednp/svg-path-commander","last_synced_at":"2026-04-06T09:03:07.021Z","repository":{"id":37413575,"uuid":"286703146","full_name":"thednp/svg-path-commander","owner":"thednp","description":"🛹 Typescript tools for advanced processing of SVG path data.","archived":false,"fork":false,"pushed_at":"2026-04-06T07:51:46.000Z","size":4374,"stargazers_count":289,"open_issues_count":1,"forks_count":25,"subscribers_count":6,"default_branch":"master","last_synced_at":"2026-04-06T08:44:18.276Z","etag":null,"topics":["absolute-values","convert-to-path","javascript","normalize-path","optimize-path","path-reverse","path-segments","relative-values","shape-draw-direction","shorthand-commands","svg","transform-functions","typescript","typescript-library"],"latest_commit_sha":null,"homepage":"https://thednp.github.io/svg-path-commander/","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/thednp.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":["thednp"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":null,"thanks_dev":null,"custom":null}},"created_at":"2020-08-11T09:32:47.000Z","updated_at":"2026-04-06T07:48:23.000Z","dependencies_parsed_at":"2024-04-21T21:04:43.021Z","dependency_job_id":"5f555cad-b521-4ff3-8452-710509f57aed","html_url":"https://github.com/thednp/svg-path-commander","commit_stats":{"total_commits":204,"total_committers":10,"mean_commits":20.4,"dds":0.5098039215686274,"last_synced_commit":"b130accc5c1d244043ab25284069a75073219cfe"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/thednp/svg-path-commander","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thednp%2Fsvg-path-commander","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thednp%2Fsvg-path-commander/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thednp%2Fsvg-path-commander/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thednp%2Fsvg-path-commander/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thednp","download_url":"https://codeload.github.com/thednp/svg-path-commander/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thednp%2Fsvg-path-commander/sbom","scorecard":{"id":878375,"data":{"date":"2025-08-11","repo":{"name":"github.com/thednp/svg-path-commander","commit":"06796fa5fc9faf4be349978dadc2d2e904f1ba51"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"1 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":2,"reason":"Found 4/19 approved changesets -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql.yml:34","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql.yml:35","Warn: no topLevel permission defined: .github/workflows/badges.yml:1","Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/codeql.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/badges.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/thednp/svg-path-commander/badges.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/badges.yml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/thednp/svg-path-commander/badges.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/thednp/svg-path-commander/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:32: update your workflow using https://app.stepsecurity.io/secureworkflow/thednp/svg-path-commander/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/thednp/svg-path-commander/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:40: update your workflow using https://app.stepsecurity.io/secureworkflow/thednp/svg-path-commander/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:61: update your workflow using https://app.stepsecurity.io/secureworkflow/thednp/svg-path-commander/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/thednp/svg-path-commander/codeql.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:51: update your workflow using https://app.stepsecurity.io/secureworkflow/thednp/svg-path-commander/codeql.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:64: update your workflow using https://app.stepsecurity.io/secureworkflow/thednp/svg-path-commander/codeql.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:77: update your workflow using https://app.stepsecurity.io/secureworkflow/thednp/svg-path-commander/codeql.yml/master?enable=pin","Info:   0 out of   7 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   4 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":7,"reason":"SAST tool detected but not run on all commits","details":["Info: SAST configuration detected: CodeQL","Warn: 0 commits out of 15 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-24T06:59:18.320Z","repository_id":37413575,"created_at":"2025-08-24T06:59:18.320Z","updated_at":"2025-08-24T06:59:18.320Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31466228,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-06T08:36:52.050Z","status":"ssl_error","status_checked_at":"2026-04-06T08:36:51.267Z","response_time":112,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["absolute-values","convert-to-path","javascript","normalize-path","optimize-path","path-reverse","path-segments","relative-values","shape-draw-direction","shorthand-commands","svg","transform-functions","typescript","typescript-library"],"created_at":"2024-08-01T15:01:53.898Z","updated_at":"2026-04-06T09:03:07.015Z","avatar_url":"https://github.com/thednp.png","language":"TypeScript","funding_links":["https://github.com/sponsors/thednp"],"categories":["TypeScript"],"sub_categories":[],"readme":"# SVGPathCommander\r\n\r\n[![Coverage Status](https://coveralls.io/repos/github/thednp/svg-path-commander/badge.svg)](https://coveralls.io/github/thednp/svg-path-commander)\r\n[![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)\r\n[![NPM Version](https://img.shields.io/npm/v/svg-path-commander.svg)](https://www.npmjs.com/package/svg-path-commander)\r\n[![NPM Downloads](https://img.shields.io/npm/dm/svg-path-commander.svg)](http://npm-stat.com/charts.html?svg-path-commander)\r\n[![jsDeliver](https://img.shields.io/jsdelivr/npm/hw/svg-path-commander)](https://www.jsdelivr.com/package/npm/svg-path-commander)\r\n\r\n\r\n![image](./docs/assets/SVGPathCommander.svg)\r\n\r\nA 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 `\u003ccircle\u003e` or `\u003crect\u003e` to `\u003cpath\u003e`.\r\n\r\n\r\nWhile you may find familiar tools inside, this library brings ***new additions***:\r\n* 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;\r\n* thanks to the community contributions we've implemented useful tools like `getPropertiesAtLength`, `getSegmentOfPoint` or `isPointInStroke`;\r\n* a tool that can *reverse path draw direction* without altering path commands, even with specific shorthand path commands;\r\n* a unique tool that can *reverse path draw direction* for path strings with only 'C' path commands;\r\n* a new and unique tool to *apply transform functions to path commands* via the modern *DOMMatrix* API.\r\n\r\n**The key differences with other libraries**:\r\n* Typescript sourced with modernized codebase, all inherited codebase has been modernized as well;\r\n* along with the modern codebase, the library also comes with strong TypeScript definitions;\r\n* this library can create 3D to 2D projections, making your SVGs look like 3D but in the SVG coordinate system;\r\n* you can use this library in both web apps and Node.js, you are not restricted to a single environment;\r\n* path command transformations are all consistent with the SVG coordinates system, where others compute transform origin only for rotation transformation.\r\n\r\n**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).\r\nThere are a couple of good reasons for this implementation:\r\n* *WebKitCSSMatrix* and *SVGMatrix* APIs are slowly pushed away by DOMMatrix, the green light for new and modern implementations;\r\n* 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;\r\n* when most tools available will be rendered absolete, we are ready for new challenges.\r\n\r\nThis library is available on [CDN](https://www.jsdelivr.com/package/npm/svg-path-commander) and [npm](https://www.npmjs.com/package/svg-path-commander). \r\n\r\n\r\n# Install\r\n\r\n```\r\nnpm install svg-path-commander\r\n# or pnpm/bun/deno add svg-path-commander\r\n```\r\n\r\n\r\n# CDN\r\nVersion 2.2.0+\r\n```html\r\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/svg-path-commander/dist/index.min.js\"\u003e\r\n```\r\n\r\nVersions before 2.2.0\r\n```html\r\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/svg-path-commander/dist/svg-path-commander.js\"\u003e\r\n```\r\n\r\n# Quick Guide\r\n\r\nFlip a path on the X axis:\r\n```js\r\nimport SVGPathCommander from 'svg-path-commander';\r\n\r\nconst path = 'M0 0L100 0L50 100';\r\n\r\nconst flippedPathString = new SVGPathCommander(path).flipX().toString();\r\n// result =\u003e 'M0 100h100L50 0'\r\n```\r\n\r\nOptimize a path string by using the `round` option, to round numbers to 2 decimals and finding shorthand where possible:\r\n```js\r\nconst optimizedPathString = new SVGPathCommander(path, {round: 2}).optimize().toString();\r\n```\r\n\r\nOr why not apply a **2D transformation** and even a **3D transformation**:\r\n```js\r\n// a transform object\r\nconst transform = {\r\n  translate: 15, // X axis translation\r\n  rotate: 15, // Z axis rotation\r\n  scale: 0.75, // uniform scale on X, Y, Z axis\r\n  skew: 15, // skew 15deg on the X axis\r\n  origin: [15, 0] // if not specified, it will use the default origin value [0, 0]\r\n}\r\nconst transformed2DPathString = new SVGPathCommander(path).transform(transform).toString();\r\n\r\n// apply a 3D transformation\r\nconst transform = {\r\n  translate: [15, 15, 15], // `[15, 15]` would apply a 2D translation, and only `15` for X axis translation\r\n  rotate: [15, 15, 15], // or only \"15\" for 2D rotation on Z axis\r\n  scale: [0.7, 0.75, 0.8], // or only \"0.7\" for 2D scale on all X, Y, Z axis\r\n  skew: [15, 15], // or only \"15\" for the X axis\r\n  origin: [15, 15, 15] // full `transform-origin` for a typical 3D transformation\r\n}\r\nconst transformed3DPathString = new SVGPathCommander(path).transform(transform).toString();\r\n```\r\n\r\nAccess the `bbox` instance property to apply a consistent `transform-origin`:\r\n```js\r\n// apply a 3D transformation with a consistent origin\r\nconst transformed3DPath = new SVGPathCommander(path);\r\nconst { cx, cy, cz } = transformed3DPath.bbox;\r\nconst transform = {\r\n  translate: [15, 15, 15], // `[15, 15]` would apply a 2D translation, and only `15` for X axis translation\r\n  rotate: [15, 15, 15], // or only \"15\" for 2D rotation on Z axis\r\n  scale: [0.7, 0.75, 0.8], // or only \"0.7\" for 2D scale on all X, Y, Z axis\r\n  skew: [15, 15], // or only \"15\" for the X axis\r\n  origin: [cx, cy, cz] // the origin\r\n}\r\nconst transformed3DPathString = transformed3DPath.transform(transform).toString();\r\n```\r\n\r\nSVGPathCommander comes with a full range of additional static methods, here's how to normalize a path:\r\n```js\r\nconst path = 'M0 0 H50';\r\n\r\nconst normalizedPath = SVGPathCommander.normalizePath(path);\r\n// result =\u003e [['M', 0, 0], ['L', 50, 0]]\r\n```\r\n\r\nReverse a path:\r\n```js\r\nconst path = SVGPathCommander.parsePathString('M0 0 H50');\r\n\r\nconst reversedPath = SVGPathCommander.reversePath(path);\r\n// result =\u003e [['M', 50, 0], ['H', 0]]\r\n```\r\n\r\nExport to string:\r\n```js\r\nconst myPathString = SVGPathCommander.pathToString([['M', 0, 0], ['L', 50, 0]]);\r\n// result =\u003e 'M0 0 L50 0'\r\n```\r\n\r\nCheck a path string validity:\r\n```js\r\nSVGPathCommander.isValidPath(path);\r\n// result =\u003e boolean\r\n```\r\n\r\nCheck if path is a certain kind of `PathArray`:\r\n```js\r\nSVGPathCommander.isAbsoluteArray([['M', 0, 0], ['L', 50, 0]]);\r\n// result =\u003e true\r\n```\r\n\r\nUse treeshake and create a custom function to apply a 3D transformation using static methods:\r\n```ts\r\nimport { parsePathString, getPathBBox, transformPath, pathToString } from 'svg-path-commander';\r\n\r\nfunction myTransformFn(pathInput: string | PathArray, transformObject: TransformObject) {\r\n  const path = parsePathString(pathInput);\r\n  const { cx, cy, cz } = getPathBBox(path);\r\n\r\n  return pathToString(\r\n    transformPath(path, {\r\n      ...transformObject, origin: [cx, cy, cz]\r\n    })\r\n  )\r\n}\r\n```\r\nIn 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.\r\n\r\n```ts\r\n// const svgViewBox = document.getElementById('my-svg').getAttribute('viewBox');\r\nconst viewBox = '0 0 24 24';\r\n\r\nconst [x, y, width, height] = viewBox.split(/\\s/).map(Number);\r\nconst origin = [\r\n  x + width / 2, // CX\r\n  y + height / 2, // CY\r\n  Math.max(width, height) + Math.min(width, height) / 2, // CZ\r\n];\r\n\r\n// use this origin for your shape transformation\r\nconst myNewString = new SVGPathCommander('M0 0 H50')\r\n  .transform({ rotate: [35, 0, 0], origin })\r\n  .toString();\r\n```\r\n\r\n\r\nConvert a shape to `\u003cpath\u003e` and transfer all non-specific attributes\r\n```js\r\nconst myCircle = document.getElementById('myCircle');\r\nSVGPathCommander.shapeToPath(myCircle, true);\r\n```\r\n\r\nAlternatively you can create `\u003cpath\u003e` from specific attributes:\r\n```js\r\nconst myRectAttr = {\r\n  type: 'rect',\r\n  x: 25,\r\n  y: 25,\r\n  width: 50,\r\n  height: 50,\r\n  rx: 5\r\n};\r\n\r\nconst myRectPath = SVGPathCommander.shapeToPath(myRectAttr);\r\ndocument.getElementById('mySVG').append(myRectPath);\r\n```\r\nServer-side using `jsdom`:\r\n```js\r\nconst { document } = new JSDOM(\r\n  `\u003chtml\u003e\r\n  \u003chead\u003e\u003c/head\u003e\r\n  \u003cbody\u003e\r\n    \u003csvg id=\"mySVG\" viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\"\u003e\r\n      \u003crect id=\"myRect\" x=\"0\" width=\"100\" height=\"100\" rx=\"15\" /\u003e\r\n    \u003c/svg\u003e\r\n  \u003c/body\u003e\r\n\u003c/html\u003e`,\r\n  {\r\n    pretendToBeVisual: true,\r\n  }\r\n).window;\r\n\r\nconst myRect = document.getElementById('myRect');\r\nSVGPathCommander.shapeToPath(myRect, true, document);\r\n```\r\n\r\nGet the path length:\r\n```js\r\nconst myPathLength = SVGPathCommander.getTotalLength('M0 0L50 0L25 50z');\r\n// result =\u003e 161.80339887498948\r\n```\r\n\r\nGet a point along the path:\r\n```js\r\nconst myPoint = SVGPathCommander.getPointAtLength('M0 0L50 0L25 50z', 85);\r\n// result =\u003e {x: 34.34752415750147, y: 31.304951684997057}\r\n```\r\n\r\nGet the path bounding box:\r\n```js\r\nconst myPathBBox = SVGPathCommander.getPathBBox('M0 0L50 0L25 50z');\r\n// result =\u003e {width: 50, height: 50, x: 0, y: 0, x2: 50, y2: 50, cx: 25, cy: 25, cz: 75}\r\n```\r\n\r\nFind intersection points between two paths:\r\n```js\r\nconst count = SVGPathCommander.pathsIntersection(\r\n  'M0 50C0 0,100 0,100 50',\r\n  'M50 0C100 0,100 100,50 100',\r\n  true\r\n);\r\n// result =\u003e 1\r\n\r\nconst points = SVGPathCommander.pathsIntersection(\r\n  'M0 50C0 0,100 0,100 50',\r\n  'M50 0C100 0,100 100,50 100',\r\n  false\r\n);\r\n// result =\u003e [{ x: 50, y: 25, t1: 0.5, t2: 0.5 }]\r\n```\r\n\r\nEqualize two paths for morphing (single subpath):\r\n```js\r\nconst [eq1, eq2] = SVGPathCommander.equalizeSegments(\r\n  'M0 0L100 0L50 100Z',\r\n  'M0 0L100 0L100 100L0 100Z'\r\n);\r\n// eq1.length === eq2.length — ready for morphing\r\n```\r\n\r\nEqualize two paths for morphing (single or multi subpath):\r\n```js\r\nconst [eq1, eq2] = SVGPathCommander.equalizePaths(\r\n  'M0 0L100 0L50 100Z',\r\n  'M0 0L100 0L100 100L0 100Z',\r\n  { close: true }\r\n);\r\n// Both paths now have the same number of segments\r\n```\r\n\r\n# WIKI\r\nFor developer guidelines, and a complete list of static methods, head over to the [wiki pages](https://github.com/thednp/svg-path-commander/wiki).\r\n\r\n\r\n# What Is It For?\r\n\r\n* 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);\r\n* animators that work with SVGs and need tools for performing specific path command processing;\r\n* front-end developers looking to spice up the content by combining, splitting or transforming paths;\r\n* font-icon creators can use it in both Node.js and web applications to process, optimize and test their creations.\r\n\r\n\r\n# Technical Considerations\r\n\r\n* 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;\r\n* 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 =\u003e 0.567, 0.50 =\u003e 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;\r\n* 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;\r\n* all 3d transformations as well as skews will convert `A` (arc) path commands to `C` (cubic bezier) due to the lack of resources;\r\n* most tools included with **SVGPathCommander** should work in your Node.js apps, but feel free to report any issue;\r\n* other path commands like `R` (catmulRomBezier), `O`, `U` (ellipse and shorthand ellipse) are not present in the current draft and are not supported;\r\n* 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;\r\n* 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.\r\n\r\n\r\n# Special Thanks\r\n\r\n* Dmitry Baranovskiy for his [Raphael.js](https://dmitrybaranovskiy.github.io/raphael/)\r\n* Vitaly Puzrin \u0026 Alex Kocharin for their [SvgPath](https://github.com/fontello/svgpath)\r\n* Jürg Lehni \u0026 Jonathan Puckey for their [Paper.js](https://github.com/paperjs/paper.js/)\r\n* Andrew Willems for his [awesome guide](https://stackoverflow.com/users/5218951/andrew-willems)\r\n* 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/)\r\n* Nicolas Debeissat for the inspiration on [svg3d](https://github.com/ndebeiss/svg3d)\r\n* Mike Bostock for his awesome [closestPoint](https://bl.ocks.org/mbostock/8027637)\r\n* James Halliday for his excelent [point-at-length](https://github.com/substack/point-at-length)\r\n* Eric Eastwood for his excelent [svg-curve-lib](https://github.com/MadLittleMods/svg-curve-lib)\r\n* PhET Interactive Simulations for their [kite](https://github.com/phetsims/kite)\r\n* [herrstrietzel](https://github.com/herrstrietzel) for his awesome [svg-pathdata-getbbox](https://github.com/herrstrietzel/svg-pathdata-getbbox)\r\n* a special thanks goes to [@vltansky](https://github.com/vltansky) for fixing tree-shaking in **SVGPathCommander**!\r\n\r\n# License\r\n**SVGPathCommander** is released under [MIT Licence](https://github.com/thednp/svg-path-commander/blob/master/LICENSE).\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthednp%2Fsvg-path-commander","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthednp%2Fsvg-path-commander","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthednp%2Fsvg-path-commander/lists"}