Skip to content

Commit dd85259

Browse files
committed
Rewrite as_inlines, as_blocks with focus on performance
This also fixes unwanted behavior of `as_blocks`, which would treat a list of Inline elements as a list of singleton Plain elements, leading to bad results.
1 parent 88819d5 commit dd85259

File tree

1 file changed

+58
-48
lines changed

1 file changed

+58
-48
lines changed

src/resources/pandoc/datadir/_utils.lua

Lines changed: 58 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -265,59 +265,69 @@ local function get_type(v)
265265
return pandoc_type
266266
end
267267

268-
local function as_inlines(v)
269-
if v == nil then
270-
return pandoc.Inlines({})
271-
end
272-
local t = pandoc.utils.type(v)
273-
if t == "Inlines" then
274-
---@cast v pandoc.Inlines
275-
return v
276-
elseif t == "Blocks" then
277-
return pandoc.utils.blocks_to_inlines(v)
278-
elseif t == "Inline" then
279-
return pandoc.Inlines({v})
280-
elseif t == "Block" then
281-
return pandoc.utils.blocks_to_inlines({v})
282-
end
283-
284-
if type(v) == "table" then
285-
local result = pandoc.Inlines({})
286-
for i, v in ipairs(v) do
287-
tappend(result, as_inlines(v))
288-
end
289-
return result
290-
end
291-
292-
-- luacov: disable
293-
fatal("as_inlines: invalid type " .. t)
294-
return pandoc.Inlines({})
295-
-- luacov: enable
296-
end
268+
--- Blocks metatable
269+
local BlocksMT = getmetatable(pandoc.Blocks{})
270+
--- Inlines metatable
271+
local InlinesMT = getmetatable(pandoc.Inlines{})
297272

298-
local function as_blocks(v)
299-
if v == nil then
300-
return pandoc.Blocks({})
301-
end
302-
local t = pandoc.utils.type(v)
303-
if t == "Blocks" then
304-
return v
305-
elseif t == "Inlines" then
306-
return pandoc.Blocks({pandoc.Plain(v)})
307-
elseif t == "Block" then
308-
return pandoc.Blocks({v})
273+
--- Turns the given object into a `Inlines` list.
274+
--
275+
-- Works mostly like `pandoc.Inlines`, but doesn't a do a full
276+
-- unmarshal/marshal roundtrip. This buys performance, at the cost of
277+
-- less thorough type checks.
278+
--
279+
-- NOTE: The input object might be modified *destructively*!
280+
local function as_inlines(obj)
281+
local pt = pandoc.utils.type(obj)
282+
if pt == 'Inlines' then
283+
return obj
309284
elseif t == "Inline" then
310-
return pandoc.Blocks({pandoc.Plain(v)})
285+
-- Faster than calling pandoc.Inlines
286+
return setmetatable({obj}, InlinesMT)
287+
elseif pt == 'List' or pt == 'table' then
288+
-- Faster than calling pandoc.Inlines
289+
return setmetatable(obj, InlinesMT)
290+
elseif pt == "Block" then
291+
return pandoc.utils.blocks_to_inlines({obj})
292+
elseif pt == "Blocks" then
293+
return pandoc.utils.blocks_to_inlines(v)
294+
else
295+
return pandoc.Inlines(obj or {})
311296
end
297+
end
312298

313-
if type(v) == "table" then
314-
return pandoc.Blocks(v)
299+
--- Turns the given object into a `Blocks` list.
300+
--
301+
-- Works mostly like `pandoc.Blocks`, but doesn't a do a full
302+
-- unmarshal/marshal roundtrip. This buys performance, at the cost of
303+
-- less thorough type checks.
304+
--
305+
-- NOTE: The input object might be modified *destructively*!
306+
--
307+
-- This might need some benchmarking.
308+
local function as_blocks(obj)
309+
local pt = pandoc.utils.type(obj)
310+
if pt == 'Blocks' then
311+
return obj
312+
elseif pt == 'Block' then
313+
return setmetatable({obj}, BlocksMT)
314+
elseif pt == 'Inline' then
315+
return setmetatable({pandoc.Plain{pt}}, BlocksMT)
316+
elseif pt == 'Inlines' then
317+
return setmetatable({pandoc.Plain(pt)}, BlocksMT)
318+
elseif pt == 'List' or (pt == 'table' and obj[1]) then
319+
-- Assigning a metatable directly is faster than calling
320+
-- `pandoc.Blocks`.
321+
if pandoc.utils.type(obj[1]) == 'Inline' then
322+
obj = {pandoc.Plain(obj)}
323+
end
324+
return setmetatable(obj, BlocksMT)
325+
elseif (pt == 'table' and obj.long) or pt == 'Caption' then
326+
-- Looks like a Caption
327+
return as_blocks(obj.long)
328+
else
329+
return pandoc.Blocks(obj or {})
315330
end
316-
317-
-- luacov: disable
318-
fatal("as_blocks: invalid type " .. t)
319-
return pandoc.Blocks({})
320-
-- luacov: enable
321331
end
322332

323333
local function match_fun(reset, ...)

0 commit comments

Comments
 (0)