Contributing a new diagram type
Step-by-step guide for adding a new diagram plugin to Schematex — from standard spec to published website example.
A step-by-step guide for adding a new diagram plugin to Schematex — from standard spec to published website example. Read
00-OVERVIEW.mdfirst for the overall architecture.
1. The Pipeline
Every diagram type follows the same pipeline:
Text (DSL) ──► Parser ──► AST ──► Layout ──► LayoutResult ──► Renderer ──► SVG- Parser — hand-written recursive descent; no parser generators, no dependencies.
- Layout — pure functions over the AST that produce absolute geometry. Deterministic, no randomness.
- Renderer — string-building SVG via
src/core/svg.ts; no DOM, SSR-safe.
Small diagrams (e.g. timing) may fuse layout into the renderer. Complex diagrams (genogram, SLD) must keep them separate and tested independently.
2. Hard Constraints (non-negotiable)
- Zero runtime dependencies. No D3, no dagre, no parser generators. Hand-write everything.
- Strict TypeScript. No
any, no un-commentedas. Types insrc/core/types.tsare the spec. - Semantic SVG. Every rendered diagram must include
<title>,<desc>, CSS classes for theming, anddata-*attributes for interactivity. No inline styles. - Use the SVG builder. Never concatenate raw SVG strings — use
src/core/svg.ts. - Test-first layout. Write failing layout tests before writing the layout code.
- Standards-compliant. Each diagram implements a published domain standard — not our invention. Cite the reference in the standard doc (IEEE, IEC, ISO, McGoldrick, etc.).
3. Step-by-Step Checklist
Step 1 — Write the standard doc
Create docs/reference/NN-{TYPE}-STANDARD.md (next free number). It must contain:
- Scope & references (IEEE / IEC / published paper).
- Symbol table with ASCII/Unicode references.
- DSL grammar (EBNF or equivalent).
- Layout rules (axes, alignment, spacing).
- 3–5 canonical test cases with expected rendering notes.
Look at 06-TIMING-STANDARD.md or 11-SINGLE-LINE-STANDARD.md as templates.
Step 2 — Add AST types to src/core/types.ts
Types are the spec. Before writing any code, commit to:
- The
DiagramTypeliteral — extend the union intypes.ts. - The AST shape: nodes, edges, metadata, any diagram-specific fields.
- The LayoutResult shape (positions, sizes, computed routing).
Ship this as its own commit so reviewers can critique the contract separately.
Step 3 — Scaffold the plugin directory
src/diagrams/{type}/
index.ts # DiagramPlugin export
parser.ts # text → AST
layout.ts # AST → LayoutResult (optional; skip for simple diagrams)
renderer.ts # LayoutResult → SVG stringindex.ts is always shaped like this:
import type { DiagramPlugin } from "../../core/types";
import { parseMyType } from "./parser";
import { renderMyType } from "./renderer";
export const myType: DiagramPlugin = {
type: "mytype",
detect(text) {
const first = text.trim().split("\n")[0]?.trim().toLowerCase() ?? "";
return first.startsWith("mytype");
},
render(text) {
const ast = parseMyType(text);
return renderMyType(ast);
},
};Step 4 — Write tests first
tests/{type}/
parser.test.ts
layout.test.ts
renderer.test.ts
e2e.test.ts # full text → SVG, snapshot string for stabilityCover every test case you committed to in the standard doc. Layout tests should assert absolute coordinates — that's what catches regressions.
Step 5 — Implement parser → layout → renderer
Follow the tests. Keep each module pure — parser takes a string and returns an AST, layout takes an AST and returns geometry, renderer takes geometry and returns a string.
Use the SVG builder:
import { svg, g, rect, text } from "../../core/svg";Never '<svg>' + ... + '</svg>'.
Step 6 — Register the plugin
Edit src/core/api.ts:
- Import
{ myType }from../diagrams/mytype. - Add it to the
plugins[]array. - Extend the
SchematexConfig.typeliteral union. - Update the
detectPluginerror message with the new keyword.
Step 7 — Quality gate
npm run typecheck
npm run test
npm run lint
npm run buildAll four must pass. If dts fails on unused locals, fix them — don't suppress.
Step 8 — Wire into the website
- Gallery tile — add an entry to
website/lib/gallery-data.ts. Thedslfield must parse — validate withnode scripts/validate-gallery.mjs. - Static SVG — add an entry to
scripts/generate-gallery-svgs.mjsand run it. The generated SVG ships with the repo and is referenced from the README. - Docs page — create
website/content/docs/{type}.mdxwith a<Playground initial={…}>and the body of the standard doc inlined. - Example page (optional) — for a real-world case study, add
website/content/examples/{slug}.mdx. - README — add a row to the gallery table with the generated SVG.
Step 9 — Update the top-level docs
README.md— gallery row.CLAUDE.md— "Completed" list at the bottom.docs/reference/00-OVERVIEW.md— status table.
4. Common Pitfalls
- Forgetting
detect()— if two plugins both returntrue, the first one wins. Make your header keyword unique. - Coordinate drift — layout tests that use relative numbers (
width / 2 + padding) mask bugs. Assert on concrete expected values. - Inline
style=attributes — blocked by the semantic-SVG rule. Use CSS classes and expose them as theme tokens insrc/core/theme.ts. - Runtime deps creeping in — if you think you need one, open an issue first. The answer is almost always "hand-write a 30-line version."
- Gallery DSL stubs that don't parse — run
node scripts/validate-gallery.mjsbefore committing. This script exists precisely because it kept happening.
5. Reference Plugins
Good examples to study, by complexity:
| Complexity | Plugin | Study for |
|---|---|---|
| Minimal | timing | Parser + renderer only, no separate layout. |
| Medium | ecomap | Clean AST → layout → renderer split. |
| Advanced | genogram | Generational layout, multi-pass routing, rich symbol set. |
| Advanced | sld | Voltage-level banding, bus routing, device clustering. |
6. Candidate Diagrams on the Roadmap
Not yet implemented — PRs welcome. Start with the standard doc (Step 1) and open a draft PR before coding.
- Fishbone / Ishikawa — cause-and-effect analysis. AST and standard doc are the main unknowns.
- Sequence diagram — UML sequence without depending on PlantUML/Mermaid conventions.
- State machine — UML state chart with hierarchical states.
- Gantt — project scheduling with dependencies and critical path.
- Network topology — L2/L3 network diagrams with device icons.
If you're adding one of these, the standard doc is doing most of the work — don't skimp on it.