Skip to content

Instantly share code, notes, and snippets.

@dblume
Last active April 5, 2017 17:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dblume/fd8f71b88df3998a84e671a81277419f to your computer and use it in GitHub Desktop.
Save dblume/fd8f71b88df3998a84e671a81277419f to your computer and use it in GitHub Desktop.
Script for converting to Atlassian Confluence's markup with Pandoc.
-- confluence_markup.lua
-- A Pandoc Atlassian Confluence Markup Writer
--
-- Invoke with: pandoc -to confluence_markup.lua
--
-- Based on pandoc/data/sampsdfsle.lua and zhzhxtrrk's "pandoc confluence markup writer"
-- Fixes tables and lists of lists
local image_index = 0
-- Character escaping
local function escape(s, in_attribute)
return s:gsub("[<>&\"']",
function(x)
if x == '<' then
return '&lt;'
elseif x == '>' then
return '&gt;'
elseif x == '&' then
return '&amp;'
elseif x == '"' then
return '&quot;'
elseif x == "'" then
return '&#39;'
else
return x
end
end)
end
-- Blocksep is used to separate block elements.
function Blocksep()
return "\n"
end
-- This function is called once for the whole document. Parameters:
-- body is a string, metadata is a table, variables is a table.
-- One could use some kind of templating
-- system here;
function Doc(body, metadata, variables)
return body
end
-- The functions that follow render corresponding pandoc elements.
-- s is always a string, attr is always a table of attributes, and
-- items is always an array of strings (the items in a list).
-- Comments indicate the types of other variables.
function Str(s)
return escape(s)
end
function Space()
return " "
end
function LineBreak()
return "\n"
end
function Para(s)
return s .. "\n"
end
function Plain(s)
return s
end
function Emph(s)
return "_" .. s .. "_"
end
function Strong(s)
return "*" .. s .. "*"
end
function Subscript(s)
return "~" .. s .. "~"
end
function Superscript(s)
return "^" .. s .. "^"
end
function Strikeout(s)
return '-' .. s .. '-'
end
function Link(s, src, tit)
return "[" .. s .. "|" .. escape(src,true) .. " " .. escape(tit,true) .. "]"
end
function CaptionedImage(src, s, tit)
image_index = image_index + 1
return "!" .. escape(src, true) .. "!\n" .. 'FIGURE ' .. image_index .. ". " .. tit .. "\n"
end
function Image(s, src, tit)
return "!" .. escape(src,true) .. "!"
end
-- lev is an integer, the header level.
function Header(lev, s, attr)
return "h" .. lev .. ". " .. s .. ""
end
function BlockQuote(s)
return "{quote}\n" .. s .. "\n{quote}"
end
function HorizontalRule()
return "----"
end
function Code(s)
return '{{' .. s .. '}}'
end
function CodeBlock(s, attr)
return "{code:" .. attr["class"] .. "}" .. s .. "{code}"
end
function make_sublist(strings, token)
buffer = {}
for str in string.gmatch(strings, "[^\n]+") do
str = str:gsub("^[*#]+ ", token .. "%1")
table.insert(buffer, str)
end
return table.concat(buffer, "\n")
end
-- Better support multiline formatting within a cell
-- prevent empty lines in cells. (Add a "&nbsp;" for empty lines.)
function fix_multiline_cell(cell)
buffer = {}
for s in string.gmatch(cell .. "\n", "([^\n]*)\n") do
if string.len(s) == 0 then
s = "&nbsp;"
end
table.insert(buffer, s)
end
return table.concat(buffer, "\n")
end
function BulletList(items, num, sty, delim)
local buffer = {}
for _, item in pairs(items) do
-- item might be a list itself. We'll have to prepend bullets
item = make_sublist(item, "*")
table.insert(buffer, "* " .. item)
end
return table.concat(buffer, "\n")
end
function OrderedList(items, num, sty, delim)
local buffer = {}
for _, item in pairs(items) do
-- item might be a list itself. We'll have to prepend bullets
item = make_sublist(item, "#")
table.insert(buffer, "# " .. item)
end
return table.concat(buffer, "\n")
end
function RawInline(format, str)
return '{{' .. str .. '}}'
end
-- Invoked with a MediaWiki {{Special:PrefixIndex...}} command
function RawBlock(format, str)
return str
end
function SoftBreak()
return "\n"
end
-- Invoked with "\[" and "\]"
function DisplayMath(s)
return s
end
function DoubleQuoted(s)
return "\"" .. escape(s) .. "\""
end
function trim(s)
-- from PiL2 20.4
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
-- Caption is a string, aligns is an array of strings,
-- widths is an array of floats, headers is an array of
-- strings, rows is an array of arrays of strings.
function Table(caption, aligns, widths, headers, rows)
local buffer = {}
local function add(s)
table.insert(buffer, s)
end
local header_row = {}
local empty_header = true
for i, h in pairs(headers) do
table.insert(header_row, trim(h))
empty_header = empty_header and h == ""
end
if not empty_header then
add('|| ' .. table.concat(header_row, ' || ') .. ' ||')
end
for _, row in pairs(rows) do
local trimmed_row = {}
for _, cell in pairs(row) do
table.insert(trimmed_row, fix_multiline_cell(trim(cell)))
end
add('| ' .. table.concat(trimmed_row, ' | ') .. ' |')
end
return "\n" .. table.concat(buffer,'\n') .. "\n"
end
-- The following code will produce runtime warnings when you haven't defined
-- all of the functions you need for the custom writer, so it's useful
-- to include when you're working on a writer.
local meta = {}
meta.__index = function(_, key)
io.stderr:write(string.format("WARNING: Undefined function '%s'\n",key))
return function() return "" end
end
setmetatable(_G, meta)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment