aboutsummaryrefslogtreecommitdiff
path: root/etc
diff options
context:
space:
mode:
authorMelody Horn <melody@boringcactus.com>2020-10-26 23:22:29 -0600
committerMelody Horn <melody@boringcactus.com>2020-10-26 23:22:29 -0600
commit5ada504d5667a6f17ee2631dd471b073b332dd33 (patch)
tree130ed731247e5fe01ed2fae366e7bf08aef46b37 /etc
parentc7ce2058a94c7fbd22fc409738ad8d15af30b170 (diff)
downloadspec-5ada504d5667a6f17ee2631dd471b073b332dd33.tar.gz
spec-5ada504d5667a6f17ee2631dd471b073b332dd33.zip
build spec in gemtext too
Diffstat (limited to 'etc')
-rw-r--r--etc/gemtext.lua297
-rw-r--r--etc/template.gmi1
2 files changed, 298 insertions, 0 deletions
diff --git a/etc/gemtext.lua b/etc/gemtext.lua
new file mode 100644
index 0000000..5fdff59
--- /dev/null
+++ b/etc/gemtext.lua
@@ -0,0 +1,297 @@
+-- Invoke with: pandoc -t gemtext.lua
+
+-- Tables to store links and footnotes, so they can be included correctly.
+local links = {}
+local notes = {}
+
+-- 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.
+-- This gives you a fragment. You could use the metadata table to
+-- fill variables in a custom lua template. Or, pass `--template=...`
+-- to pandoc, and pandoc will do the template processing as usual.
+function Doc(body, metadata, variables)
+ local buffer = {}
+ local function add(s)
+ table.insert(buffer, s)
+ end
+ add(body)
+ if #notes > 0 then
+ add('')
+ for _,note in pairs(notes) do
+ add(note)
+ end
+ end
+ return table.concat(buffer, '\n')
+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 s
+end
+
+function Space()
+ return " "
+end
+
+function SoftBreak()
+ return " "
+end
+
+function LineBreak()
+ return "\n"
+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 SmallCaps(s)
+ return s
+end
+
+function Strikeout(s)
+ return '~~' .. s .. '~~'
+end
+
+function Link(s, tgt, tit, attr)
+ if tgt:match("%.html$") and not tgt:match("^https?://") then
+ tgt = tgt:gsub("%.html$", ".gmi")
+ end
+ table.insert(links, "=> " .. tgt .. " " .. s)
+ return s
+end
+
+function Image(s, src, tit, attr)
+ table.insert(links, "=> " .. src .. " [IMG] " .. s)
+ return s
+end
+
+function Code(s, attr)
+ return "`" .. s .. "`"
+end
+
+function InlineMath(s)
+ return "\\(" .. s .. "\\)"
+end
+
+function DisplayMath(s)
+ return "\\[" .. s .. "\\]"
+end
+
+function SingleQuoted(s)
+ return "‘" .. s .. "’"
+end
+
+function DoubleQuoted(s)
+ return "“" .. s .. "”"
+end
+
+function Note(s)
+ local num = #notes + 1
+ local num_fn = string.gsub(num, '0', '⁰')
+ :gsub('1', '¹')
+ :gsub('2', '²')
+ :gsub('3', '³')
+ :gsub('4', '⁴')
+ :gsub('5', '⁵')
+ :gsub('6', '⁶')
+ :gsub('7', '⁷')
+ :gsub('8', '⁸')
+ :gsub('9', '⁹')
+ -- add a list item with the note to the note table.
+ table.insert(notes, num_fn .. ' ' .. s)
+ -- return the footnote reference, linked to the note.
+ return num_fn
+end
+
+function Span(s, attr)
+ return s
+end
+
+function RawInline(format, str)
+ if format == "gemtext" then
+ return str
+ else
+ return ''
+ end
+end
+
+function Cite(s, cs)
+ local ids = {}
+ for _,cit in ipairs(cs) do
+ table.insert(ids, cit.citationId)
+ end
+ return s .. ids:concat(",")
+end
+
+function Plain(s)
+ return s
+end
+
+function Para(s)
+ local finished = s .. "\n"
+ if #links > 0 then
+ local link_text = links[1]:match('=> [^ ]+ (.+)')
+ if link_text == s and #links == 1 then
+ finished = links[1] .. "\n"
+ else
+ finished = finished .. table.concat(links, "\n") .. "\n"
+ end
+ end
+ links = {}
+ return finished
+end
+
+-- lev is an integer, the header level.
+function Header(lev, s, attr)
+ return string.rep("#", lev) .. " " .. s .. "\n"
+end
+
+function BlockQuote(s)
+ return "> " .. s:gsub("\n", "\n> "):gsub("\n> $", "\n")
+end
+
+function HorizontalRule()
+ return "-----\n"
+end
+
+function LineBlock(ls)
+ return table.concat(ls, '\n') .. "\n"
+end
+
+function CodeBlock(s, attr)
+ return "```\n" .. s .. "\n```\n"
+end
+
+function BulletList(items)
+ local buffer = {}
+ for _, item in pairs(items) do
+ local finished = false
+ if #links > 0 then
+ local link_text = links[1]:match('=> [^ ]+ (.+)')
+ if link_text == item then
+ table.insert(buffer, links[1])
+ table.remove(links, 1)
+ finished = true
+ end
+ end
+ if not finished then
+ table.insert(buffer, "* " .. item)
+ for _,link in pairs(links) do
+ table.insert(buffer, link)
+ end
+ links = {}
+ end
+ end
+ return table.concat(buffer, "\n") .. "\n"
+end
+
+function OrderedList(items)
+ local buffer = {}
+ for i, item in pairs(items) do
+ table.insert(buffer, i .. ". " .. item)
+ end
+ return table.concat(buffer, "\n") .. "\n"
+end
+
+function DefinitionList(items)
+ local buffer = {}
+ for _,item in pairs(items) do
+ local k, v = next(item)
+ table.insert(buffer, k .. ":\n" .. table.concat(v, "\n"))
+ end
+ return table.concat(buffer, "\n") .. "\n"
+end
+
+function CaptionedImage(src, tit, caption, attr)
+ return '=> ' .. src .. ' [IMG] ' .. caption .. '\n'
+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
+ add("<table>")
+ if caption ~= "" then
+ add("<caption>" .. caption .. "</caption>")
+ end
+ if widths and widths[1] ~= 0 then
+ for _, w in pairs(widths) do
+ add('<col width="' .. string.format("%.0f%%", w * 100) .. '" />')
+ end
+ end
+ local header_row = {}
+ local empty_header = true
+ for i, h in pairs(headers) do
+ table.insert(header_row,'<th>' .. h .. '</th>')
+ empty_header = empty_header and h == ""
+ end
+ if empty_header then
+ head = ""
+ else
+ add('<tr class="header">')
+ for _,h in pairs(header_row) do
+ add(h)
+ end
+ add('</tr>')
+ end
+ local class = "even"
+ for _, row in pairs(rows) do
+ class = (class == "even" and "odd") or "even"
+ add('<tr class="' .. class .. '">')
+ for i,c in pairs(row) do
+ add('<td>' .. c .. '</td>')
+ end
+ add('</tr>')
+ end
+ add('</table>')
+ return table.concat(buffer,'\n') .. "\n"
+end
+
+function RawBlock(format, str)
+ if format == "gemtext" then
+ return str
+ else
+ return ''
+ end
+end
+
+function Div(s, attr)
+ return s
+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)
diff --git a/etc/template.gmi b/etc/template.gmi
new file mode 100644
index 0000000..36d66c2
--- /dev/null
+++ b/etc/template.gmi
@@ -0,0 +1 @@
+$body$