simplify-svg-path
v1.1.0
Published
Minimal path simplification library based on Skia's PathOps
Downloads
354
Maintainers
Readme
SimplifySvgPath
A minimal path simplification library based on Skia's PathOps
This is a fork of google/skia - specifically a stripped-down version focusing only on SVG path simplification.
About
This package provides a tiny WebAssembly build of Skia's powerful PathOps functionality, allowing you to simplify SVG paths by removing self-intersections and overlaps. The entire WASM bundle is only ~260KB, making it suitable for use in browsers and Node.js applications.
Installation
npm install simplify-svg-pathFeatures
- ✨ Simple API - Easy-to-use functions for path simplification
- 🎯 Tiny Size - Only ~260KB WASM bundle
- 🚀 Fast - Powered by Skia's battle-tested PathOps
- 🌐 Universal - Works in Node.js and browsers
- 📦 Self-contained - No external dependencies
Quick Start
import SimplifySvgPathInit from 'simplify-svg-path';
async function main() {
// Initialize the module
const SimplifySvgPath = await SimplifySvgPathInit();
// Convenience helper: takes an SVG path string, returns simplified string
const simplified = SimplifySvgPath.simplifySvgPath('M0 0L100 100L100 0L0 100Z');
console.log(simplified);
// Or use the Path API for more control:
const path = SimplifySvgPath.Path.MakeFromSVGString('M0 0L100 100L100 0L0 100Z');
const simplifiedPath = path.simplify();
if (simplifiedPath) {
console.log(simplifiedPath.toSVGString());
}
}
main();API
simplifySvgPath(svgPathString)
A convenience function that takes an SVG path string and returns the simplified path string.
- Parameters
svgPathString(string) - An SVG path data stringfillType(optional, enum) - Fill type for the path (default isWinding)
- Returns: Simplified SVG path string, or
nullif the path is invalid
Fill Types
An enumeration with supported fill types:
Winding- Non-zero winding fill ruleEvenOdd- Even-odd fill rule
Path API
For more advanced usage:
Path.MakeFromSVGString(svgPath)- Create a path from SVG path dataPath.MakeFromSVGString(svgPath, fillType)- Create a path with specified fill typepath.toSVGString()- Convert path back to SVG string formatpath.simplify()- Simplify the path by removing self-intersections and overlapspath.getFillType()- Get the fill type of the pathpath.setFillType(fillType)- Set the fill type of the path
Entry points
The WebAssembly binary is environment agnostic, but the JavaScript glue emscripten
generates around it is not: a build that knows about Node.js loads its binary through
module, fs, path and url, which browser bundlers cannot resolve and warn about.
The package therefore ships one build per environment and picks between them through the
browser and node export conditions, so import 'simplify-svg-path' gives you the
right one automatically:
| Entry point | Build | Loads the WASM binary via |
| ---------------------------- | ------------------------ | ------------------------- |
| simplify-svg-path | resolved by condition | - |
| simplify-svg-path/web | dist/simplifypath.web.js | fetch |
| simplify-svg-path/node | dist/simplifypath.node.js | fs |
| simplify-svg-path/simplifypath.wasm | the binary itself, shared by both builds | - |
Import simplify-svg-path/web or simplify-svg-path/node directly to pin one build,
for example when bundling for the browser from a tool that does not set the browser
condition. The two builds expose exactly the same API.
If you supply the binary yourself - through wasmBinary, instantiateWasm or
locateFile - the web build works anywhere, since none of its loading code runs.
TypeScript
TypeScript definitions are included in the package.
import SimplifySvgPathInit from 'simplify-svg-path';
const SimplifySvgPath = await SimplifySvgPathInit();
const result = SimplifySvgPath.simplifySvgPath('M0 0L10 10');Repository Structure
.
├── skia/ # Skia source code (submodule or fork)
│ └── modules/simplifypath/ # Our minimal PathOps module
│ ├── compile.sh # Build script for the WASM module
│ ├── path_simplify_bindings.cpp
│ ├── pathops.js
│ ├── BUILD.gn
│ └── BUILD.bazel
├── simplify-svg-path/ # NPM package
│ ├── dist/ # Build outputs (generated)
│ │ ├── simplifypath.web.js # Browser build
│ │ ├── simplifypath.node.js # Node.js build
│ │ ├── simplifypath.wasm # Shared by both builds
│ │ └── index.d.ts
│ ├── test.js
│ ├── package.json
│ ├── LICENSE
│ └── README.md
├── setup.sh # Setup script (sync dependencies)
├── build.sh # Build script (compile and copy)
└── README.md # This fileSetup
Prerequisites
- Python 3.12+
- Node.js 22+
Initial Setup
Clone this repository:
git clone https://github.com/hylimo/simplify-svg-path.git cd simplify-svg-pathRun the setup script to sync Skia dependencies:
./setup.shThis will run
python3 tools/git-sync-depsinside the Skia directory to fetch all required dependencies.
Building
To build the SimplifySvgPath module:
./build.shThis will:
- Navigate to
skia/modules/simplifypath/ - Run the compile script, which builds the WASM module once per target environment
(
webandnode) intoskia/out/simplifypath_wasm/<environment>/ - Copy the generated glue to
simplify-svg-path/dist/simplifypath.<environment>.js, plus the WASM binary - identical across environments - tosimplify-svg-path/dist/ - Copy this README to
simplify-svg-path/
The built files will be available in simplify-svg-path/dist/.
Testing
After building, you can run the test suite:
cd simplify-svg-path
npm testCI/CD
This repository includes GitHub Actions workflows:
.github/workflows/build.yml- Builds and tests on push/PR.github/workflows/publish.yml- Publishes to NPM on releases
To publish a new version:
- Update the version in
simplify-svg-path/package.json - Create a new GitHub release
- The publish workflow will automatically build and publish to NPM
License
This project is based on Skia and is licensed under the BSD-3-Clause license, the same as Skia.
Original Skia license text:
Copyright (c) 2011 Google Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.See LICENSE for the full Skia license.
Attribution
This is a fork and minimal build of google/skia. All credit for the PathOps implementation goes to the Skia team at Google.
Contributing
Contributions are welcome! Please feel free to submit issues or pull requests.
