Skip to content
Ferrigura

Ferrigura / Comparisons

Pele

Pele is an independent renderer of Mermaid syntax, written by kepano for Obsidian to render diagrams quickly and in the app's theme. It is TypeScript with no dependencies, MIT-licensed, and published as the npm package pele (repository obsidianmd/pele, created on 2026-10-05; version 1.9.0 as of 2026-10-24). Facts below are from its documentation and sources at that version, unless they are marked as measured here.

What it is

Pele reads the Mermaid syntax of every diagram type built into Mermaid 12.1.0 (33 families) and draws them in its own layout and its own visual style. It says so plainly: node positions, spacing and edge paths differ from Mermaid, Mermaid's themes and themeVariables do not apply, and labels are SVG text: line breaks, bold and italic, and since 1.9.0 sub- and superscript, monospace and underlined runs from the matching HTML tags, all drawn as SVG text, not as HTML. Math ($$...$$) is drawn by a typesetter the host passes in (1.8.0); without one, the label shows the TeX source. Its parsers are tested against Mermaid's parser specs and with differential fuzzing. Its goal is a fast renderer with Mermaid's input language, not Mermaid's output.

The API is synchronous. render(source, options) returns the SVG as a string with its natural size; parse() gives a model that can be rendered at several widths; mount(element, source) renders into an element and redraws when the container resizes or web fonts arrive. Diagram types can be imported one by one (pele/diagrams/<type>) or loaded on first use (pele/lazy).

Why it is fast

Pele reports 0.05 to 0.3 ms per diagram, against 6 to 82 ms for Mermaid.js, and 230 kB against 1.6 MB gzipped (its own figures). Measured here (the overview has the method, in the run of 2026-10-24): 0.05 ms in the median over 215 fixtures in Node, 0.15 ms at the 90th percentile, against 7.75 ms for Mermaid in Chromium and 0.70 ms for ferrigura's Node addon; pele.js with every diagram type is 702 kB, 261 kB gzipped. The sources show where the time goes, or rather does not:

  • No DOM while rendering. The SVG is built as a string (src/svg/builder.ts). Mermaid inserts every label into the page and measures it with getBBox() or getComputedTextLength(), which makes the browser lay out the page each time; that is the largest cost Pele avoids.
  • Cheap text measurement. A browser measures with the 2D canvas's measureText, which needs no layout. Elsewhere, a built-in table of Arial advances for the 95 printable ASCII characters estimates the width, with a fixed width for wide (CJK) and other characters (src/text/measurer.ts). An app can pass its own measurer.
  • Its own, light layouts. Three modules carry the diagrams: a layered, Sugiyama-style layout of a flat graph (src/layout/layered.ts), compound graphs (compound.ts) and lanes (lanes.ts). There is no dagre, ELK or cytoscape, and no iterative force-directed layout such as the cose-bilkent and fcose runs Mermaid makes for mindmaps and architecture diagrams.
  • No theme pipeline. Colors are CSS custom properties (--pele-bg, --pele-fg, --pele-series-1 to -8, ...) set on the SVG or its container, so a color change needs no new render. Mermaid computes the theme's variables, merges configurations and runs DOMPurify for each render.

How it differs from ferrigura

TopicPeleferrigura
GoalMermaid's syntax, its own drawingMermaid's drawing: the same geometry within 0.05 px on every comparable fixture
LayoutIts own layered, compound and lane layoutsMermaid's engines, ported: ELK Layered, cose-bilkent, fcose, the tidy tree, and each type's own renderer
Text measurementCanvas in a browser, an Arial width table elsewhere; depends on the fonts of the hostThe bundled faces, shaped with HarfRust and rounded as Chromium rounds; the same on every host
FontsThe page's fonts (--pele-font); mount() measures again when they changeLexica Ultralegible and Atkinson Hyperlegible Mono, embedded as a subset, so every viewer draws what was measured
ColorsCSS custom properties, eight series colorsCSS custom properties with presentation attributes as a fallback (decision 0011); Mermaid's redux themes
Small screensAdapts the layout: maxWidth, and a vertical layout below 640 px (autoDirection)Scales the diagram, as Mermaid does
Runs inAny JavaScript runtime, browser or server, no DOMRust: a library, a CLI and a native Node addon; no browser and no WebAssembly (decision 0006)
Diagram typesAll 33 of Mermaid 12.1.033 of 33 (P1, P2, P3 and swimlanes), those of Mermaid 12.2.0
SecurityEscapes text, filters links, images and styles, limits source, output and edgesDOMPurify's rules on the texts, as the reference runs them; no scripts or callbacks

What ferrigura can learn from it

  • The responsive layout: rendering a model at the container's width, and switching a wide LR flowchart to vertical on a narrow screen, is a feature Mermaid lacks. ferrigura could offer it as an option outside the parity mode.
  • The ordered list of aims for edge routing at the top of layered.ts (lines apart from each other, few crossings, short and simple paths, ends at the middle of a side, balance, square ends, source order, compactness) is a clear statement of what a good layered drawing is.
  • Limits on source length, output size and edge count, with a dedicated error code, are a simple guard for untrusted input.
  • Math through a typesetter that the host passes in keeps the library small. ferrigura leaves math out for now; taking it the same way would spare it a TeX engine of its own.