Skip to content

Repository files navigation

SVG Parts

tests License: GPL v3 Python Inkscape

Split a single SVG into multiple standalone, cropped SVG files.

📖 No command line needed — see the user guide: English · Español

Splitting a drawing by fill colour

SVG Parts supports two complementary splitting strategies:

  • 🌳 XML tree (layers, groups, shapes...)
  • 🎨 Fill color

Typical use cases:

  • Laser cutting
  • Cricut / vinyl cutting
  • EVA foam templates
  • Multi-color printing
  • Extracting individual assets from complex SVGs

One core, four frontends

The same splitting engine powers four different frontends:

  • 🧩 Inkscape extension
  • 💻 Command-line tool
  • 🐍 Python library
  • 🌐 Web application (Pyodide)

The core splitting algorithm is shared across every frontend. Differences in the exported output are limited to backend-specific capabilities. Both supported SVG engines are tested against the same input documents to ensure consistent behaviour and to catch regressions.


Usage

Python

There's no PyPI package yet. core/ imports itself by absolute name (from core.backend import ...), so the repo root has to be on sys.path — either run from it, or point at it:

import sys
sys.path.insert(0, "/path/to/svgparts")   # not needed if that's your cwd

from core.api import export_parts

result = export_parts(
    svg_text,
    split_mode="fill-color"
)

for part in result["parts"]:
    print(part["name"])

export_parts() is string in, strings out — it never touches the filesystem, which is what lets the same call run under Pyodide.

Command line

pip install svgelements

python3 svgparts.py drawing.svg \
    -o output \
    --split-mode=fill-color

Tree mode:

python3 svgparts.py drawing.svg \
    -o output \
    --split-mode=tree \
    --only-leaves \
    --depth=3

Arguments (--help output; the engines listed under --engine are whichever ones are importable where you run it):

positional arguments:
  svg_file              input SVG file

options:
  -h, --help            show this help message and exit
  --version             show program's version number and exit
  -o OUTPUT_DIR, --output-dir OUTPUT_DIR
                        output directory (default: parts)
  --engine {inkex,svgelements}
                        SVG engine to use (default: auto-detect; available here: inkex, svgelements)
  --split-mode {tree,fill-color}
                        split by XML tree structure or by fill color (default: tree)
  --depth DEPTH         max tree depth, -1 = unlimited (default: -1)
  --only-leaves         keep only the deepest checked type per branch, not every matching layer/group/shape along the way (tree mode)
  --no-layers           don't export layers (tree mode)
  --no-groups           don't export groups (tree mode)
  --shapes              also export individual shapes (tree mode)
  --margin MARGIN       crop margin in mm (default: 0.5)
  --full-fidelity       tree AND fill-color mode: preserve the full document (defs, gradients, original group structure) instead of flattening to
                        plain <path> elements. Only works with --engine=inkex; ignored (with a warning) otherwise. Off by default because in tree
                        mode with --only-leaves this means one full-document deep-copy per exported shape -- can get slow on complex documents.
  --preserve-doc-size   keep every exported part at the ORIGINAL document's size and viewBox instead of cropping it to its own bounding box
                        (--margin then has nothing to apply to). Useful when the parts have to line up with each other afterwards, since they all
                        keep one coordinate system. Only affects --full-fidelity output; ignored, with a warning, otherwise, since flattened parts
                        are built from scratch around their own bounding box.
  --output-format {svg,dxf}
                        output file format (default: svg). 'dxf' needs the optional ezdxf + svgelements + numpy packages (pip install ezdxf
                        svgelements numpy) and always flattens (DXF has no defs/gradients/group-structure to preserve).

Inkscape

Copy

  • svgparts.inx
  • svgparts_inkex.py
  • core/
  • backends/ (only inkex_backend.py is ever used here)
  • assets/icon.svg (referenced by <icon> in the .inx)

into your User Extensions folder and restart Inkscape.

Or run ./package_for_inkscape.sh and unzip the result there — it builds exactly that set, and nothing else.

The extension appears under:

Extensions → Export → SVG Parts

If objects are selected, only the selection is exported.


Web

A browser version is available at

https://svgparts.kraft-steam.com/

The web application runs entirely in the browser using Pyodide, reusing the same Python code as the CLI and library. Since Inkscape's inkex library is difficult to run in a browser, the web frontend transparently uses the svgelements backend.


Architecture

core/                      engine-agnostic logic (no inkex/svgelements imports)
  backend.py                 SvgBackend ABC + auto-detecting factory
  exporter.py                tree-mode / fill-color-mode splitting, SVG serialization
  api.py                     in-memory API: string in, strings out (no filesystem)
  dxf_writer.py              optional DXF output (needs ezdxf+svgelements+numpy;
                                  guarded import, everything else works without it)
backends/
  inkex_backend.py           adapter over inkex (Inkscape's own library)
  svgelements_backend.py     adapter over svgelements (pure Python, no C deps)
  
svgparts.py                 standalone CLI -- no inkex dependency
svgparts_inkex.py           Inkscape extension entry point (see svgparts.inx)
svgparts.inx                Inkscape extension descriptor

The project follows a simple dependency inversion design.

core/ contains all splitting logic and never imports inkex or svgelements.

Instead, both engines implement the same SvgBackend interface.

---
config:
  theme: 'base'
  themeVariables:
    primaryColor: '#FEFEFE'
    primaryTextColor: '#555555'
    primaryBorderColor: '#AAAAAA'
    lineColor: '#555555'
    secondaryColor: '#666666'
    tertiaryColor: '#AAAAAA'
    
---

flowchart TB
    subgraph Frontends
        API[Python API]
        CLI[CLI]
        INK[Inkscape]
        PYODIDE[Pyodide]
    end

    CORE["<b>core</b><br/>engine-agnostic splitting logic"]
    BACKEND["<b>SvgBackend</b><br/>abstract contract + auto-detecting factory"]

    subgraph Backends
        INKEX[Inkex backend]
        SVGEL[svgelements backend]
    end

    API --> CORE
    CLI --> CORE
    INK --> CORE
    PYODIDE --> CORE

    CORE --> BACKEND

    BACKEND --> INKEX
    BACKEND --> SVGEL

Loading

This means the splitting algorithm exists only once while supporting multiple SVG engines.

Adding a new backend requires implementing the SvgBackend interface without changing the core algorithm.


Features

  • Split by XML tree
  • Split by fill color
  • Crop every exported SVG (opt out with --preserve-doc-size)
  • Flatten inherited styles
  • Recover referenced gradients, clip paths and patterns
  • Optional full-fidelity export (inkex)
  • Optional DXF export
  • Selection-aware inside Inkscape
  • Pure in-memory Python API
  • Runs inside Pyodide

License

GPL-3.0-or-later — see LICENSE for the full text, and the header of each source file.

About

Split SVG files by fill color or XML structure into separate cropped files, for Inkscape, Cricut, laser cutting and CNC.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages