Lua filter changes
Quarto v1.4 includes the following new features for Lua filters:
Support for crossreferenceable elements in filters
Quarto v1.4 brings significant changes to the handling of figures, tables, listings, etc. These changes simplify the writing of Lua filters that targets those elements, but will generally require changes in existing.
The FloatRefTarget
AST node
In v1.4, crossreferenceable elements all have a single generic type, FloatRefTarget
. This element can be constructed explicitly in a Lua filter. It can also be used as the element to be processed in a Lua filter directly.
-- A filter targeting FloatRefTarget nodes
return {
FloatRefTarget = function(float)
if float.caption_long then
float.caption_long.content:insert(pandoc.Str("[This will appear at the beginning of every caption]"))
return float
end
end
}
FloatRefTarget
nodes have the following fields:
type
: The type of element:Figure
,Table
,Listing
, etc. Quarto v1.4 supports custom node types that can be declared at the document or project level.content
: The content of the Figure, Table, etc. Quarto v1.4 accepts any content in anyFloatRefTarget
type (so if your tables are better displayed as an image, you can use that.).caption_long
: The caption that appears in the main body of the documentcaption_short
: The caption that appears in the element collations (such as a list of tables, list of figures, etc.)identifier
,attributes
,classes
: these are analogous toAttr
fields in Pandoc AST elements like spans and divs.identifier
, in addition, needs to be the string that is used in a crossref (fig-cars
,tbl-votes
,lst-query
, and so on).parent_id
: if aFloatRefTarget
is a subfloat of a parent multiple-element float, thenparent_id
will hold the identifier of the parent float.
Custom formats and Custom renderers
Quarto v1.4 adds support for extensible renderers of quarto AST nodes such as FloatRefTarget
, Callout
. In order to declare a custom renderer, add the following to a Lua filter:
local predicate = function(float)
-- return true if this renderer should be used;
-- typically, this will return true if the custom format is active.
end
local renderer = function(float)
-- returns a plain Pandoc representation of the rendered figure.
end
quarto._quarto.ast.add_renderer(
"FloatRefTarget",
predicate,
renderer)
Relative paths in require()
calls
In larger, more complex filters, it becomes useful to structure your Lua code in modules. Quarto v1.4 supports the use of relative paths in require()
calls so that small modules can be easily created and reused.
For example:
filter.lua
local utility = require('./utils')
function Pandoc(doc)
-- process
end
Using relative paths this way in quarto makes it harder for multiple filters to accidentally create conflicting module names (as would eventually happen when using the standard Lua require('utils')
syntax). It’s possible to refer to subdirectories and parent directories as well:
filter2.lua
local parsing = require('./utils/parsing')
function Pandoc(doc)
-- process
end
utils/parsing.lua
local utils = require("../utils")
-- ...
More precise targeting of AST processing phases
Before Quarto 1.4, Lua filters are either “pre” filters (the default setting), or “post” filters. Those filters are specified like this:
# "pre" filters:
filters:
- pre_filter_1.lua
- pre_filter_2.lua
# ...
# "post" filters:
filters:
- quarto
- post_filter_1.lua
- post_filter_2.lua
# ...
This syntax continues to work in 1.4. In addition, it is now possible to specify more precisely the place where a specific filter will be inserted. Quarto’s AST processing phase is now split into three parts: ast
, quarto
, and render
.
ast
: normalizes the input syntax from Pandoc, recognizing constructs such asCallout
,FloatRefTarget
, and so on.quarto
: processes the normalized syntax, for example by resolving cross-references.render
: produces format-specific output from the processed input.
In Quarto 1.4, Lua filters can be inserted before or after any of these stages:
filters:
- at: pre-ast
path: filter1.lua
- at: post-quarto
path: filter2.lua
- at: post-render
path: filter3.lua
Any of the stages can be prefixed by pre-
or post-
. In Quarto 1.4, pre-quarto
and post-ast
correspond to the same insertion location in the filter chain, as do post-quarto
and pre-render
. The “pre” and “post” filter syntax from Quarto 1.3 remains valid. “Pre” filters are injected at the pre-quarto
entry point, and “post” filters are injected at the post-render
entry point.
The new syntax also supports JSON filters, as 1.3 filters do. Either use type: json
explicitly, or use a path that doesn’t end in .lua
. Conversely, type: lua
will force the file to be treated as a Lua filter.