Standalone LaTeX/TikZ skill for non-tensor paper figures: node/edge macros, lint-on-warning build, golden examples, and negative fixtures.
4.6 KiB
superfig.sty API
\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
\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.
\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
\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
\sfgroup[role=attn]{block}{(attn)(ffn)}{} % empty overlay; caption the group
\sflane{R1}
\sfcaption{block}{主路模块}{注意力 + 前馈}
\sfcallout{N1}{38mm}{R1}{title}{body}
\sfgroupneeds 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\sfrowband, 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.\sfnolaneturns the shared caption baseline off.
Bottom
\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.