I spent some more time learning more about writing filters and have made some progress.On 06/01/2023 04:34 AM, 'William Lupton' via pandoc-discuss wrote:
Am I correct in thinking that when you say "filter" here, you really mean "writer"?
In filters, you can use the 'traverse' field to force top-down traversal. See https://pandoc.org/lua-filters.html#traversal-order
In writers, you can choose to call doc:walk(), which will honour 'traverse'. See https://pandoc.org/custom-writers.html#example-modified-markdown-writer (and example below)
However, if you use pandoc.scaffolding.Writer (as I think you are?) then I suspect that you can't control the traversal order (but I'm not sure that it makes sense to do so, because, for example, surely you always want the contents of a <div> to have been traversed before you add '<div>' and '</div>'?).
With the custom writer shown below, and with an input file that consists of the single line 'Text' (and using my logging module), you get this with the default 'typewise' traversal:
(#) inline Str "Text"
(#) inlines Inlines[1] {[1] Str "Text"}
(#) block Para {content: Inlines[1] {[1] Str "Text"}}
(#) blocks Blocks[1] {[1] Para {content: Inlines[1] {[1] Str "Text"}}}
(#) meta Meta {}
(#) doc Pandoc {
blocks: Blocks[1] {
[1] Para {
content: Inlines[1] {
[1] Str "Text"
}
}
}
meta: Meta {}
}
...and this with 'topdown' traversal:
(#) doc Pandoc {
blocks: Blocks[1] {
[1] Para {
content: Inlines[1] {
[1] Str "Text"
}
}
}
meta: Meta {}
}
(#) meta Meta {}
(#) blocks Blocks[1] {[1] Para {content: Inlines[1] {[1] Str "Text"}}}
(#) block Para {content: Inlines[1] {[1] Str "Text"}}
(#) inlines Inlines[1] {[1] Str "Text"}
(#) inline Str "Text"
The writer:
local logging = require 'logging'
local function report(label, elem)
logging.temp(label, elem)
end
-- 'typewise' (default) or 'topdown'
local traverse = 'topdown'
function Writer (doc, opts)
local filter = {
traverse = traverse,
Inline = function(inline)
report('inline', inline)
end,
Inlines= function(inlines)
report('inlines', inlines)
end,
Block = function(block)
report('block', block)
end,
Blocks = function(blocks)
report('blocks', blocks)
end,
Meta = function(meta)
report('meta', meta)
end,
Pandoc = function(doc)
report('doc', doc)
end,
}
return pandoc.write(doc:walk(filter), 'html', opts)
end
Thank you for your thoughtful response. I realize I have used the term 'filter' and 'writer' cavalierly. I have a "slightly" complicated layout I want to output from the writer and my thought right now is that I should try to add the <div> and </div> in the right places in a filter and then let the writer just output the resulting html.
I may have to traverse the AST several times in my filter to accomplish the result since multiple <div></div> need to be added at different levels to achieve the desired output.
I just downloaded your logging filter to aid in the development and am also working on formalizing the rules for adding <div></div>.