svg-round-corners
A tiny, dependency-free JavaScript library that rounds sharp corners in SVG path data into smooth arcs.
Repository Health
Technical Analysis
svg-round-corners is a small, dependency-free JavaScript library that transforms the sharp corners in an SVG path element’s d attribute into smooth rounded arcs. It parses raw path command strings built from straight-line commands (M, L, H, V, Z), normalizes them into absolute coordinates, and inserts elliptical arc (A) commands at each corner with a configurable radius.
The library exposes three functions: parsePath() to tokenize a path string into normalized commands, roundCommands() to insert arcs into an already-parsed command array, and roundCorners() as a convenience wrapper that combines both steps in one call. It ships bundled TypeScript type definitions and works in both ESM and CommonJS environments, making it easy to drop into design tools, chart libraries, or any codebase that generates SVG paths programmatically and needs friendlier, rounded corners without hand-authoring bezier curve math.
What You Get
- A parsePath() function that tokenizes and normalizes raw SVG path ‘d’ strings into an array of absolute-coordinate commands
- A roundCommands() function that inserts elliptical arc commands at each corner of an already-parsed command array
- A roundCorners() convenience function that combines parsing and rounding into a single call
- Bundled TypeScript type definitions (types.d.ts) for IDE autocomplete and type checking
- Dual module support — usable as an ES module (lib/index.js) or a CommonJS require (dist/svg-round-corners.js)
Common Use Cases
- Rounding the corners of programmatically generated chart bars, polygons, or icon shapes
- Softening hard-edged SVG illustrations exported from design tools before rendering in the browser
- Adding rounded corners to dynamically computed shapes in data visualization libraries
- Post-processing SVG paths generated by other geometry libraries to give them a friendlier, rounded look
Under The Hood
Architecture
The library is organized into two small modules: lib/index.js exposes the three public functions (parsePath, roundCommands, roundCorners) while lib/utils.js holds the geometry and command-manipulation helpers (getAngle, getOffset, getTangentNoHyp, markOverlapped, convertToAbsolute, and friends) that the public functions compose. parsePath() tokenizes the raw ‘d’ string with regexes, converts relative commands to absolute via convertToAbsolute, and normalizes H/V shorthand into L commands. roundCommands() then splits the command array into subpaths at each M marker, marks overlapping lineTo commands so they’re excluded from rounding, and walks each subpath inserting an elliptical arc (A) command between straight segments using trigonometry (getAngle, getOffset, getTangentNoHyp) to compute arc radius, sweep direction, and endpoint offsets. The separation between orchestration (index.js) and pure geometry helpers (utils.js) keeps each function narrowly scoped and testable in isolation; there are no classes, no external state, and no side effects beyond the explicitly-mutated command array passed in.
Tech Stack The library itself is dependency-free vanilla JavaScript, published as both an ES module (lib/index.js) and a UMD/CommonJS bundle (dist/svg-round-corners.js) built with Webpack 5 and Babel 7 (via babel-loader and @babel/preset-env). The build is split into three Webpack configs (webpack.dev.js, webpack.demo.js, webpack.prod.js) for local development, the GitHub Pages demo site, and the production npm bundle respectively. Type definitions are hand-written in a standalone types.d.ts rather than compiled from TypeScript source. Testing runs on Karma with the Jasmine assertion framework and a Chrome launcher, with ESLint (typescript-eslint parser, despite the JS-only source) enforcing style via .eslintrc.json.
Code Quality The project has real unit test coverage: tests/index.spec.js exercises the three public functions against fixture data in tests/variables.js (including a regression test asserting the output never contains NaN for degenerate straight-line input), and tests/utils.spec.js tests the internal geometry helpers directly (getAngle, getDistance, getTangentNoHyp, mod, and others) with concrete numeric expectations. Functions carry JSDoc comments describing parameters and return shapes, and ESLint is configured, though there is no CI workflow in the repository (no .github/workflows) so tests only run locally or via prepublishOnly before an npm publish. Error handling is minimal — the library assumes well-formed path input rather than validating or throwing on malformed ‘d’ strings.
API Design
The public surface is intentionally small: three functions with a consistent radius/round-digits signature, sensible default behavior (rounding is skipped unless a round argument is passed), and a convenience function (roundCorners) that saves callers from chaining parsePath and roundCommands themselves for the common case. Naming maps directly to SVG path semantics (parsePath, roundCommands), which keeps the learning curve low for anyone already familiar with the ‘d’ attribute grammar. The tradeoff is that consumers who need to reason about individual commands (for animation or further transformation) must work with the library’s internal command-object shape ({ marker, values, … }), which is documented in types.d.ts and the README’s parsePath() example output.