From 4a28382c39281d0a05146d8f352cae7ba9fabbb7 Mon Sep 17 00:00:00 2001 From: vsaranov Date: Fri, 10 Jan 2025 17:29:33 +0100 Subject: [PATCH 1/3] Add support for GitHub-style alerts --- md.lua | 47 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/md.lua b/md.lua index 295fecf..c8bb99f 100644 --- a/md.lua +++ b/md.lua @@ -80,7 +80,7 @@ end local function externalLinkEscape(str, t) local nomatches = true - for m1, m2, m3 in gmatch(str, '(.*)%[(.*)%](.*)') do + for m1, m2, m3 in gmatch(str, '(.*)%[%w(.*)%](.*)') do if nomatches then t[#t + 1] = match(m1, '^(.-)!?$'); nomatches = false end if byte(m1, #m1) == byte '!' then t[#t + 1] = {type = 'img', attributes = {alt = m2}} @@ -197,6 +197,7 @@ local PATTERN_RULE1 = "^%s?%s?%s?(-%s*-%s*-[%s-]*)$" local PATTERN_RULE2 = "^%s?%s?%s?(*%s**%s**[%s*]*)$" local PATTERN_RULE3 = "^%s?%s?%s?(_%s*_%s*_[%s_]*)$" local PATTERN_CODEBLOCK = "^%s*%`%`%`(.*)" +local PATTERN_BLOCKALERT = "^%s*> %[!(.*)%]" local PATTERN_BLOCKQUOTE = "^%s*> (.*)$" local PATTERN_ULIST = "^%s*[%*%-] (.+)$" local PATTERN_OLIST = "^%s*%d+%. (.+)$" @@ -211,6 +212,7 @@ local PATTERNS = { PATTERN_RULE2, PATTERN_RULE3, PATTERN_CODEBLOCK, + PATTERN_BLOCKALERT, PATTERN_BLOCKQUOTE, PATTERN_ULIST, PATTERN_OLIST, @@ -349,6 +351,41 @@ local function readBlockQuote(pop, peek, tree, links) end end +local function readBlockAlert(pop, peek, tree, links) + local line = peek() + local type_alert, txt = match(line, PATTERN_BLOCKALERT) + if type_alert then + local indent = getIndentLevel(line) + local ba = { + type = "div" + } + ba.attributes = { + class = format('markdown-alert markdown-alert-%s', lower(type_alert)) + } + + tree[#tree + 1] = ba + if match(pop(), PATTERN_BLOCKQUOTE) then + local bqh = { + type = "p" + } + bqh.attributes = { + class = 'markdown-alert-icon' + } + ba[#ba + 1] = bqh + + local bqv = readFragment(pop, peek, links, function(l) + local tp = isSpecialLine(l) + return tp and tp ~= PATTERN_BLOCKQUOTE + end) + + ba[#ba + 1] = bqv + ba[#ba + 1] = '\r\n' + end + + return peek() + end +end + local function readList(pop, peek, tree, links, expectedIndent) if not peek() then return end if expectedIndent and getIndentLevel(peek()) ~= expectedIndent then return end @@ -398,9 +435,11 @@ function readLineStream(stream, tree, links) tree = tree or {} links = links or {} while peek() do - if not readBlockQuote(pop, peek, tree, links) then - if not readList(pop, peek, tree, links) then - readSimple(pop, peek, tree, links) + if not readBlockAlert(pop, peek, tree, links) then + if not readBlockQuote(pop, peek, tree, links) then + if not readList(pop, peek, tree, links) then + readSimple(pop, peek, tree, links) + end end end end From 09207c0f2e459bdf381e73f60614440230334bd4 Mon Sep 17 00:00:00 2001 From: vsaranov Date: Thu, 6 Feb 2025 22:19:27 +0100 Subject: [PATCH 2/3] refactoring readBlockAlert() --- md.lua | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/md.lua b/md.lua index c8bb99f..b3111b0 100644 --- a/md.lua +++ b/md.lua @@ -355,21 +355,16 @@ local function readBlockAlert(pop, peek, tree, links) local line = peek() local type_alert, txt = match(line, PATTERN_BLOCKALERT) if type_alert then - local indent = getIndentLevel(line) local ba = { - type = "div" - } - ba.attributes = { - class = format('markdown-alert markdown-alert-%s', lower(type_alert)) + type = "div", + attributes = { class = format('markdown-alert markdown-alert-%s', lower(type_alert)) } } tree[#tree + 1] = ba if match(pop(), PATTERN_BLOCKQUOTE) then local bqh = { - type = "p" - } - bqh.attributes = { - class = 'markdown-alert-icon' + type = "p", + attributes = { class = 'markdown-alert-icon' } } ba[#ba + 1] = bqh From 7ea94d5e5d422d9829c695d1f3d06f44ef20a62c Mon Sep 17 00:00:00 2001 From: vsaranov Date: Thu, 6 Feb 2025 22:26:37 +0100 Subject: [PATCH 3/3] add tables with hyphens and pipes --- md.lua | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/md.lua b/md.lua index b3111b0..1deb3c1 100644 --- a/md.lua +++ b/md.lua @@ -202,6 +202,7 @@ local PATTERN_BLOCKQUOTE = "^%s*> (.*)$" local PATTERN_ULIST = "^%s*[%*%-] (.+)$" local PATTERN_OLIST = "^%s*%d+%. (.+)$" local PATTERN_LINKDEF = "^%s*%[(.*)%]%s*%:%s*(.*)" +local PATTERN_TABLE = "^%s*|(.*)|%s*$" -- List of patterns local PATTERNS = { @@ -216,7 +217,8 @@ local PATTERNS = { PATTERN_BLOCKQUOTE, PATTERN_ULIST, PATTERN_OLIST, - PATTERN_LINKDEF + PATTERN_LINKDEF, + PATTERN_TABLE } local function isSpecialLine(line) @@ -381,6 +383,71 @@ local function readBlockAlert(pop, peek, tree, links) end end +local function readTable(pop, peek, tree, links) + local line = peek() + local row1, txt = match(line, PATTERN_TABLE) + if row1 then + local t = { + type = "table", + attributes = { class = 'table table-markdown' } + } + + tree[#tree + 1] = t + local thead = { type = "thead" } + t[#t + 1] = thead + local tbody = { type = "tbody" } + t[#t + 1] = tbody + + local thead_ok = false + while true do + line = pop() + if not line then break end + -- add header + if thead_ok == false then + thead_ok = true + if match(line, "^%s*|%s*%-%-%-") then + local tr = { type = "tr" } + thead[#thead + 1] = tr + for col in row1:gmatch("[^|]+") do + local th = { col, type = "th" } + tr[#tr + 1] = th + end + line = pop() + else + local tr = { + type = "tr", + attributes = { class = '' } + } + tbody[#tbody + 1] = tr + for col in row1:gmatch("[^|]+") do + local td = { col, type = "td" } + tr[#tr + 1] = td + end + end + end + + local row, txt = match(line, PATTERN_TABLE) + if row then + local tr = { + type = "tr", + attributes = { class = '' } + } + tbody[#tbody + 1] = tr + + for col in row:gmatch("[^|]+") do + local td = { col, type = "td" } + tr[#tr + 1] = td + end + + else + break + end + end + + return peek() + end +end + local function readList(pop, peek, tree, links, expectedIndent) if not peek() then return end if expectedIndent and getIndentLevel(peek()) ~= expectedIndent then return end @@ -432,8 +499,10 @@ function readLineStream(stream, tree, links) while peek() do if not readBlockAlert(pop, peek, tree, links) then if not readBlockQuote(pop, peek, tree, links) then - if not readList(pop, peek, tree, links) then - readSimple(pop, peek, tree, links) + if not readTable(pop, peek, tree, links) then + if not readList(pop, peek, tree, links) then + readSimple(pop, peek, tree, links) + end end end end