Documentation for this module may be created at Module:MarkdownConverter/doc
local p = {}
-- Main conversion function
function p.convert(markdown)
if not markdown or markdown == "" then
return ""
end
local text = markdown
-- Headers (### -> === ===, ## -> == ==, # -> = =)
text = text:gsub("###%s*(.-)%s*\n", "=== %1 ===\n")
text = text:gsub("##%s*(.-)%s*\n", "== %1 ==\n")
text = text:gsub("#%s*(.-)%s*\n", "= %1 =\n")
-- Bold (**text** -> '''text''')
text = text:gsub("%*%*(.-)%*%*", "'''%1'''")
-- Italic (*text* -> ''text'')
text = text:gsub("%*(.-)%*", "''%1''")
-- Strikethrough (~~text~~ -> <s>text</s>)
text = text:gsub("~~(.-)~~", "<s>%1</s>")
-- Code blocks (```lang\ncode``` -> <syntaxhighlight lang="lang">code</syntaxhighlight>)
text = text:gsub("```(%w*)%s*\n(.-)```", function(lang, code)
if lang and lang ~= "" then
return '<syntaxhighlight lang="' .. lang .. '">' .. code .. '</syntaxhighlight>'
else
return '<pre>' .. code .. '</pre>'
end
end)
-- Inline code (`code` -> <code>code</code>)
text = text:gsub("`([^`]+)`", "<code>%1</code>")
-- Unordered lists (- item -> * item)
text = text:gsub("\n%-%s*(.-)%s*\n", "\n* %1\n")
text = text:gsub("^%-%s*(.-)%s*\n", "* %1\n")
-- Ordered lists (1. item -> # item)
text = text:gsub("\n%d+%.%s*(.-)%s*\n", "\n# %1\n")
text = text:gsub("^%d+%.%s*(.-)%s*\n", "# %1\n")
-- Links ([text](url) -> [url text])
text = text:gsub("%[(.-)%]%((.-)%)", "[%2 %1]")
-- Images ( -> [[File:url|alt]])
text = text:gsub("!%[(.-)%]%((.-)%)", "[[File:%2|%1]]")
-- Horizontal rules (--- -> ----)
text = text:gsub("\n%-%-%-+\n", "\n----\n")
-- Blockquotes (> text -> {{quote|text}})
text = text:gsub("\n>%s*(.-)%s*\n", "\n{{quote|%1}}\n")
text = text:gsub("^>%s*(.-)%s*\n", "{{quote|%1}}\n")
-- Tables (basic support)
text = p.convertTables(text)
return text
end
-- Helper function for table conversion
function p.convertTables(text)
-- This is a basic table converter
-- Markdown: | col1 | col2 |
-- Wikitext: {| class="wikitable" \n! col1 !! col2 \n|}
local lines = {}
for line in text:gmatch("[^\n]*") do
table.insert(lines, line)
end
local result = {}
local inTable = false
local isHeader = true
for i, line in ipairs(lines) do
if line:match("^%s*|.*|%s*$") then
if not inTable then
table.insert(result, '{| class="wikitable"')
inTable = true
isHeader = true
end
-- Skip separator lines (|---|---|)
if not line:match("^%s*|%-+|") then
local cells = {}
for cell in line:gmatch("|%s*(.-)%s*") do
if cell ~= "" then
table.insert(cells, cell)
end
end
if #cells > 0 then
if isHeader then
table.insert(result, "! " .. table.concat(cells, " !! "))
isHeader = false
else
table.insert(result, "|- ")
table.insert(result, "| " .. table.concat(cells, " || "))
end
end
end
else
if inTable then
table.insert(result, "|}")
inTable = false
end
table.insert(result, line)
end
end
if inTable then
table.insert(result, "|}")
end
return table.concat(result, "\n")
end
-- Parser function for direct use in templates
function p.parseMarkdown(frame)
local markdown = frame.args[1] or frame:getParent().args[1] or ""
return p.convert(markdown)
end
return p