# 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.