aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.build.yml13
-rw-r--r--.gitignore1
-rw-r--r--LICENSE.md2
-rw-r--r--Makefile25
-rw-r--r--README.md2
-rw-r--r--etc/gemtext.lua297
-rw-r--r--etc/template.gmi1
7 files changed, 330 insertions, 11 deletions
diff --git a/.build.yml b/.build.yml
index fe0e2ed..cf489ae 100644
--- a/.build.yml
+++ b/.build.yml
@@ -15,19 +15,24 @@ tasks:
make
- compress: |
tar czf spec-html.tar.gz crowbar-spec/*.html
+ tar czf spec-gmi.tar.gz crowbar-spec/*.gmi
- test-page-count: |
cd crowbar-spec
make check
- upload: |
- upload() {
- rsync --rsh="ssh -o StrictHostKeyChecking=no" -rlt8hP --del $@ services@boringcactus.com:/var/www/html/crowbar-lang.org/
+ upload-to() {
+ dest=$1
+ shift
+ rsync --rsh="ssh -o StrictHostKeyChecking=no" -rlt8hP --del $@ services@boringcactus.com:$dest
}
cd crowbar-spec
- upload *.html spec.pdf
+ upload-to /var/www/html/crowbar-lang.org/ *.html spec.pdf
+ upload-to /var/www/gmi/crowbar-lang.org/ *.gmi spec.pdf
- notify: |
cd crowbar-spec
message="crowbar spec updated: $(git log -1 --no-decorate --oneline)"
- echo "$message" | ssh -o StrictHostKeyChecking=no services@boringcactus.com 'sh -c "cat > ~/irc/chat.freenode.net/#crowbar-lang/in"'
+ echo "/NOTICE #crowbar-lang :$message" | ssh -o StrictHostKeyChecking=no services@boringcactus.com 'sh -c "cat > ~/irc/chat.freenode.net/#crowbar-lang/in"'
artifacts:
- crowbar-spec/spec.pdf
- spec-html.tar.gz
+ - spec-gmi.tar.gz
diff --git a/.gitignore b/.gitignore
index 17a66eb..055b012 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
/*.html
+/*.gmi
/spec.pdf
diff --git a/LICENSE.md b/LICENSE.md
index 1d968be..20ffc56 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -3,4 +3,4 @@ title: License
---
[![Creative Commons BY-SA License](https://i.creativecommons.org/l/by-sa/4.0/80x15.png)](http://creativecommons.org/licenses/by-sa/4.0/)
-This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/").
+This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/).
diff --git a/Makefile b/Makefile
index 258580a..7bd231c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
.POSIX:
.SUFFIXES:
-.SUFFIXES: .md .html
+.SUFFIXES: .md .html .gmi
# commands
GIT = git
@@ -10,9 +10,12 @@ PDFINFO = pdfinfo
# input files
SRC = index.md vs-c.md tagged-unions.md types.md safety.md errors.md syntax.md LICENSE.md
HTML = $(SRC:.md=.html)
+GMI = $(SRC:.md=.gmi)
+
+all: spec.pdf $(GMI)
spec.pdf: $(HTML)
- if $(GIT) describe --tags --exact-match 2>/dev/null; \
+ @if $(GIT) describe --tags --exact-match 2>/dev/null; \
then \
metadata="subtitle=$$($(GIT) describe --tags --exact-match)"; \
else \
@@ -21,11 +24,23 @@ spec.pdf: $(HTML)
$(PANDOC) --defaults=etc/pdf.yml -M "$$metadata" -o $@ $(HTML)
.md.html:
- offset=`echo $(SRC) | awk '{for (i=1; i<=NF; i++) if ($$i == "$<") print (i-1) }'`; \
+ @offset=`echo $(SRC) | awk '{for (i=1; i<=NF; i++) if ($$i == "$<") print (i-1) }'`; \
$(PANDOC) --defaults=etc/md.yml --number-offset=$$offset -o $@ $<
-clean:
- rm -f $(HTML) spec.pdf
+.md.gmi:
+ @offset=`echo $(SRC) | awk '{for (i=1; i<=NF; i++) if ($$i == "$<") print (i-1) }'`; \
+ $(PANDOC) --defaults=etc/md.yml --write=etc/gemtext.lua --template=etc/template.gmi --number-offset=$$offset -o $@ $<
+
+clean: clean-pdf clean-html clean-gmi
+
+clean-pdf:
+ rm -f spec.pdf
+
+clean-html:
+ rm -f $(HTML)
+
+clean-gmi:
+ rm -f $(GMI)
check: spec.pdf
test $$($(PDFINFO) spec.pdf | grep Pages | awk '{ print $$2 }') -le 200
diff --git a/README.md b/README.md
index 4fecfad..58dde4f 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
project home: <https://crowbar-lang.org> <https://sr.ht/~boringcactus/crowbar-lang/>
-read the spec: <https://crowbar-lang.org> <https://man.sr.ht/~boringcactus/crowbar-spec/>
+read the spec: <https://crowbar-lang.org> <https://crowbar-lang.org/spec.pdf> <https://man.sr.ht/~boringcactus/crowbar-spec/>
reference compiler: <https://git.sr.ht/~boringcactus/crowbar-reference-compiler>
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$