Graphs - SVG Charts

GRAPH generates a chart as a pure <svg> element — no wrapping page, no HTML boilerplate. The output is a real Value::Html fragment, the same native node type built for OcaltQL HTML — embed it directly via HTML APPEND, or emit it as raw SVG markup.

Native rendering. Chart geometry — scaling data into pixel coordinates, computing axis tick intervals, generating line/curve paths, calculating pie-slice arcs — is computed natively inside the OcaltQL runtime, matching the hand-built precedent of the JSON parser, the HTML parser, the WHERE-clause AST, and the CALCULATE expression parser elsewhere in this platform. No external charting library is shelled out to.

Syntax

Full Form
GRAPH TYPE "bar" WITH ?data
TITLE "My Chart"
FORMAT 800 BY 400
THEME "dark"
AXIS X "Month" AND Y "Revenue"
SET ?svg

All modifiers are optional. Minimal form:

Minimal Form — Inline Data
GRAPH TYPE "pie" WITH ["school" AS 35 AND "home" AS 50 AND "play" AS 15] SET ?svg
(* Raw relative values — the renderer computes proportions itself *)

Modifiers

Modifier Syntax Description
TITLETITLE "string"Chart title displayed above the graph
FORMATFORMAT 800 BY 400Width by height, in pixels
THEMETHEME "dark"Colour palette. Options: "dark", "light", "ocean", "pastel"
AXISAXIS X "label" AND Y "label" AND Z "label"Axis labels. Z for 3D/contour types.

Data Tiers

Tier 1 — inline key/value pairs, built with the confirmed object-literal bracket syntax (pie, donut, funnel, gauge, waffle, progress):

Tier 1 — Inline
GRAPH TYPE "pie" WITH ["sales" AS 40 AND "ops" AS 35 AND "dev" AS 25] SET ?svg

Tier 2 — single-series variable (bar, line, area, scatter, histogram, sparkline, wave, etc.). Shape: ["labels" AS [...] AND "values" AS [...]].

Tier 2 — Building the Data Explicitly
NEW ARRAY SET ?labels
AFTER APPEND "Jan" TO ?labels
AFTER APPEND "Feb" TO ?labels
AFTER APPEND "Mar" TO ?labels
AFTER NEW ARRAY SET ?values
AFTER APPEND 1200 TO ?values
AFTER APPEND 1900 TO ?values
AFTER APPEND 1500 TO ?values
AFTER NEW OBJECT SET ?data
AFTER SET ?data("labels") AS ?labels
AFTER SET ?data("values") AS ?values
AFTER GRAPH TYPE "line" WITH ?data TITLE "Q1 Revenue" SET ?svg

Tier 3 — multi-series variable (bar-grouped, stacked area, radar, candlestick, sankey, tree, etc.). Shape: ["labels" AS [...] AND "series" AS [["name" AS ... AND "values" AS [...]]]].

Tier 3 — Multi-Series
GRAPH TYPE "bar-grouped" WITH ?data TITLE "Regional Sales" SET ?svg

Charting Data Straight from the Database

SELECT ROWS → GROUP BY → GRAPH
GROUP BY "status" FROM DB "shopdb" TABLE "orders" SET ?grouped
AFTER NEW ARRAY SET ?labels
AFTER NEW ARRAY SET ?values
AFTER FOREACH ?grouped SET ?row
OPEN
  APPEND ?row("status") TO ?labels
  AFTER APPEND ?row("count") TO ?values
CLOSE
AFTER NEW OBJECT SET ?data
AFTER SET ?data("labels") AS ?labels
AFTER SET ?data("values") AS ?values
AFTER GRAPH TYPE "bar" WITH ?data TITLE "Orders by Status" SET ?svg

Embedding the Result

Appending into an HTML Document
NEW HTML SET ?page
AFTER HTML "h1" TEXT "Sales Report"
AFTER HTML APPEND ?svg TO ?page
AFTER EMIT ?page
Emitting Raw SVG Directly
GRAPH TYPE "pie" WITH ["school" AS 35 AND "home" AS 50 AND "play" AS 15] SET ?svg
AFTER EMIT ?svg

Reopening a Saved Chart

A chart emitted to a file is ordinary SVG. GRAPH OPEN reads one back into the same native Value::Html fragment GRAPH TYPE produces — so a chart written by one script can be embedded, appended to, or re-emitted by another, using the same tree machinery as HTML REVERSE.

Write a Chart, Reopen It Elsewhere
GRAPH TYPE "bar" WITH ?data TITLE "Q1 Revenue" SET ?svg
AFTER FILE WRITE "/root/charts/q1.svg" CONTENT ?svg

(* ...a later script... *)

GRAPH OPEN "/root/charts/q1.svg" SET ?svg
AFTER NEW HTML SET ?page
AFTER HTML APPEND ?svg TO ?page
AFTER EMIT ?page

Graph Types

Type string Tier Data shape
bar2["labels" AS [...] AND "values" AS [...]]
bar-grouped3["labels" AS [...] AND "series" AS [["name" AS ... AND "values" AS [...]]]]
bar-stacked3["labels" AS [...] AND "series" AS [["name" AS ... AND "values" AS [...]]]]
line2["labels" AS [...] AND "values" AS [...]]
line-multi3["labels" AS [...] AND "series" AS [["name" AS ... AND "values" AS [...]]]]
area2["labels" AS [...] AND "values" AS [...]]
area-stacked3["labels" AS [...] AND "series" AS [["name" AS ... AND "values" AS [...]]]]
scatter2["points" AS [["x" AS ... AND "y" AS ...]]]
bubble2["points" AS [["x" AS ... AND "y" AS ... AND "size" AS ...]]]
histogram2["values" AS [...]]
box3["labels" AS [...] AND "series" AS [["name" AS ... AND "values" AS [...]]]]
violin3["labels" AS [...] AND "series" AS [["name" AS ... AND "values" AS [...]]]]
dot2["labels" AS [...] AND "values" AS [...]]
heatmap3["x_labels" AS [...] AND "y_labels" AS [...] AND "matrix" AS [[...]]]
treemap3["nodes" AS [["name" AS ... AND "value" AS ... AND "parent" AS ...]]]
waffle1/2inline, or ["segments" AS [["name" AS ... AND "value" AS ...]]]
sparkline2["values" AS [...]]
pie1/2inline, or ["segments" AS [["name" AS ... AND "value" AS ...]]]
donut1/2inline, or ["segments" AS [["name" AS ... AND "value" AS ...]]]
funnel1/2inline, or ["stages" AS [["name" AS ... AND "value" AS ...]]]
waterfall2["labels" AS [...] AND "values" AS [...]] (negative values allowed)
sunburst3["nodes" AS [["name" AS ... AND "value" AS ... AND "parent" AS ...]]]
radar3["axes" AS [...] AND "series" AS [["name" AS ... AND "values" AS [...]]]]
gauge1/2inline, or ["value" AS ... AND "min" AS ... AND "max" AS ...]
polar3["labels" AS [...] AND "series" AS [["name" AS ... AND "values" AS [...]]]]
candlestick3["labels" AS [...] AND "series" AS [["name" AS ... AND "ohlc" AS [["o" AS ... AND "h" AS ... AND "l" AS ... AND "c" AS ...]]]]]
ohlc3same as candlestick
sankey3["nodes" AS [["name" AS ...]] AND "links" AS [["source" AS ... AND "target" AS ... AND "value" AS ...]]]
node-edge3["nodes" AS [["id" AS ... AND "label" AS ...]] AND "edges" AS [["from" AS ... AND "to" AS ... AND "label" AS ...]]]
force3same as node-edge
tree3["nodes" AS [["id" AS ... AND "label" AS ... AND "parent" AS ...]]]
flowchart3["nodes" AS [["id" AS ... AND "label" AS ... AND "type" AS ...]] AND "edges" AS [["from" AS ... AND "to" AS ... AND "label" AS ...]]]
state3["states" AS [["id" AS ... AND "label" AS ...]] AND "transitions" AS [["from" AS ... AND "to" AS ... AND "label" AS ...]] AND "initial" AS ...]
wave2["values" AS [...] AND "sample_rate" AS ...]
error-bar3["labels" AS [...] AND "series" AS [["name" AS ... AND "values" AS [...] AND "errors" AS [...]]]]
contour3["x" AS [...] AND "y" AS [...] AND "z" AS [[...]]]
gantt3["tasks" AS [["name" AS ... AND "start" AS ... AND "end" AS ... AND "group" AS ...]]]
timeline3["events" AS [["label" AS ... AND "date" AS ... AND "group" AS ...]]]
calendar-heat2["points" AS [["date" AS ... AND "value" AS ...]]]
progress1/2inline, or ["value" AS ... AND "max" AS ...]
step2["labels" AS [...] AND "values" AS [...]]
bullet2["value" AS ... AND "target" AS ... AND "ranges" AS [...]]