figdown 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/dist/figdown.js +736 -111
- package/dist/figdown.mjs +736 -111
- package/examples/evpn-fabric.svg +3 -4
- package/examples/showcase/arp-resolution.svg +1 -1
- package/examples/showcase/ethernet-frame.svg +1 -1
- package/examples/showcase/l2-forwarding-logic.svg +1 -1
- package/examples/showcase/tcp-handshake.svg +1 -1
- package/examples/showcase/tcp-header.svg +1 -1
- package/examples/showcase/tcp-state-machine.svg +1 -1
- package/guide/expressing.md +27 -15
- package/guide/layout.md +4 -4
- package/package.json +1 -1
- package/skill/figdown/SKILL.md +5 -5
- package/skill/figdown/figdown.html +742 -114
- package/skill/figdown/reference/experimental/block.md +60 -0
- package/skill/figdown/reference/experimental/chart.md +32 -0
- package/skill/figdown/reference/experimental/flowchart.md +97 -10
- package/skill/figdown/reference/experimental/statechart.md +55 -9
- package/skill/figdown/reference/experimental/timing.md +1 -1
- package/skill/figdown/reference/experimental/topology.md +148 -22
- package/skill/figdown/reference/reading.md +13 -1
- package/skill/figdown/reference/scene.md +75 -22
- package/skill/figdown/reference/experimental/constructs.md +0 -90
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Genre `block` — markers and zones (EXPERIMENTAL)
|
|
2
|
+
|
|
3
|
+
`threshold` and `band` are **outside the v0.1 conformance surface and outside
|
|
4
|
+
the compatibility promise**. The engine accepts them and your document keeps
|
|
5
|
+
working, but they may change or be withdrawn in a later `0.x`. The parser
|
|
6
|
+
emits no warning, so a line that parses tells you nothing. Use them when the
|
|
7
|
+
figure genuinely needs them; if the figure must be portable, do not, and if
|
|
8
|
+
you use one anyway, say so beside the figure.
|
|
9
|
+
|
|
10
|
+
**Both belong to `block` alone.** They are declared by this genre and by no
|
|
11
|
+
other: writing either under `topology`, `flowchart` or `statechart` is a line
|
|
12
|
+
error that says so and gives the ground. `block` earns them because it is the
|
|
13
|
+
genre those figures are actually authored in; a state's box, a flowchart
|
|
14
|
+
stage's box and a device's box have no extent that means anything, so a line
|
|
15
|
+
drawn 60% down one asserts nothing a reader can read.
|
|
16
|
+
|
|
17
|
+
Load `../scene.md` first — this file adds two words to `block`'s vocabulary
|
|
18
|
+
and changes none of it.
|
|
19
|
+
|
|
20
|
+
```figdown
|
|
21
|
+
figdown 0.1 block
|
|
22
|
+
group pool "Storage pool"
|
|
23
|
+
node used "In use" in=pool
|
|
24
|
+
threshold "High watermark = stop writes" in=pool offset=80%
|
|
25
|
+
threshold "Low watermark = resume writes" in=pool offset=45%
|
|
26
|
+
band "Reserved" 15% in=pool fill=#fee2e2
|
|
27
|
+
band "Shared quota" 20..70% in=pool extend=down
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
- `threshold` needs a quoted label **and** `offset=<0..100>%`, both mandatory
|
|
31
|
+
— the `%` included. There is no `value=` and no `ref=`.
|
|
32
|
+
- `band` needs a quoted label **first**, then either one percentage (a size)
|
|
33
|
+
or an explicit `<a>..<b>%` range. `..` is the language's ONE range
|
|
34
|
+
separator; the hyphen form is a line error. `extend=up|down|left|right`, and `up`
|
|
35
|
+
is the default.
|
|
36
|
+
- Both attach to a node or a group via `in=`.
|
|
37
|
+
- **Attach at the scope the fact belongs to.** A limit shared by everything in
|
|
38
|
+
a group is one group-level marker; a fact true of one element attaches to
|
|
39
|
+
that element. The renderer may draw the two the same way — the difference is
|
|
40
|
+
in the text, and the text is the knowledge.
|
|
41
|
+
|
|
42
|
+
## The label is the knowledge, and `offset=` is not a value
|
|
43
|
+
|
|
44
|
+
`offset=` is a fraction of the target's **rendered extent** — where to paint
|
|
45
|
+
the line — **not a value of any quantity**. The target declares no scale, so
|
|
46
|
+
there is no conversion and nothing to convert. Put the number in the label or
|
|
47
|
+
it is not in the document.
|
|
48
|
+
|
|
49
|
+
**This is the trap, and it is worth naming.** In the domain these figures
|
|
50
|
+
usually come from, a threshold is a queue depth **with a numeric value**: an
|
|
51
|
+
active-queue-management minimum and maximum threshold (RFC 2309, RFC 7567)
|
|
52
|
+
is a number of packets or bytes. FigDown borrowed the word from exactly that
|
|
53
|
+
domain and did **not** borrow the attribute the domain defines it by. So
|
|
54
|
+
`threshold "Max cap" in=q offset=80%` invites a reader to take 80% as the
|
|
55
|
+
threshold value. It is a paint position. Write
|
|
56
|
+
`threshold "Max cap = 800 KB" in=q offset=80%` and the figure says what you
|
|
57
|
+
mean.
|
|
58
|
+
|
|
59
|
+
The same holds for `band`: a band is a range over that same scale-free
|
|
60
|
+
extent. Its label is the whole of what it asserts.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Charts from a table — `chart`, `type=` (EXPERIMENTAL)
|
|
2
|
+
|
|
3
|
+
Outside the v0.1 conformance surface and outside the compatibility promise:
|
|
4
|
+
the engine accepts it, but it may change or be withdrawn in a later `0.x`,
|
|
5
|
+
and the parser emits no warning. If the figure must be portable, keep the
|
|
6
|
+
table and drop the chart.
|
|
7
|
+
|
|
8
|
+
**`chart` is composition, not subject vocabulary.** It says nothing about
|
|
9
|
+
what the figure is *of*, so it is not one of the words a genre declares for
|
|
10
|
+
its own domain — it is legal wherever a `table` region is legal, which is the
|
|
11
|
+
`table` genre and every scene genre, and it means the same thing in all of
|
|
12
|
+
them.
|
|
13
|
+
|
|
14
|
+
```figdown
|
|
15
|
+
figdown 0.1 table
|
|
16
|
+
table t "Throughput"
|
|
17
|
+
| Port | Gbps |
|
|
18
|
+
|------|------|
|
|
19
|
+
| 1 | 25 |
|
|
20
|
+
| 2 | 40 |
|
|
21
|
+
chart t type=bar3d
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- `chart <table-id>` is the whole grammar. It draws from a `table` declared
|
|
25
|
+
in the same document and is defined by that reference, so the id must
|
|
26
|
+
already exist.
|
|
27
|
+
- `type=` is the only option key and `bar3d` is its only value.
|
|
28
|
+
- A scene document can carry both halves: open a `table` region inside it for
|
|
29
|
+
the numbers, then `chart` that id.
|
|
30
|
+
|
|
31
|
+
For anything a chart library would do better, keep the raster and put the
|
|
32
|
+
numbers in a table (`../transcribe.md`).
|
|
@@ -1,15 +1,27 @@
|
|
|
1
|
-
# Genre `flowchart` — EXPERIMENTAL
|
|
1
|
+
# Genre `flowchart` — EXPERIMENTAL
|
|
2
2
|
|
|
3
3
|
The genre itself is outside the v0.1 conformance surface: it may change or be
|
|
4
|
-
withdrawn in a later `0.x
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
**
|
|
11
|
-
|
|
12
|
-
|
|
4
|
+
withdrawn in a later `0.x` without a migration entry. A portable figure uses
|
|
5
|
+
`block` instead.
|
|
6
|
+
|
|
7
|
+
Use `flowchart` when the figure is a **procedure**: stages performed in
|
|
8
|
+
order, with branches. `flow down` is the default here.
|
|
9
|
+
|
|
10
|
+
**This file is `flowchart`'s whole vocabulary.** Load it and `../layout.md`
|
|
11
|
+
and you can author in this genre; do not load another genre's file, because
|
|
12
|
+
another genre's declaration of a word is not authority for this one. In
|
|
13
|
+
particular this genre declares **no container**: there is no `group`, and
|
|
14
|
+
`in=` and `gap=` are **not this genre's option keys** — `in=` named a `group`
|
|
15
|
+
id and nothing else, so it went out with `group` rather than stay accepted with
|
|
16
|
+
no value that could resolve. Writing either is a line error that names the
|
|
17
|
+
withdrawal. Say what a container would have said with a `class`
|
|
18
|
+
whose label states it — it earns a legend entry and applies to every member at
|
|
19
|
+
once — or split the procedure into two figures joined by `external` endpoints.
|
|
20
|
+
|
|
21
|
+
**Under `figdown 0.2` the connector is `flowline`, not `edge`** — the word the
|
|
22
|
+
flowchart domain commonly uses for the symbol ISO 5807 §9.3.1 names *Line*.
|
|
23
|
+
Same operators, same labels, same option keys, same model; only the word
|
|
24
|
+
changed.
|
|
13
25
|
|
|
14
26
|
**The spelling is gated by the version you declare.** Under
|
|
15
27
|
`figdown 0.1 flowchart`, `edge` is still the word and `flowline` is a line
|
|
@@ -95,3 +107,78 @@ spelling, and only you know which one you did.
|
|
|
95
107
|
figure the reader has to guess at.
|
|
96
108
|
|
|
97
109
|
**There is no loop keyword.** A plain back-edge *is* the loop.
|
|
110
|
+
|
|
111
|
+
## `external` — the boundary, which is not the `terminator`
|
|
112
|
+
|
|
113
|
+
```figdown
|
|
114
|
+
figdown 0.2 flowchart
|
|
115
|
+
flow down
|
|
116
|
+
external ingress "Frame arrives on a port"
|
|
117
|
+
terminator start "Begin lookup"
|
|
118
|
+
process lookup "Look up destination"
|
|
119
|
+
external egress "Frame leaves the switch"
|
|
120
|
+
flowline ingress -> start
|
|
121
|
+
flowline start -> lookup
|
|
122
|
+
flowline lookup -> egress
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
`external` is an **out-of-figure endpoint**: the procedure connects to it and
|
|
126
|
+
this figure does not describe it. It is **never drawn** — the flowline simply
|
|
127
|
+
ends open — and it takes **no option key at all**. `terminator` is the
|
|
128
|
+
opposite: a drawn stage of this procedure, its start or its end.
|
|
129
|
+
|
|
130
|
+
So the question to ask is *whose* start it is. The first box of **this**
|
|
131
|
+
procedure is a `terminator`. A step that belongs to some other procedure, or
|
|
132
|
+
to the world outside the figure, is an `external`.
|
|
133
|
+
|
|
134
|
+
ISO 5807 §9.4.2 names this concept — its **Terminator** symbol is "an exit
|
|
135
|
+
to, or an entry from, the outside world" — and this genre already spells that
|
|
136
|
+
word `terminator` for the drawn start/end symbol, so the ISO term is taken
|
|
137
|
+
and `external` keeps FigDown's own spelling. Note what follows: ISO has no
|
|
138
|
+
word at all for a boundary that is *never drawn*, which is what `external`
|
|
139
|
+
is. The spelling is FigDown's, not ISO's, and this file is the only place
|
|
140
|
+
that says so.
|
|
141
|
+
|
|
142
|
+
## Presentation, layout intent and quoting
|
|
143
|
+
|
|
144
|
+
`flow` takes `flow right|down|left|up` — one of the four, once per document,
|
|
145
|
+
before the stages. `flow down` is this genre's default. `rank a,b,c` pulls
|
|
146
|
+
peers onto one row or column: ONE comma-delimited token, no spaces.
|
|
147
|
+
|
|
148
|
+
Values from a fixed list are written **bare**, never quoted: `shape=box`,
|
|
149
|
+
`style=dashed`, `flow down`. So are ids. Labels always take quotes.
|
|
150
|
+
|
|
151
|
+
`shape=` is pure geometry — `shape=box` (the default), `shape=rounded`,
|
|
152
|
+
`shape=circle`, `shape=ellipse`, `shape=diamond`, `shape=cylinder`, and
|
|
153
|
+
nothing else. `style=` takes `style=solid`, `style=dashed` or `style=dotted`.
|
|
154
|
+
|
|
155
|
+
`class` declares what a colour **means**, and colour that means something
|
|
156
|
+
must be a `class`:
|
|
157
|
+
|
|
158
|
+
```figdown
|
|
159
|
+
figdown 0.2 flowchart
|
|
160
|
+
class yes "Yes path" stroke=#16a34a
|
|
161
|
+
class no "No path" stroke=#dc2626
|
|
162
|
+
decision check "Valid?"
|
|
163
|
+
process accept "Accept"
|
|
164
|
+
process reject "Reject"
|
|
165
|
+
flowline check -> accept class=yes
|
|
166
|
+
flowline check -> reject class=no
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
A class a flowline joins MUST declare `stroke=` or `style=`; a `fill=`-only
|
|
170
|
+
class joined by one is an error naming `stroke=`. `fill=` and `stroke=` are
|
|
171
|
+
legal on any drawn element, but a flowline has no interior, so `fill=` on one
|
|
172
|
+
is an error.
|
|
173
|
+
|
|
174
|
+
The connector's operators are `->`, `<-`, `--` and `<->`. In a procedure you
|
|
175
|
+
almost always want `->`: a step follows another step in one direction, and an
|
|
176
|
+
undirected or two-way flowline asserts an order the reader cannot recover.
|
|
177
|
+
|
|
178
|
+
Endpoint labels nest (`flowline a [retry 1] -- b`); quote them when they hold
|
|
179
|
+
a line break or an unbalanced bracket. A `#` inside a bracket label is
|
|
180
|
+
ordinary text and needs no quotes, because `[ ]` is a verbatim region.
|
|
181
|
+
|
|
182
|
+
Under `figdown 0.3` any of these lines may carry `note=`, a drawn aside in
|
|
183
|
+
prose: `process parse "Parse body" note="…"`. It is never parsable and never
|
|
184
|
+
where a structural fact lives.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Genre `statechart` — EXPERIMENTAL
|
|
1
|
+
# Genre `statechart` — EXPERIMENTAL
|
|
2
2
|
|
|
3
3
|
The genre itself is outside the conformance surface: it may change or be
|
|
4
4
|
**withdrawn** in a later `0.x` without a migration. A portable figure uses
|
|
@@ -9,12 +9,45 @@ The genre itself is outside the conformance surface: it may change or be
|
|
|
9
9
|
error, and a deliberately named one: `genre "statechart" requires figdown 0.2`.
|
|
10
10
|
An engine may not read a `0.1` document as though it were `0.2`.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
## The vocabulary, which is two words
|
|
13
|
+
|
|
14
|
+
**This file is `statechart`'s whole vocabulary.** Load it and `../layout.md`
|
|
15
|
+
and you can author in this genre; do not load another genre's file, because
|
|
16
|
+
another genre's declaration of a word is not authority for this one.
|
|
17
|
+
|
|
18
|
+
This genre declares **two** words of its own — a node is a **`state`** and a
|
|
19
|
+
connector is a **`transition`**, both taken from OMG UML 2.5.1 §14 — and
|
|
20
|
+
**that is the entire list**. It names no container, no boundary, no marker,
|
|
21
|
+
no band and no bundle. Writing one of those here is a line error that states
|
|
22
|
+
the ground rather than guessing at a spelling, and `node` or `edge` here is a
|
|
23
|
+
line error naming the word to write instead.
|
|
24
|
+
|
|
25
|
+
Three more words are legal because they are not about states at all:
|
|
26
|
+
`class` (what a colour means), `flow` and `rank` (layout intent). Nothing in
|
|
27
|
+
UML competes for them.
|
|
28
|
+
|
|
29
|
+
Two consequences worth stating, because an author arriving from another genre
|
|
30
|
+
will reach for both:
|
|
31
|
+
|
|
32
|
+
- **There is no grouping construct.** `in=` and `gap=` are **not this genre's
|
|
33
|
+
option keys** — writing either is a line error that names the withdrawal.
|
|
34
|
+
A composite state, a region and a history are things this genre cannot
|
|
35
|
+
express; a `class` can say two states share a mode, and that is a different
|
|
36
|
+
and weaker claim. Do not fake a superstate. **`in=`'s spelling is RESERVED
|
|
37
|
+
here**: if composite states are ever earned, they arrive as nesting on
|
|
38
|
+
`state` through this exact key, with a `state` id as its value (UML 2.5.1
|
|
39
|
+
§14.2.3.4) — which is why the key was withdrawn rather than left pointing at
|
|
40
|
+
a container.
|
|
41
|
+
- **There is no out-of-figure endpoint.** A transition to something the
|
|
42
|
+
figure does not describe has no spelling. Draw the state, or leave the
|
|
43
|
+
transition out and say so in the prose beside the figure.
|
|
44
|
+
|
|
45
|
+
**`external` in particular is not available, and it is reserved.** UML 2.5.1
|
|
46
|
+
§14 already defines `TransitionKind` as `external | internal | local`, where
|
|
47
|
+
an *external* transition is one that exits and re-enters its source state,
|
|
48
|
+
firing its exit and entry behaviours. That is a defined term of art in this
|
|
49
|
+
genre's own source standard. If `external` ever appears in `statechart` it
|
|
50
|
+
will mean what UML means by it, never "an endpoint outside the figure".
|
|
18
51
|
|
|
19
52
|
`flow right` is the default, as in `block`; `flowchart`'s `down` default does
|
|
20
53
|
**not** apply here.
|
|
@@ -38,6 +71,19 @@ transition locked -[push]-> locked # self-transition: the event happens
|
|
|
38
71
|
flow right
|
|
39
72
|
```
|
|
40
73
|
|
|
74
|
+
`flow` takes `flow right|down|left|up` — one of the four, once per document.
|
|
75
|
+
`rank a,b` pulls peers onto one row or column: ONE comma-delimited token, no
|
|
76
|
+
spaces. Values from a fixed list are bare (`shape=box`, `style=dashed`,
|
|
77
|
+
`flow right`); labels always take quotes.
|
|
78
|
+
|
|
79
|
+
`shape=` is pure geometry and changes only the drawing — `shape=box` (the
|
|
80
|
+
default), `shape=rounded`, `shape=circle`, `shape=ellipse`, `shape=diamond`,
|
|
81
|
+
`shape=cylinder`. `style=` takes `style=solid`, `style=dashed` or
|
|
82
|
+
`style=dotted`. A class a transition joins MUST declare `stroke=` or
|
|
83
|
+
`style=`; `fill=` on a transition is an error, because a line has no
|
|
84
|
+
interior. Under `figdown 0.3` a line may carry `note=`, a drawn aside in
|
|
85
|
+
prose — never parsable, never where a structural fact lives.
|
|
86
|
+
|
|
41
87
|
## What the genre adds, which is a reading and not a syntax
|
|
42
88
|
|
|
43
89
|
Everything above parses identically under `block`. The genre earns its
|
|
@@ -74,8 +120,8 @@ existence in what you are entitled to conclude from it.
|
|
|
74
120
|
as initial is inventing a fact.
|
|
75
121
|
- **No ordering among transitions.** Peer edges have no sequence, and an
|
|
76
122
|
ordinal in a label is naming, not order.
|
|
77
|
-
- **No hierarchy, no regions, no history.**
|
|
78
|
-
|
|
123
|
+
- **No hierarchy, no regions, no history.** There is no grouping construct to
|
|
124
|
+
misuse for one.
|
|
79
125
|
- **Nothing from the layout zone.** `pin` is arrangement for humans; skip it.
|
|
80
126
|
|
|
81
127
|
**Reclassifying costs more than one line now.** Changing `flowchart` to
|
|
@@ -1,38 +1,164 @@
|
|
|
1
|
-
# Genre `topology` — EXPERIMENTAL
|
|
1
|
+
# Genre `topology` — EXPERIMENTAL
|
|
2
2
|
|
|
3
3
|
The genre itself is outside the v0.1 conformance surface: it may change or be
|
|
4
|
-
withdrawn in a later `0.x
|
|
5
|
-
|
|
6
|
-
the compatibility promise.
|
|
4
|
+
withdrawn in a later `0.x` without a migration entry. A portable figure uses
|
|
5
|
+
`block` instead, which is inside the compatibility promise.
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
intent
|
|
7
|
+
Use `topology` when the figure is a **network of devices and the links
|
|
8
|
+
between them** — fabrics, overlays, access layers, peering diagrams. The
|
|
9
|
+
nodes are devices or endpoints and the edges are physical or logical links,
|
|
10
|
+
not dataflow steps. That intent is what the genre carries; it matters to a
|
|
11
|
+
reader and to nothing else.
|
|
12
|
+
|
|
13
|
+
**This file is `topology`'s whole vocabulary.** Load it and `../layout.md`
|
|
14
|
+
and you can author in this genre; do not load another genre's file, because
|
|
15
|
+
another genre's declaration of a word is not authority for this one. Words
|
|
16
|
+
`topology` does **not** declare — and there are several a `block` author
|
|
17
|
+
would reach for — are line errors that say so and give the ground.
|
|
18
|
+
|
|
19
|
+
## The vocabulary, in one figure
|
|
12
20
|
|
|
13
21
|
```figdown
|
|
14
22
|
figdown 0.1 topology
|
|
15
23
|
title "Leaf-spine fabric"
|
|
16
|
-
|
|
24
|
+
|
|
25
|
+
flow right # reading direction; ONE per document,
|
|
26
|
+
# before the nodes
|
|
27
|
+
|
|
17
28
|
node s1 "Spine 1"
|
|
18
29
|
node s2 "Spine 2"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
node
|
|
22
|
-
|
|
23
|
-
|
|
30
|
+
|
|
31
|
+
group pod "Pod A" gap=0 # a container; gap=0 packs its members
|
|
32
|
+
node l1 "Leaf 1" in=pod # flush against each other. The id is
|
|
33
|
+
node l2 "Leaf 2" in=pod # required and exists only so other lines
|
|
34
|
+
# can name it
|
|
35
|
+
|
|
36
|
+
node fw "Firewall" shape=rounded
|
|
37
|
+
node store "Config store" shape=cylinder style=solid
|
|
38
|
+
|
|
39
|
+
external wan "To WAN" # outside the figure. NEVER drawn as a
|
|
40
|
+
# shape — the link simply ends open there
|
|
41
|
+
|
|
42
|
+
edge l1 -- s1 # ops: -> <- -- <->
|
|
24
43
|
edge l1 -- s2
|
|
25
44
|
edge l2 -- s1
|
|
26
45
|
edge l2 -- s2
|
|
27
|
-
edge s1
|
|
28
|
-
|
|
46
|
+
edge s1 -> wan # arrow points at `wan`
|
|
47
|
+
edge wan <- s2
|
|
48
|
+
edge fw <-> store
|
|
49
|
+
edge l1 -[lacp]-> fw # on-line label splits the operator
|
|
50
|
+
edge l2 [ge-0/0/1] -- [xe-0/0/0] fw # endpoint labels: ports, roles
|
|
51
|
+
edge s1 -- s2 style=dotted # spines not cabled to each other
|
|
52
|
+
|
|
53
|
+
rank l1,l2 # pull peers onto one row/column. ONE
|
|
54
|
+
# comma-delimited token, no spaces
|
|
55
|
+
|
|
56
|
+
class uplink "Uplink, 40G" stroke=#0284c7
|
|
29
57
|
edge l2 -- s2 class=uplink
|
|
58
|
+
|
|
59
|
+
bundle lag1 "LAG to the leaf pair" l1--s1,l2--s1
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`flow` takes `flow right|down|left|up` — one of the four, once per document.
|
|
63
|
+
|
|
64
|
+
Values from a fixed list are written **bare**, never quoted: `shape=box`,
|
|
65
|
+
`style=dashed`, `flow down`, `gap=0`. So are ids. Labels are the opposite
|
|
66
|
+
and always take quotes.
|
|
67
|
+
|
|
68
|
+
`shape=` is **pure geometry, no domain nouns** — `shape=box` (the default),
|
|
69
|
+
`shape=rounded`, `shape=circle`, `shape=ellipse`, `shape=diamond`,
|
|
70
|
+
`shape=cylinder`, and nothing else. There is no router symbol, no switch
|
|
71
|
+
symbol and no cloud: a cloud in a source drawing is an ellipse or a group,
|
|
72
|
+
with what it *is* — "the internet", "the transit provider" — written in the
|
|
73
|
+
label. `style=` takes `style=solid`, `style=dashed` or `style=dotted`.
|
|
74
|
+
|
|
75
|
+
`class` declares what a colour **means** and is the only way to make colour
|
|
76
|
+
carry meaning; a class an edge joins MUST declare `stroke=` or `style=`, and
|
|
77
|
+
a `fill=`-only class joined by an edge is an error naming `stroke=`. `fill=`
|
|
78
|
+
and `stroke=` are legal on any element, but an `edge` has no interior, so
|
|
79
|
+
`fill=` on one is an error.
|
|
80
|
+
|
|
81
|
+
Endpoint labels nest (`edge a [xe-0/0/0:1] -- b`); quote them when they hold
|
|
82
|
+
a line break or an unbalanced bracket (`edge a ["slot\n1/1"] -- b`). A `#`
|
|
83
|
+
inside a bracket label is ordinary text and needs no quotes —
|
|
84
|
+
`edge a -[hop #1]-> b` — because `[ ]` is a verbatim region.
|
|
85
|
+
|
|
86
|
+
Under `figdown 0.3` any of these lines may carry `note=`, a drawn aside in
|
|
87
|
+
prose: `node s1 "Spine 1" note="…"`, `edge l1 -- s1 note="…"`,
|
|
88
|
+
`title "Fabric" note="…"`. It is never parsable and never where a structural
|
|
89
|
+
fact lives.
|
|
90
|
+
|
|
91
|
+
## `group` is not a multicast group
|
|
92
|
+
|
|
93
|
+
`group` here is a **container**: a box drawn round its members, one nesting
|
|
94
|
+
level deep — a pod, a rack, a site, a tenant. It is not IGMP or MLD
|
|
95
|
+
membership, and `group g "224.0.0.5"` does not say what a reader of that
|
|
96
|
+
address expects.
|
|
97
|
+
|
|
98
|
+
The spelling stays anyway, because in this domain every synonym is more
|
|
99
|
+
taken than the word is: `zone` belongs to DNS and to firewalls, `cluster` to
|
|
100
|
+
route reflection (RFC 4456), `domain` to inter-domain traffic engineering
|
|
101
|
+
(RFC 7926), `area` to OSPF, `site` to EVPN. Trading a soft collision for a
|
|
102
|
+
hard one is a bad trade — and this collision **is** soft, because the drawing
|
|
103
|
+
contradicts the wrong reading: a multicast group is never drawn as a box
|
|
104
|
+
round its members.
|
|
105
|
+
|
|
106
|
+
## `external` is not an external route
|
|
107
|
+
|
|
108
|
+
`external` is an **out-of-figure endpoint**: something this figure talks to
|
|
109
|
+
but does not describe. It is never drawn, it takes **no option key at all**,
|
|
110
|
+
and the link to it simply ends open.
|
|
111
|
+
|
|
112
|
+
It is not an external route — not an OSPF Type 5 or Type 7 LSA, not an eBGP
|
|
113
|
+
peer, not "the external interface". Same soft collision, same reason for
|
|
114
|
+
keeping the spelling: an `external` is never drawn at all, so a reader who
|
|
115
|
+
starts with the routing sense finds nothing on the page to sustain it. Where
|
|
116
|
+
the figure means *the router that faces outside*, that router is a `node`
|
|
117
|
+
with a label saying so; `external` is for what the figure leaves out.
|
|
118
|
+
|
|
119
|
+
## `bundle` — a LAG, an ECMP set, an Ethernet Segment
|
|
120
|
+
|
|
121
|
+
```figdown
|
|
122
|
+
figdown 0.1 topology
|
|
123
|
+
node leaf "Leaf"
|
|
124
|
+
node s1 "Spine 1"
|
|
125
|
+
node s2 "Spine 2"
|
|
126
|
+
edge leaf -- s1
|
|
127
|
+
edge leaf -- s2
|
|
128
|
+
bundle ecmp "ECMP uplink set, 2 × 100G" leaf--s1,leaf--s2
|
|
30
129
|
```
|
|
31
130
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
131
|
+
A **link bundle**: a set of parallel links between the same pair of devices
|
|
132
|
+
operated as one logical link. Its referents are the ones this domain already
|
|
133
|
+
names — a link aggregation group (IEEE 802.1AX), an equal-cost multipath
|
|
134
|
+
set, an EVPN Ethernet Segment — and the ring drawn round the member links is
|
|
135
|
+
the same thing the domain means. The domain reading and the drawn reading
|
|
136
|
+
are one reading; this is the cell where the word and the referent agree, and
|
|
137
|
+
it is why `topology` declares `bundle` and the general-purpose genre has no
|
|
138
|
+
use for it.
|
|
139
|
+
|
|
140
|
+
`bundle` is EXPERIMENTAL even inside this experimental genre. It is spelled
|
|
141
|
+
`bundle` and not after the standard's own noun deliberately: *aggregation*
|
|
142
|
+
is right for a link aggregation group and false for an equal-cost multipath
|
|
143
|
+
set and for an Ethernet Segment, so the standard's word cannot be taken
|
|
144
|
+
whole and an umbrella spelling is the honest one.
|
|
145
|
+
|
|
146
|
+
- The member list is ONE comma-delimited token, no spaces.
|
|
147
|
+
- Each member must name an edge that **already exists** and is unambiguous.
|
|
148
|
+
There is no way to address one of two parallel edges between the same
|
|
149
|
+
pair, so a bundle over parallel links cannot be spelled — declare the
|
|
150
|
+
members as distinct edges to distinct peers, as above.
|
|
151
|
+
- `bundle` takes `fill=`, `stroke=` and `style=`; the dashed ring is drawn
|
|
152
|
+
for you.
|
|
153
|
+
|
|
154
|
+
## Two mistakes this genre invites
|
|
155
|
+
|
|
156
|
+
**A shared medium is not a star.** Flattening a bus, a broadcast segment, a
|
|
157
|
+
shared VLAN or a fabric's underlay into point-to-point links changes what the
|
|
158
|
+
figure asserts: the shared thing reaches every participant at once. Model it
|
|
159
|
+
as one intermediate `node` that fans out.
|
|
35
160
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
161
|
+
**Geography is not carried by the layout zone.** If where a device sits is
|
|
162
|
+
part of the claim — a site, a rack, a country — say it with a `group` and a
|
|
163
|
+
label. Delete every `pin` and the figure must still be the same figure
|
|
164
|
+
(`../layout.md`).
|
|
@@ -25,6 +25,18 @@ syntax detail in the other files beside it.
|
|
|
25
25
|
- **Authored prose** in a `description=` is quotable and displayable, and
|
|
26
26
|
**never parsable**. Quote it, attribute it to its field, and stop. It
|
|
27
27
|
carries no structure, no relation and no condition.
|
|
28
|
+
- **A `note=` is authored prose too, on the same terms** (`figdown 0.3`).
|
|
29
|
+
It is quotable and displayable and **never parsable**. It is an **aside**:
|
|
30
|
+
its content is not a fact about the figure's structure. You MAY attribute
|
|
31
|
+
it to the element that carries it — attachment is by syntactic position, so
|
|
32
|
+
there is never a question of which element is meant — and you MUST NOT
|
|
33
|
+
infer a participant, an edge or a category from it. A `note=` on `title`
|
|
34
|
+
(`doc.note`) belongs to the **figure**, not to any element.
|
|
35
|
+
- **`description=` and `note=` are not the same channel and neither replaces
|
|
36
|
+
the other.** They divide by AUDIENCE: `description=` is written **for you**
|
|
37
|
+
and puts no ink on the page; `note=` is written for the **human** and always
|
|
38
|
+
draws. Both may appear in one document, and an element carrying both is
|
|
39
|
+
making two statements to two readers, not saying one thing twice.
|
|
28
40
|
|
|
29
41
|
## Genre-specific readings
|
|
30
42
|
|
|
@@ -71,7 +83,7 @@ Widths, colours and alignment never change it.
|
|
|
71
83
|
**`timing`.** Cycle *t* is the *t*-th character of the lane. `.` continues
|
|
72
84
|
the previous value, and cycles stay contiguous across a gap.
|
|
73
85
|
|
|
74
|
-
**`statechart`** (EXPERIMENTAL, `figdown 0.2`
|
|
86
|
+
**`statechart`** (EXPERIMENTAL, `figdown 0.2` and later). Nodes are **states** — modes
|
|
75
87
|
the machine is *in* — and edges are **transitions** on an event. This is the
|
|
76
88
|
one reading you may not derive from the drawing: a cyclic figure with a
|
|
77
89
|
self-loop is just as likely to be a polling `flowchart`, and the word "state
|
|
@@ -1,27 +1,37 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Genre `block` — things and the connections between them
|
|
2
2
|
|
|
3
|
-
Status:
|
|
4
|
-
the whole scene surface; `topology`, `flowchart` and `statechart` reuse them
|
|
5
|
-
and add — or **rename** — their own, in their own files.
|
|
3
|
+
Status: NORMATIVE and portable.
|
|
6
4
|
|
|
7
|
-
Load this for any figure made of **things and the connections between
|
|
5
|
+
Load this for any figure made of **things and the connections between
|
|
6
|
+
them** whose line 1 says `block`. Everything below is `block`'s own
|
|
7
|
+
vocabulary; nothing below is authority for any other genre.
|
|
8
8
|
|
|
9
|
-
**
|
|
10
|
-
|
|
9
|
+
**Every scene genre declares its own words.** There are four, and each one's
|
|
10
|
+
vocabulary is declared once, in its own file:
|
|
11
11
|
|
|
12
|
-
| genre
|
|
13
|
-
|
|
14
|
-
| `block
|
|
15
|
-
| `
|
|
16
|
-
| `
|
|
12
|
+
| genre on line 1 | where its vocabulary is declared |
|
|
13
|
+
|---|---|
|
|
14
|
+
| `block` | this file |
|
|
15
|
+
| `topology` | `experimental/topology.md` |
|
|
16
|
+
| `flowchart` | `experimental/flowchart.md` |
|
|
17
|
+
| `statechart` | `experimental/statechart.md` |
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
A word two of them spell the same is **two declarations that happen to agree
|
|
20
|
+
today**, never one inherited — each genre may withdraw, rename or constrain
|
|
21
|
+
its own without touching the others, and each carries its own reading advice
|
|
22
|
+
because the same word can be safe in one domain and misleading in another.
|
|
23
|
+
So do not carry a word from this file into another genre and do not go
|
|
24
|
+
looking here for a word another genre's file did not give you: a word the
|
|
25
|
+
genre on line 1 does not declare is a **line error that states the ground**,
|
|
26
|
+
not a spellcheck.
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
Three words are spelled the same in all four and are not subject vocabulary
|
|
29
|
+
at all — `class` says what a colour *means*, `flow` and `rank` state layout
|
|
30
|
+
intent. None of them names a thing in the world, so no domain holds a rival
|
|
31
|
+
meaning for one, and each genre's file repeats them rather than sending you
|
|
32
|
+
here.
|
|
33
|
+
|
|
34
|
+
## The vocabulary, in one figure
|
|
25
35
|
|
|
26
36
|
```figdown
|
|
27
37
|
figdown 0.1 block
|
|
@@ -67,8 +77,8 @@ edge retry -> reject class=slow
|
|
|
67
77
|
`flow` takes `flow right|down|left|up` — one of the four, once per document.
|
|
68
78
|
|
|
69
79
|
Values from a fixed list are written **bare**, never quoted: `shape=box`,
|
|
70
|
-
`style=dashed`, `flow down`, `
|
|
71
|
-
|
|
80
|
+
`style=dashed`, `flow down`, `gap=0`. So are ids. Labels are the opposite
|
|
81
|
+
and always take quotes.
|
|
72
82
|
|
|
73
83
|
`shape=` is **pure geometry, no domain nouns** — `shape=box` (the default),
|
|
74
84
|
`shape=rounded`, `shape=circle`, `shape=ellipse`, `shape=diamond`,
|
|
@@ -82,6 +92,26 @@ inside a bracket label is ordinary text and needs no quotes —
|
|
|
82
92
|
`edge a -[hop #1]-> b` — because `[ ]` is a verbatim region, like a quoted
|
|
83
93
|
string, a comment and a pipe row.
|
|
84
94
|
|
|
95
|
+
## What `group` and `external` claim here, and what they do not
|
|
96
|
+
|
|
97
|
+
`block` is the **general-purpose** genre: it has no single domain, and that
|
|
98
|
+
is what general-purpose means. So its two container-and-boundary words carry
|
|
99
|
+
no domain caveat, and you should not supply one.
|
|
100
|
+
|
|
101
|
+
- **`group`** is a container and nothing more — a box drawn round its
|
|
102
|
+
members, one nesting level deep. It asserts no ownership, no lifecycle, no
|
|
103
|
+
address space and no failure domain. Whatever the grouping *means* goes in
|
|
104
|
+
the label.
|
|
105
|
+
- **`external`** is an out-of-figure endpoint: something the figure talks to
|
|
106
|
+
but does not describe. It is **never drawn** — the edge simply ends open —
|
|
107
|
+
it takes **no option key at all**, and there is no source standard behind
|
|
108
|
+
the spelling. It is FigDown's own word for FigDown's own boundary.
|
|
109
|
+
|
|
110
|
+
A genre with one domain cannot be this quiet. `topology`'s file has to warn
|
|
111
|
+
its reader off a rival reading of both words before it can use either; this
|
|
112
|
+
file has nothing to warn about, and that asymmetry is why the two
|
|
113
|
+
declarations are separate.
|
|
114
|
+
|
|
85
115
|
## Field-tested pitfalls
|
|
86
116
|
|
|
87
117
|
**Containment is not an edge.** An edge from a node to its own container
|
|
@@ -129,5 +159,28 @@ a `node` styled to look like one.
|
|
|
129
159
|
## Where to go next
|
|
130
160
|
|
|
131
161
|
- The figure came out scrambled, or placement is the message → `layout.md`
|
|
132
|
-
- Marker lines
|
|
133
|
-
`experimental/
|
|
162
|
+
- Marker lines and zone bands over a `block` figure →
|
|
163
|
+
`experimental/block.md` (EXPERIMENTAL)
|
|
164
|
+
- Bars drawn from a `table` region → `experimental/chart.md` (EXPERIMENTAL)
|
|
165
|
+
|
|
166
|
+
## The drawn annotation — `note=` (`figdown 0.3`)
|
|
167
|
+
|
|
168
|
+
`note=` is an **attribute on the annotated element's own line**, and the
|
|
169
|
+
element it is about is the element it is written on: `node a "A" note="…"`,
|
|
170
|
+
`group g "G" note="…"`, `edge a -> b note="…"`, `title "T" note="…"`.
|
|
171
|
+
There is no id, no target key and no locator, so there is never a question
|
|
172
|
+
of which of several identically-labelled elements is meant.
|
|
173
|
+
|
|
174
|
+
**What you may conclude.** The text is authored prose — quotable,
|
|
175
|
+
displayable, **never parsable**. It is an aside about the element, not a
|
|
176
|
+
fact about the figure's structure. Attribute it to its carrier and stop;
|
|
177
|
+
do not infer a participant, an edge or a category from it. A `note=` on
|
|
178
|
+
`title` is about the **figure** and about no element.
|
|
179
|
+
|
|
180
|
+
**What it is not.** It is not `description=`. The two divide by AUDIENCE:
|
|
181
|
+
`description=` is machine-facing and draws nothing beyond an SVG `<title>`;
|
|
182
|
+
`note=` is human-facing and always draws. And **where a typed slot exists,
|
|
183
|
+
a note is never where the fact lives** — a category is a `class` meaning, a
|
|
184
|
+
containment is `in=`, a direction is the operator. If a note's text looks
|
|
185
|
+
like structure, it is still prose: read the structure off the construct that
|
|
186
|
+
states it.
|