PlantUML Fences Design

Shipped in 2.5.1 (2026-10-26); @startsalt and @startnwdiag were added in 2.5.2. The repo spec is docs/superpowers/specs/2026-10-25-plantuml-fences-design.md; this page is the as-built summary. It is the second renderer on the hook described in RenderedFencesDesign, and the first one that draws on the server. For a live example, see the agent feature-delivery activity diagram on About.

Why PlantUML after Mermaid: fork/join activity and deep class diagrams

Mermaid has no real UML activity notation and only shallow class diagrams. Wikantik pages need two things it cannot give:

People and content agents write and edit these diagrams by hand. Deriving diagrams from code is left to the agent; the wiki does not do it.

Spike results: activity diagrams, Smetana layout, speed and failure modes

The spike used plantuml-mit 1.2026.9; the release pins 1.2026.8.

Which diagram types draw

@startuml diagrams are accepted, plus @startsalt wireframes and @startnwdiag network diagrams, which PlantUML 1.2026.8 only recognises under their own start line. A browser test per type proves these draw in the reader, in light and dark:

DrawsRefused as unsupported-diagram
class, object, component, deployment, sequence, activity (new and legacy syntax), state, use case, timing, C4 (!include <C4/…>), ArchiMate, json objects, creole text, sprites, entity; salt wireframes (@startsalt); network diagrams (@startnwdiag)any other @start… kind: mindmap, gantt, WBS, YAML, regex, EBNF, Chen ER, ditaa; info commands (version, license, help, crash)

Salt and nwdiag lay themselves out without Graphviz, so the engine does not add the Smetana pragma to them. A salt wireframe:

@startsalt
{
  Login    | "agent@example.com "
  Password | "****              "
  [Cancel] | [  Sign in  ]
}
@endsalt

A network diagram:

@startnwdiag
nwdiag {
  network dmz {
    address = "203.0.113.0/24"
    proxy [address = "203.0.113.10"];
  }
  network internal {
    address = "10.0.0.0/24"
    proxy [address = "10.0.0.1"];
    wiki [address = "10.0.0.20"];
    db [address = "10.0.0.30"];
  }
}
@endnwdiag

License decisions that keep Wikantik commercially licensable

PartLicenseDecision
PlantUML coreMITShaded into wikantik-plantuml, with the MIT text in META-INF/LICENSE-plantuml.txt.
Smetana (Graphviz port)EPL-1.0, file-level weak copyleftKept, with META-INF/NOTICE-plantuml.txt stating the licence and where its source is.
DitaaLGPL-3.0Stripped from the shipped jar at build time. PlantUmlLicenseArchTest fails the build if it returns.
Standard-library icon setsVariousStripped to C4; !include <…> is refused except for the C4 allow-list.

Wikantik never shows a PlantUML-generated error or welcome image, which is where PlantUML may place sponsored messages.

How a plantuml fence becomes a drawing: placeholders resolved at the edge

flowchart LR
  MD[Page markdown] --> Parse[Flexmark node renderer]
  Parse --> Check{Fail-closed policy}
  Check -->|refused| Refusal[Source plus reason]
  Check -->|allowed| Ph[Signed placeholder]
  Ph --> Cache[HTML and embed caches]
  Cache --> Resolve[Resolve at HTML exit]
  Resolve --> Pool[Bounded PlantUML pool]
  Pool --> Scrub[SVG scrub and id prefix]
  Scrub --> Out[Light and dark SVG]
  click Out "/wiki/RenderedFencesDesign"

Policy, sandbox and limits against hostile or pathological diagrams

Reader, editor and dark-mode behaviour

Corpus checking with check-plantuml.sh

bin/check-plantuml.sh [--json] <files|dir|-> draws every PlantUML diagram it finds through the same policy and engine. It exits 0 when all diagrams draw, 1 when some fail, and 2 when the checker itself fails — the same contract as check-mermaid.mjs.

Deliberately out of scope for PlantUML fences

See WikantikDevelopmentHub for the rest of the platform designs.