Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 33 additions & 19 deletions src/resources/filters/ast/customnodes.lua
Original file line number Diff line number Diff line change
Expand Up @@ -77,35 +77,49 @@ function run_emulated_filter(doc, filter)
end

-- performance: if filter is empty, do nothing
local t = pandoc.utils.type(doc)
if sz == 0 then
return doc
elseif sz == 1 then
elseif t == "Pandoc" then
local result
local t
if filter.Pandoc then
-- performance: if filter is only Pandoc, call that directly instead of walking.
result = filter.Pandoc(doc) or doc
elseif filter.Meta then
-- performance: if filter is only Meta, call that directly instead of walking.
t = pandoc.utils.type(doc)
if t == "Pandoc" then
if sz == 1 and (filter.Pandoc or filter.Meta) then
if filter.Pandoc then
-- performance: if filter is only Pandoc, call that directly instead of walking.
result = filter.Pandoc(doc) or doc
else
assert(filter.Meta)
-- performance: if filter is only Meta, call that directly instead of walking.
local result_meta = filter.Meta(doc.meta) or doc.meta
result = doc
result.meta = result_meta
else
goto regular
end
else
goto regular
end
if in_filter then
profiler.category = ""
if in_filter then
profiler.category = ""
end
return result
elseif sz == 2 and filter.Pandoc and filter.Meta then
-- performance: if filter is only Pandoc and Meta, call that directly instead of walking.
result = filter.Pandoc(doc) or doc
t = pandoc.utils.type(doc)
local result_meta = filter.Meta(doc.meta) or doc.meta
result = doc
result.meta = result_meta
if in_filter then
profiler.category = ""
end
return result
end
return result
end


::regular::
-- performance/feature: if filter's `traverse` is "scoped", use
-- Quarto's scoped walk instead of the regular walk
-- Since scoped_walk does not generate a new document,
-- there can be good reasons to use it even with access to scopes
-- is not needed.
-- As a result, we allow "mutable" as a synonym for "scoped"
if filter.traverse == "scoped" or filter.traverse == "mutable" then
return _quarto.ast.scoped_walk(doc, filter)
end

-- if user passed a table corresponding to the custom node instead
-- of the custom node, then first we will get the actual node
Expand Down
73 changes: 48 additions & 25 deletions src/resources/filters/ast/scopedwalk.lua
Original file line number Diff line number Diff line change
Expand Up @@ -253,32 +253,9 @@ function scoped_walk(outer_node, filter)
return node
end

-- else
quarto.utils.dump(node)
fail("unexpected node type in handling content: " .. nt)
-- end

-- local ct = pandoc.utils.type(content)
-- if ct == "Blocks" then
-- process_blocks(content)
-- elseif ct == "Inlines" then
-- process_inlines(content)
-- elseif ct == "List" then
-- for i, c in ipairs(content) do
-- local cct = pandoc.utils.type(c)
-- if cct == "Blocks" then
-- process_blocks(content)
-- elseif cct == "Inlines" then
-- process_inlines(content)
-- else
-- quarto.utils.dump(content)
-- fail("unexpected node type in Block or Inline content: " .. cct)
-- end
-- end
-- fail("unexpected node type in Block or Inline content: " .. cct)
-- end
quarto.utils.dump(node)
fail("unexpected node type in handling content: " .. nt)
end

local function process_custom(node)
local t = node.attributes.__quarto_custom_type
local result, done = process_handler(filter[t] or filter.Custom, node)
Expand All @@ -296,6 +273,44 @@ function scoped_walk(outer_node, filter)
process_content(node)
return node
end
local function process_meta(node)
local function inner_meta_walk(obj)
local ot = pandoc.utils.type(obj)
if ot == "Inlines" or ot == "MetaInlines" then
return process_inlines(obj)
end
if ot == "Blocks" or ot == "MetaBlocks" then
return process_blocks(obj)
end
if ot == "List" or ot == "MetaList" then
for i, v in ipairs(obj) do
obj[i] = inner_meta_walk(v)
end
return obj
end
if ot == "table" or ot == "MetaMap" then
for k, v in pairs(obj) do
obj[k] = inner_meta_walk(v)
end
return obj
end
return obj
end
local result, done = process_handler(filter.Meta, node)
if done then
return result
end
return inner_meta_walk(node)
end
local function process_pandoc(node)
local result, done = process_handler(filter.Pandoc, node)
if done then
return result
end
node.meta = process_meta(node.meta)
node.blocks = process_blocks(node.blocks)
return node
end

inner = function(node)
scope:insert(node)
Expand All @@ -309,7 +324,15 @@ function scoped_walk(outer_node, filter)
result = process_blocks(node)
elseif nt == "Inlines" then
result = process_inlines(node)
elseif nt == "Pandoc" then
result = process_pandoc(node)
elseif nt == "List" then
for i, v in ipairs(node) do
node[i] = inner(v)
end
else
quarto.utils.dump(scope)
print(node)
fail("unexpected node type: " .. nt)
end

Expand Down
74 changes: 40 additions & 34 deletions src/resources/filters/customnodes/shortcodes.lua
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,41 @@ function shortcodes_filter()
})
local filter

local block_handler = function(node)
local block_handler
local inline_handler
local code_handler

local function process(doc)
-- first walk them in block context
doc = _quarto.ast.walk(doc, {
Para = block_handler,
Plain = block_handler,
Code = code_handler,
RawBlock = code_handler,
CodeBlock = code_handler,
})

doc = _quarto.ast.walk(doc, {
Shortcode = inline_handler,
RawInline = code_handler,
Image = function(el)
el.src = shortcode_lpeg.wrap_lpeg_match(code_shortcode, el.src)
return el
end,
Link = function(el)
el.target = shortcode_lpeg.wrap_lpeg_match(code_shortcode, el.target)
return el
end,
Span = function(el)
if el.classes:includes("quarto-shortcode__-escaped") then
return pandoc.Str(el.attributes["data-value"])
end
end,
})
return doc
end

block_handler = function(node)
if (node.t == "Para" or node.t == "Plain") and #node.content == 1 then
node = node.content[1]
end
Expand All @@ -238,17 +272,17 @@ function shortcodes_filter()
return nil
end
local result, struct = handle_shortcode(custom_data, node)
return _quarto.ast.walk(shortcodeResultAsBlocks(result, struct.name, custom_data), filter)
return process(shortcodeResultAsBlocks(result, struct.name, custom_data))
end

local inline_handler = function(custom_data, node)
inline_handler = function(custom_data, node)
local result, struct = handle_shortcode(custom_data, node)
local r1 = shortcodeResultAsInlines(result, struct.name, custom_data)
local r2 = _quarto.ast.walk(r1, filter)
local r2 = process(r1)
return r2
end

local code_handler = function(el)
code_handler = function(el)
-- don't process shortcodes in code output from engines
-- (anything in an engine processed code block was actually
-- proccessed by the engine, so should be printed as is)
Expand All @@ -266,35 +300,7 @@ function shortcodes_filter()
end

filter = {
Pandoc = function(doc)
-- first walk them in block context
doc = _quarto.ast.walk(doc, {
Para = block_handler,
Plain = block_handler,
Code = code_handler,
RawBlock = code_handler,
CodeBlock = code_handler,
})

doc = _quarto.ast.walk(doc, {
Shortcode = inline_handler,
RawInline = code_handler,
Image = function(el)
el.src = shortcode_lpeg.wrap_lpeg_match(code_shortcode, el.src)
return el
end,
Link = function(el)
el.target = shortcode_lpeg.wrap_lpeg_match(code_shortcode, el.target)
return el
end,
Span = function(el)
if el.classes:includes("quarto-shortcode__-escaped") then
return pandoc.Str(el.attributes["data-value"])
end
end,
})
return doc
end
Pandoc = process
}
return filter
end
Expand Down
5 changes: 3 additions & 2 deletions src/resources/filters/quarto-pre/output-location.lua
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ end
function output_location()
if _quarto.format.isRevealJsOutput() then
return {
traverse = "mutable",
Blocks = function(blocks)
local newBlocks = pandoc.List()
local newBlocks = pandoc.Blocks({})
for _,block in pairs(blocks) do
local outputLoc = collectCellOutputLocation(block)
if outputLoc then
Expand All @@ -95,7 +96,7 @@ function output_location()
newBlocks:insert(block)
end
end
return newBlocks
return newBlocks, false
end
}
else
Expand Down
1 change: 1 addition & 0 deletions src/resources/filters/quarto-pre/outputs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ function unroll_cell_outputs()
-- the param("output-divs", true) check is now done in flags.lua

return {
traverse = "mutable",
-- unroll output divs for formats (like pptx) that don't support them
Div = function(div)

Expand Down
10 changes: 2 additions & 8 deletions src/resources/filters/quarto-pre/resolvescopedelements.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,8 @@
function resolve_scoped_elements()
local resolve_table_colwidths_scoped = require("modules/tablecolwidths").resolve_table_colwidths_scoped

local scoped_filter = {
Table = resolve_table_colwidths_scoped
}
return {
-- because our emulated filter has a special case for Pandoc documents
-- which doesn't create copies, we don't need to return doc here
Pandoc = function(doc)
_quarto.ast.scoped_walk(doc.blocks, scoped_filter)
end
traverse = "scoped",
Table = resolve_table_colwidths_scoped,
}
end