npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

svg2wkt

v0.1.0

Published

Convert an SVG string into a WKT (Well-Known Text) geometry string. Zero dependencies, TypeScript, ESM + CJS + UMD.

Readme

svg2wkt

Convert an SVG string into a WKT (Well-Known Text) geometry string.

  • Zero runtime dependencies — no DOM, no bezier library. SVG parsing, path sampling and arc flattening are all implemented from scratch.
  • TypeScript — ships type declarations.
  • Universal — ESM, CommonJS and a UMD build for direct use from a CDN.
  • Runs in Node, browsers, Deno and bundlers.

Inspired by David McClure's svg-to-wkt, rebuilt in modern TypeScript with no dependencies.

Install

npm install svg2wkt

Usage

ESM / TypeScript

import { svgToWkt } from 'svg2wkt';

svgToWkt('<svg><rect width="2" height="2"/></svg>');
// 'GEOMETRYCOLLECTION(POLYGON((0 0,2 0,2 -2,0 -2,0 0)))'

CommonJS

const { svgToWkt } = require('svg2wkt');

Browser via CDN (UMD)

<script src="https://unpkg.com/svg2wkt"></script>
<script>
  // exposed as a global `svg2wkt`
  console.log(svg2wkt.svgToWkt('<circle cx="0" cy="0" r="10"/>'));
</script>

API

svgToWkt(svg, options?) => string

Converts an SVG string into a WKT GEOMETRYCOLLECTION. Supported elements are converted in document order; everything else is ignored.

| Element | WKT output | | ----------- | ------------- | | <line> | LINESTRING | | <polyline>| LINESTRING | | <polygon> | POLYGON | | <rect> | POLYGON | | <circle> | POLYGON (approximated) | | <ellipse> | POLYGON (approximated) | | <path> | POLYGON / LINESTRING / MULTILINESTRING (curves sampled; see below) |

A <path> maps each subpath by whether it is explicitly closed with Z/z: closed subpaths become polygon rings, open ones become linestrings. See closePaths to override.

pathToWkt(d, options?) => string

Converts a single SVG path d attribute into WKT. With the default closePaths: 'auto', Z-closed subpaths form a POLYGON (first ring exterior, the rest holes) and open subpaths form a LINESTRING (or MULTILINESTRING); a path with both yields a GEOMETRYCOLLECTION. Returns '' if the path produces no geometry.

import { pathToWkt } from 'svg2wkt';

pathToWkt('M0 0 H10 V10 H0 Z', { flipY: false });
// 'POLYGON((0 0,10 0,10 10,0 10,0 0))'   // closed -> polygon

pathToWkt('M0 0 H10 V10', { flipY: false });
// 'LINESTRING(0 0,10 0,10 10)'           // open -> linestring

Options

| Option | Type | Default | Description | | ----------- | --------- | ------- | ----------- | | flipY | boolean | true | Negate the Y axis. SVG's Y axis points down; WKT geometry is conventionally Y-up, so flipping is usually desired. Set to false to keep coordinates exactly as in the SVG. | | precision | number | 3 | Number of decimal places kept in output coordinates. | | density | number | 1 | Sampling density for curved geometry (circles, ellipses, path curves), in sample points per unit of length. Higher = smoother and more vertices. | | applyViewBox | boolean | false | Apply the <svg> viewBox → viewport mapping so output is in rendered/pixel space instead of raw content units (see below). | | viewport | { width, height } | — | Explicit viewport size (px) for the root <svg>, overriding its width/height. Setting this implies applyViewBox: true. | | closePaths | 'auto' \| 'always' | 'auto' | How to treat <path> subpaths not closed with Z. 'auto': closed → polygon ring, open → linestring. 'always': every subpath is closed into a ring, so a path is always a POLYGON. |

Path commands

All SVG path commands are supported, in both absolute and relative form: M/m, L/l, H/h, V/v, C/c, S/s, Q/q, T/t, A/a and Z/z. Cubic and quadratic béziers are flattened by adaptive sampling, and elliptical arcs are flattened via the endpoint-to-center parameterization from the SVG spec.

Transforms

transform attributes are fully supported, including all SVG transform functions — matrix, translate, scale, rotate (with optional center), skewX and skewY. Transforms on ancestor <g>/<svg> elements are inherited and composed with an element's own transform, so nested groups behave as expected.

svgToWkt('<g transform="translate(10 0)"><rect width="1" height="1" transform="scale(2)"/></g>', {
  flipY: false,
});
// 'GEOMETRYCOLLECTION(POLYGON((10 0,12 0,12 2,10 2,10 0)))'

Note: pathToWkt(d) operates on a bare path string and therefore applies no transform; use svgToWkt for transform-aware conversion.

viewBox

By default, output coordinates are in the SVG's content coordinate system (the numbers as authored). Set applyViewBox: true to instead map content through the <svg> viewBox → viewport transform, producing rendered/pixel space coordinates:

const svg = '<svg viewBox="0 0 100 100" width="500" height="500"><rect width="10" height="10"/></svg>';

svgToWkt(svg, { flipY: false });
// 'GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0)))'         // content units

svgToWkt(svg, { flipY: false, applyViewBox: true });
// 'GEOMETRYCOLLECTION(POLYGON((0 0,50 0,50 50,0 50,0 0)))'         // scaled x5 to viewport
  • preserveAspectRatio is honored, including none (non-uniform scale), meet/slice, and xMin/xMid/xMax + YMin/YMid/YMax alignment.
  • For viewBox-only SVGs with no intrinsic size, pass viewport: { width, height } (which also enables applyViewBox). With no resolvable viewport at all, the mapping falls back to scale 1, applying only the viewBox min-x/min-y offset.
  • Nested <svg> elements with their own viewBox are handled too.
  • viewBox composes with transform attributes and the flipY option.

Notes & limitations

  • Rounded <rect> corners (rx/ry) are ignored — rectangles are emitted as their four corners.
  • width/height units: only unitless and px values are resolved for the viewport; %, em, in, etc. fall back to the offset-only mapping above.
  • Open vs. closed paths: by default a subpath is a POLYGON ring only if it ends in Z/z; otherwise it is a LINESTRING. Use closePaths: 'always' for the original always-POLYGON behavior. Multiple closed rings model holes (e.g. the letter "O") within a single POLYGON, but disjoint filled regions are not split into a MULTIPOLYGON.
  • Degenerate shapes (zero radius/size, too few points) are skipped.

Demo

An interactive demo lives in docs/: it converts a default SVG, lets you edit the source or drag & drop your own .svg file, tweak options live, and renders the resulting WKT geometry next to the original so you can compare them.

Run it locally:

npm run build            # also vendors the UMD bundle into docs/svg2wkt.js
# then serve the folder, e.g.
npx --yes serve docs     # or: python3 -m http.server -d docs

Publishing on GitHub Pages

A workflow at .github/workflows/deploy-pages.yml builds the library, vendors the UMD bundle into docs/, runs the tests, and deploys docs/ to GitHub Pages on every push to main (and on manual dispatch). One-time setup: in Settings → Pages, set Source to GitHub Actions.

Because CI rebuilds it, the generated docs/svg2wkt.js is git-ignored and does not need to be committed.

Development

npm run build   # emit dist/esm, dist/cjs and dist/umd
npm test        # build, then run the test suite (Node's built-in runner)

The build uses only tsc; the UMD bundle is produced by a small Node script that wraps the compiled output. There are no third-party runtime or build dependencies.

License

MIT