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

cavalier-contours-js

v0.1.1

Published

Pure TypeScript port of the cavalier_contours Rust library: 2D polyline parallel offsetting (with arc segments) and boolean operations.

Readme

cavalier-contours-js

npm version license

Pure TypeScript/JavaScript port of the cavalier_contours Rust library — 2D polyline offsetting and boolean operations with arc segment (bulge) support. No Rust, no WASM: plain ES modules that run in any modern browser, web worker, or Node.

▶ Live interactive demo

Ported 1:1 from the Rust source (v0.7.0) and validated by the complete translated Rust test suite (232 tests). License: MIT OR Apache-2.0, same as the original. The bundled spatial index is a port of static_aabb2d_index (itself derived from flatbush).

Features

  • Parallel offset of open and closed polylines, including self-intersecting ones
  • Boolean operations: union ("or"), intersection ("and"), difference ("not"), "xor"
  • Shape offset: multi-polyline shapes with holes/islands, offset while maintaining hole relationships
  • Queries: signed area, path length, extents, winding number, closest point, containment, self-intersects, find-intersects
  • Arc segments are first-class via the bulge representation (bulge = tan(θ/4); 1 = half circle)
  • Zero runtime dependencies; plain ESM + TypeScript declarations (~74 kB unminified, ~20 kB gzipped)

Install

npm install cavalier-contours-js

ESM-only. Works in modern Node (≥18), bundlers, and directly in the browser — dist/ uses fully-specified relative imports, so you can serve it and import it from a <script type="module"> or an ES-module worker without a bundler.

Quick start

import { Polyline, plineClosed, plineOpen, Shape } from "cavalier-contours-js";

// Rounded slot: two lines + two half-circle arcs (bulge = 1)
const slot = plineClosed([
  [0, 0, 0],   // x, y, bulge
  [10, 0, 1],
  [10, 5, 0],
  [0, 5, 1],
]);

slot.area();                        // signed area (CCW positive)
slot.pathLength();
slot.extents();                     // { minX, minY, maxX, maxY } | null
slot.windingNumber({ x: 5, y: 2.5 });

// Parallel offset — positive offsets a CCW polyline inward; returns 0..n polylines
const inward: Polyline[] = slot.parallelOffset(1.0);
const outward = slot.parallelOffset(-1.0);

// Boolean operations
const rect = plineClosed([[5, -2, 0], [15, -2, 0], [15, 7, 0], [5, 7, 0]]);
const union = slot.boolean(rect, "or");     // "or" | "and" | "not" | "xor"
for (const { pline } of union.posPlines) {
  // resulting positive-space polylines
}
union.negPlines;                             // holes in the result, if any

// Multi-polyline shape (outline + holes), offset keeping island relationships
const outer = plineClosed([[0, 0, 0], [100, 0, 0], [100, 100, 0], [0, 100, 0]]); // CCW
const hole  = plineClosed([[30, 30, 0], [30, 70, 0], [70, 70, 0], [70, 30, 0]]); // CW
const shape = Shape.fromPlines([outer, hole]);
const offset = shape.parallelOffset(5);
offset.ccwPlines.forEach(p => render(p.polyline)); // outlines
offset.cwPlines.forEach(p => render(p.polyline));  // holes

Building polylines imperatively

const pl = new Polyline({ isClosed: true });
pl.add(0, 0, 0);
pl.add(10, 0, 0.5);

Web worker transfer

Polyline.toFlatArrays() returns { x, y, bulge } as Float64Arrays (transferable); reconstruct with Polyline.fromFlatArrays(x, y, bulge, isClosed).

Options

Every algorithm takes an optional options object mirroring the Rust API, e.g.:

slot.parallelOffset(1.0, { handleSelfIntersects: true, posEqualEps: 1e-5 });
slot.boolean(rect, "or", { posEqualEps: 1e-5 });
shape.parallelOffset(5, { offsetDistEps: 1e-4, sliceJoinEps: 1e-4 });

Notes on the port

  • Numeric type is number (f64) — identical IEEE-754 arithmetic to the Rust f64 implementation; transcendental functions may differ in final ULPs, absorbed by the library's fuzzy epsilons.
  • userdata values are number[] (the Rust API uses u64; values above 2^53 lose precision).
  • Rust Option<T> maps to T | null.

Contributing

git clone https://github.com/msurguy/cavalier-contours-js.git
cd cavalier-contours-js
npm install        # also builds dist/ via the prepare script
npm test           # Vitest — ports of the entire Rust test suite (232 tests)
npm run typecheck
npm run build

There is also an interactive demo in demo/ (cd demo && npm install && npm run dev).

Releasing

Releases are published to npm automatically via GitHub Actions using npm Trusted Publishing (OIDC) — no NPM_TOKEN secret is stored anywhere, and every release carries a provenance attestation.

To cut a release:

npm version patch          # or minor / major — bumps package.json, commits, and tags
git push origin main --tags
gh release create vX.Y.Z --generate-notes

Publishing a GitHub Release triggers the workflow, which typechecks, runs the full test suite, builds, and runs npm publish --provenance. Watch it with gh run watch — a green ✓ appears next to the new version on npm.

The demo redeploys to GitHub Pages on every push to main.

License

Licensed under either of

at your option — the same dual license as the original cavalier_contours Rust crate.