qownnotes-scripts/selected-markdown-to-bbcode/panbbcode.lua

294 lines
5.0 KiB
Lua

-- panbbcode - BBCode writer for pandoc
-- Copyright (C) 2014 Jens Oliver John < dev ! 2ion ! de >
-- Licensed under the GNU General Public License v3 or later.
-- Written for Lua 5.{1,2}
-- PRIVATE
local function enclose(t, s, p)
if p then
return string.format("[%s=%s]%s[/%s]", t, p, s, t)
else
return string.format("[%s]%s[/%s]", t, s, t)
end
end
local function lookup(t, e)
for _,v in ipairs(t) do
if v == e then
return true
end
end
return false
end
local strlen_ger_utf8_t = { [0xc3] = { 0xa4, 0x84, 0xbc, 0x9c, 0xb6, 0x96, 0x9f } }
-- FIXME: check also the byte *after* occurences of 0xc3 (and keep the
-- loop for that)
local function strlen_ger_utf8(w)
local s = {}
local len = 0
w:gsub("(.)", function (c)
table.insert(s, c:byte())
end)
for i=1,#s do
if strlen_ger_utf8_t[s[i]] then
i = i + 1
else
len = len + 1
end
end
return len
end
local function column(s, sep, blind)
local s = s
local sep = sep or " "
local blind = blind or ""
local ret = ""
local y = {}
local x = {}
local cm = 0
local i = 0
for line in s:gmatch("[^\r\n]+") do
local ly = {}
local cc = 0
line:gsub("[^@]+", function (m)
local len = #m
cc = cc + 1
if cc > cm then
x[cc] = 0
cm = cc
end
if len > x[cc] then
x[cc] = len
end
table.insert(ly, m)
end)
table.insert(y, ly)
end
for _,line in ipairs(y) do
for tmp=1,(#x-#line) do
table.insert(line, blind)
end
for i,word in ipairs(line) do
-- workaround for common German utf-8 umlauts
local wl = word:match("[öäüÖÄÜß]") and strlen_ger_utf8(word) or #word
if wl < x[i] then
for tmp=1,(x[i]-wl) do
word = word .. " "
end
end
ret = ret .. word .. sep
end
ret = ret .. '\n'
end
return ret
end
-- PUBLIC
local cache_notes = {}
function Doc( body, meta, vars )
local buf = {}
local function _(e)
table.insert(buf, e)
end
if meta['title'] and meta['title'] ~= "" then
_(meta['title'])
end
_(body)
if #cache_notes > 0 then
_("--")
for i,n in ipairs(cache_notes) do
_(string.format("[%d] %s", i, n))
end
end
return table.concat(buf, '\n')
end
function Str(s)
return s
end
function Space()
return ' '
end
function LineBreak()
return '\n'
end
function Emph(s)
return enclose('em', s)
end
function Strong(s)
return enclose('b', s)
end
function Subscript(s)
return string.format("{%s}", s)
end
function Superscript(s)
return string.format("[%s]", s)
end
function SmallCaps(s)
return s
end
function Strikeout(s)
return enclose('s', s)
end
function Link(s, src, title)
return enclose('url', s, src)
end
function Image(s, src, title)
return enclose('img', s, src)
end
function CaptionedImage(src, attr, title)
if not title or title == "" then
return enclose('img', src)
else
return enclose('img', src, title)
end
end
function Code(s, attr)
return string.format("[code]%s[/code]", s)
end
function InlineMath(s)
return s
end
function DisplayMath(s)
return s
end
function Note(s)
table.insert(cache_notes, s)
return string.format("[%d]", #cache_notes)
end
function Span(s, attr)
return s
end
function Plain(s)
return s
end
function Para(s)
return s
end
function Header(level, s, attr)
if level == 1 then
return enclose('h', s)
elseif level == 2 then
return enclose('b', enclose('u', s))
else
return enclose('b', s)
end
end
function BlockQuote(s)
local a, t = s:match('@([%w]+): (.+)')
if a then
return enclose('quote', t or "Unknown" , a)
else
return enclose('quote', s)
end
end
function Cite(s)
return s
end
function Blocksep(s)
return "\n\n"
end
function HorizontalRule(s)
return '--'
end
function CodeBlock(s, attr)
return enclose('code', s)
end
local function makelist(items, ltype)
local buf = string.format("[list=%s]", ltype)
for _,e in ipairs(items) do
buf = buf .. enclose('*', e) .. '\n'
end
buf = buf .. '[/list]'
return buf
end
function BulletList(items)
return makelist(items, '*')
end
function OrderedList(items)
return makelist(items, '1')
end
function DefinitionList(items)
local buf = ""
local function mkdef(k,v)
return string.format("%s: %s\n", enclose('b', k), v)
end
for _,e in ipairs(items) do
for k,v in pairs(items) do
buf = buf .. mkdef(k,v)
end
end
return buf
end
function html_align(align)
return ""
end
function Table(cap, align, widths, headers, rows)
local buf = {}
for _,r in ipairs(rows) do
local rbuf = ""
for i,c in ipairs(r) do
if i~=#r then
rbuf = rbuf .. c .. '@'
else
rbuf = rbuf .. c
end
end
table.insert(buf, rbuf)
end
local cin = table.concat(buf, '\n')
return enclose('code', column(cin))
end
function Div(s, attr)
return s
end
-- boilerplate
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)