-- center-v.lua
-- Pandoc Lua filter for converting ~V~ section break symbols
-- into properly centered paragraphs in EPUB/DOCX/HTML output.
--
-- Handles multiple input patterns that Obsidian might produce:
-- 1.
\n~V~\n (HTML blocks wrapping subscript)
-- 2. Raw ~V~ as a paragraph
-- 3. The tilde-based subscript interpretation (~V~ → subscript V)
local function make_centered()
if FORMAT == "epub" or FORMAT == "epub3" or FORMAT == "html" or FORMAT == "html5" then
return pandoc.RawBlock("html", '~V~
')
elseif FORMAT == "docx" or FORMAT == "openxml" then
return pandoc.RawBlock("openxml", [[
~V~
]])
else
return pandoc.Para({pandoc.Str("~V~")})
end
end
function Pandoc(doc)
local newblocks = {}
local i = 1
while i <= #doc.blocks do
local b1 = doc.blocks[i]
local b2 = doc.blocks[i+1]
local b3 = doc.blocks[i+2]
-- Pattern 1: block + subscript V + block
if b1 and b2 and b3
and b1.t == "RawBlock" and b1.format == "html" and b1.text:match("^%s*$")
and b2.t == "Plain"
and #b2.content == 1
and b2.content[1].t == "Subscript"
and #b2.content[1].content == 1
and b2.content[1].content[1].t == "Str"
and b2.content[1].content[1].text == "V"
and b3.t == "RawBlock" and b3.format == "html" and b3.text:match("^%s*$")
then
table.insert(newblocks, make_centered())
i = i + 3
-- Pattern 2: Single paragraph containing just "~V~"
elseif b1 and b1.t == "Para"
and #b1.content == 1
and b1.content[1].t == "Str"
and b1.content[1].text == "~V~"
then
table.insert(newblocks, make_centered())
i = i + 1
-- Pattern 3: Plain block with subscript V (standalone, no center tags)
elseif b1 and b1.t == "Plain"
and #b1.content == 1
and b1.content[1].t == "Subscript"
and #b1.content[1].content == 1
and b1.content[1].content[1].t == "Str"
and b1.content[1].content[1].text == "V"
then
table.insert(newblocks, make_centered())
i = i + 1
-- Pattern 4: Para with Str "~" + Subscript "V" + Str "~" (tilde interpreted separately)
elseif b1 and b1.t == "Para"
and #b1.content == 3
and b1.content[1].t == "Str" and b1.content[1].text == "~"
and b1.content[2].t == "Subscript"
and #b1.content[2].content == 1
and b1.content[2].content[1].t == "Str"
and b1.content[2].content[1].text == "V"
and b1.content[3].t == "Str" and b1.content[3].text == "~"
then
table.insert(newblocks, make_centered())
i = i + 1
else
table.insert(newblocks, b1)
i = i + 1
end
end
doc.blocks = newblocks
return doc
end