|
------------------------------------------------------------------------------- |
|
-- Slimdown - A very basic pattern-based Markdown parser. |
|
-- Supports the following elements (and can be extended via addRule()): |
|
-- |
|
-- * Headers |
|
-- * Links |
|
-- * Bold |
|
-- * Emphasis |
|
-- * Deletions |
|
-- * Quotes |
|
-- * Inline code |
|
-- * Blockquotes |
|
-- * Ordered/unordered lists |
|
-- * Horizontal rules |
|
-- |
|
-- Website: |
|
-- PHP: https://gist.github.com/jbroadway/2836900 |
|
-- Lua: https://gist.github.com/paulcuth/8967731 |
|
-- |
|
-- @module Slimdown |
|
-- @author Johnny Broadway <[email protected]> |
|
-- @author Paul Cuthbertson <[email protected]> |
|
-- @license MIT |
|
-- |
|
|
|
|
|
------------------------------------------------------------------------------- |
|
-- Trims whitespace from the beginning and end of a string. |
|
-- @tparam string str String to be trimmed. |
|
-- @treturn string Trimmed string. |
|
-- |
|
local function trim (str) |
|
return str:match '^[%s\n]*(.-)[%s\n]*$' |
|
end |
|
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------- |
|
-- Mark up a line as an HTML paragraph. |
|
-- @tparam string line The line to mark up. |
|
-- @treturn string HTML tag. |
|
-- |
|
local function parseParagraph (line) |
|
local trimmed = trim(line) |
|
|
|
if |
|
string.find(trimmed, '^</?ul') |
|
or string.find(trimmed, '^</?ol') |
|
or string.find(trimmed, '^</?li') |
|
or string.find(trimmed, '^</?h') |
|
or string.find(trimmed, '^</?p') |
|
or string.find(trimmed, '^</?bl') |
|
then |
|
return '\n'..line..'\n' |
|
end |
|
|
|
return string.format('\n<p>%s</p>\n', trimmed) |
|
end |
|
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------- |
|
-- Mark up a line as an HTML unordered list. |
|
-- @tparam string item The line to mark up. |
|
-- @treturn string HTML tag. |
|
-- |
|
local function parseUnorderedList (item) |
|
return string.format('\n<ul>\n\t<li>%s</li>\n</ul>', trim(item)) |
|
end |
|
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------- |
|
-- Mark up a line as an HTML ordered list. |
|
-- @tparam string item The line to mark up. |
|
-- @treturn string HTML tag. |
|
-- |
|
local function parseOrderedList (item) |
|
return string.format('\n<ol>\n\t<li>%s</li>\n</ol>', trim(item)) |
|
end |
|
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------- |
|
-- Mark up a line as an HTML blockquote. |
|
-- @tparam string item The line to mark up. |
|
-- @treturn string HTML tag. |
|
-- |
|
local function parseBlockquote (item) |
|
return string.format('\n<blockquote>%s</blockquote>', trim(item)) |
|
end |
|
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------- |
|
-- Mark up a line as an HTML ordered list. |
|
-- @tparam string chars The characters used to markdown the header. |
|
-- @tparam string header Header string. |
|
-- @treturn string HTML tag. |
|
-- |
|
local function parseHeader (chars, header) |
|
local level = #chars |
|
return string.format('<h%d>%s</h%d>', level, trim(header), level) |
|
end |
|
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------- |
|
-- Conversion rules. |
|
-- |
|
local rules = { |
|
{ '(#+)(.-%\n)', parseHeader }, -- headers |
|
{ '%[(.-)%]%((.-)%)', '<a href="%2">%1</a>' }, -- links |
|
{ '%*%*([^%\n]-)%*%*', '<strong>%1</strong>' }, -- bold * |
|
{ '__([^%\n]-)__', '<strong>%1</strong>' }, -- bold _ |
|
{ '%*([^%\n]-)%*', '<em>%1</em>' }, -- emphasis * |
|
{ '_([^%\n]-)_', '<em>%1</em>' }, -- emphasis _ |
|
{ '~~([^%\n]-)~~', '<del>%1</del>' }, -- del |
|
{ ':"([^%\n]-)":', '<q>%1</q>' }, -- quote |
|
{ '`([^%\n]-)`', '<code>%1</code>' }, -- inline code |
|
{ '```(.-)```', '<code>%1</code>' }, -- code block |
|
{ '%\n%*([^%\n]*)', parseUnorderedList }, -- ul lists |
|
{ '%\n[0-9]+%.([^%\n]*)', parseOrderedList }, -- ol lists |
|
{ '%\n%-%-%-%-%-%-*', '\n<hr />' }, -- horizontal rule |
|
{ '%\n>([^%\n]*)', parseBlockquote }, -- blockquotes > |
|
{ '%\n>([^%\n]*)', parseBlockquote }, -- blockquotes > |
|
{ '%\n([^%\n]+)%\n', parseParagraph }, -- add paragraphs |
|
{ '</ul>%s*<ul>%\n', '' }, -- fix extra ul |
|
{ '</ol>%s*<ol>%\n', '' }, -- fix extra ol |
|
{ '</blockquote>%s*<blockquote>', '</br>' }, -- fix extra blockquote |
|
} |
|
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------- |
|
-- Adds a new rule to the mix. |
|
-- @usage slimdown.addRule(':%)', '<img src="smiley.png" />') |
|
-- @tparam string pattern Pattern to match. |
|
-- @tparam string|function replacement Replacement string or parsing function. |
|
-- |
|
function addRule (pattern, replacement) |
|
table.insert(rules, { pattern, replacement }) |
|
end |
|
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------- |
|
-- Renders markdown text as HTML. |
|
-- @usage slimdown.render('[Slimdown in Lua](https://gist.github.com/paulcuth/8967731)') |
|
-- @tparam string text Markdown content. |
|
-- @treturn string HTML. |
|
-- |
|
function render (text) |
|
text = '\n'..text..'\n' |
|
|
|
for i = 1, #rules do |
|
text = string.gsub(text, unpack(rules[i])) |
|
end |
|
|
|
return trim(text) |
|
end |
|
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------- |
|
-- Module definition |
|
return { |
|
addRule = addRule, |
|
render = render |
|
} |
|
|