local module = {} local function styleLists(s) local lines = {} for line in (s .. "\n"):gmatch("([^\n]*)\n") do table.insert(lines, line) end local result = {} local inUl = false local inOl = false for _, line in ipairs(lines) do local ulItem = line:match("^[%-%*%+]%s+(.*)") local olItem = line:match("^%d+%.%s+(.*)") if ulItem then if inOl then table.insert(result, "") inOl = false end if not inUl then table.insert(result, "") inUl = false end if not inOl then table.insert(result, "
    ") inOl = true end table.insert(result, "
  1. " .. olItem .. "
  2. ") else if inUl then table.insert(result, "") inUl = false end if inOl then table.insert(result, "
") inOl = false end table.insert(result, line) end end if inUl then table.insert(result, "") end if inOl then table.insert(result, "") end return table.concat(result, "\n") end local function styleParagraph(s) local lines = {} for line in (s .. "\n"):gmatch("([^\n]*)\n") do table.insert(lines, line) end local result = {} local pLines = {} local function flushP() if #pLines > 0 then table.insert(result, "

" .. table.concat(pLines, "\n") .. "

") pLines = {} end end for _, line in ipairs(lines) do local isBlock = line:match("^<") or line:match("^#") local isEmpty = line:match("^%s*$") if isBlock or isEmpty then flushP() table.insert(result, line) else table.insert(pLines, line) end end flushP() return table.concat(result, "\n") end function module.transform(s) -- blockquote local lines = {} for line in (s .. "\n"):gmatch("([^\n]*)\n?") do local nline = line:gsub("^>%s*(.*)", "
%1
") table.insert(lines, nline) end s = table.concat(lines, "\n") -- lists s = styleLists(s) -- paragraph s = styleParagraph(s) s = s:gsub("

", "") -- line breaks s = s:gsub("\r?\n", "
") -- remove
tags around block elements local blockTags = { "ul", "ol", "li", "blockquote", "p", "h1", "h2", "h3", "h4", "h5", "h6", "hr" } for _, tag in ipairs(blockTags) do s = s:gsub("()
", "%1") s = s:gsub("
()", "%1") s = s:gsub("(<" .. tag .. ">)
", "%1") s = s:gsub("
(<" .. tag .. ">)", "%1") end -- self-closing hr s = s:gsub("(
)
", "%1") s = s:gsub("
(
)", "%1") -- headers s = s:gsub("######%s*(.-)%s*
", "
%1
") s = s:gsub("#####%s*(.-)%s*
", "
%1
") s = s:gsub("####%s*(.-)%s*
", "

%1

") s = s:gsub("###%s*(.-)%s*
", "

%1

") s = s:gsub("##%s*(.-)%s*
", "

%1

") s = s:gsub("#%s*(.-)%s*
", "

%1

") -- TODO: h1 and h2 using == and -- -- bold and italic text s = s:gsub("%*%*(.-)%*%*", "%1") s = s:gsub("%*(.-)%*", "%1") s = s:gsub("%_%_(.-)%_%_", "%1") s = s:gsub("%_(.-)%_", "%1") -- images s = s:gsub("!%[(.-)%]%((.-)%)", '%1') -- links s = s:gsub("%[(.-)%]%((.-)%)", '%1') -- code s = s:gsub("`(.-)`", "%1") -- horizontal rule s = s:gsub("%-%-%-", "
") return s end return module