Add source linter, negative test fixtures, and fallback guidance
- scripts/lint.py: reject raw rectangles, absolute coordinates, hue-budget and callout/group/formula-order violations at the source level - tests/invalid/ + tests/lint-invalid/: negative fixtures proving the package and linter reject bad input; test.sh now runs both directions - references/fallback.md: degraded path when no LaTeX is available - tests/group-callout.tex: exercise \stgroup and \stcallout - agents/openai.yaml: agent config - Docs and .sty updated to match
This commit is contained in:
@@ -58,6 +58,9 @@
|
||||
\stcaption{Wc}{$\mathbf W^{(r)}$}{$d\times T$}
|
||||
\stcaption{Z}{$\mathbf Z$}{$T\times T$}
|
||||
|
||||
\sttopformula{F}{$\displaystyle
|
||||
\operatorname{flow}(X,W)\;:\;\text{对象按自身边界框依次占位}$}
|
||||
|
||||
\stbbox{all}
|
||||
\stmeaningbox{mb}{15cm}{all}
|
||||
{$T$ 序列长,$d$ 模型维,$r$ 低秩维}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
% Regression test for \stgroup and \stcallout.
|
||||
% - a group over one stack (the three sheets are one composite object),
|
||||
% - a group over two adjacent shards (the pair is one partitioned parent),
|
||||
% - a side card hanging off the right edge of each band.
|
||||
% No absolute coordinate appears anywhere in this figure.
|
||||
% ../scripts/build.sh group-callout.tex
|
||||
\documentclass[border=10pt]{standalone}
|
||||
\usepackage[cjk]{supertensor}
|
||||
|
||||
\stsetrole{act}{stTeal}
|
||||
\stsetrole{w}{stOrange}
|
||||
\stsetrole{q}{stTeal}
|
||||
\stsetrole{k}{stViolet}
|
||||
\stsetrole{v}{stCoral}
|
||||
|
||||
\stdim{T}{7}
|
||||
\stdim{d}{5}
|
||||
\stdim{dh}{3}
|
||||
|
||||
\begin{document}
|
||||
\begin{tikzpicture}
|
||||
|
||||
\ststage{S1}{一、分组框:把已经排好的面命名为一个复合对象}
|
||||
\strow{R1}{T}
|
||||
\stface[role=act, bracket=true]{X}{}{T}{d}
|
||||
\stlink{l1}{三路投影}
|
||||
\stgroup[role=q]{QG}
|
||||
\ststack[role=q]{Q}{}{T}{dh}{3}
|
||||
\stgroupend
|
||||
\stgroup[role=k]{KG}
|
||||
\ststack[role=k]{K}{}{T}{dh}{3}
|
||||
\stgroupend
|
||||
\stgroup[role=v]{VG}
|
||||
\ststack[role=v]{V}{}{T}{dh}{3}
|
||||
\stgroupend
|
||||
\strowend
|
||||
\stcaption{X}{$\mathbf X$}{$T\times d$}
|
||||
\stcaption{QG}{$\mathbf q$}{$h\times T\times d_h$}
|
||||
\stcaption{KG}{$\mathbf k$}{$h\times T\times d_h$}
|
||||
\stcaption{VG}{$\mathbf v$}{$h\times T\times d_h$}
|
||||
\stcallout{N1}{4.2cm}{R1}{分组框在说什么}%
|
||||
{外框与里面的面同色,因为它圈的是同一个对象的多头视图,不是一个新张量。
|
||||
框的内边距计入行的包围盒,所以下面的符号轨仍然从框底起算。}
|
||||
|
||||
\ststage{S2}{二、分组框圈住两片相邻的分片,标注它们合起来是谁}
|
||||
\strow{R2}{T}
|
||||
\stface[role=act]{H}{}{T}{d}
|
||||
\stglyph{m2}{$\times$}
|
||||
\stgroup[role=w, pad=2.2mm]{WG}
|
||||
\stcol{Wc}{d}
|
||||
\stface[role=w]{Wa}{}{dh}{T}
|
||||
\stface[role=w, gap=0pt]{Wb}{}{2}{T}
|
||||
\stcolend
|
||||
\stgroupend
|
||||
\stlink{l2}{}
|
||||
\stface[role=q, bracket=true]{Z}{}{T}{T}
|
||||
\strowend
|
||||
\stcaption{H}{$\mathbf H$}{$T\times d$}
|
||||
\stcaption{WG}{$\mathbf W$}{$d\times T$}
|
||||
\stcaption{Z}{$\mathbf Z$}{$T\times T$}
|
||||
\stcallout{N2}{4.2cm}{R2}{一行一张卡}%
|
||||
{同一个 band 上挂两张卡会被 lint 拒绝:并排的说明卡是仪表盘,不是图。}
|
||||
|
||||
\sttopformula{F}{$\displaystyle \mathbf Z=\mathbf H\,\mathbf W,\qquad
|
||||
\mathbf W=\begin{bmatrix}\mathbf W_a\\ \mathbf W_b\end{bmatrix}$}
|
||||
|
||||
\stbbox{all}
|
||||
\stmeaningbox{mb}{17cm}{all}
|
||||
{$T$ 序列长,$d$ 模型维,$d_h$ 头宽,$h$ 头数}
|
||||
{}
|
||||
{分组框是横向的子流:成员写在块里,所以它只能圈住相邻的对象;
|
||||
两侧的内边距各占一份宽度,箭头也接在外框上而不是成员上——
|
||||
否则连接线会穿过一个并非自己端点的框。
|
||||
说明卡挂在 band 右侧,并把纵向游标压到自己底边以下,所以卡片过高只会撑开空白,
|
||||
不会压住下一段。}
|
||||
|
||||
\end{tikzpicture}
|
||||
\end{document}
|
||||
@@ -0,0 +1,7 @@
|
||||
\documentclass[border=2pt]{standalone}
|
||||
\usepackage[en]{supertensor}
|
||||
\stdim{d}{4}
|
||||
\stdim{d}{7}
|
||||
\begin{document}\begin{tikzpicture}
|
||||
\stface{A}{(0,0)}{d}{d}
|
||||
\end{tikzpicture}\end{document}
|
||||
@@ -0,0 +1,8 @@
|
||||
\documentclass[border=2pt]{standalone}
|
||||
\usepackage[en]{supertensor}
|
||||
\stsetrole{idx}{stOrange}
|
||||
\stdim{m}{2}
|
||||
\stdim{n}{3}
|
||||
\begin{document}\begin{tikzpicture}
|
||||
\stindexface[role=idx]{I}{(0,0)}{m}{n}{0,1,2,3,4}
|
||||
\end{tikzpicture}\end{document}
|
||||
@@ -0,0 +1,8 @@
|
||||
\documentclass[border=2pt]{standalone}
|
||||
\usepackage[en]{supertensor}
|
||||
\stsetrole{x}{stTeal}
|
||||
\stdim{m}{2}
|
||||
\stdim{n}{3}
|
||||
\begin{document}\begin{tikzpicture}
|
||||
\stface[role=x,pattern=data,data={303}]{A}{(0,0)}{m}{n}
|
||||
\end{tikzpicture}\end{document}
|
||||
@@ -0,0 +1,8 @@
|
||||
\documentclass[border=2pt]{standalone}
|
||||
\usepackage[en]{supertensor}
|
||||
\stsetrole{x}{stTeal}
|
||||
\stdim{m}{2}
|
||||
\stdim{n}{3}
|
||||
\begin{document}\begin{tikzpicture}
|
||||
\stface[role=x,pattern=data,data={303,34}]{A}{(0,0)}{m}{n}
|
||||
\end{tikzpicture}\end{document}
|
||||
@@ -0,0 +1,7 @@
|
||||
\documentclass[border=2pt]{standalone}
|
||||
\usepackage[en]{supertensor}
|
||||
\stsetrole{x}{stTeal}
|
||||
\stdim{d}{3}
|
||||
\begin{document}\begin{tikzpicture}
|
||||
\stface[role=x,pattern=solid,level=9]{A}{(0,0)}{d}{d}
|
||||
\end{tikzpicture}\end{document}
|
||||
@@ -0,0 +1,7 @@
|
||||
\documentclass[border=2pt]{standalone}
|
||||
\usepackage[en]{supertensor}
|
||||
\stsetrole{x}{stTeal}
|
||||
\stdim{d}{3}
|
||||
\begin{document}\begin{tikzpicture}
|
||||
\stface[role=x,pattern=checkerboard]{A}{(0,0)}{d}{d}
|
||||
\end{tikzpicture}\end{document}
|
||||
@@ -0,0 +1,8 @@
|
||||
\documentclass[border=2pt]{standalone}
|
||||
\usepackage[en]{supertensor}
|
||||
\stsetrole{x}{stTeal}
|
||||
\stsetrole{x}{stCoral}
|
||||
\stdim{d}{3}
|
||||
\begin{document}\begin{tikzpicture}
|
||||
\stface[role=x]{A}{(0,0)}{d}{d}
|
||||
\end{tikzpicture}\end{document}
|
||||
@@ -0,0 +1,7 @@
|
||||
\documentclass{standalone}
|
||||
\usepackage[en]{supertensor}
|
||||
\stdim{d}{3}
|
||||
\begin{document}\begin{tikzpicture}
|
||||
\stface{A}{(0,0)}{d}{d}
|
||||
\sttopformula{F}{$A$}
|
||||
\end{tikzpicture}\end{document}
|
||||
@@ -0,0 +1,12 @@
|
||||
% A callout anchored to a face rather than to a band: the card lands beside a
|
||||
% single operand and reads as a step in the computation.
|
||||
\documentclass{standalone}
|
||||
\usepackage[en]{supertensor}
|
||||
\stdim{T}{4}
|
||||
\begin{document}\begin{tikzpicture}
|
||||
\strow{R1}{T}
|
||||
\stface{A}{}{T}{T}
|
||||
\strowend
|
||||
\stcallout{N1}{3cm}{A}{aside}{anchored to a face, not to the band}
|
||||
\sttopformula{F}{$A$}
|
||||
\end{tikzpicture}\end{document}
|
||||
@@ -0,0 +1,13 @@
|
||||
% Two asides on one band: a dashboard, not a figure. The second card belongs
|
||||
% in \stmeaningbox.
|
||||
\documentclass{standalone}
|
||||
\usepackage[en]{supertensor}
|
||||
\stdim{T}{4}
|
||||
\begin{document}\begin{tikzpicture}
|
||||
\strow{R1}{T}
|
||||
\stface{A}{}{T}{T}
|
||||
\strowend
|
||||
\stcallout{N1}{3cm}{R1}{first}{one aside per band}
|
||||
\stcallout{N2}{3cm}{R1}{second}{this one has nowhere to go}
|
||||
\sttopformula{F}{$A$}
|
||||
\end{tikzpicture}\end{document}
|
||||
@@ -0,0 +1,9 @@
|
||||
\documentclass{standalone}
|
||||
\usepackage[en]{supertensor}
|
||||
\stdim{d}{3}
|
||||
\begin{document}\begin{tikzpicture}
|
||||
\sttopformula{F}{$A$}
|
||||
\strow{row}{d}
|
||||
\stface{A}{}{d}{d}
|
||||
\strowend
|
||||
\end{tikzpicture}\end{document}
|
||||
@@ -0,0 +1,12 @@
|
||||
% An unclosed \stgroup swallows the rest of the band into its fit list; TeX
|
||||
% only reports the resulting empty row, which does not point at the cause.
|
||||
\documentclass{standalone}
|
||||
\usepackage[en]{supertensor}
|
||||
\stdim{T}{4}
|
||||
\begin{document}\begin{tikzpicture}
|
||||
\strow{R1}{T}
|
||||
\stgroup{G}
|
||||
\stface{A}{}{T}{T}
|
||||
\strowend
|
||||
\sttopformula{F}{$A$}
|
||||
\end{tikzpicture}\end{document}
|
||||
@@ -0,0 +1,18 @@
|
||||
\documentclass{standalone}
|
||||
\usepackage[en]{supertensor}
|
||||
\stsetrole{a}{stTeal}
|
||||
\stsetrole{b}{stOrange}
|
||||
\stsetrole{c}{stCoral}
|
||||
\stsetrole{d}{stViolet}
|
||||
\stsetrole{e}{stInk}
|
||||
\stdim{x}{2}
|
||||
\begin{document}\begin{tikzpicture}
|
||||
\strow{row}{x}
|
||||
\stface[role=a]{A}{}{x}{x}
|
||||
\stface[role=b]{B}{}{x}{x}
|
||||
\stface[role=c]{C}{}{x}{x}
|
||||
\stface[role=d]{D}{}{x}{x}
|
||||
\stface[role=e]{E}{}{x}{x}
|
||||
\strowend
|
||||
\sttopformula{F}{$A+B+C+D+E$}
|
||||
\end{tikzpicture}\end{document}
|
||||
@@ -0,0 +1,6 @@
|
||||
\documentclass{standalone}
|
||||
\usepackage[en]{supertensor}
|
||||
\begin{document}\begin{tikzpicture}
|
||||
\fill (0,0) rectangle (2,2);
|
||||
\sttopformula{F}{$A$}
|
||||
\end{tikzpicture}\end{document}
|
||||
@@ -1,3 +1,5 @@
|
||||
% supertensor-lint: allow-absolute, allow-missing-formula
|
||||
% Legacy absolute-placement smoke test; flow layout is covered by flow.tex.
|
||||
\documentclass[border=8pt]{standalone}
|
||||
\usepackage[cjk]{supertensor}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user