Folio Writer's compile pipeline covers the 99% — citations, cross-references, templates, formats. Lua filters are the escape hatch for the last 1%: the journal's odd house rule, your own shorthand, the thing no checkbox anticipates. A filter is a few lines of Lua that rewrite the document during compilation, and pandoc runs them natively — nothing to install.
When pandoc compiles your manuscript, it first parses the Markdown
into a document tree — paragraphs, headers, spans, citations. A Lua
filter is a set of functions named after those elements; each one gets
called with every matching element and may return a replacement. Return
nothing to leave it alone, return {} to delete it, return
new elements to transform it. That's the whole model.
.lua file — keeping it in the
project (e.g. a Filters subfolder in Research) means it
syncs and travels with the manuscript.Type @@today anywhere; the compiled document carries the
compile date — useful in cover letters and draft watermarks:
-- today.lua
function Str(el)
if el.text == "@@today" then
return pandoc.Str(os.date("%B %e, %Y"))
end
end
Write notes-to-self in a fenced div, visible while drafting, guaranteed absent from output:
::: draft Ask Wei whether the 2019 calibration applies here. :::
-- strip-draft.lua
function Div(el)
if el.classes:includes("draft") then
return {} -- deleted from every compiled format
end
end
Attach it only to your submission profiles and the notes still appear in your advisor-draft profile — per-profile filters are exactly for this.
Give [key result]{.highlight} a real meaning per format —
a yellow mark in HTML, a highlight in LaTeX PDFs:
-- highlight.lua
function Span(el)
if not el.classes:includes("highlight") then return nil end
if FORMAT:match("latex") then
local out = pandoc.Inlines(pandoc.RawInline("latex", "\\hl{"))
out:extend(el.content)
out:insert(pandoc.RawInline("latex", "}"))
return out
elseif FORMAT:match("html") then
local out = pandoc.Inlines(pandoc.RawInline("html", ""))
out:extend(el.content)
out:insert(pandoc.RawInline("html", ""))
return out
end
end
For the LaTeX branch, add the highlighting package once in the Format
metadata: header-includes: \usepackage{soul}.
Two habits make filter-writing painless. To see the tree you're
matching against, run pandoc -t native on a snippet in
Terminal — it prints exactly the elements your functions will receive.
And when a compile misbehaves, Compile & Preview Log shows the
full pandoc command line and its output, filter errors included. One
Folio-specific note: a filter whose file has moved is skipped rather than
failing the compile — check the log if a filter seems silently
inactive.
The pandoc Lua filter documentation lists every element and helper, and the community's filter collection is full of ready-made ones — abbreviation handling, table tweaks, diagram rendering. Anything there drops straight into the compile sheet.