Last active
April 5, 2017 17:25
-
-
Save dblume/fd8f71b88df3998a84e671a81277419f to your computer and use it in GitHub Desktop.
Script for converting to Atlassian Confluence's markup with Pandoc.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- 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 '<' | |
elseif x == '>' then | |
return '>' | |
elseif x == '&' then | |
return '&' | |
elseif x == '"' then | |
return '"' | |
elseif x == "'" then | |
return ''' | |
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 " " 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 = " " | |
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