diff options
Diffstat (limited to 'garkup.lua')
-rw-r--r-- | garkup.lua | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/garkup.lua b/garkup.lua new file mode 100644 index 0000000..2469aa8 --- /dev/null +++ b/garkup.lua @@ -0,0 +1,116 @@ +local html = require'html' +local prose = require'prose' + +local function highlight(code) + -- todo + return html.T.pre(code) +end + +local function mode_code(S) + local lang = S:line():match("^```(%w+) ?(.*)") + + local text = "" + for line in S:lines() do + if line:match("^```") then + break + else + text = text .. line + end + end + S:emit(highlight(text)) +end + +local function mode_list(S) + local items = {} + for line in S:lines() do + if line:match("^%*") then + local content = line:gsub("^%*%s*","") + table.insert(items, html.T.li(prose(S,content))) + else + S:unline(line) + break + end + end + S:emit(html.T.ul(items)) +end + +local function mode_heading(S) + local level, line = S:line():match("^#*()%s*(.*)") + level = level - 1 + S:emit(html.tag('h'..level, prose(S,line))) +end + +local mode_patterns = { + { "^```", mode_code }, + { "^*", mode_list }, + { "^#", mode_heading }, +} + +local function match_mode_pattern(S, line) + for i, row in ipairs(mode_patterns) do + local pattern, mode = row[1], row[2] + if line:match(pattern) then return mode end + end +end + +local function mode_paragraphs(S) + local para = "" + local function finish() + if para:match("%S") then + S:emit(html.T.p(prose(S,para))) + end + para = "" + end + + for line in S:lines() do + local newmode = match_mode_pattern(S, line) + if newmode then + S:unline(line) + finish() + return newmode(S) + elseif line:match("%S") then + para = para .. line + else + finish() + end + end +end + +local function split_lines(text) + local lines = {} + for x in text:gmatch("[^\n]*") do + table.insert(lines, x.."\n") + end + return lines +end + +local State = {} +function State.new(input) + return setmetatable({ + the_lines = split_lines(input) + }, {__index=State}) +end + +function State.emit(self, x) + print(html.html(x)) +end +function State.line(self) + return table.remove(self.the_lines, 1) +end +function State.unline(self, line) + table.insert(self.the_lines, 1, line) +end +function State.lines(self) + return State.line, self +end +function State.remaining(self) + return #self.the_lines > 0 +end +function State.toplevel(self) + while self:remaining() do + mode_paragraphs(self) + end +end + + +State.new(io.read"a"):toplevel() |