Skip to content

Instantly share code, notes, and snippets.

@CodeSandwich
Created June 23, 2024 15:22
Show Gist options
  • Save CodeSandwich/35cd06d3925ca8c48ce950fb4b8be2ca to your computer and use it in GitHub Desktop.
Save CodeSandwich/35cd06d3925ca8c48ce950fb4b8be2ca to your computer and use it in GitHub Desktop.
local function length(elem)
return pandoc.text.len(pandoc.utils.stringify(elem))
end
function insert(doc, inserted, idx, before)
idx = idx or -1
local total_length = length(doc)
if(idx < 0) then
idx = idx + 1 + total_length
end
if(idx < 1 or idx > total_length) then
error("Index out of bounds")
end
local function insert_string(string, inserted, idx, before)
if(before) then idx = idx - 1 end
local prefix = pandoc.text.sub(string, 1, idx)
local suffix = pandoc.text.sub(string, idx + 1)
return prefix..inserted..suffix
end
local function insert_inlines(elem, inserted, before)
elem = pandoc.Inlines(elem)
inserted = pandoc.Inlines(inserted)
if(before) then
return inserted..elem
else
return elem..inserted
end
end
local function inline(elem)
if(idx == 0) then
return nil, false
end
local elem_length = length(elem)
if(elem_length < idx) then
idx = idx - elem_length
return nil, false
end
if(elem.t == "Str") then
elem = insert_string(elem.text, inserted, idx, before)
elseif(elem.t == "Code" or elem.t == "Math") then
elem.text = insert_string(elem.text, inserted, idx, before)
elseif(elem.t == "Space" or elem.t == "LineBreak" or elem.t == "SoftBreak")
or (elem.t == "RawInline" and elem.format == "html" and string.find(elem.text, "^<br")) then
elem = insert_inlines(elem, inserted, before)
elseif(elem.t == "Quoted" and (elem.quotetype == "SingleQuote" or elem.quotetype == "DoubleQuote")) then
if((idx == 1 and before) or (idx == length and not before)) then
elem = insert_inlines(elem, inserted, before)
elseif(idx == 1 or idx == length) then
elem.content = insert_inlines(elem.content, inserted, not before)
else
idx = idx - 1
return nil, true
end
else
return nil, true
end
idx = 0
return elem, false
end
return doc:walk({traverse = 'topdown', Inline = inline})
end
function testInsert(markup, inserted, idx, before, expected)
local doc = pandoc.read(markup, "markdown")
doc = insert(doc, inserted, idx, before)
local actual = pandoc.write(doc, "markdown")
actual = string.gsub(actual, "\n$", "")
if(actual == expected) then
print("Test successful")
else
print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>")
print("Test failed!")
print("Invalid result of inserting '"..inserted.."' "
..(before and "before" or "after").." index "..idx.." into:")
print(markup)
print("Actual:")
print(actual)
print("Expected:")
print(expected)
print(pandoc.json.encode(doc))
print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
end
end
-- Str
testInsert("abc", "X", 2, true, "aXbc")
testInsert("abc", "X", 2, false, "abXc")
-- Code
testInsert("`abc`", "X", 2, true, "`aXbc`")
testInsert("`abc`", "X", 2, false, "`abXc`")
-- Math
testInsert("$abc$", "X", 2, true, "$aXbc$")
testInsert("$abc$", "X", 2, false, "$abXc$")
-- Space
testInsert("*a* *b*", "X", 2, true, "*a*X *b*")
testInsert("*a* *b*", "X", 2, false, "*a* X*b*")
-- LineBreak
testInsert("*a*\\\n*b*", "X", 2, true, "*a*X\\\n*b*")
testInsert("*a*\\\n*b*", "X", 2, false, "*a*\\\nX*b*")
-- SoftBreak
testInsert("*a*\n*b*", "X", 2, true, "*a*X *b*")
testInsert("*a*\n*b*", "X", 2, false, "*a* X*b*")
-- RawInline
testInsert("*a*`<br>`{=html}*b*", "X", 2, true, "*a*X`<br>`{=html}*b*")
testInsert("*a*`<br>`{=html}*b*", "X", 2, false, "*a*`<br>`{=html}X*b*")
-- SingleQuote
testInsert("*a*'*b*'*c*", "X", 2, true, "*a*X'*b*'*c*")
testInsert("*a*'*b*'*c*", "X", 2, false, "*a*'X*b*'*c*")
testInsert("*a*'*b*'*c*", "X", 3, true, "*a*'*Xb*'*c*")
testInsert("*a*'*b*'*c*", "X", 3, false, "*a*'*bX*'*c*")
testInsert("*a*'*b*'*c*", "X", 4, true, "*a*'*b*X'*c*")
testInsert("*a*'*b*'*c*", "X", 4, false, "*a*'*b*'X*c*")
-- DoubleQuote
testInsert('*a*"*b*"*c*', "X", 2, true, '*a*X"*b*"*c*')
testInsert('*a*"*b*"*c*', "X", 2, false, '*a*"X*b*"*c*')
testInsert('*a*"*b*"*c*', "X", 3, true, '*a*"*Xb*"*c*')
testInsert('*a*"*b*"*c*', "X", 3, false, '*a*"*bX*"*c*')
testInsert('*a*"*b*"*c*', "X", 4, true, '*a*"*b*X"*c*')
testInsert('*a*"*b*"*c*', "X", 4, false, '*a*"*b*"X*c*')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment