Figures as text in Markdown — one source, two readers.
A missing edge still looks fine. Text doesn’t. An invented node and a dropped edge are both invisible in a picture that looks fine. FigDown keeps figures as text whose source states the meaning — participants, containment, field widths, table structure — so the next reader can check it, not just look at it.
FigDown is an open standard for describing figures as plain text inside Markdown, so that one source serves two readers who need completely different things from it:
.fd for meaning. Participants,
relationships, containment, field widths, table structure — none of it locked
inside a bitmap.source: figures/one-source-two-readers.fd — this figure is FigDown.
Below is one FigDown document in both of its forms. The picture on
the left is what a human reads; the text on the right is what an agent reads. They
are the same content, the picture was rendered from that text by FigDown itself,
and the text is examples/dns.fd in
full — 30 lines, nothing elided.
# FigDown — figures as text. Spec: https://github.com/FigDown/figdown
figdown 0.1 bitfield
# DNS Message Header — RFC 1035 §4.1.1
# Each row is 16 bits, MSB-0 numbering (bit 0 at left).
bitfield dns "DNS Message Header (RFC 1035)" word=16 numbering=msb0
# Row 1: Transaction ID
field "ID" 16 description="Identifier assigned by the program that generates the query; copied into the reply"
# Row 2: Flags (QR + Opcode + AA + TC + RD + RA + Z + RCODE = 16 bits)
field QR:1,Opcode:4,AA:1,TC:1,RD:1,RA:1,Z:3,RCODE:4
# Row 3: Question Count
field "QDCOUNT" 16 description="Number of entries in the question section"
# Row 4: Answer Record Count
field "ANCOUNT" 16 description="Number of resource records in the answer section"
# Row 5: Authority Record Count
field "NSCOUNT" 16 description="Number of name server resource records in the authority section"
# Row 6: Additional Record Count
field "ARCOUNT" 16 description="Number of resource records in the additional records section"
# Variable-length sections (one representative row each)
break
field "Question / Answer / Authority / Additional sections" * description="Variable-length sections follow the header; see RFC 1035 §4.1.2–4.1.4"
source: examples/dns.fd — a bit
ruler numbering 0–15, and a flags word split into eight sub-byte fields at
their real widths. No Markdown-native diagram tool draws that. An agent reads the
same facts off the text: RCODE is the low four bits of the second
16-bit word, and the sections after the header have a width the document
deliberately declines to give.
A .fd is not one picture per file. One document can
yield several forms that have to keep agreeing with each other — and a
figure is only evidence at a size where its text can be read, so there is one
here, at full width.
source: examples/vxlan-encap.fd
— the same frame before and after encapsulation in one document, plus the
encapsulation overhead. The legend is derived from the class
declarations; nobody drew it.
examples/pvlan-flows.fd
goes further and needs its own page: one document yielding a topology, a derived
legend and two rule tables, because the prohibitions that define a private VLAN
cannot be drawn as arrows and have to be written down. It is 1243×832 with
four sub-figures, so it is shown full size in the
example gallery rather than shrunk to fit here.
.fd and need to read it correctly
The reading contract for language version figdown 0.5, in
read/0.5/: what each construct means, and what you may not infer.
One file per genre — including experimental/sequence.md for an
interaction ladder. Earlier language versions keep their own frozen directory
beside it. Nothing needs installing — the files are Markdown, the
.fd is text, and reading it requires no renderer, no package and no
network.
spec/.
Every released version keeps one git tag and one archived engine page
that is never rewritten, so a figure written today can always be re-rendered exactly
as it was. Current release v0.5.1:
archive/0.5/figdown.html. Earlier archived
pages (0.1–0.4) and every release's tag are indexed
in spec/migrations.md. The editor above
tracks the current development state and is not an archive.