svg

Type-safe SVG generation library for Kit

Files

FileDescription
.editorconfigEditor formatting configuration
.gitignoreGit ignore rules for build artifacts and dependencies
.tool-versionsasdf tool versions (Zig, Kit)
LICENSEMIT license file
README.mdThis file
examples/animations.kitExample: animations
examples/colors.kitExample: colors
examples/filters.kitExample: filters
examples/shapes.kitExample: shapes
examples/simple.kitExample: simple
kit.tomlPackage manifest with metadata and dependencies
src/animation.kitSVG Animation Elements
src/attrs.kitAttribute Builders
src/bbox.kitBounding Box Utilities
src/colors.kitColor System for SVG
src/document.kitSVG Document Creation
src/elements.kitBasic Shape Elements
src/filters.kitSVG Filter Effects
src/gradients.kitGradient Definitions
src/groups.kitGroup Elements
src/main.kitKit SVG - Type-Safe SVG Generation
src/markers.kitMarker Helpers
src/matrix.kit2D Affine Transformation Matrix
src/paths.kitPath DSL
src/render.kitSVG Rendering
src/shapes.kitConvenience Shapes
src/transforms.kitTransform Helpers
src/types.kitCore Types for SVG Generation
tests/document.test.kitTests for document
tests/gradients.test.kitTests for gradients
tests/groups.test.kitTests for groups
tests/paths.test.kitTests for paths
tests/phase1.test.kitTests for phase1
tests/phase2.test.kitTests for phase2
tests/phase3.test.kitTests for phase3
tests/phase4.test.kitTests for phase4
tests/phase5.test.kitTests for phase5
tests/phase6.test.kitTests for phase6
tests/phase7.test.kitTests for phase7
tests/phase8.test.kitTests for phase8
tests/shapes.test.kitTests for shapes
tests/text.test.kitTests for text
tests/transforms.test.kitTests for transforms

Dependencies

None

Installation

kit add gitlab.com/kit-lang/packages/kit-svg.git

Usage

import Kit.SVG as SVG

# Create a simple SVG document
doc = SVG.new {width: 200.0, height: 200.0}
  |> SVG.add (SVG.rect {x: 10.0, y: 10.0, width: 80.0, height: 60.0, fill: "#3498db"})
  |> SVG.add (SVG.circle {cx: 150.0, cy: 100.0, r: 40.0, fill: "#e74c3c"})

output = SVG.render doc

Basic Shapes

# Rectangle with rounded corners
SVG.rect {x: 0.0, y: 0.0, width: 100.0, height: 50.0, rx: 5.0, fill: "blue"}

# Circle
SVG.circle {cx: 50.0, cy: 50.0, r: 25.0, stroke: "black", stroke-width: "2"}

# Ellipse
SVG.ellipse {cx: 50.0, cy: 50.0, rx: 40.0, ry: 20.0}

# Line
SVG.line {x1: 0.0, y1: 0.0, x2: 100.0, y2: 100.0, stroke: "red"}

# Polygon (closed shape)
SVG.polygon {points: [SVG.pt 50.0 0.0, SVG.pt 100.0 100.0, SVG.pt 0.0 100.0], fill: "green"}

Path DSL

# Build complex paths with the path DSL
path = SVG.path-new
  |> SVG.move-to 10.0 10.0
  |> SVG.line-to 90.0 10.0
  |> SVG.curve-to {x1: 100.0, y1: 50.0, x2: 90.0, y2: 90.0, x: 50.0, y: 90.0}
  |> SVG.close-path
  |> SVG.path-fill "purple"
  |> SVG.path-stroke "black"

Transforms

# Transform helper functions
translate-str = SVG.translate 50.0 100.0     # "translate(50 100)"
rotate-str = SVG.rotate 45.0                 # "rotate(45)"
scale-str = SVG.scale 2.0                    # "scale(2)"

# Apply to groups
g = SVG.group-new
  |> SVG.group-transform (SVG.translate 100.0 50.0)
  |> SVG.group-add (SVG.rect {x: 0.0, y: 0.0, width: 20.0, height: 20.0})

Gradients

# Create a linear gradient
grad = SVG.linear-gradient "myGrad"
  |> SVG.gradient-stop {offset: 0.0, color: "red"}
  |> SVG.gradient-stop {offset: 1.0, color: "blue"}

# Use in a shape
doc = SVG.new {width: 100.0, height: 100.0}
  |> SVG.add-def grad
  |> SVG.add (SVG.rect {x: 0.0, y: 0.0, width: 100.0, height: 100.0, fill: SVG.url "myGrad"})

Convenience Shapes

# Star shape
star = SVG.star {
  cx: 100.0, cy: 100.0,
  points: 5,
  outer-r: 50.0, inner-r: 25.0,
  fill: "gold"
}

# Regular polygon (hexagon)
hexagon = SVG.regular-polygon {
  cx: 100.0, cy: 100.0,
  sides: 6,
  radius: 50.0,
  fill: "blue"
}

# Arrow shape
arrow = SVG.arrow {
  start: {x: 0.0, y: 50.0},
  end: {x: 100.0, y: 50.0},
  head-size: 10.0,
  stroke: "black"
}

# Rounded rectangle shorthand
rounded = SVG.rounded-rect {
  x: 10.0, y: 10.0,
  width: 100.0, height: 50.0,
  radius: 10.0,
  fill: "blue"
}

Markers

# Create arrow marker for line endpoints
arrow-mark = SVG.arrow-marker {id: "arrow", size: 10.0, color: "black"}

# Create circle/dot marker
dot = SVG.circle-marker {id: "dot", radius: 3.0, fill: "red"}

# Square and diamond markers also available
square = SVG.square-marker {id: "square", size: 6.0, fill: "blue"}
diamond = SVG.diamond-marker {id: "diamond", size: 8.0, fill: "green"}

# Add markers to document
doc = SVG.new {width: 200.0, height: 100.0}
  |> SVG.add-def arrow-mark
  |> SVG.add (SVG.line {
    x1: 10.0, y1: 50.0, x2: 190.0, y2: 50.0,
    stroke: "black",
    marker-end: SVG.marker-url "arrow"
  })

Colors

The Colors module (import separately) provides a comprehensive color system:

import Kit.SVG.Colors as Color

# Create colors in different formats
red = Color.rgb 255 0 0
blue = Color.hex "#0000ff"
green = Color.hsl 120.0 1.0 0.5
semi-transparent = Color.rgba 255 0 0 0.5

# Convert between formats
hex-red = Color.to-hex red            # "#ff0000"
css-str = Color.to-css blue           # "#0000ff"
hsl-green = Color.to-hsl green        # HSL 120.0 1.0 0.5

# Manipulate colors
light-red = Color.lighten 0.2 red     # Make 20% lighter
dark-blue = Color.darken 0.2 blue     # Make 20% darker
vivid = Color.saturate 0.3 green      # Increase saturation
muted = Color.desaturate 0.3 green    # Decrease saturation

# Color operations
complement = Color.complement red      # Get complementary color
rotated = Color.rotate-hue 60.0 red   # Rotate hue by degrees
gray = Color.grayscale red            # Convert to grayscale
inverted = Color.invert red           # Invert color
mixed = Color.mix red blue 0.5        # Mix two colors
with-alpha = Color.with-alpha 0.5 red # Set opacity

Animation

The Animation module (import separately) provides SVG declarative animations:

module SvgAnimationExample

import Kit.SVG.Animation as Animation

# Animate a single attribute
fade = Animation.animate {
  attribute: "opacity",
  values: "0;1",
  dur: "2s",
  fill-mode: "freeze"
}

# Transform animations (rotate, scale, translate)
spin = Animation.animate-transform {
  transform-type: "rotate",
  values: "0 50 50;360 50 50",
  dur: "3s",
  repeat-count: "indefinite"
}

# Motion along a path
motion = Animation.animate-motion {
  path: "M0,0 C50,0 50,100 100,100",
  dur: "4s",
  rotate: "auto"
}

# Set a value at a specific time
show = Animation.set {
  attribute: "visibility",
  to: "visible",
  begin: "1s"
}

# Convenience functions
fade-in = Animation.fade-in "1s"
fade-out = Animation.fade-out "1s"
pulse = Animation.pulse "0.5s"
spinning = Animation.spin 50.0 50.0 "2s"
shake = Animation.shake "0.3s"
bounce = Animation.bounce "0.5s"
color-change = Animation.color-transition "blue" "red" "2s"
draw = Animation.draw-stroke "100" "2s"

# Render animation to XML
xml = Animation.render-animate fade

Filter Effects

The Filters module (import separately) provides SVG filter effects:

import Kit.SVG.Filters as Filters

# Basic effects
blur = Filters.gaussian-blur 5.0
offset = Filters.offset 3.0 3.0
saturate = Filters.saturate 0.5
hue-shift = Filters.hue-rotate 90.0
gray = Filters.grayscale()

# Create a simple blur filter
blur-filter = Filters.blur-filter "myBlur" 8.0

# Create a drop shadow
shadow = Filters.drop-shadow {
  id: "shadow",
  dx: 3.0, dy: 3.0,
  blur: 5.0,
  color: "black",
  opacity: 0.5
}

# Create a glow effect
glow = Filters.glow {
  id: "glow",
  blur: 5.0,
  color: "yellow"
}

# Inner shadow
inner = Filters.inner-shadow {
  id: "inner",
  dx: 2.0, dy: 2.0,
  blur: 3.0,
  color: "black"
}

# Emboss and sharpen
emboss = Filters.emboss "embossed"
sharpen = Filters.sharpen "sharpened" 1.0

# Build custom filters with effects chain
custom = Filters.simple-filter "custom" [
  Filters.offset 2.0 2.0,
  Filters.gaussian-blur 3.0,
  Filters.merge ["SourceGraphic", "blur"]
]

# Apply filter to element
doc = SVG.new {width: 200.0, height: 200.0}
  |> SVG.add-def shadow
  |> SVG.add (SVG.rect {
    x: 50.0, y: 50.0, width: 100.0, height: 100.0,
    fill: "blue",
    filter: Filters.filter-url "shadow"
  })

Transform Matrix

The Matrix module (import separately) provides 2D transformation matrices:

import Kit.SVG.Matrix as Matrix

# Create transformation matrices
identity = Matrix.identity
t = Matrix.translate 10.0 20.0
s = Matrix.scale 2.0
r = Matrix.rotate 45.0
rx = Matrix.rotate-around 45.0 50.0 50.0  # Rotate around point

# Combine transformations
combined = Matrix.multiply s t
composed = Matrix.compose [t, s, r]

# Transform a point
p = Matrix.transform-point combined 5.0 10.0
# p.x and p.y contain transformed coordinates

# Matrix operations
det = Matrix.determinant combined
inv = Matrix.inverse combined  # Returns Option

# Extract components
translation = Matrix.get-translation combined
scale-factors = Matrix.get-scale combined
rotation = Matrix.get-rotation combined

# Convert to SVG string
str = Matrix.to-string combined            # "matrix(a b c d e f)"
transform = Matrix.to-transform-string t   # "translate(10 20)"

Bounding Box

The BBox module (import separately) provides geometry calculations:

import Kit.SVG.BBox as BBox

# Create bounding boxes from shapes
rect-bbox = BBox.from-rect 10.0 20.0 100.0 50.0
circle-bbox = BBox.from-circle 100.0 100.0 50.0
line-bbox = BBox.from-line 10.0 20.0 100.0 80.0
points-bbox = BBox.from-points [{x: 10.0, y: 20.0}, {x: 100.0, y: 80.0}]

# Get properties
x = BBox.get-x rect-bbox
y = BBox.get-y rect-bbox
width = BBox.get-width rect-bbox
height = BBox.get-height rect-bbox
center = BBox.center rect-bbox        # {x, y}
area = BBox.area rect-bbox
aspect = BBox.aspect-ratio rect-bbox

# Combine bounding boxes
merged = BBox.merge bbox1 bbox2
merged-all = BBox.merge-all [bbox1, bbox2, bbox3]
intersection = BBox.intersect bbox1 bbox2  # Returns Option

# Containment and overlap tests
inside = BBox.contains-point? 50.0 50.0 rect-bbox
contains = BBox.contains-box? outer inner
overlaps = BBox.overlaps? bbox1 bbox2

# Transform bounding boxes
expanded = BBox.expand 5.0 rect-bbox      # Grow by 5 on all sides
contracted = BBox.contract 5.0 rect-bbox  # Shrink by 5
translated = BBox.translate 10.0 20.0 rect-bbox
scaled = BBox.scale 2.0 rect-bbox         # Scale from center

# Convert to SVG viewBox
viewbox = BBox.to-viewbox rect-bbox       # "10 20 100 50"

Text Features

# Basic text
text = SVG.text {x: 50.0, y: 50.0, content: "Hello", fill: "black"}

# Multi-line text block (splits on newlines)
block = SVG.text-block {
  x: 10.0, y: 30.0,
  content: "Line 1\nLine 2\nLine 3",
  fill: "black",
  line-height: 20.0
}

# Text along a path
text-path = SVG.text-path {
  content: "Curved text",
  href: "myPath",  # Reference to a path element
  fill: "blue"
}

# Rich text with styled spans
rich = SVG.rich-text {
  x: 10.0, y: 50.0,
  spans: [
    SVG.tspan-styled {text: "Bold", font-weight: "bold"},
    SVG.tspan {text: " and "},
    SVG.tspan-styled {text: "Red", fill: "red"}
  ]
}

Rendering

# Compact XML output (single line, no extra whitespace)
compact = SVG.render doc

# Pretty-printed XML with indentation
pretty = SVG.render-pretty doc

API Reference

Document

FunctionDescription
new {width, height, ...}Create new SVG document
view-box minX minY w h docSet viewBox attribute
add element docAdd element to document
add-all elements docAdd multiple elements
add-def def docAdd definition (gradient, marker, etc.)
render docRender to XML string
render-pretty docRender with indentation

Elements

FunctionDescription
rect {...}Rectangle element
circle {...}Circle element
ellipse {...}Ellipse element
line {...}Line element
polyline {...}Open polyline
polygon {...}Closed polygon
text {...}Text element
text-block {...}Multi-line text
text-path {...}Text along path
rich-text {...}Text with styled spans
image {...}Image element
use {...}Symbol reference
title strTitle metadata
desc strDescription metadata
style strEmbedded CSS styles
raw strRaw XML string

Path DSL

FunctionDescription
path-newCreate empty path
move-to x yMove to absolute position
move-to-rel dx dyMove relative
line-to x yLine to absolute position
line-to-rel dx dyLine relative
horizontal-to xHorizontal line to
vertical-to yVertical line to
curve-to {...}Cubic bezier curve
smooth-to {...}Smooth cubic bezier
quad-to {...}Quadratic bezier
smooth-quad-to x ySmooth quadratic
arc-to {...}Elliptical arc
close-pathClose path
path-fill colorSet fill
path-stroke colorSet stroke
path-stroke-width wSet stroke width

Groups

FunctionDescription
group-newCreate empty group
group-add element groupAdd element
group-add-all elements groupAdd multiple elements
group-id id groupSet ID attribute
group-class class groupSet class attribute
group-transform transform groupSet transform

Transforms

FunctionDescription
translate x yTranslation string
rotate degreesRotation string
rotate-around degrees cx cyRotation around point
scale factorUniform scale
scale-xy sx syNon-uniform scale
skew-x degreesHorizontal skew
skew-y degreesVertical skew

Gradients

FunctionDescription
linear-gradient idCreate linear gradient
radial-gradient idCreate radial gradient
gradient-stop {offset, color, ...}Add color stop
gradient-direction {x1, y1, x2, y2}Set gradient direction
url idCreate URL reference

Markers

FunctionDescription
arrow-marker {id, size, ...}Arrow marker
circle-marker {id, radius, ...}Circle marker
square-marker {id, size, ...}Square marker
diamond-marker {id, size, ...}Diamond marker
marker-url idCreate marker URL reference

Shapes

FunctionDescription
star {cx, cy, points, outer-r, inner-r, ...}Star shape
regular-polygon {cx, cy, sides, radius, ...}Regular polygon
arrow {start, end, head-size, ...}Arrow with head
rounded-rect {x, y, width, height, radius, ...}Rounded rectangle

License

MIT License - see LICENSE for details.

Exported Functions & Types

FilterEffect

Filter effect - represents a single filter primitive

Variants

FeGaussianBlur {_0, _1, _2}
FeOffset {_0, _1, _2, _3}
FeBlend {_0, _1, _2, _3}
FeColorMatrix {_0, _1, _2, _3}
FeFlood {_0, _1, _2}
FeMorphology {_0, _1, _2, _3}
FeComposite {_0, _1, _2, _3, _4, _5, _6, _7}
FeMergeNode {_0}
FeMerge {_0, _1}
FeImage {_0, _1}
FeTurbulence {_0, _1, _2, _3, _4}
FeDisplacementMap {_0, _1, _2, _3, _4, _5}
FeConvolveMatrix {_0, _1, _2, _3, _4, _5}

Filter

Filter definition - a named filter containing effects

Variants

Filter {_0, _1, _2, _3, _4, _5, _6}

filter

Create a filter definition.

Config fields: - id: String - unique identifier for the filter - x: Float - x position (default: -10%) - y: Float - y position (default: -10%) - width: Float - width (default: 120%) - height: Float - height (default: 120%) - color-interpolation-filters: String - "sRGB" or "linearRGB"

{id: String, ...} -> [FilterEffect] -> Filter

simple-filter

Create a simple filter with just an ID and effects.

NonEmptyString -> [FilterEffect] -> Filter

gaussian-blur

Create a Gaussian blur effect.

NonNegativeFloat -> FilterEffect

gaussian-blur-io

Create a Gaussian blur with input/output.

NonNegativeFloat -> String -> String -> FilterEffect

offset

Create an offset effect.

Float -> Float -> FilterEffect

offset-io

Create an offset effect with input/output.

Float -> Float -> String -> String -> FilterEffect

blend

Create a blend effect.

Modes: normal, multiply, screen, darken, lighten, overlay, color-dodge, color-burn, hard-light, soft-light, difference, exclusion

String -> String -> String -> FilterEffect

blend-io

Create a blend effect with result.

String -> String -> String -> String -> FilterEffect

color-matrix

Create a color matrix effect.

Types: matrix, saturate, hueRotate, luminanceToAlpha

String -> String -> FilterEffect

color-matrix-io

Create a color matrix with input/output.

String -> String -> String -> String -> FilterEffect

saturate

Create a saturate effect (convenience for color-matrix saturate).

Float -> FilterEffect

hue-rotate

Create a hue-rotate effect (convenience for color-matrix hueRotate).

Float -> FilterEffect

grayscale

Create a grayscale effect (saturate 0).

() -> FilterEffect

flood

Create a flood (solid color) effect.

String -> Float -> FilterEffect

flood-io

Create a flood effect with result.

String -> Float -> String -> FilterEffect

morphology

Create a morphology effect (dilate or erode).

Operators: dilate, erode

String -> NonNegativeFloat -> FilterEffect

morphology-io

Create a morphology effect with input/output.

String -> NonNegativeFloat -> String -> String -> FilterEffect

dilate

Create a dilate effect (expand shapes).

NonNegativeFloat -> FilterEffect

erode

Create an erode effect (shrink shapes).

NonNegativeFloat -> FilterEffect

composite

Create a composite effect.

Operators: over, in, out, atop, xor, arithmetic

String -> String -> String -> FilterEffect

composite-arithmetic

Create a composite effect with arithmetic coefficients.

Float -> Float -> Float -> Float -> String -> String -> FilterEffect

merge

Create a merge effect combining multiple inputs.

[String] -> FilterEffect

merge-io

Create a merge effect with result.

[String] -> String -> FilterEffect

image

Create an image effect.

String -> FilterEffect

turbulence

Create a turbulence effect (noise).

Types: turbulence, fractalNoise

String -> Float -> Int -> FilterEffect

displacement-map

Create a displacement map effect.

Float -> String -> String -> String -> String -> FilterEffect

blur-filter

Create a simple blur filter.

NonEmptyString -> NonNegativeFloat -> Filter

drop-shadow

Create a drop shadow filter.

{id: String, dx: Float, dy: Float, blur: Float, color: String, opacity: Float} -> Filter

inner-shadow

Create an inner shadow filter.

{id: String, dx: Float, dy: Float, blur: Float, color: String} -> Filter

glow

Create a glow filter.

{id: String, blur: Float, color: String} -> Filter

emboss

Create an emboss filter.

NonEmptyString -> Filter

sharpen

Create a sharpen filter.

NonEmptyString -> NonNegativeFloat -> Filter

render-effect

Render a filter effect to XML string.

FilterEffect -> String

render-filter

Render a filter definition to XML string.

Filter -> String

filter-url

Generate a filter URL reference for use in style attributes.

NonEmptyString -> String

Color

Color type supporting multiple color spaces

Variants

RGB {_0, _1, _2}
RGBA {_0, _1, _2, _3}
HSL {_0, _1, _2}
HSLA {_0, _1, _2, _3}
Hex {_0}
Named {_0}

to-rgb

Convert any color to RGB format.

Color -> Color

to-hsl

Convert any color to HSL format.

Color -> Color

to-hex

Convert any color to a hex string (e.g., "#ff0000").

Color -> String

to-css

Convert any color to a CSS-compatible string. Returns hex for RGB, rgba() for RGBA, hsl() for HSL, hsla() for HSLA.

Color -> String

lighten

Lighten a color by a given amount (0.0 to 1.0).

Float -> Color -> Color

darken

Darken a color by a given amount (0.0 to 1.0).

Float -> Color -> Color

saturate

Increase saturation by a given amount (0.0 to 1.0).

Float -> Color -> Color

desaturate

Decrease saturation by a given amount (0.0 to 1.0).

Float -> Color -> Color

complement

Get the complementary color (opposite on color wheel).

Color -> Color

rotate-hue

Rotate hue by a given number of degrees.

Float -> Color -> Color

with-alpha

Set the alpha (opacity) of a color.

Float -> Color -> Color

mix

Mix two colors together. weight is the amount of the first color (0.0 to 1.0).

Color -> Color -> Float -> Color

grayscale

Convert a color to grayscale.

Color -> Color

invert

Invert a color.

Color -> Color

rgb

Create an RGB color from values 0-255.

Int -> Int -> Int -> Color

rgba

Create an RGBA color from RGB values 0-255 and alpha 0.0-1.0.

Int -> Int -> Int -> Float -> Color

hsl

Create an HSL color from hue 0-360, saturation 0.0-1.0, lightness 0.0-1.0.

Float -> Float -> Float -> Color

hsla

Create an HSLA color.

Float -> Float -> Float -> Float -> Color

hex

Create a color from a hex string.

String -> Color

named

Create a named color.

String -> Color

star

Create a star shape.

Parameters:

  • config - Record with cx, cy, points, outer-r, inner-r (required);
  • fill, stroke, stroke-width, id, class (optional)

Returns: Element: A path element representing a star

SVG.star {cx: 100.0, cy: 100.0, points: 5, outer-r: 50.0, inner-r: 25.0, fill: "gold"}

regular-polygon

Create a regular polygon shape.

Parameters:

  • config - Record with cx, cy, sides, radius (required);
  • fill, stroke, stroke-width, id, class (optional)

Returns: Element: A path element representing a regular polygon

SVG.regular-polygon {cx: 100.0, cy: 100.0, sides: 6, radius: 50.0, fill: "blue"}

arrow

Create an arrow shape (line with arrowhead).

Parameters:

  • config - Record with start (Point or {x, y}), end (Point or {x, y}), head-size (required);
  • stroke, stroke-width, id, class (optional)

Returns: Element: A path element representing an arrow

SVG.arrow {start: {x: 0.0, y: 0.0}, end: {x: 100.0, y: 100.0}, head-size: 10.0, stroke: "black"}

rounded-rect

Create a rounded rectangle with uniform corner radius.

Parameters:

  • config - Record with x, y, width, height, radius (required);
  • fill, stroke, stroke-width, opacity, id, class (optional)

Returns: Element: A rect element with uniform corner radius

SVG.rounded-rect {x: 10.0, y: 10.0, width: 100.0, height: 50.0, radius: 10.0, fill: "blue"}

path-new

Create an empty path element.

Returns: Element: An empty path element

SVG.path-new
  |> SVG.move-to 0.0 0.0
  |> SVG.line-to 100.0 100.0
  |> SVG.close-path

move-to

Add a move-to command to a path.

move-to-rel

Add a relative move-to command to a path.

line-to

Add a line-to command to a path.

line-to-rel

Add a relative line-to command to a path.

horizontal-to

Add a horizontal line command to a path.

horizontal-rel

Add a relative horizontal line command to a path.

vertical-to

Add a vertical line command to a path.

vertical-rel

Add a relative vertical line command to a path.

curve-to

Add a cubic bezier curve command to a path.

curve-to-rel

Add a relative cubic bezier curve command to a path.

smooth-to

Add a smooth cubic bezier curve command to a path.

smooth-to-rel

Add a relative smooth cubic bezier curve command to a path.

quad-to

Add a quadratic bezier curve command to a path.

quad-to-rel

Add a relative quadratic bezier curve command to a path.

smooth-quad-to

Add a smooth quadratic bezier curve command to a path.

smooth-quad-to-rel

Add a relative smooth quadratic bezier curve command to a path.

arc-to

Add an arc command to a path.

arc-to-rel

Add a relative arc command to a path.

close-path

Close the current path.

path-fill

Set fill on a path.

path-stroke

Set stroke on a path.

path-stroke-width

Set stroke-width on a path.

path-stroke-linecap

Set stroke-linecap on a path.

path-stroke-linejoin

Set stroke-linejoin on a path.

path-stroke-dasharray

Set stroke-dasharray on a path.

path-stroke-dashoffset

Set stroke-dashoffset on a path.

rect-path

Create a path element from rectangle coordinates. Returns a closed rectangular path.

Parameters:

  • config - Record with x, y, width, height (required)

Returns: Element: A path element representing a rectangle

SVG.rect-path {x: 10.0, y: 10.0, width: 100.0, height: 50.0}
  |> SVG.path-fill "blue"

circle-path

Create a path element approximating a circle using bezier curves. Returns a closed circular path.

Parameters:

  • config - Record with cx, cy, r (required)

Returns: Element: A path element approximating a circle

SVG.circle-path {cx: 50.0, cy: 50.0, r: 25.0}
  |> SVG.path-fill "red"

arc-path

Create an arc path from start angle to end angle.

Parameters:

  • config - Record with cx, cy, r, start, end (all in degrees; required)

Returns: Element: A path element representing an arc

SVG.arc-path {cx: 50.0, cy: 50.0, r: 40.0, start: 0.0, end: 90.0}
  |> SVG.path-stroke "blue"
  |> SVG.path-fill "none"

pie-slice-path

Create a pie slice path (arc with lines to center).

Parameters:

  • config - Record with cx, cy, r, start, end (all in degrees; required)

Returns: Element: A path element representing a pie slice

SVG.pie-slice-path {cx: 100.0, cy: 100.0, r: 80.0, start: 0.0, end: 60.0}
  |> SVG.path-fill "orange"

new

Create a new SVG document with the given dimensions.

Parameters:

  • config - Record with width and height (both required)

Returns: SvgDoc: A new SVG document

doc = SVG.new {width: 400, height: 300}

view-box

Set the viewBox attribute on an SVG document.

Parameters:

  • doc - The SVG document
  • box - Record with min-x, min-y, width, height

Returns: SvgDoc: Document with viewBox set

doc |> SVG.view-box {min-x: 0, min-y: 0, width: 100, height: 100}

add

Add an element to the SVG document.

Parameters:

  • doc - The SVG document
  • element - The element to add

Returns: SvgDoc: Document with element added

doc |> SVG.add (SVG.rect {x: 0, y: 0, width: 100, height: 50})

add-all

Add multiple elements to the SVG document.

Parameters:

  • doc - The SVG document
  • elements - List of elements to add

Returns: SvgDoc: Document with elements added

doc |> SVG.add-all [rect1, rect2, circle1]

add-def

Add a definition (gradient, pattern, marker, etc.) to the SVG document.

Parameters:

  • doc - The SVG document
  • def - The definition to add

Returns: SvgDoc: Document with definition added

doc |> SVG.add-def gradient

arrow-marker

Create an arrow marker pointing right.

Parameters:

  • config - Record with id, size (required); color (optional, defaults to "black")

Returns: Def: A marker definition with an arrow shape

arrow = SVG.arrow-marker {id: "arrow", size: 10.0}
doc |> SVG.add-def arrow

circle-marker

Create a circle marker.

Parameters:

  • config - Record with id, radius (required); fill (optional, defaults to "black")

Returns: Def: A marker definition with a circle shape

dot = SVG.circle-marker {id: "dot", radius: 3.0, fill: "red"}
doc |> SVG.add-def dot

square-marker

Create a square marker.

Parameters:

  • config - Record with id, size (required); fill (optional, defaults to "black")

Returns: Def: A marker definition with a square shape

square = SVG.square-marker {id: "square", size: 6.0, fill: "blue"}
doc |> SVG.add-def square

diamond-marker

Create a diamond marker.

Parameters:

  • config - Record with id, size (required); fill (optional, defaults to "black")

Returns: Def: A marker definition with a diamond shape

diamond = SVG.diamond-marker {id: "diamond", size: 8.0, fill: "green"}
doc |> SVG.add-def diamond

marker-url

Create a marker URL reference for use with marker-start, marker-mid, or marker-end.

Animate

Animation element for animating a single attribute Fields: attribute-name, from, to, by, values, dur, begin, end, repeat-count, repeat-dur, fill-mode, calc-mode, key-times, key-splines, additive, accumulate

Variants

Animate {_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15}

AnimateTransform

Transform animation element Fields: type, from, to, by, values, dur, begin, end, repeat-count, repeat-dur, fill-mode, calc-mode, key-times, key-splines, additive, accumulate

Variants

AnimateTransform {_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15}

AnimateMotion

Motion animation element (animate along a path) Fields: path, mpath-href, rotate, dur, begin, end, repeat-count, repeat-dur, fill-mode, calc-mode, key-times, key-splines, key-points

Variants

AnimateMotion {_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12}

Set

Set element (sets a value at a specific time) Fields: attribute-name, to, begin, end, dur

Variants

Set {_0, _1, _2, _3, _4}

animate

Create an animate element to animate a single attribute.

Required config fields: - attribute: String - the attribute to animate (e.g., "cx", "opacity", "fill")

Optional config fields: - from: String - starting value - to: String - ending value - by: String - relative change - values: String - semicolon-separated keyframe values - dur: String - duration (e.g., "2s", "500ms") - begin: String - when to start (e.g., "0s", "click", "mouseover") - end: String - when to end - repeat-count: String - number of repetitions or "indefinite" - repeat-dur: String - total duration of repetitions - fill-mode: String - "freeze" or "remove" (what happens after) - calc-mode: String - "discrete", "linear", "paced", or "spline" - key-times: String - semicolon-separated time values (0 to 1) - key-splines: String - cubic bezier control points - additive: String - "replace" or "sum" - accumulate: String - "none" or "sum"

{attribute: String, ...} -> Animate

animate-transform

Create an animateTransform element for transform animations.

Required config fields: - type: String - transform type: "translate", "scale", "rotate", "skewX", "skewY"

Optional config fields: - from: String - starting transform values - to: String - ending transform values - by: String - relative change - values: String - semicolon-separated keyframe values - dur: String - duration - begin: String - when to start - end: String - when to end - repeat-count: String - repetitions or "indefinite" - repeat-dur: String - total duration - fill-mode: String - "freeze" or "remove" - calc-mode: String - interpolation mode - key-times: String - time values - key-splines: String - bezier control points - additive: String - "replace" or "sum" - accumulate: String - "none" or "sum"

{type: String, ...} -> AnimateTransform

animate-motion

Create an animateMotion element for path-based animation.

Optional config fields: - path: String - SVG path data for motion - mpath-href: String - reference to a path element by ID - rotate: String - "auto", "auto-reverse", or angle in degrees - dur: String - duration - begin: String - when to start - end: String - when to end - repeat-count: String - repetitions or "indefinite" - repeat-dur: String - total duration - fill-mode: String - "freeze" or "remove" - calc-mode: String - interpolation mode - key-times: String - time values - key-splines: String - bezier control points - key-points: String - points along the path

{...} -> AnimateMotion

set

Create a set element to set an attribute at a specific time.

Required config fields: - attribute: String - the attribute to set - to: String - the value to set

Optional config fields: - begin: String - when to set the value - end: String - when to revert (optional) - dur: String - how long to maintain the value

{attribute: String, to: String, ...} -> Set

fade-in

Create a simple fade-in animation.

String -> Animate

fade-out

Create a simple fade-out animation.

String -> Animate

pulse

Create a pulse animation (scale up and down).

String -> AnimateTransform

spin

Create a continuous rotation animation.

Float -> Float -> String -> AnimateTransform

shake

Create a horizontal shake animation.

String -> AnimateTransform

bounce

Create a bounce animation (vertical).

String -> AnimateTransform

color-transition

Create a color transition animation.

String -> String -> String -> Animate

draw-stroke

Create a stroke dash animation (drawing effect).

String -> String -> Animate

render-animate

Render an Animate element to XML string.

Animate -> String

render-animate-transform

Render an AnimateTransform element to XML string.

AnimateTransform -> String

render-animate-motion

Render an AnimateMotion element to XML string.

AnimateMotion -> String

render-set

Render a Set element to XML string.

Set -> String

Matrix

2D affine transformation matrix Fields: a, b, c, d, e, f (following SVG matrix notation)

Variants

Matrix {_0, _1, _2, _3, _4, _5}

identity

Create the identity matrix (no transformation).

translate

Create a translation matrix.

scale

Create a uniform scale matrix.

scale-xy

Create a non-uniform scale matrix.

rotate

Create a rotation matrix (angle in degrees).

rotate-around

Create a rotation matrix around a point (angle in degrees).

skew-x

Create a skewX matrix (angle in degrees).

skew-y

Create a skewY matrix (angle in degrees).

multiply

Multiply two matrices (compose transformations). The result applies m2 first, then m1.

compose

Compose a list of matrices (left to right application). compose [m1, m2, m3] applies m1 first, then m2, then m3.

determinant

Calculate the determinant of a matrix.

inverse

Calculate the inverse of a matrix. Returns None if the matrix is not invertible (determinant is 0).

transform-point

Apply a matrix transformation to a point.

is-identity?

Check if a matrix is the identity matrix.

to-string

Convert matrix to SVG matrix() transform string.

to-transform-string

Convert matrix to individual transform operations (if possible). This produces more readable output for simple transforms. Falls back to matrix() for complex transforms.

get-a

Get the a component (scale x / cos rotation).

get-b

Get the b component (skew y / sin rotation).

get-c

Get the c component (skew x / -sin rotation).

get-d

Get the d component (scale y / cos rotation).

get-e

Get the e component (translate x).

get-f

Get the f component (translate y).

get-translation

Extract translation components.

get-scale

Extract scale factors (approximate, assumes no skew).

get-rotation

Extract rotation angle in degrees (approximate, assumes no skew).

BBox

Axis-aligned bounding box Fields: x (left), y (top), width, height

Variants

BBox {_0, _1, _2, _3}

new

Create a bounding box from x, y, width, height.

from-rect

Create a bounding box from a rectangle.

from-circle

Create a bounding box from a circle.

from-ellipse

Create a bounding box from an ellipse.

from-line

Create a bounding box from a line.

from-points

Create a bounding box from a list of points. Each point is a record with x and y fields.

from-extents

Create a bounding box from min/max coordinates.

empty

Create an empty bounding box (zero size at origin).

infinite

Create an "infinite" bounding box for initial merge operations. Use this as starting point when merging multiple boxes.

get-x

Get the x coordinate (left edge).

get-y

Get the y coordinate (top edge).

get-width

Get the width.

get-height

Get the height.

get-right

Get the right edge (x + width).

get-bottom

Get the bottom edge (y + height).

center

Get the center point.

top-left

Get the top-left corner.

top-right

Get the top-right corner.

bottom-left

Get the bottom-left corner.

bottom-right

Get the bottom-right corner.

area

Get the area of the bounding box.

perimeter

Get the perimeter of the bounding box.

aspect-ratio

Get the aspect ratio (width / height).

merge

Merge two bounding boxes into one that contains both.

merge-all

Merge a list of bounding boxes.

intersect

Intersect two bounding boxes. Returns None if they don't overlap.

contains-point?

Check if a point is inside the bounding box.

contains-box?

Check if the first bounding box completely contains the second.

overlaps?

Check if two bounding boxes overlap.

expand

Expand a bounding box by a given amount on all sides.

expand-sides

Expand a bounding box by different amounts on each side.

contract

Contract a bounding box by a given amount on all sides. Will not create negative dimensions.

translate

Translate a bounding box by dx, dy.

scale

Scale a bounding box uniformly around its center.

scale-from-origin

Scale a bounding box from origin (0, 0).

is-empty?

Check if a bounding box is empty (zero or negative dimensions).

is-valid?

Check if a bounding box is valid (positive dimensions).

is-square?

Check if a bounding box is square (width equals height).

to-viewbox

Convert to SVG viewBox attribute value.

to-record

Convert to a record with named fields.

to-string

Convert to a string representation.

linear-gradient

Create a linear gradient definition.

gradient-direction

Set the direction of a linear gradient.

radial-gradient

Create a radial gradient definition.

gradient-stop

Add a stop to a gradient.

url

Create a URL reference for use with fill/stroke.

with-fill

Set the fill attribute on an element.

with-stroke

Set the stroke attribute on an element.

with-stroke-width

Set the stroke-width attribute on an element.

with-opacity

Set the opacity attribute on an element.

with-id

Set the id attribute on an element.

with-class

Set the class attribute on an element.

with-transform

Set the transform attribute on an element.

with-title

Add a title element to an SVG document.

with-desc

Add a desc element to an SVG document.

with-stroke-linecap

Set the stroke-linecap attribute on an element.

with-stroke-linejoin

Set the stroke-linejoin attribute on an element.

with-stroke-dasharray

Set the stroke-dasharray attribute on an element.

group-new

Create an empty group element.

Returns: Element: An empty group element

SVG.group-new
  |> SVG.group-add rect
  |> SVG.group-add circle

group-add

Add an element to a group.

group-add-all

Add multiple elements to a group.

group-id

Set the ID attribute on a group.

group-class

Set the class attribute on a group.

group-transform

Set the transform attribute on a group.

render

Render an SVG document to an XML string.

Parameters:

  • doc - The SVG document to render

Returns: String: The SVG as an XML string

xml = SVG.render doc
File.write "output.svg" xml

render-pretty

Render an SVG document with pretty printing.

Parameters:

  • doc - The SVG document to render
  • indent - Number of spaces for indentation

Returns: String: The SVG as a pretty-printed XML string

format-num

Format a number for SVG output. Integers are rendered without decimal points.

translate

Create a translate transform string.

rotate

Create a rotate transform string.

rotate-around

Create a rotate transform string around a point.

scale

Create a scale transform string.

scale-xy

Create a scale transform string with separate x and y factors.

skew-x

Create a skewX transform string.

skew-y

Create a skewY transform string.

PathCommand

Path command for the Path DSL

Variants

MoveTo {_0, _1}
MoveToRel {_0, _1}
LineTo {_0, _1}
LineToRel {_0, _1}
HorizontalTo {_0}
HorizontalRel {_0}
VerticalTo {_0}
VerticalRel {_0}
CurveTo {_0, _1, _2, _3, _4, _5}
CurveToRel {_0, _1, _2, _3, _4, _5}
SmoothTo {_0, _1, _2, _3}
SmoothToRel {_0, _1, _2, _3}
QuadTo {_0, _1, _2, _3}
QuadToRel {_0, _1, _2, _3}
SmoothQuadTo {_0, _1}
SmoothQuadToRel {_0, _1}
ArcTo {_0, _1, _2, _3, _4, _5, _6}
ArcToRel {_0, _1, _2, _3, _4, _5, _6}
ClosePath

GradientStop

Gradient stop: offset (0-1), color, opacity (0-1)

Variants

GradientStop {_0, _1, _2}

TSpan

Text span: dx, dy, content

Variants

TSpan {_0, _1, _2}

RichSpan

Rich text span with styling options RichSpan: content, dx, dy, fill, font-family, font-size, font-weight, font-style, baseline-shift

Variants

RichSpan {_0, _1, _2, _3, _4, _5, _6, _7, _8}

Point

Point: x, y coordinates

Variants

Point {_0, _1}

Element

SVG element types

Variants

ERect {_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16}
ECircle {_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13}
EEllipse {_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14}
ELine {_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13}
EPolyline {_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10}
EPolygon {_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10}
EPath {_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10}
EText {_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10}
EGroup {_0, _1, _2, _3}
EImage {_0, _1, _2, _3, _4, _5, _6}
EUse {_0, _1, _2, _3, _4, _5, _6}
ETitle {_0}
EDesc {_0}
EStyle {_0}
ETextPath {_0, _1, _2, _3, _4, _5, _6}
ERichText {_0, _1, _2, _3, _4, _5, _6, _7, _8, _9}
ERaw {_0}

Def

Definition types (gradients, patterns, markers, etc.)

Variants

DLinearGradient {_0, _1, _2, _3, _4, _5}
DRadialGradient {_0, _1, _2, _3, _4, _5, _6}
DPattern {_0, _1, _2, _3}
DMarker {_0, _1, _2, _3, _4, _5, _6}
DClipPath {_0, _1}
DMask {_0, _1}
DSymbol {_0, _1, _2}

SvgDoc

SVG document: width, height, view-box, preserve-aspect-ratio, defs, children

Variants

SvgDoc {_0, _1, _2, _3, _4, _5}

rect

Create a rectangle element.

Parameters:

  • config - Record with x, y, width, height (required); rx, ry, fill, stroke, etc. (optional)

Returns: Element: A rectangle element

SVG.rect {x: 10.0, y: 10.0, width: 100.0, height: 50.0}
SVG.rect {x: 10.0, y: 10.0, width: 100.0, height: 50.0, rx: 5.0, fill: "#ff0000"}

circle

Create a circle element.

Parameters:

  • config - Record with cx, cy, r (required)

Returns: Element: A circle element

SVG.circle {cx: 50.0, cy: 50.0, r: 25.0}
SVG.circle {cx: 50.0, cy: 50.0, r: 25.0, fill: "red"}

ellipse

Create an ellipse element.

Parameters:

  • config - Record with cx, cy, rx, ry (required)

Returns: Element: An ellipse element

SVG.ellipse {cx: 50.0, cy: 50.0, rx: 40.0, ry: 20.0}

line

Create a line element.

Parameters:

  • config - Record with x1, y1, x2, y2 (required)

Returns: Element: A line element

SVG.line {x1: 0.0, y1: 0.0, x2: 100.0, y2: 100.0}

polyline

Create a polyline element (open shape).

Parameters:

  • config - Record with points (list of Point values)

Returns: Element: A polyline element

SVG.polyline {points: [SVG.pt 0.0 0.0, SVG.pt 50.0 25.0, SVG.pt 100.0 0.0]}

polygon

Create a polygon element (closed shape).

Parameters:

  • config - Record with points (list of Point values)

Returns: Element: A polygon element

SVG.polygon {points: [SVG.pt 50.0 0.0, SVG.pt 100.0 100.0, SVG.pt 0.0 100.0]}  # Triangle

pt

Create a point for use with polyline and polygon.

text

Create a text element.

Parameters:

  • config - Record with x, y, content (required)

Returns: Element: A text element

SVG.text {x: 50.0, y: 50.0, content: "Hello"}

image

Create an image element.

Parameters:

  • config - Record with x, y, width, height, href (required)

Returns: Element: An image element

SVG.image {x: 0.0, y: 0.0, width: 100.0, height: 100.0, href: "logo.png"}

use

Create a use element to reference a symbol.

Parameters:

  • config - Record with href, x, y, width, height

Returns: Element: A use element

SVG.use {href: "my-symbol", x: 0.0, y: 0.0, width: 50.0, height: 50.0}

raw

Create a raw XML element (for custom SVG content).

title

Create a title element for accessibility.

Parameters:

  • content - The title text

Returns: Element: A title element

SVG.title "My Chart"

desc

Create a desc element for accessibility.

Parameters:

  • content - The description text

Returns: Element: A desc element

SVG.desc "A bar chart showing quarterly sales"

style

Create a style element for embedded CSS.

Parameters:

  • css - The CSS content

Returns: Element: A style element

SVG.style ".highlight { fill: yellow; }"

text-block

Create a text block with automatic line wrapping based on newlines.

The leading parameter controls line spacing as a multiplier of font-size. For example, leading: 1.5 with font-size: 16 results in 24px line spacing.

Parameters:

  • config - Record with x, y, content (required); leading, font-size, fill, etc. (optional)

Returns: Element: A text element with tspan children for each line

SVG.text-block {x: 10.0, y: 20.0, content: "Line 1\nLine 2\nLine 3", leading: 1.5, font-size: "16"}

text-path

Create a text-path element for text flowing along a path.

Parameters:

  • config - Record with href (path id), content (required); start-offset, spacing, method, id, class (optional)

Returns: Element: A textPath element

SVG.text-path {href: "curve", content: "Text along a curve", start-offset: "10%"}

tspan-styled

Create a rich text span with styling.

Parameters:

  • config - Record with content (required); dx, dy, fill, font-family, font-size, font-weight, font-style, baseline-shift (optional)

Returns: RichSpan: A styled text span

SVG.tspan-styled {content: "bold text", font-weight: "bold"}
SVG.tspan-styled {content: "italic", font-style: "italic"}
SVG.tspan-styled {content: "subscript", baseline-shift: "sub", font-size: "smaller"}

tspan

Create a simple rich text span (just content, no styling).

Parameters:

  • content - The text content

Returns: RichSpan: A plain text span

SVG.tspan "plain text"

rich-text

Create a rich text element from a list of styled spans.

Parameters:

  • config - Record with x, y (required); fill, font-family, font-size, font-weight, anchor, id, class (optional)
  • spans - List of RichSpan values

Returns: Element: A text element with rich content

SVG.rich-text {x: 10.0, y: 20.0, font-size: "16"} [
  SVG.span "Normal text ",
  SVG.tspan-styled {content: "bold", font-weight: "bold"},
  SVG.span " and ",
  SVG.tspan-styled {content: "italic", font-style: "italic"}
]