GEML block types, illustrated · page 4 of 5 · spec 1.0 · 中文

GEML Blocks Illustrated · diagram

diagram is used two ways. One hosts an external DSL: the body goes verbatim to the renderer format= selects, and the processor's only duty is not to interpret it. The other is the built-in geml-chart: the chart is described entirely in attributes and bound to a table or a record array, so the processor can check it piece by piece and a mistyped column name is a build error. A third, geml-code-graph, is interpreted too but takes the opposite stance: the embed carries one attribute and nothing else. All three are measured here; the chart's fifteen checks match A.4 row for row.

Board

15 rules, each with its source and status

Specified written into the specification or an accepted GEP. Observed not specified; what the reference implementation does today. Draft gap something a draft should say and does not. No implementation gap was found on this page.

Specified 11 Observed 3 Draft gap 1
RuleSourceStatus
External DSLs
1Raw body; format= selects a pluggable renderer (mermaid, graphviz, d2, plantuml …). A processor must expose the renderer registry and must not interpret the body. An unknown format is a warning; the body is kept.§7 · A.4Specified
2#id makes the diagram referenceable: [[#flow]], with the caption as link text.§7 · §5.2Specified
3No {{key}} interpolation in a raw body; a %% line is body text.§4Specified
4The reference implementation's registry knows mermaid, graphviz, d2, plantuml, geml-chart and geml-code-graph. Only mermaid has a bundled engine: it emits pre.mermaid and loads the mermaid module on the page; the other three DSLs emit pre.diagram-src data-format= verbatim with no warning; vega-lite and any unknown name warn.--to htmlObserved
Data binding and geml-chart
5data= takes the three targets a table's src= takes: a csv/tsv or json/jsonl file, #id, doc.geml#id. A table contributes its model (computed columns included); a data block must be a record array, and every column the chart references must be a scalar in every record; a violation is an error.§7.1 · A.4Specified
6geml-chart lives entirely in attributes: type is one of five, bar line area pie scatter; channels x (category), y (value; a comma list is several series), series, size; x and y required; rows=data|all|summary. The body should be empty; a non-empty one warns.§7.1Specified
7Build-time checks: no data, target not a table, not a record array, no type, unknown type, missing channel, unknown column, unknown rows, non-numeric y, rows=summary with no summary row → error; an unused channel, rows=all with no summary row → warning.A.4Specified
8External data is fetched at render time and column checks are deferred to the renderer; http(s) needs renderer opt-in, because fetching a URL discloses the reader's address and time.§7.1 · §9.4Specified
9For more (annotations, reference lines, heatmaps) use a hosted DSL: format=vega-lite data=#fy; the body is raw and not column-checked.§7.1Specified
10Rendering: geml-chart emits an inline svg.geml-chart role="img" with rect / path / text; no external script.--to htmlObserved
geml-code-graph (GEP-0003, accepted; codemap profile §6)
11geml-code-graph is an interpreted diagram format: a layered method-flow view over a codemap document tree. The embed takes exactly one attribute, src=, naming the codemap's index.geml or one container document; the body is empty, and a non-empty one warns.GEP-0003 · codemap §6Specified
12Roots and depth are never authored at the embed: they come from the meta of the document src points at (entry, graph-depth). View configuration travels with the data, so the embed cannot drift; a different root means pointing at a different container document, and method-level drill-down is a click, not an attribute.GEP-0003Specified
13A missing src= and an unresolvable src are both warnings: nothing to draw, but the document is not wrong.A.4Specified
14Rendering: figure.code-graph > div.cg-mount data-start data-graph, the graph data inlined as JSON and laid out by a page script at draw time; a failed resolution puts a p.render-error in the same figure.--to htmlObserved
15data= may name a view as readily as a table, and for a derived column it must: compute=/summary= are a view's, so the column they produce exists only there. Charting §6.1's FY is data=#fy25-report y=FY; aiming the same chart at the base table is chart: column `FY` not found in table. (This was carried here as a draft gap while GEP-0012 said nothing about charts; §7 now settles it in the normative text.)§7.1 · §6.1Specified
DSL

Four external DSLs and one unknown name

The processor treats them identically: keep the body verbatim. The only difference is whether the renderer has an engine.

mermaid · graphviz · d2 · plantuml · foo Specified rendering observed
GEML · d1-diagram.geml
=== diagram {#flow format=mermaid caption="Review flow"}
graph LR
  A[Draft] --> B{Review}
  B -->|ok| C[Publish]
===
=== diagram {#gv format=graphviz}
digraph { a -> b }
===
=== diagram {#d2 format=d2}
a -> b
===
=== diagram {#pu format=plantuml}
@startuml
a -> b
@enduml
===
=== diagram {#odd format=foo}
anything at all, {{title}} is not interpolated in raw
===
See [[#flow]].
geml check · --to html
warning: no registered renderer for diagram format `foo`; body kept raw (line 21)
0 error(s), 1 warning(s)
figure #flow › pre.mermaid · rendered once the page loads the mermaid module
Draft→Review→ ok →Publish
figure #gv › pre.diagram-src data-format="graphviz" · registered, no bundled engine, source shown
digraph { a -> b }
figure #odd › unknown format, body kept
anything at all, {{title}} is not interpolated in raw

See Review flow.

Rule
§7: format selects the renderer, the raw body is handed over verbatim, and the processor must expose the registry and never interpret the body. An unknown format is only a warning because nothing was lost — nobody drew it, that is all.
Two kinds of "not drawn"
In the measurement, graphviz, d2 and plantuml are in the registry, so they do not warn, but the reference implementation bundles no engine for them and emits the source with a data-format; a host can attach its own engine. vega-lite, though §7.1 uses it as an example, is not in the registry and warns. That is the normal state of an open registry, not a gap.
raw
{{title}} is not interpolated in a raw body (§4) and reaches the output as written; so does %%.
chart

geml-chart: the chart lives in attributes, so it can be checked

Four working examples: bound to a view that derives a computed column, to a record array, to a csv file drawing two series, and with the summary row as an extra point.

Four data sources, one way of describing Specified
GEML · from d2-chart.geml
=== table {#fy format=csv}
Segment,Q1,Q2
Cloud,124.5,131.2
Hardware,88.1,84.6
===
=== view {#fy-report src=#fy compute="FY = Q1 + Q2" summary="Segment = 'Total'; FY = sum(FY)"}
===                                    %% the table holds facts; the view derives FY and the Total row
=== data {#recs}
[{"seg": "Cloud", "fy": 255.7}, {"seg": "Hardware", "fy": 172.7}]
===

=== diagram {#ok format=geml-chart data=#fy-report type=bar x=Segment y=FY caption="FY revenue"}
===                                    %% FY exists only on the view, so bind there — not to #fy
=== diagram {#ok2 format=geml-chart data=#recs type=pie x=seg y=fy}
===                                    %% record array: keys project to columns
=== diagram {#ok3 format=geml-chart data=rows.csv type=line x=Segment y="Q1, Q2"}
===                                    %% a file; a comma list = two series
=== diagram {#sumrow format=geml-chart data=#fy-report type=bar x=Segment y=FY rows=all}
===                                    %% the summary row as one extra point
--to html · #okno diagnostics
svg.geml-chart role="img" · viewBox 0 0 760 380 · rect + text.c-tick
3001500
255.7
172.7
CloudHardware
Inline SVG, no external script. #ok2 is a pie, #ok3 two lines, #sumrow has an extra Total bar. All four bodies are empty.
Why checkable
§7.1: format still only selects the renderer, but the whole description is in attributes the processor can read, so column names, the data id and rows are validated against the table at build time. The body stays empty; anything written there is an ignored-diagram-body warning.
Sources
The three targets have a table's src= shape. A table contributes its own columns; a view over it contributes the derived ones as well, which is why y=FY has to name #fy-report and not #fy — pointing the chart at the base table is a build error (chart: column `FY` not found in table). A data block must be a non-empty sequence of maps, and every referenced column must be a scalar in every record; unreferenced columns may hold anything. A file is an anonymous table or record source.
type
The five values only change how the channels are drawn; they never add attributes. For other shapes switch to a hosted DSL, such as format=vega-lite data=#fy, raw body, columns unchecked.
Checks

Fifteen checks, in one run

Eleven errors and four warnings, matching A.4 row for row.

d2-chart.geml · d3-chart.geml Specified
GEML
=== diagram {#e1 format=geml-chart type=bar x=Segment y=FY}          ← no data
=== diagram {#e2 format=geml-chart data=#n …}                    ← #n is a note
=== diagram {#e3 format=geml-chart data=#badrecs x=seg y=fy}     ← record 2 lacks fy
=== diagram {#e4 format=geml-chart data=#fy-report x=Segment y=FY}  ← no type
=== diagram {#e5 … type=donut …}
=== diagram {#e6 … type=bar x=Segment}                          ← no y
=== diagram {#e7 … y=Nope}
=== diagram {#w1 … type=bar x=Segment y=FY size=Q1}             %% bar does not draw size
=== diagram {#e8 … rows=everything}
=== diagram {#w2 … type=bar x=Segment y=FY}
this body is ignored
===
=== diagram {#e9 … y=Segment}                                ← y column is not numeric

%% d3: #plain is a view with compute= but no summary=
=== diagram {#s1 … data=#plain rows=summary}
=== diagram {#s2 … data=#plain rows=all}
=== diagram {#cg format=geml-code-graph}                         %% no src
=== diagram {#vl format=vega-lite data=#plain}
{"mark": "bar", "encoding": {"y": {"field": "Nope"}}}    %% columns not checked
===
geml check11 error 4 warning
warning: geml-chart body is ignored; the chart spec lives in attributes (line 45)
error: geml-chart: missing `data=#id` (line 27)
error: geml-chart: data target `#n` is not a table (line 29)
error: geml-chart: column `fy` is missing or non-scalar in record 2 (line 31)
error: chart: missing `type` (line 33)
error: chart: unknown type `donut` (supported: bar, line, area, pie,
  scatter; use format=vega-lite for others) (line 35)
error: chart: missing required channel `y` (line 37)
error: chart: column `Nope` not found in table (line 39)
warning: chart: `size` is ignored for type `bar` (line 41)
error: chart: unknown rows scope `everything` (data|all|summary) (line 43)
error: chart: non-numeric value in a y column (line 48)

d3-chart.geml
warning: geml-code-graph: missing `src=` (nothing to render) (line 12)
warning: no registered renderer for diagram format `vega-lite`; body kept raw (line 14)
error: chart: rows=summary but the table has no summary row (line 8)
warning: chart: rows=all but the table has no summary row; using data rows (line 10)
error
The chart description itself does not hold together: no data, data not a table, a record missing a column, no type, a type outside the five, a missing required channel, a column that does not exist, rows outside the three, a non-numeric y, a summary row requested where none exists. All decidable at build time, hence errors.
warning
Drawable but with something extra or missing: a channel the type does not use, rows=all with no summary row (data rows are drawn), a body that was written (ignored). A code-graph without src warns too: nothing to draw, document not wrong.
vega-lite
The Nope column in the body was not checked, as §7.1 says of hosted DSLs; the warning is that the registry has no renderer for it, not a column error.
code-graph

geml-code-graph: a codemap drawn as a method-flow graph

GEP-0003, accepted. Interpreted like geml-chart, but at the other extreme: the embed carries src= and nothing else.

Pointing at the real codemap in the playground Specified rendering observedThe probe ran inside playground/codemap/ and was deleted afterwards; that directory holds the index.geml and one document per container that geml codemap build generated.
GEML · _probe-cg.geml
=== diagram {#g format=geml-code-graph src=index.geml caption="Repo graph"}
===
=== diagram {#g2 format=geml-code-graph src=geml-parser--chart.ts.geml#chart}
===                                    %% with a fragment: not a target it accepts
=== diagram {#g3 format=geml-code-graph src=nowhere.geml}
===
=== diagram {#g4 format=geml-code-graph src=index.geml}
body here is ignored
===
geml check --root playground/codemap · --to html
warning: geml-code-graph: cannot resolve document
  `geml-parser--chart.ts.geml#chart` (line 7)
warning: geml-code-graph: cannot resolve document `nowhere.geml` (line 9)
warning: geml-code-graph body is ignored; the embed is configured by
  `src=` alone (line 11)
0 error(s), 3 warning(s)   exit 0

<figure class="code-graph" id="g"><div class="cg-mount" data-start="…" data-graph="{…}">
<figure class="code-graph" id="g2"><p class="render-error">…
<figure class="code-graph" id="g3"><p class="render-error">…
figure.code-graph #g › div.cg-mount · graph data inlined as JSON, laid out at draw time
index.geml · entry→container→method⋯ click to drill down
Roots and depth come from index.geml's meta; the embed did not write them, and cannot.
src only
GEP-0003: view configuration travels with the data. The root is the codemap document's entry, the depth its graph-depth; the embed cannot write either, so it cannot drift from the data. A different root means a different container document; method-level detail is a click on a node — interaction, not an attribute.
vs chart
Two interpreted formats, two philosophies: geml-chart puts the whole description in attributes so the processor can check every column name; geml-code-graph puts the whole description on the data side so the embed is left with one pointer. Both keep the body empty.
Weights
A missing or unresolvable src is a warning, like a code block's route: nothing to draw, but what the document describes exists somewhere and the document itself is not wrong.
Evidence

Probe files and measured output

All run with the repository's current build, node geml-parser/dist/geml.js.

ProbeCoverscheck resultWhere on this page
d1-diagram.gemlmermaid, graphviz, d2, plantuml, unknown foo, raw not interpolated, caption as link text1 warningExternal DSLs
d2-chart.geml · rows.csvfour working charts; no data, not a table, not a record array, no type, unknown type, missing channel, unknown column, unused channel, unknown rows, non-empty body, non-numeric y9 error 2 warninggeml-chart, Checks
d3-chart.gemlrows=summary with no summary row, rows=all with none, code-graph without src, vega-lite body unchecked1 error 3 warningChecks
playground/codemap/_probe-cg.gemlthe real codemap's index, a target with a fragment, a missing document, a non-empty body3 warninggeml-code-graph