Replies: 3 comments 3 replies
-
|
Also filed as an issue for |
Beta Was this translation helpful? Give feedback.
-
That's a question for the developer of the filter.
It does, take a simple example or ask Claude to use simple example when testing/investigating.
---
title: Title of the document
format:
pdf:
filters:
- format-latex.lua
html: default
---
## Overview
Body text goes here.
--- format-latex.lua
--- A simple Pandoc Lua filter that logs messages when the output format is LaTeX.
function Pandoc(doc)
if FORMAT:match("latex") then
io.stderr:write("[format-latex] Output format is LaTeX.\n")
io.stderr:write("[format-latex] Number of blocks: " .. #doc.blocks .. "\n")
io.stderr:write("[format-latex] LaTeX filter processing complete.\n")
end
return doc
end
Unclear what you are asking. Freeze and Cache are two different features. The former is handled by Quarto to save the text result/output after computation, the latter is handled by the engine ( Since you are using Claude, ask it to create a small and simple reproducible example. |
Beta Was this translation helpful? Give feedback.
-
|
Thank you @mcanouil — your suggestion to create a minimal reproducible example was The TestI created a minimal repro document with three tests, available in the repo:
The document is configured with Each test defines a multi-line Test 1 — \providecommand{\myone}[1]{%
\textit{T1: #1}%
}followed by Test 2 — Same definition, but via Test 3 — The macro emitted by inline R via Results (from the generated
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Description
For nearly two weeks I've been struggling to re-build the HTML & PDF versions of my book, Visualizing Multivariare Data and Models in R. I get the same, persistent error every time. Each build takes ~18 min, so this is extremely frustrating.
With the help of Claude, I think I tracked this down to two problems, one related to the
tarleb/parse-latexextension and the other to the Quarto freeze/cache mechanism, described below. I'll also post this as an issue fortarleb/parse-latex, but the behavior I saw leads me to ask for help here.I've documented the attempts at solving this problem at Two Weeks in Quarto / Pandoc / LaTeX Hell
Problem
The
tarleb/parse-latexextension, when listed underformat: html: filters:in_quarto.yml, still expands user-defined LaTeX macros during the PDF pandoc pass. This is seems to be because the filter callspandoc.read(raw.text,'latex')on raw LaTeX blocks, which populates pandoc's internal macro table. Subsequentpandoc.read()calls on raw inline content then expand those macros — using whatever multi-line\providecommandor\newcommanddefinition was registered — and the expanded text contains%characters from the definition body, causing Xelatex to fail!When a Markdown footnote reference (
.[^fn]) follows the expanded inline in the source, the last%comments out the.\footnote{opener, producing:A compounding factor: Quarto's freeze cache does not track changes to
{{< include >}}'d files, so stale macro definitions can persist in cached chapter output even after the included file is corrected.Setup
documentclass: krantz)tarleb/parse-latex_quarto.yml:My
_quarto.ymlincludes:The book uses
{{< include latex/latex-commands.qmd >}}at the top of every chapter.latex-commands.qmddefines fallback versions of custom indexing macros for HTML rendering contexts:These same macros are also defined (authoritatively) in
latex/preamble.texviainclude-in-header, which is loaded before the document body for PDF output.\providecommandis used inlatex-commands.qmdso that the preamble definitionstake precedence for PDF.
Inline R functions (
dataset(),pkg(),func()inR/common.R) emit these macrosas raw LaTeX inlines:
The
.qmdsource then has a Markdown footnote immediately after:The Error
Every PDF build failed at the same location:
The generated
index.tex(Quarto's internal tex file, compiled by xelatex) contained:The
%at the end of the last\index{}line comments out.\footnote{. LaTeXnever opens the footnote, encounters orphaned text, and when it hits the closing
}of the footnote, reports
Extra }.Investigation: Two Weeks of Failed Fixes
Fix 1 — Remove
\nfrom inline R outputThe R functions originally emitted:
The explicit
\ncaused pandoc to add%at each line break. We switched to acustom LaTeX macro call:
Result: Error persisted.
Fix 2 — Delete all freeze caches
Suspected the
.quarto/_freeze/*/execute-results/tex.jsonfiles were stale and serving old multi-line output. Deleted all 15+tex.jsonfiles.Result: Error persisted. Caches were regenerated with new
\ixd{}format —but the expansion was still happening downstream.
Fix 3 — Move parse-latex to
format: html: filters:onlyparse-latex was originally in the global
filters:list. Moved it toformat: html: filters:to prevent it running during the PDF pandoc pass.Result: Error persisted.
Fix 4 — Change parse-latex.lua FORMAT guard
The filter's built-in guard was:
Hypothesis: Quarto's PDF pandoc pass uses a FORMAT value that doesn't contain
"latex"(e.g."pdf"or a Quarto-internal format). Changed to:Result: Error persisted. Most
\ixd{}calls inindex.texwere still expanded(785
\index{}occurrences vs. only 4 unexpanded\ixd{}).Fix 5 — Make preamble.tex macro definitions single-line
Hypothesis: parse-latex expands
\ixd{}using its definition frompreamble.tex, and the multi-line definition body (with%at line ends) causes the problem. Changed to single-line:Result: Error persisted. The content of
index.texwas identical — unchanged by the preamble fix. This ruled out preamble.tex as the source of the definition being used.Root Cause
Inspecting the freeze cache (
tex.json) revealed that it contained not just the knitr R output, but the full resolved chapter content including the{{< include latex/latex-commands.qmd >}}content. Crucially,tex.jsonstored the old multi-line\providecommand{\ixd}definition:"\\providecommand{\\ixd}[1]{%\n \\index{#1@\\texttt{#1} data}%\n \\index{datasets!#1@\\texttt{#1}}%\n}"The mechanism:
tex.jsonfrom the freeze cache (which embeds thelatex-commands.qmdcontent with multi-line
\providecommand{\ixd})RawBlockhandler callspandoc.read(raw.text, 'latex')on the raw LaTeX block containing\providecommand{\ixd}\ixdin pandoc's internal macro table with the multi-line bodyRawInlinehandler processes\ixd{Prestige}and callspandoc.read("\ixd{Prestige}", 'latex')\ixd's definition and expands it — producing the multi-linebody with
%literally included%from the definition body commentsout the
.\footnote{that follows on the same line in the sourceThis happens even though parse-latex is in
format: html: filters:only. The FORMATguard changes had no effect because — regardless of format —
pandoc.read()callswithin a Lua filter share pandoc's global macro table.
Changing
preamble.texhad no effect because parse-latex never readspreamble.texvia
pandoc.read()— it only processes raw LaTeX blocks that appear in the documentbody, which come from the freeze cache, not from
include-in-header.Compounding factor: freeze cache doesn't track
{{< include >}}dependenciesAfter fixing
latex-commands.qmdto use single-line definitions, thetex.jsonfreeze caches still contained the old multi-line definitions — because Quarto's freeze invalidation only tracks changes to the main.qmdfile, not to{{< include >}}'d files. The fix required:latex-commands.qmdto single-line definitionstex.jsonfreeze caches to force regenerationThe Fix
latex/latex-commands.qmd— single-line\providecommandbodiesWhen parse-latex expands these via
pandoc.read(), the expansion body contains no%characters. The.\footnote{that follows in the source is no longer commented out.Delete all
tex.jsonfreeze cachesfind .quarto/_freeze -name "tex.json" -deleteRequired because Quarto does not invalidate freeze caches when included files change.
Questions / Requests
Is parse-latex's
pandoc.read()behavior — registering macro definitions inpandoc's global macro table and then expanding them in subsequent calls — expected
or a side effect? The filter is designed for HTML output only, but its
pandoc.read()calls have PDF-build side effects because the macro table is globalwithin a pandoc process.
Should
format: html: filters:actually prevent a filter from running during thePDF pandoc pass? Our experience suggests it does not — the filter appears to run
regardless of format placement. The FORMAT guard (
if not FORMAT:match 'html' then return {} end) also did not prevent the macro expansion side effects.Should the freeze cache track
{{< include >}}file dependencies? Currently,changing an included file requires manual cache deletion. This is a significant
problem when included files define LaTeX macros that are then embedded in cached
chapter output.
Environment
Beta Was this translation helpful? Give feedback.
All reactions