Documentation

Geon
DSL Reference

A zero-dependency JavaScript library that renders static 2D geometric scenes from a concise, natural-language-like DSL into SVG — directly in the browser.

No dependencies Single file SVG output Browser native

Design philosophy: Geon is deliberately minimal. No curly braces, no semicolons, no heavy punctuation. Line-based declarations, lowercase keywords, and order-sensitive evaluation keep programs readable and predictable.


Quickstart

Drop geon.js into your page. Call Geon.render(source, container). That's it.

<!-- 1. Include the library -->
<script src="geon.js"></script>

<!-- 2. Create a container -->
<div id="canvas"></div>

<!-- 3. Render a scene -->
<script>
Geon.render(`
  scene 600x400
  grid x -5 to 5 step 1 y -5 to 5 step 1

  point A (0,0)
  circle C center A r 2 stroke blue

  label A "Origin"
  label C "Circle C"
`, document.getElementById("canvas"));
</script>

Installation

Geon is a single file with zero external dependencies. Download and include it directly.

# Via <script> tag (recommended)
<script src="geon.js"></script>

# Or inline the contents of geon.js directly into your HTML

Once included, the global Geon object is available on window.


Program Structure

Every Geon program follows this grammar. Both scene and grid are mandatory and must appear before any statements.

Program   ::= SceneDecl GridDecl Statement*
Statement ::= Point | Segment | Circle | Polygon | Label
Strict order: Geon does not support forward references. Every identifier must be declared before it is used. Statements are evaluated top-to-bottom, exactly as written.

Scene

Declares the SVG viewport dimensions in pixels. Must be the first statement.

scene <width>x<height>
Example
scene 600x400   # 600px wide, 400px tall
scene 800x800   # Square canvas
FieldTypeDescription
widthintegerSVG width in pixels
heightintegerSVG height in pixels

Grid

Defines the logical coordinate system — the bounds and step interval for both axes. The grid is rendered as light lines in the SVG, with the x=0 and y=0 axes drawn darker.

grid x <xmin> to <xmax> step <dx> y <ymin> to <ymax> step <dy>
Example
grid x -5 to 5 step 1 y -5 to 5 step 1
grid x 0 to 10 step 2 y 0 to 10 step 2
FieldConstraintDescription
xmin / xmaxxmin < xmaxHorizontal logical bounds
ymin / ymaxymin < ymaxVertical logical bounds
dx / dy> 0Grid line interval
Note: The Y-axis is inverted from SVG's default. In Geon, positive Y goes up, matching standard math conventions.

Point

Declares a named point. Points render as small filled circles and serve as anchors for other shapes.

point <id> (<x>,<y>)
point <id> <AnchorExpr>
Examples
point A (0,0)                 # Absolute coordinate
point B A + (2,1)             # Offset from another point
point P C.center + (1,0)      # Offset from circle center
point Q T.p2                   # Second vertex of polygon T

Segment

Draws a line between two anchor expressions. Renders as an SVG <line>.

segment <id> from <AnchorExpr> to <AnchorExpr> [style]
Examples
segment AB from A to B
segment S from (-2,0) to (2,0) stroke red width 3
segment R from A to C.center stroke blue
AnchorReturns
segId.fromStart point of the segment
segId.toEnd point of the segment

Circle

Draws a circle. The radius is specified in logical (grid) units. Renders as SVG <circle>.

circle <id> center <AnchorExpr> r <number> [style]
Examples
circle C center A r 2
circle C center (0,0) r 3 stroke blue fill rgba(0,0,255,0.1)
circle D center C.center r 0  # Renders as a dot
AnchorReturns
circleId.centerCenter point of the circle
Radius = 0 is allowed and renders as a point. Negative radius throws an error.

Polygon

Draws a closed polygon through a sequence of anchor expressions. Requires at least 3 points. Renders as SVG <polygon>.

polygon <id> points <AnchorExpr> <AnchorExpr> <AnchorExpr> ... [style]
Examples
polygon T points A B (1,2)
polygon Q points (-1,-1) (1,-1) (1,1) (-1,1) fill rgba(255,0,0,0.2)
AnchorReturns
polyId.p1, p2, p3, …The Nth vertex (1-indexed)
polyId.centroid (label only)Geometric center of the polygon

Anchor Expressions

An anchor expression resolves to a 2D coordinate. They are used wherever a position is needed.

AnchorExpr ::=
    (x,y)                      # Literal coordinate
  | pointId                    # Named point
  | shapeId.anchor            # Named anchor on a shape
  | AnchorExpr + (dx,dy)     # Vector offset
Supported Shape Anchors
ShapeAnchorDescription
pointpointIdThe point itself
circlecircleId.centerCenter of the circle
polygonpolyId.p1polyId.pNNth vertex
segmentsegId.from, segId.toEndpoints
Valid Vector Addition
# ✓ Right-hand side must always be a literal (dx,dy)
point P A + (1,0)
point Q C.center + (-1,2)

# ✗ Cannot add two anchor refs together
point B A + A   # Error: expected (dx,dy)
Circular dependencies are detected. An anchor chain that references itself — directly or transitively — is a hard error.

Styling

Style tokens are appended inline after the shape declaration. All tokens are optional; unspecified properties use their defaults.

circle C center (0,0) r 2  stroke blue  fill rgba(0,100,255,0.15)  width 3
segment S from A to B       stroke #e07b54  width 2
polygon T points A B (1,2)  fill rgba(255,0,0,0.2)  stroke red
TokenDefaultAccepts
strokeblackAny CSS color: named, hex, rgb, rgba
fillnoneAny CSS color, or none
width2Number ≥ 0 (pixels)
Invalid color names are passed directly to SVG — the browser will silently use its fallback. Negative width is an error.

Labels

Attaches a text annotation to a declared shape or point. Labels are always rendered as the topmost layer, after all shapes.

label <target> "<text>"
Examples
label A  "Origin"
label C  "Unit Circle"
label T  "Triangle"
label AB "Hypotenuse"

# Multiple labels on the same target are both rendered (stacked)
label A "First"
label A "Second"
Target TypeLabel Anchors At
pointExact point location
circleCenter of the circle
segmentMidpoint of the segment
polygonCentroid of the polygon

Rendering Order

Geon renders in three layers, in this fixed sequence:

Layer 1 Grid lines and axis labels
Layer 2 Shapes — in declaration order (later shapes appear on top)
Layer 3 Labels — always on top, regardless of where label appears in source
circle A center (0,0) r 2   # drawn first → underneath
circle B center (1,0) r 2   # drawn second → on top of A

Coordinate System

Geon uses a standard mathematical coordinate system: Y increases upward. This is the opposite of SVG's default (where Y increases downward). The mapping is handled automatically.

# Logical space (Geon)    →   SVG pixel space
(xmin, ymax)  top-left    →   (0, 0)
(xmax, ymin)  bottom-right →  (width, height)
(0, 0)        origin      →   center (if grid is symmetric)

JavaScript API

The global Geon object exposes a single function.

Signature
Geon.render(source: string, container: HTMLElement): Result

Result ::= { success: true }
         | { success: false, error: string }
Behavior
ConditionEffect
SuccessClears container, appends the rendered <svg>
ErrorClears container, appends a styled error message div; returns { success: false, error }
Example with error handling
const result = Geon.render(source, document.getElementById('canvas'));
if (!result.success) {
  console.error('Geon error:', result.error);
}

Error Reference

All errors include a line number where possible. Errors stop execution immediately — no partial rendering occurs.

ErrorTrigger
Missing scene declaration No scene statement in program
Missing grid declaration No grid statement in program
Undefined identifier 'X' Referencing a name that was never declared
Duplicate identifier 'X' Declaring the same name twice
Circular reference A point that depends on itself (directly or transitively)
Invalid anchor 'X.prop' Accessing a property that does not exist on the shape (e.g. circle.radius)
Polygon requires >= 3 points A polygon with fewer than 3 vertices
Radius must be >= 0 A circle with a negative radius
Width must be >= 0 A negative width style token
Grid step must be > 0 A step value of zero or negative
Grid x min must be < x max Inverted grid range
Undefined label target 'X' label X "..." where X was never declared
Unknown keyword 'X' Unrecognized keyword — also catches capitalized keywords like Point
Malformed coordinate Coordinates like (1,) or (,2)
Expected (dx,dy) after '+' Vector addition with non-literal right-hand side

Edge Cases

A summary of how Geon handles boundary and degenerate inputs.

Forward References
Using an identifier before it is declared
Error
segment S from A to B   # Error: A not declared yet
point A (0,0)
point B (1,1)
Circular Dependency
Two or more points that form a dependency cycle
Error
point A B + (1,0)   # A depends on B
point B A + (0,1)   # B depends on A → cycle
Zero Radius Circle
A circle with radius = 0
Allowed
circle C center (0,0) r 0   # Renders as a dot
Zero-Length Segment
A segment whose endpoints are identical
Allowed
point A (1,1)
segment S from A to A   # Renders as point-like line
Degenerate / Collinear Polygon
All points on the same line (area = 0)
Allowed (renders as line)
polygon T points (0,0) (1,1) (2,2)
Self-Intersecting Polygon
A non-simple (butterfly/bowtie) polygon
Allowed
polygon P points (0,0) (2,2) (0,2) (2,0)   # SVG handles it
Coordinates Outside Grid
Points or shapes outside the declared bounds
Allowed (SVG clips)
point A (1000,1000)   # Will be outside SVG viewport
Extra Whitespace
Multiple spaces between tokens
Allowed
point   A    (0,0)   # Valid
Capitalized Keywords
Keywords must be lowercase
Error
Point A (0,0)    # Error: keywords are lowercase
Circle C ...     # Error

Full Example

A complete Geon program demonstrating all major features: anchor chaining, shape anchors, polygon fill, and labels.

scene 600x400
grid x -5 to 5 step 1 y -5 to 5 step 1

# Define anchor points
point A (0,0)
point B (3,0)

# Draw a segment between them
segment AB from A to B stroke #555 width 2

# Circle centered on A
circle C center A r 2 stroke blue fill rgba(0,0,255,0.08)

# Triangle using A, B, and a literal coordinate
polygon T points A B (1,3) fill rgba(255,100,0,0.15) stroke orange

# Point derived from circle center
point P C.center + (1,0)

# Labels
label A  "Origin"
label C  "Circle C"
label T  "Triangle"
label AB "Base"