cvpr: fidelity pass aligning with cvpr.sty + LaTeX article-class#72
Open
DzmingLi wants to merge 11 commits into
Open
cvpr: fidelity pass aligning with cvpr.sty + LaTeX article-class#72DzmingLi wants to merge 11 commits into
DzmingLi wants to merge 11 commits into
Conversation
f0f43d2 to
8b90bab
Compare
cvpr.sty:49 loads the caption package as:
\RequirePackage[
format=plain,
labelformat=simple,
labelsep=period,
font=small,
compatibility=false
]{caption}
Notably absent is `singlelinecheck=false`. The caption package's
default `singlelinecheck=true` behavior is therefore active:
- captions that fit on a single line → centered
- captions that wrap to multiple lines → left-justified
The previous show rule was effectively always-left:
show figure.caption: set align(center)
show figure.caption: it => block({
align(left, it)
})
The outer `set align(center)` was overridden by the inner
`align(left, it)` inside the block — single-line captions never
got centered.
Fix uses `layout(container => measure(...))` to detect natural
caption width vs available container width: if it fits one line,
center; otherwise left-align with wrapping.
cvpr.sty:34 includes \RequirePackage{amsmath}. With amsmath, LaTeX
authors signal numbering intent via the choice of environment:
- $$ ... $$ / \[ ... \] → display math, NOT numbered
- \begin{equation} ... \end{equation} → auto-numbered (1), (2), ...
typst has no equivalent dual environment — every block equation is
numbered when `set math.equation(numbering: "(1)")` is in effect.
This prints sequential numbers next to throwaway display math
(intermediate algebra steps, derivations) that authors never
intended to reference.
We use the typst `<eq:foo>` label as the "intent to number" signal:
$ x = y $ ← unlabeled, no number
$ x = y $ <eq:foo> ← labeled, gets "(1)"
This mirrors LaTeX practice: only equations the author plans to
\eqref{...} get a number; the rest stay unnumbered.
The recursion guard (`if it.numbering == none`) prevents the
recreated equation below from re-entering the show rule. The
counter rollback fixes the otherwise-off-by-one numbering: typst's
outer `set` rule increments the equation counter eagerly, so an
unlabeled equation between two labeled ones would skip a number
without the rollback.
650fa22 to
bc89bc1
Compare
cvpr.sty defines only three section command levels:
\cvprsection (level 1)
\cvprsubsection (level 2)
\cvprsubsubsection (level 3)
`\paragraph{...}` (level 4) is left to the article-class default,
which renders as a bold run-in inline heading on the same line as
the paragraph that follows, with about 6pt of above-skip glue.
Empirical pdftotext-bbox measurement against the LaTeX render:
normal baseline-to-baseline gap: 11.96pt
above a \paragraph{...} mini-head: 18.17pt
─────
6.21pt extra above-skip
Without an explicit show rule, typst falls through to the default
block heading style — `\paragraph{Foo.}` becomes a freestanding
bold line, breaking the run-in semantics. This show rule:
- emits a 7.1pt strut (`weak: false` so it survives layout
collapsing against the preceding paragraph break)
- wraps the heading body in a `box(...)` so it stays inline and
the next paragraph continues on the same baseline
- appends an en-space (0.6em) gap to the body sentence
290b752 to
4b2042a
Compare
cvpr.sty:36 declares \RequirePackage{booktabs} — booktabs-style
horizontal rules are part of the canonical CVPR table aesthetic:
\toprule 1.5pt thick rule (\heavyrulewidth = 0.08em)
\midrule 0.5pt thin rule (\lightrulewidth = 0.05em)
\bottomrule 1.5pt thick rule
\aboverulesep / \belowrulesep 2pt vertical gap around each rule
typst's `table.hline()` draws a line at row boundaries but provides
no padding semantics — applying it directly produces lines flush
against adjacent cell baselines, visually wrong for booktabs.
These three helpers expand to hline + colspan-aware empty cells
that reproduce the booktabs vertical gaps. Naming follows booktabs
LaTeX commands directly so users coming from a LaTeX cvpr.sty
workflow recognize the API immediately.
…titlesupplementary
The previous `appendix` parameter only did `set heading(numbering:
"A.1") + counter(heading).update(0)` and rendered the content
in-flow.
But the semantics were incomplete. cvpr.sty's macro is:
\def\maketitlesupplementary{
\newpage
\twocolumn[
\centering \Large \textbf{\thetitle}\\
\vspace{0.5em}Supplementary Material \\
\vspace{1.0em}
]
}
This does a pagebreak, re-prints the paper title in cross-column
space at the top of the new page, and adds a "Supplementary
Material" subtitle, before continuing in the body's 2-column
layout. The previous typst implementation skipped all of that
and just shifted heading numbering.
This commit:
- adds `pagebreak(weak: true)` on the supplementary entry
- adds a `place(top, scope: "parent", float: true, ...)` that
re-renders the title + "Supplementary Material" subtitle as a
cross-column header (typst's equivalent of LaTeX `\twocolumn[...]`)
- keeps the heading numbering shift to "A.1." (preserved daskol
behavior — supplementary sections numbered A.1, A.2, ...)
- updates README.md to rename `appendix` → `supplementary`
18f9646 to
95aaf93
Compare
…sys.inputs
The previous `accepted: false | true | none` parameter encoded
modes via boolean tri-state, with `accepted != none and not
accepted` scattered across six conditional branches (banner,
ruler, anonymous-author replacement, page-number footer, ...).
Three issues:
1. cvpr.sty:55-61 declares `[review]`, `[rebuttal]`, and `[final]`
as first-class string options on one axis, plus an orthogonal
`[pagenumbers]` toggle. A boolean tri-state can't directly
express rebuttal, and forced an opaque encoding for the third
option. The orthogonal pagenumbers axis was missing entirely.
2. The conditional `accepted != none and not accepted` reads like
a riddle. Every reader has to mentally unfold which mode that is
(review).
3. Switching mode required editing main.typ — passing a different
literal to `accepted:`. cvpr.sty's LaTeX equivalent
`\usepackage[review]{cvpr}` switches at compile time, no source
edit needed.
Replaces with a mirror of cvpr.sty's two-axis design:
mode: "review" ← line numbers, banner, anon authors
mode: "final" ← camera-ready; real authors, no banner (default)
mode: "rebuttal" ← rebuttal; smaller title, no author block,
top vspace pulled up per cvpr.sty:282-287
page-numbers: auto | true | false ← orthogonal toggle;
auto = mode=review default
Default is `mode: "final"` to match cvpr.sty:55-58 (`\toggletrue
{cvprfinal}` is set unconditionally; only an explicit option flips
it). Authors who haven't passed `--input mode=...` get camera-ready
output, the same as `\usepackage{cvpr}` without options.
Daskol's previous `accepted: none` ("arxiv preprint") is dropped.
That state was visually identical to `accepted: true` (final): same
no-banner, no-ruler, no-line-numbers layout. The only difference
was a hint in PDF metadata, which the template did not actually
emit. So the third state was redundant — users who wanted "looks
like final but not yet camera-ready" just write `mode: "final"`,
since the visual is the same and PDF metadata isn't differentiated.
The `[pagenumbers]` axis covers the remaining variation (camera-
ready look + visible page numbers, useful for length-checking
before the final submission).
Rebuttal-mode title layout is implemented in this commit:
cvpr.sty:282-307 specifies smaller title font (\large vs \Large),
top pulled up by ~0.3in (negative \vspace*), tightened post-title
gap (-22pt vs +24pt) to fit the rebuttal page budget, and an
empty author block (the `\iftoggle{cvprrebuttal}{}{...}` branch
is empty — reviewers know the authors at rebuttal stage but the
slot is intentionally blank to keep the title page tight).
95aaf93 to
cfab2db
Compare
cvpr.sty inherits article.cls's paragraph behavior, where the first
paragraph after `\@startsection`-derived elements (\section,
\subsection, ...) is set with `\@afterindentfalse` (no indent), but
the first paragraph after non-heading blocks (`\quote`, `\figure`,
`\begin{equation}`, ...) IS indented as a normal continuation
paragraph. CVPR papers use `\quote` regularly (e.g. for showing
example author guidelines, citing reviewer-style abstracts in the
rebuttal-mode preamble), so getting this case right matters.
This fully matches article-class / cvpr.sty paragraph behavior:
- heading → next paragraph: not indented (suppressed by state)
- quote/figure/equation → next paragraph: indented (auto via all: true)
- first paragraph inside a quote: indented (auto via all: true,
once the quote's first-line-indent override is dropped)
- consecutive paragraphs: indented (typst default consecutive rule)
The `#indent = h(12pt)` helper that previously existed for manual
post-block indentation is removed: the auto-indent show rule
covers every site that called it.
cvpr.sty ships a coordinated set of 13 emphasized + period-aware
abbreviation macros via:
\def\eg{\emph{e.g}\onedot} \def\Eg{\emph{E.g}\onedot}
\def\ie{\emph{i.e}\onedot} \def\Ie{\emph{I.e}\onedot}
\def\cf{\emph{cf}\onedot} \def\Cf{\emph{Cf}\onedot}
\def\etc{\emph{etc}\onedot} \def\vs{\emph{vs}\onedot}
\def\wrt{w.r.t\onedot} \def\dof{d.o.f\onedot}
\def\iid{i.i.d\onedot} \def\wolog{w.l.o.g\onedot}
\def\etal{\emph{et al}\onedot}
`\onedot` (cvpr.sty:461-463) is a smart period-and-xspace combinator
that adds a trailing `.` only when the next character isn't already
one — so authors can write `\eg, foo` (gets period auto), `\eg.` (no
double period), `\eg foo` (xspace handles trailing space) without
worrying which case they're in. The typst port previously had only
`#eg` and `#etal` as hardcoded literals, missing the other 11
abbrevs and the `\onedot` guard.
Adds the 11 missing abbreviations matching cvpr.sty's emphasis
decisions: `eg`/`Eg`/`ie`/`Ie`/`cf`/`Cf`/`etc`/`vs`/`etal` are
italicized; `wrt`/`dof`/`iid`/`wolog` are plain (cvpr.sty
intentionally doesn't `\emph` them). The trailing period lives
outside the `emph` (`emph[X] + "."`, not `emph[X.]`) so it sits
in the same plain-text run as any author-typed `.` and the
collapse regex below can fire across the boundary.
Adds a single regex show rule that emulates `\onedot`:
show regex("\.\.[^.]"): m => "." + m.text.slice(2)
Matches `.` `.` `<non-period>`, replaces with `.` `<non-period>` —
collapsing double periods while preserving the next character.
typst auto-ligatures `...` to Unicode ellipsis (single codepoint)
so the regex never sees `...` and ellipsis stays intact. Real `..`
in numeric ranges (e.g. "1..5") is rare in CVPR writing.
cvpr.sty inherits LaTeX article-class's \thanks{...} mechanism for
title-block footnotes (e.g. corresponding-author marker). Authors
write inline:
\author{... Hao Lu\thanks{Corresponding author.} ...}
article-class's `\thanks` does three things:
1. \footnotemark + \footnotetext pair sharing the regular footnote
counter — so \thanks and \footnote tap the same counter.
2. Inside \maketitle, the mark is rendered via \fnsymbol — the
symbol cycle `*, †, ‡, §, ¶, ‖, **, ††, ‡‡, §§, ¶¶, ‖‖`.
Outside \maketitle the mark is \arabic.
3. article.cls calls `\setcounter{footnote}{0}` at the end of
`\maketitle`. So body footnotes start fresh at `1` even after
N \thanks markers. With three \thanks and two body footnotes,
marks render as: `*`, `†`, `‡`, `1`, `2`.
This commit ports those semantics by exporting `thanks(body)` with
the \fnsymbol numbering cycle, resetting the footnote counter after
make-title, and making `author.name` content-typed (so authors can
put `name: [Hao Lu#thanks[...]]` without crashing the document
metadata path).
cvpr.sty:37 declares `\RequirePackage[numbers,sort&compress]{natbib}`
and CVPR papers conventionally use `\bibliographystyle{ieeenat_fullname}`,
which gives:
1. Compact citation clusters `[1, 3-5]` — sorted, ranged, single
bracket pair per cluster.
2. Full author names (no initials), Oxford comma only with 3+ authors.
3. Sentence-case titles (no quotes).
4. Compact journal `vol(issue):pages, year` form.
5. Conference: `In Container, pages X-Y. Pub, year.` with publisher,
`In Container, pages X-Y, year.` without.
Rename `cvpr/ieee.csl` → `cvpr/cvpr.csl` and apply the CVPR-specific
patches below. `<info>` is rewritten to declare CVPR identity (title,
id, summary, links to cvpr-org/author-kit + ieee_fullname.bst),
matching what the file actually formats.
Patches applied:
- `<citation collapse="citation-number">` + brackets moved from
`<group>` to `<layout>` so each cluster wraps in one pair (was
`[7], [11], [12], [13], [14]`, now `[7, 11-14]`).
- `<bibliography><sort>` by author then date — alphabetical entry
order (was insertion order).
- `<name>` element: drop `initialize-with=". "` for full names,
raise `et-al-min` to 11 with `et-al-use-first="10"`, drop
`delimiter-precedes-last="always"` so 2-author cites read
`A and B` not `A, and B`.
- `<macro name="title">`: drop `quotes="true"`, add
`text-case="sentence"` to non-italic branch.
- Author suffix: `, ` → `. ` in bibliography layout.
- `<macro name="event">`: capitalize "in" → "In" before container.
- New `<macro name="vol-pages-compact">`: emits `VOL(ISSUE):PAGES`
when issue exists (`9(6):544`), else `VOL:PAGES` (`37:48810-48837`).
- New `<macro name="page-long">`: emits `pages X-Y` with long form.
- article-journal: title `. ` then `container, vol-pages-compact, year.`
- paper-conference: conditional on `publisher` —
with: `title. event, page-long. publisher, year.`
without: `title. event, page-long, year.`
- chapter: title `. ` then `In container, ..., page-long, year.`
`cvpr/lib.typ` switches `bibliography(style: ...)` to `cvpr.csl`.
Output now matches LaTeX/ieeenat_fullname.bst field-for-field, modulo
hayagriva sentence-case lowercasing hyphenated and all-caps words
differently from BST (`Context-Motion` → `Con-text-motion`,
`UAVs` → `Uavs`); use `{...}` brace protection in source bib/yml to
opt out per-word.
LaTeX `pagebackref` (review-mode page-numbers-where-cited annotation
appended to each bibliography entry) is not implemented in this
commit. typst's `bibliography()` element collapses entries into one
opaque block with no per-entry hook, and the community `retrofit`
package's grid/block detection broke on typst 0.14. When typst#942
(Bibliography customization API) lands a per-entry rendering hook,
backref can be added via show rules without bypassing
`bibliography()` ourselves.
cfab2db to
dd0b292
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
11-commit fidelity pass over cvpr/ aligning with cvpr.sty + LaTeX article-class behavior. Each commit is atomic with cvpr.sty line refs in the message — see individual commits for rationale.
Partially addresses #14: cvpr.csl now matches cvpr.sty + ieeenat_fullname.bst field-for-field. Backref support (LaTeX
pagebackref) is not included — typst'sbibliography()collapses entries into one opaque block with no per-entry hook, blocking show-rule injection. When typst#942 (Bibliography customization API) lands a per-entry rendering hook, backref can be added via show rules without bypassingbibliography()ourselves.I made some design choices that might be up for debate. Feel free to discuss with me!