paper-core
v0.1.2
Published
TypeScript port of paper.js path geometry — no DOM, no canvas, no SVG.
Readme
paper-core
A TypeScript port of paper.js path geometry, with everything DOM-, canvas-, and SVG-related stripped out.
Drop-in source-compatible for the path subset: new Path.Circle(...).unite(other).getPathData() works exactly as in paper.js.
What's included
- Math primitives:
Point,Size,Rectangle,Matrix,Line(withLinkedPoint/LinkedSize/LinkedRectanglefor bound accessors likepath.position.x = 5) - Numerics:
Numerical(root finding, Gauss-Legendre integration, cubic/quadratic solvers) - Spatial index:
CollisionDetection(sweep-and-prune) - Path geometry:
Segment,SegmentPoint,Curve,CurveLocation,PathFlattener,PathFitter - Path classes:
PathItem(abstract base),Path,CompoundPath - Constructors:
Path.Line,Path.Circle,Path.Rectangle,Path.RoundRectangle,Path.Ellipse,Path.Arc,Path.RegularPolygon,Path.Star - Boolean ops:
unite,intersect,subtract,exclude,divide,resolveCrossings,reorient,getInteriorPoint - Path builder:
moveTo,lineTo,cubicCurveTo,quadraticCurveTo,curveTo,arcTo,closePathand their*Byrelative variants - String I/O:
getPathData(matrix?, precision?)/setPathData(data)(SVG path-data string format)
What's NOT included
Out of scope for this port:
- DOM, canvas rendering, SVG export/import
- Colors, gradients, fills, strokes, styles, blend modes, opacity
- Text
- Project / Layer / Group / View / Raster / Shape / SymbolItem
- PaperScope, PaperScript
- Events (mouse, keyboard, frame)
- Animation / tweens
- HTTP / network
- JSON serialization (
exportJSON/importJSON) hitTest(planned for v0.2)
For rendering, use path.getPathData() and feed it to your renderer of choice (an <svg> <path d=...> element, a Canvas Path2D, etc.).
Install
npm install paper-coreUsage
import { Path, CompoundPath, Point } from 'paper-core';
const a = new Path.Circle({ center: [50, 50], radius: 30 });
const b = new Path.Rectangle({ point: [40, 40], size: [50, 50] });
const union = a.unite(b);
console.log(union.getPathData(null, 2));
// => "M..." (SVG-compatible path data string)
// Boolean ops compose
const result = a.unite(b).subtract(new Path.Circle({ center: [70, 70], radius: 10 }));
// Compound paths (e.g., rectangle with hole)
const ring = new CompoundPath({
children: [
new Path.Circle({ center: [100, 100], radius: 50 }),
new Path.Circle({ center: [100, 100], radius: 20 }),
],
});
ring.setFillRule('evenodd');default export is also provided for paper.Path.Circle style access:
import paper from 'paper-core';
const p = new paper.Path.Circle({ center: [50, 50], radius: 30 });Differences from paper.js
The library was deliberately stripped of all rendering / scene-graph concerns. As a result:
- No
paper.setup()orProject. Path objects exist standalone. Methods likepath.insertAbove(other)from paper.js are gone — boolean ops return a fresh detachedPathIteminstead. - No
_style. The single style touchpoint we kept is_fillRule(used by boolean ops). Set viapath.setFillRule('evenodd' | 'nonzero'). getStrokeBounds(options, matrix?)takes an explicit options object ({ strokeWidth, strokeJoin, strokeCap, miterLimit, strokeScaling }) instead of pulling from aStyleinstance.- 3/120 parity divergences with upstream paper.js, all in the subpath enumeration order for non-intersecting
unite/excludecases. Geometry is identical; justM...z M...zis emitted in a different order. Captured intest/parity/paperjs-parity.test.ts.
Architecture
- Native ES classes throughout. No
Base.extend/Base.injectmechanism. Itemwas collapsed intoPathItembecause there are only two concrete subclasses (Path,CompoundPath). The ~4000 LOC ofItem.jsthat handled events / projects / styles / rasters got dropped; what remained (matrix, bounds caching, transforms, position/pivot, clone) lives directly onPathItem.Base.readpolymorphism preserved via a typed_readImpl(list, start, count?)protocol so consumer code likenew Point({ x: 1, y: 2 }),new Point([1, 2]),new Point(1, 2)all still work.LinkedPoint/LinkedRectanglepreserved —path.position.x = 5mutates back.- Boolean ops live in
src/path/PathItem.Boolean.tsand augmentPathItem.prototypevia TypeScript module augmentation.
Development
git clone <repo>
cd paper-core
npm install
npm test # vitest watch mode
npm run test:run # one-shot
npm run typecheck # tsc --noEmit
npm run build # tsup → dist/{index.js,index.cjs,index.d.ts}
npm run smoke # parity check against `paper` npm packageCredit
Paper.js is © 2011–2020 Jürg Lehni & Jonathan Puckey. This is a derivative port of their work under the same MIT license.
