diff options
Diffstat (limited to 'prose.lua')
-rw-r--r-- | prose.lua | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/prose.lua b/prose.lua new file mode 100644 index 0000000..ceadec0 --- /dev/null +++ b/prose.lua @@ -0,0 +1,90 @@ +local html = require'html' + +local extensions = {} + +local function prose(S, text) + -- this may be a hack + local replacements = {} + local SO, SI = "\x0e", "\x0f" + -- if debugview then SO,SI = "\x1b[7m", "\x1b[0m" end + local function emplace(s) + table.insert(replacements, s) + return SO .. #replacements .. SI + end + + -- no way to match 'after ws or at start of string' + -- so, just add ws to start and end of string + -- this may also be a hack + text = ' ' .. text .. ' ' + + local function simple_sub(delim, tagname) + return { + "(%s)"..delim..'(.-)'..delim..'(%W)', -- wo wimple + function(a,x,b) return a..emplace(html.T[tagname](x))..b end + } + end + + local function extension(str) + local verb, rest = str:match("^{(%w+);%s*(.*)}$") + if verb then + return emplace(extensions[verb](S, rest)) + end + local verbonly = str:match("^{(%w+)}$") + if verbonly then + return emplace(extensions[verbonly](S)) + end + error("invalid extension syntax: "..str) + end + + local subs = { + { "%b{}", extension }, + simple_sub('%*', 'strong'), + simple_sub('_', 'em'), + simple_sub('`', 'code'), + } + + for i, row in ipairs(subs) do + local pattern,replacement = row[1], row[2] + text = text:gsub(pattern,replacement) + end + + text = text:gsub("^%s*",""):gsub("%s*$","") + -- print(text) + local insects = {""} + local n = 1 + while n <= #text do + local _, nn, id = text:find('^'..SO:gsub("%[","%%[").."(%d+)"..SI:gsub("%[","%%["), n) + if nn then + table.insert(insects, replacements[tonumber(id)]) + table.insert(insects, "") + n = nn + 1 + else + local c = text:sub(n,n) + -- print("'"..c.."'") + insects[#insects] = insects[#insects] .. c + n = n + 1 + end + end + + -- for i,n in ipairs(insects) do print(i,type(n),n) end + + return insects +end + +extensions.fn = function(S,text) + S.footnotes = S.footnotes or {} + local n = #S.footnotes + 1 + local link_id = "fnref_"..n + local note_id = "fn_"..n + S.footnotes[n] = html.T.li({id=note_id}, { + prose(S,text), html.safe" ", + html.T.a({href="#"..link_id, role="doc-backlink"}, html.safe"↩︎")}) + return html.T.sup({id=link_id}, html.T.a({href="#"..note_id, role='doc-noteref'}, '('..n..')')) +end + +extensions.fns = function(S) + if not S.footnotes then return "" end + return {html.T.hr{}, html.T.ol(S.footnotes)} +end + +return prose |