Documentation
Geon
DSL Reference
A zero-dependency JavaScript library that renders static 2D mathematical graphics from a concise, natural-language-like DSL into SVG — directly in the browser.
Design philosophy: Geon is deliberately minimal. Line-based declarations, lowercase keywords, and order-sensitive evaluation keep programs readable and predictable, while v2 adds variables, expressions, plots, reusable styles, and more geometric primitives.
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 600x600 grid x -5 to 5 step 1 y -5 to 5 step 1 let r = 2 point A (0,0) point B polar (r,30) circle C center A r r stroke blue fill lightblue opacity 0.35 segment AB from A to B stroke black width 2 arrow end plot S y=x^2-2 from -3 to 3 stroke crimson width 2 label A "Origin" position southwest label C "Circle C" color blue label S "Parabola" color crimson `, 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 needs one scene and one grid. Identifiers are resolved top-to-bottom, so declare points and shapes before using them.
Program ::= SceneDecl GridDecl Statement* Statement ::= Let | Style | Point | Midpoint | Segment | Circle | Ellipse | Rect | Arc | Polygon | Line | Ray | Bezier | Plot | Intersect | Label | Layer
Scene
Declares the SVG viewport dimensions in pixels. Must be the first statement.
scene <width>x<height>
scene 600x400 # 600px wide, 400px tall scene 800x800 # Square canvas
| Field | Type | Description |
|---|---|---|
width | integer | SVG width in pixels |
height | integer | SVG 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>
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
| Field | Constraint | Description |
|---|---|---|
xmin / xmax | xmin < xmax | Horizontal logical bounds |
ymin / ymax | ymin < ymax | Vertical logical bounds |
dx / dy | > 0 | Grid line interval |
Expressions & Variables
Geon v2 supports numeric expressions in coordinates, polar tuples, radii, dimensions, plot formulas, and let declarations. Function calls such as sin(30) are safest inside tuple expressions; scalar fields and plot formulas should be compact single-token expressions such as r*0.5 or x^2-2.
let <name> = <expression>
let r = 2.5 let theta = 30 point A (r*cos(theta), r*sin(theta)) circle C center A r r*0.5
| Supported | Syntax |
|---|---|
| Operators | +, -, *, /, ^ |
| Constants | pi, tau, e |
| Degree trig | sin, cos, tan |
| Radian trig | sinr, cosr, tanr |
| Other functions | sqrt, abs, floor, ceil, round, log, exp, sign |
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> point <id> polar (<r>,<degrees>)
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 point R polar (3,45) # Polar coordinate from origin
Midpoint
Creates a named point halfway between two existing point-like identifiers.
midpoint <id> of <pointA> <pointB>
midpoint M of A B label M "midpoint"
Segment
Draws a line between two anchor expressions. Renders as an SVG <line>.
segment <id> from <AnchorExpr> to <AnchorExpr> [style]
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
| Anchor | Returns |
|---|---|
segId.from | Start point of the segment |
segId.to | End point of the segment |
segId.mid | Midpoint of the segment |
Circle
Draws a circle. The radius is specified in logical (grid) units.
circle <id> center <AnchorExpr> r <expression> [style]
circle C center A r 2 circle C center (0,0) r 3 stroke blue fill lightblue opacity 0.35 circle D center C.center r 0 # Renders as a dot
| Anchor | Returns |
|---|---|
circleId.center | Center point of the circle |
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]
polygon T points A B (1,2) polygon Q points (-1,-1) (1,-1) (1,1) (-1,1) fill pink opacity 0.6
| Anchor | Returns |
|---|---|
polyId.p1, p2, p3, … | The Nth vertex (1-indexed) |
polyId.centroid | Geometric center of the polygon |
v2 Primitives
Geon v2 adds ellipses, rectangles, arcs, infinite lines, rays, and cubic Bezier curves. All accept the same inline style tokens as existing shapes.
ellipse E center A rx 3 ry 1.5 stroke purple rect R at (-2,2) w 4 h 2 stroke black fill gainsboro opacity 0.5 arc K center A r 3 from 20 to 160 stroke orange width 3 line L through A B stroke gray dash 4,4 ray Y from A through (1,1) stroke red arrow end bezier BZ from (-4,-1) control (-2,3) (2,-3) to (4,1) stroke green
| Primitive | Syntax | Anchors |
|---|---|---|
ellipse | ellipse id center A rx x ry y | center |
rect | rect id at A w x h y | topleft, topright, bottomleft, bottomright, center |
arc | arc id center A r x from deg to deg | center |
line | line id through A B | p1, p2, mid |
ray | ray id from A through B | origin |
bezier | bezier id from A control B C to D | from, to, mid |
Plot & Intersect
Plots sample y=<expression> over an x-domain. Intersections create point symbols from supported shape pairs.
plot P y=x^2 from -3 to 3 stroke crimson width 2 plot Q y=x^3-x from -3 to 3 step 0.05 stroke blue line L through (-3,0) (3,0) circle C center (0,0) r 2 intersect X L C label X "first" label X_2 "second"
step is omitted, plots sample roughly 300 points. Intersections support line-family vs line-family, line-family vs circle, and circle vs circle; the second intersection, when present, is named id_2.
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
| Shape | Anchor | Description |
|---|---|---|
| point | pointId | The point itself |
| circle | circleId.center | Center of the circle |
| ellipse | ellipseId.center | Center of the ellipse |
| rect | rectId.topleft, topright, bottomleft, bottomright, center | Rectangle corners and center |
| arc | arcId.center | Center of the arc |
| polygon | polyId.p1 … polyId.pN | Nth vertex |
| segment | segId.from, segId.to, segId.mid | Endpoints and midpoint |
| line | lineId.p1, lineId.p2, lineId.mid | Defining points and midpoint |
| ray | rayId.origin | Ray origin |
| bezier | bezierId.from, bezierId.to, bezierId.mid | Endpoints and endpoint midpoint |
# ✓ 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)
(r*cos(30), r*sin(30)).
Styling
Style tokens are appended inline after a shape or label declaration, or defined once in a named style block and applied with use.
style construction { stroke gray width 1 dash 4,4 opacity 0.75 } circle C center (0,0) r 2 stroke blue fill lightblue opacity 0.35 width 3 segment S from A to B use construction arrow end label A "Origin" color red size 14
| Token | Default | Accepts |
|---|---|---|
stroke | black | Single-token CSS color names are safest; # starts comments |
fill | none | Single-token CSS color names, or none |
width | 2 | SVG stroke width |
dash | null | SVG dash array such as 4,4 |
opacity | 1 | Number, commonly 0 to 1 |
arrow | null | start, end, or both |
color | #222 | Single-token CSS color names for labels |
size | 12 | Label font size |
use | n/a | Name of a declared style block |
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>" [position <direction>] [style]
label A "Origin" label C "Unit Circle" label T "Triangle" label AB "Hypotenuse" label P "North-east label" position northeast color crimson # Multiple labels on the same target are both rendered; overlaps are auto-avoided label A "First" label A "Second"
| Target Type | Label Anchors At |
|---|---|
| point | Exact point location |
| circle | Center of the circle |
| segment | Midpoint of the segment |
| polygon | Centroid of the polygon |
| rect | Center of the rectangle |
| plot | Middle sampled point |
north, south, east, west, northeast, northwest, southeast, and southwest. Without a hint, labels use automatic overlap avoidance.
Rendering Order
Geon renders in three layers, in this fixed sequence:
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
layer <name> is accepted as a source marker, but the current renderer still uses this fixed grid, shapes, labels order.
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 rendering plus parse/resolve helpers for tooling.
Geon.render(source: string, container: HTMLElement): Result Result ::= { success: true } | { success: false, error: string }
| Condition | Effect |
|---|---|
| Success | Clears container, appends the rendered <svg> |
| Error | Clears container, appends a styled error message div; returns { success: false, error } |
const result = Geon.render(source, document.getElementById('canvas')); if (!result.success) { console.error('Geon error:', result.error); }
Geon.parse(source) # returns { ast, styleBlocks } or throws Geon.resolve(source) # returns resolved scene, grid, symbols, labels, vars Geon.version # "2.0.0"
Error Reference
All errors include a line number where possible. Errors stop execution immediately — no partial rendering occurs.
| Error | Trigger |
|---|---|
Missing 'scene WxH' |
No scene statement in program |
Missing 'grid x ... y ...' |
No grid statement in program |
Undefined identifier 'X' |
Referencing a name that was never declared |
Duplicate id 'X' |
Declaring the same name twice |
Invalid anchor 'X.prop' |
Accessing a property that does not exist on the shape (e.g. circle.radius) |
Expression error in (...) |
A coordinate expression could not be evaluated |
Undefined variable or function: 'x' |
An expression references an unknown variable or function |
Division by zero |
An expression divides by zero |
Polygon requires >= 3 points |
A polygon with fewer than 3 vertices |
Invalid radius |
A circle with a negative radius |
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 |
No intersection found between 'A' and 'B' |
Supported shapes do not intersect |
Cannot intersect shapes of types ... |
Intersection requested for unsupported shape types |
Edge Cases
A summary of how Geon handles boundary and degenerate inputs.
Full Example
A complete Geon v2 program demonstrating variables, reusable styles, polar points, new primitives, plotting, intersections, and labels.
scene 700x450 grid x -6 to 6 step 1 y -4 to 4 step 1 let r = 2.5 let angle = 35 style construction { stroke gray width 1 dash 4,4 opacity 0.75 } # Define anchor points point A (0,0) point B polar (r,angle) midpoint M of A B # Core geometry segment AB from A to B stroke gray width 2 arrow end circle C center A r r stroke blue fill lightblue opacity 0.35 ellipse E center M rx 1.4 ry 0.6 stroke purple fill plum opacity 0.35 rect R at (-5,3) w 2 h 1.25 stroke black fill gainsboro opacity 0.5 arc K center A r 3 from 20 to 150 stroke orange width 3 # Lines, curves, and derived points line L through (-5,-1) (5,2) use construction ray Y from A through (1,1) stroke crimson arrow end bezier BZ from (-4,-2) control (-2,3) (2,-3) to (4,2) stroke green width 2 plot P y=x^2-2 from -3 to 3 step 0.05 stroke crimson width 2 intersect X L C # Labels label A "Origin" position southwest size 14 color black label B "Polar point" position northeast label M "Midpoint" position south label C "Circle C" color blue label X "Intersection" label P "y = x^2 - 2" color crimson