Skip to content
Ferrigura

Ferrigura / Architecture

Architecture

ferrigura renders Mermaid diagram text to SVG in Rust, without a browser (0006). This page is the map: what happens to a diagram, which crate does it, and where each part is decided. The reasons are in the decisions; what was learned along the way is in LEARNINGS.md; each diagram type has its page under diagrams/.

From text to SVG

flowchart LR
  text[Diagram text] --> pre[Preprocess and detect]
  pre --> parse[Parse]
  parse --> model[Canonical model]
  config[Configuration and theme] --> view[Typed view]
  model --> render[Lay out and render]
  view --> render
  render --> svg[SVG with embedded font subsets]
  1. Preprocess and detect (ferrigura-syntax): line endings are normalized, the YAML front matter and the %%{init}%% directives are read, and the detector picks the diagram type from the start of the text.
  2. Parse (ferrigura-syntax): a hand-written parser per diagram type fills a DB that follows Mermaid's diagram DB (0007).
  3. Model (ferrigura-model): the DB's state as the canonical model of the type, the form the harness compares with the reference (0008, canonical-model.md).
  4. Configuration and theme (ferrigura-model, ferrigura): defaults per process, the site configuration and theme per Renderer, the diagram's front matter and directives per render; the renderer receives a typed, read-only Context (0008, 0011).
  5. Lay out and render (ferrigura-render): either a renderer of the type's own (sequence, gantt, pie, timeline and the other chart-like types) or the unified renderer, which builds the layout data as Mermaid's getData() does and lays it out with one of the ported engines (0012).
  6. Text (ferrigura-text): every label is measured and wrapped with the bundled fonts, written as SVG text, and the glyphs used are embedded as font subsets (0009, 0010).

The facade, ferrigura, ties it together: Renderer::new(config) resolves the configuration once, renderer.render(text) returns the SVG, and ferrigura::render(text, config) is the shorthand.

Crates

A Cargo workspace under crates/. Diagram types are modules inside the crates, not crates of their own.

CrateDoesLicense
ferriguraThe facade: Renderer, render, RenderOptions; the repository's root packageMIT
ferrigura-cliThe command-line tool ferriguraMIT
ferrigura-nodeThe Node.js addon (napi-rs), published through npm, not crates.io (0016)MIT
ferrigura-syntaxPreprocessing, detection, the lexers and parsers of every diagram type, YAML, sanitizationMIT
ferrigura-modelThe canonical models, the configuration (generated from schema/config.schema.yaml by build.rs), themes and tokensMIT
ferrigura-renderThe renderers, the unified renderer (shapes, clusters, edges, the ELK glue, the tidy tree), the Markdown reader, SVG outputMIT
ferrigura-textFonts, measurement, wrapping, subsetting; the bundled facesMIT AND OFL-1.1 AND CC-BY-4.0
ferrigura-elkELK Layered, ported from JavaEPL-2.0
ferrigura-cosecose-bilkent and fcoseMIT
ferrigura-swimlaneMermaid's swimlane layoutMIT
ferrigura-vennThe layout of @upsetjs/venn.jsMIT
ferrigura-jsmathJavaScript's Math as V8 computes it, bit for bitMIT AND Apache-2.0 WITH LLVM-exception AND BSD-3-Clause
ferrigura-pathChromium's bounding box of an SVG path, bit for bitMIT AND BSD-3-Clause

Licenses follow the sources of the ported code (0013); each crate that ports or bundles anything lists it in its NOTICE.md.

Around the crates

PathHolds
node/The npm packages: the facade @ferrigura/core and the platform packages (0016)
tools/portThe harness: the differential runs against the reference, the geometry runs in Chromium, the corpus capture tools, and the lint and format setup of the repository (0015)
tools/referenceThe pin, the patches and setup.sh, which build the reference (0014)
tools/snapshotsdiff.sh, which shows which renders a change moved
tools/releasepublish-crates.sh, for publishing a release by hand (0004)
e2e/diagramsThe fixtures: the .mmd corpus the harness and the tests render; e2e/platform/dev-diagrams holds more inputs

Limits

What ferrigura does not do, on purpose or not yet:

  • Out of scope: browsers and WebAssembly, raster output, Mermaid's JavaScript API and callbacks (0006); HTML labels and math in labels (0009); look: handDrawn; the dagre layout and the ELK algorithms other than Layered (0012); Mermaid's classic themes (0011).
  • Not yet: fallback fonts for the scripts the bundled faces do not cover (CJK, kana, Arabic, some emoji and symbols) must be registered by the user (0010); flowchart images and icon packs. The diagram pages list what each type still lacks.