Standalone LaTeX/TikZ skill for non-tensor paper figures: node/edge macros, lint-on-warning build, golden examples, and negative fixtures.
123 lines
4.6 KiB
Markdown
123 lines
4.6 KiB
Markdown
# superfig.sty API
|
|
|
|
```tex
|
|
\documentclass[border=10pt]{standalone}
|
|
\usepackage[cjk]{superfig} % cjk: ctex + fandol (XeLaTeX). en: English rail labels.
|
|
```
|
|
|
|
Build with `./scripts/build.sh fig.tex` — it puts `assets/` on `TEXINPUTS`.
|
|
|
|
The build first runs `scripts/lint.py`. It rejects ledger changes, more than four
|
|
active hues, raw `\draw`/`\fill`/`\path`, a formula placed before the last row, a
|
|
callout that is not an aside on a `\sfrow` band, a second callout, and a group
|
|
with fewer than two members. Intentional galleries may put
|
|
`% superfig-lint: allow-raw-tikz, allow-multiple-callouts` near the top; do not
|
|
add an exemption to a deliverable merely to make it pass.
|
|
|
|
Rules for *when* to use each primitive live in `grammar.md` and `layout.md`.
|
|
|
|
## Ledgers
|
|
|
|
```tex
|
|
\sfsetrole{input}{sfTeal} % role -> color. Macros take a ROLE, never a color.
|
|
\sfsetlabels{A}{O}{M} % override the three meaning-box rail labels
|
|
\sfsetrail{5.4em} % width of the bold label rail (`[en]` defaults wider)
|
|
```
|
|
|
|
Colors: `sfTeal sfOrange sfCoral sfViolet sfGray sfInk`. An unknown role falls
|
|
back to gray **and emits a package warning**, which `build.sh` turns into a
|
|
failed build. Redeclaring a role with a different color warns and keeps the
|
|
original mapping.
|
|
|
|
Lengths: `\sfgutter` (6 mm), `\sfrowgap` (3.5 mm), `\sfblockgap` (9 mm),
|
|
`\sflinklen` (10 mm).
|
|
|
|
## Flow layout
|
|
|
|
Empty `at` places the object at the cursor. Hand-written offsets are for
|
|
genuinely non-linear topology.
|
|
|
|
```tex
|
|
\sfstage{SA}{stage heading}
|
|
\sfrow{R1}{16mm}
|
|
\sfnode[role=input]{x}{输入 $x$}{16mm}{12mm}
|
|
\sfconn{e1}{预处理}
|
|
\sfnode[role=model]{f}{模型 $f_\theta$}{18mm}{12mm}
|
|
\sfrowend
|
|
\sflane{R1}
|
|
\sfcaption{x}{$x$}{原始输入}
|
|
```
|
|
|
|
| macro | does |
|
|
|---|---|
|
|
| `\sfstage{name}{text}` | stage heading on the left rail, below all ink so far |
|
|
| `\sfrow{name}{height}` | open a band; `height` is a length |
|
|
| `\sfrowend` | `fit` the band into `name` |
|
|
| `\sfnode[keys]{name}{label}{w}{h}` | one semantic object |
|
|
| `\sfop{name}{glyph}` | operator in the flow; reserves its own width |
|
|
| `\sfconn{name}{label}` | connector; empty label reserves `\sflinklen` of bare arrow |
|
|
| `\sfgap{4mm}` / `\sfvgap{4mm}` | extra space, horizontal / vertical |
|
|
| `\sfleftrail{x}` | move the left rail |
|
|
| `\sfbbox{all}` | everything drawn so far, as one node |
|
|
| `\sftopformula{F}{math}` | claim/formula, centered on what was actually drawn |
|
|
| `\sftrack{node}` | fold a hand-placed TikZ node into the bbox and vertical cursor |
|
|
| `\sflayoutreset` | start over |
|
|
|
|
`\sfnode` keys: `role=` (default `neutral`), `level=` (`1/2/3` → `!30/!55/!80`),
|
|
`gap=` (space *before* this object in a row), `bracket=` (matrix-style arms),
|
|
`at={}` (empty = cursor; a coordinate bypasses the row).
|
|
|
|
Call `\sftopformula` **after** the last `\sfrowend`. A formula placed first is
|
|
centered on a figure whose width is not yet known.
|
|
|
|
## Fixed topology
|
|
|
|
```tex
|
|
\sfnode[role=enc, at={(0,-22mm)}]{in}{输入}{16mm}{10mm}
|
|
\sfarrow{in.east}{attn.west}
|
|
\sfarrowlabel[bend left=18]{in.north}{add.north}{残差}
|
|
```
|
|
|
|
`\sfarrow` / `\sfarrowlabel` take the same `to[]` options as TikZ (`bend left`,
|
|
`out=south, in=north`). The label uses `auto` so a vertical edge does not sit
|
|
the text on the shaft. Route is on the background layer.
|
|
|
|
Keep `at=` on a coarse grid or derive it from existing anchors
|
|
(`at={($(te.east)!0.5!(ve.east)+(20mm,0)$)}`).
|
|
|
|
## Groups, captions, callouts
|
|
|
|
```tex
|
|
\sfgroup[role=attn]{block}{(attn)(ffn)}{} % empty overlay; caption the group
|
|
\sflane{R1}
|
|
\sfcaption{block}{主路模块}{注意力 + 前馈}
|
|
\sfcallout{N1}{38mm}{R1}{title}{body}
|
|
```
|
|
|
|
- `\sfgroup` needs at least two members in the fit list. A single-node outline
|
|
is a package warning. After a row, the group refits that row so `\sflane{R1}`
|
|
hangs captions below the outline.
|
|
- Prefer an empty overlay caption and `\sfcaption{group}{...}{...}`. An overlay
|
|
sits on the north-west corner and collides with skip edges.
|
|
- `\sfcallout{name}{width}{band}{title}{body}` hangs off a **finished** `\sfrow`
|
|
band, one per figure. Inside an open row it is a package error; a non-band
|
|
anchor or a second card is a warning.
|
|
- `\sfcaptiontop{name}{text}` is the occasional label above a node.
|
|
- `\sfnolane` turns the shared caption baseline off.
|
|
|
|
## Bottom
|
|
|
|
```tex
|
|
\sfbbox{all}
|
|
\sfmeaningbox{mb}{96mm}{all}{idea}{objects}{mechanism}
|
|
\sfsignature{subject}{mb} % optional; subject only
|
|
```
|
|
|
|
Arg 2 is the total box width. An empty `{}` row is dropped. `\usepackage[en]`
|
|
switches the rails to Concept / Objects / Mechanism.
|
|
|
|
## Lint exemptions
|
|
|
|
`% superfig-lint: allow-raw-tikz, allow-multiple-callouts, allow-single-group`
|
|
near the top of the source. Deliverables normally have none.
|