Skip to content

Fix natbib citations rendering inline instead of in the margin - #135

Merged
cderv merged 3 commits into
mainfrom
fix-48
May 19, 2026
Merged

Fix natbib citations rendering inline instead of in the margin#135
cderv merged 3 commits into
mainfrom
fix-48

Conversation

@cderv

@cderv cderv commented May 19, 2026

Copy link
Copy Markdown
Collaborator

When tufte::tufte_handout() (or tufte_book()) is used with citation_package: natbib, citations render inline as plain author-year text with a bibliography only at the bottom, instead of appearing as margin sidenotes like tufte-latex does for hand-written \cite{} calls.

Root Cause

Pandoc with citation_package: natbib emits \citep{key} for [@key] and \citet{key} for @key, never the bare \cite{} form. The tufte-latex classes only redefine \cite to route through the margin sidenote machinery (inst/rmarkdown/templates/tufte_handout/patches/tufte-common.def, line 970); natbib's own \citep and \citet are left untouched, so they render inline like in any non-tufte document.

Fix

Patch tufte-common.def to redefine \citep and \citet via \RenewDocumentCommand, guarded by the existing @tufte@loadnatbib boolean:

\ifthenelse{\boolean{@tufte@loadnatbib}}{%
  \RenewDocumentCommand{\citep}{o o m}{\cite{#3}}%
  \RenewDocumentCommand{\citet}{o o m}{\citeauthor{#3}~(\citeyear{#3})\cite{#3}}%
}{}

\citep now produces a margin sidenote (superscript marker in body, full reference in the margin). \citet keeps natbib's textual "Author (Year)" form inline AND adds the full reference to the margin — the proper Tufte book style, preserving prose for textual citations. The redefinitions delegate to \cite rather than \@tufte@normal@cite directly so they pick up tufte's in-sidenote swap when nested inside \sidenote{}.

\RenewDocumentCommand is available in the LaTeX kernel since 2020-10, so no extra \usepackage{xparse} is needed.

The patch is also registered in tools/update-tufte-common-def.R so future upstream refreshes re-apply it automatically.

Known limitations

  • Optional \citep[prefix][locator]{key} arguments are dropped. [@key, p. 5] places the entry in the margin but does not echo "p. 5".
  • \citeyearpar (emitted for [-@key] suppress-author) is intentionally left at natbib's default inline rendering.

Test plan

  • Render tufte::tufte_handout() with citation_package: natbib and [@key] — superscript in body, full entry in margin
  • Same with @key — body shows "Author (Year)" + superscript, margin shows full entry
  • Multi-key [@a; @b] — single superscript, margin shows both entries joined with "and"
  • [-@key] — renders inline as (YEAR), no margin entry (by design)
  • tufte::tufte_book(), tufte_handout2(), tufte_book2() behave the same
  • Citation inside ^[footnote] does not error
  • devtools::test() passes

Fixes #48

cderv added 2 commits May 19, 2026 14:46
Pandoc emits \citep / \citet when citation_package: natbib is set,
but tufte-latex only redirects \cite, so citations rendered inline
instead of as margin sidenotes. Patch tufte-common.def to redefine
both commands via \RenewDocumentCommand: \citep routes through
\cite (margin entry), \citet adds the "Author (Year)" textual form
inline plus the margin entry. \citeyearpar ([-@key]) is intentionally
untouched; optional prefix/locator arguments are dropped.
@cderv
cderv merged commit edda21f into main May 19, 2026
18 checks passed
@cderv
cderv deleted the fix-48 branch May 19, 2026 13:40
cderv added a commit that referenced this pull request May 21, 2026
The xparse signature `{o o m}` used by the #48 patch reads the next token
as the mandatory argument when no optional argument is present. For
raw-LaTeX `\citep*{key}` that token is `*`, so the citation key `{key}`
gets dropped on the floor and the star becomes the cite argument, with
broken output and undefined-citation warnings.

Pandoc never emits the starred forms itself, so the bug only reaches
users who type natbib commands directly in their .Rmd. Add `s` to the
signature on both `\citep` and `\citet` so the star is consumed, then
route the unstarred margin path either way. The keep-generator-in-sync
copy in tools/update-tufte-common-def.R is updated to match.

Follow-up to roborev review on #48 (PR #135).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Broken margin citations in PDF and footnote citations in HTML

1 participant