From d8b4e0955185af9ec1e598a0e6daa23d9a9bb1e3 Mon Sep 17 00:00:00 2001 From: murat Date: Mon, 29 Jun 2026 17:05:02 +0300 Subject: [PATCH] chore: create styling module --- styling.lua | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 styling.lua diff --git a/styling.lua b/styling.lua new file mode 100644 index 0000000..1fb4b86 --- /dev/null +++ b/styling.lua @@ -0,0 +1,140 @@ +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