-- Copyright 2020-2023 atusy and Kenshi Muto
local function review_inline(x)
return pandoc.RawInline("review", x)
end
local beginchild = {pandoc.Plain(review_inline("//beginchild"))}
local endchild = {pandoc.Plain(review_inline("//endchild"))}
local function markdown(text)
return pandoc.read(
text,
"markdown-auto_identifiers-smart+east_asian_line_breaks",
PANDOC_READER_OPTIONS
).blocks[1].content
end
local function support_blankline(constructor)
--[[
Returns a function that splits a block into blocks separated by a Div
element which defines blank lines.
The Re:VIEW Lua writer subsequently transforms the Div element into
`//blankline` commands.
]]
local construct = constructor or pandoc.Para
return function(x)
local blocks = {construct({})}
local i = 1
local n_break = 0
local content = blocks[i].content
for j, elem in ipairs(x.content) do
if elem.tag == "LineBreak" then
-- Count the repeated number of LineBreak
n_break = n_break + 1
elseif n_break == 1 then
-- Do nothing if LineBreak is not repeated
table.insert(content, pandoc.LineBreak())
table.insert(content, elem)
n_break = 0
elseif n_break > 1 then
-- Convert LineBreak's into //blankline commands
table.insert(blocks, pandoc.Div({}, {blankline = n_break - 1}))
table.insert(blocks, construct({elem}))
i = i + 2
content = blocks[i].content
n_break = 0
else
-- Do nothing on elements other than LineBreak
table.insert(content, elem)
end
end
return blocks
end
end
local function nestablelist(elem)
--[[
Support items with multiple blocks in
BulletList, OrderedList, and DefinitionList.
]]
for _, block in ipairs(elem.content) do
local second = block[2]
if second then
if second.tag == "BulletList" then
table.insert(second.content, 1, beginchild)
elseif second.tag then
table.insert(block, 2, pandoc.BulletList(beginchild))
else
for _,definition in ipairs(second) do
if definition[2] then
table.insert(definition, 2, pandoc.BulletList(beginchild))
table.insert(definition, pandoc.BulletList(endchild))
end
end
end
local last = block[#block]
if last.tag == "BulletList" then
table.insert(last.content, endchild)
elseif last.tag then
table.insert(block, pandoc.BulletList(endchild))
end
end
end
return elem
end
local function support_strong(child)
--[[
Returns a function that converts `***text***` as Span with the strong class
(i.e., `[text]{.strong}`).
Pandoc treats `***` as Emph wrapped by Strong, but is not documented.
This filter also supports the inverse order just for sure.
The Lua writer, review.lua, further converts the text to `@strong{text}`
]]
return function(elem)
if (#elem.content == 1) and (elem.content[1].tag == child) then
return pandoc.Span(elem.content[1].content, {class = 'strong'})
end
end
end
local function caption_div(div)
local class = div.classes[1]
local caption = div.attributes.caption
if ((#div.content == 1) and
(div.content[1].content) and
(#div.content[1].content == 1) and
(div.content[1].content[1].tag == "Math") and
(div.identifier)) then
class = "texequation[" .. div.identifier .. "]"
local math_text = (div.content[1].content[1].text
):gsub("^\n+", ""):gsub("\n+$", "")
if caption == nil then
return pandoc.RawBlock(
"review",
"//" .. class .. "{\n" .. math_text .. "\n//}"
)
end
div.content = {pandoc.RawBlock("review", math_text)}
end
if class == nil then
return nil
end
if caption then
local begin = pandoc.Para(markdown(caption))
table.insert(begin.content, 1, review_inline("//" .. class .. "["))
table.insert(begin.content, review_inline("]{"))
table.insert(div.content, 1, begin)
table.insert(div.content, pandoc.RawBlock("review", "//}"))
div.classes = {"review-internal"}
return div
end
end
local function noindent(para)
first = para.content[1]
if (first and (first.tag == "RawInline") and
(first.format == "tex") and
(first.text:match("^\\noindent%s*"))) then
para.content[1] = review_inline("//noindent\n")
if para.content[2].tag == "SoftBreak" then
table.remove(para.content, 2)
end
end
return para
end
local function figure(fig)
-- Pandoc 3.x adds pandoc.Figure
if #fig.content > 1 or #fig.content[1].content > 1 then
error("NotImplemented")
end
local base = fig.content[1].content[1]
local attr = {}
for k, v in pairs(base.attributes) do
attr[k] = v
end
local classes = {}
for _, v in pairs(base.classes) do
table.insert(classes, "." .. v)
end
attr.classes = table.concat(classes, " ")
attr.identifier = base.attr.identifier
attr.is_figure = "true"
return pandoc.Image(
base.title,
base.src,
pandoc.utils.stringify(fig.caption),
attr
)
end
return {
{Emph = support_strong("Strong")},
{Strong = support_strong("Emph")},
{Plain = support_blankline(pandoc.Plain)},
{Para = support_blankline(pandoc.Para)},
{Para = noindent},
-- blankline must be processed before lists
{BulletList = nestablelist},
{OrderedList = nestablelist},
{DefinitionList = nestablelist},
{Div = caption_div},
{Figure = figure},
}