local H={}H.__index=H H.ClassName="\077\097\114\107\100\111\119\110\080\097\114\115\101\114"function H.new(A)local Q=setmetatable({},H)Q._text=A or error("\078\111 \116\101\120\116")return Q end function H.GetLines(H)local A={}local Q=H._text.."\n"for H in Q:gmatch("\040\091\094\r\n\093\042\041\091\r\n\093")do table.insert(A,H)end return A end function H.ParseList(A,H)local Q={}local u for H,A in pairs(H)do local T,V,K if type(A)=="\115\116\114\105\110\103"then T,V,K=A:match("\094\040\091 \t\093\042\041\040\091\037-\037\042\093\041\037\115\042\040\046\043\041\037\115\042\036")end if T and(V and K)then T=T:gsub("    ","\088")T=T:gsub(" ","")T=T:gsub("\t","\088")local H=#T+1 if u and u.Level~=H then table.insert(Q,u)u=nil end if u then table.insert(u,K)else u={}u.Level=H u.Type="\076\105\115\116"table.insert(u,K)end else if u then table.insert(Q,u)u=nil end table.insert(Q,A)end end if u then table.insert(Q,u)end return Q end function H.ParseHeaders(A,H)local Q={}for H,A in pairs(H)do local u,T if type(A)=="\115\116\114\105\110\103"then u,T=A:match("\094\037\115\042\040\091\035\093\043\041\037\115\042\040\046\043\041\037\115\042\036")end local V=u and#u if T and(V and(V>=1 and V<=5))then table.insert(Q,{Type="\072\101\097\100\101\114";Level=V,Text=T})else table.insert(Q,A)end end return Q end function H.ParseParagraphs(A,H)local Q={}local u for H,A in pairs(H)do if type(A)=="\116\097\098\108\101"then table.insert(Q,A)else if A:match("\091\094\037\115\093")then if u then u=u..(" "..A)else u=A end else if u then table.insert(Q,u)u=nil end end end end if u then table.insert(Q,u)end return Q end function H.Parse(H)local A=H:GetLines()A=H:ParseList(A)A=H:ParseHeaders(A)A=H:ParseParagraphs(A)return A end return H
--- Parses text into markdown
-- @classmod MarkdownParser

local MarkdownParser = {}
MarkdownParser.__index = MarkdownParser
MarkdownParser.ClassName = "MarkdownParser"

function MarkdownParser.new(text)
	local self = setmetatable({}, MarkdownParser)

	self._text = text or error("No text")

	return self
end

function MarkdownParser:GetLines()
	local lines = {}
	local text = self._text .. "\n" -- append extra line to force ending match
	for line in text:gmatch("([^\r\n]*)[\r\n]") do
		table.insert(lines, line)
	end
	return lines
end

function MarkdownParser:ParseList(oldLines)
	local lines = {}
	local currentList

	for _, line in pairs(oldLines) do
		local space, bullet, text

		if type(line) == "string" then
			space, bullet, text = line:match("^([ \t]*)([%-%*])%s*(.+)%s*$")
		end

		if space and bullet and text then
			space = space:gsub("    ", "X")
			space = space:gsub(" ", "")
			space = space:gsub("\t", "X")
			local Level = #space + 1

			if currentList and currentList.Level ~= Level then
				table.insert(lines, currentList)
				currentList = nil
			end

			if currentList then
				table.insert(currentList, text)
			else
				currentList = {}
				currentList.Level = Level
				currentList.Type = "List"

				table.insert(currentList, text)
			end
		else
			if currentList then
				table.insert(lines, currentList)
				currentList = nil
			end
			table.insert(lines, line)
		end
	end

	if currentList then
		table.insert(lines, currentList)
	end

	return lines
end

function MarkdownParser:ParseHeaders(oldLines)
	local lines = {}

	for _, line in pairs(oldLines) do
		local poundSymbols, text

		if type(line) == "string" then
			poundSymbols, text = line:match("^%s*([#]+)%s*(.+)%s*$")
		end

		local level = poundSymbols and #poundSymbols
		if text and level and level >= 1 and level <= 5 then
			table.insert(lines, {
				Type = "Header";
				Level = level;
				Text = text;
			})
		else
			table.insert(lines, line)
		end
	end

	return lines
end

function MarkdownParser:ParseParagraphs(oldLines)
	local lines = {}

	local currentParagraph
	for _, line in pairs(oldLines) do
		if type(line) == "table" then
			table.insert(lines, line)
		else
			if line:match("[^%s]") then
				if currentParagraph then
					currentParagraph = currentParagraph .. " " .. line
				else
					currentParagraph = line
				end
			else
				if currentParagraph then
					table.insert(lines, currentParagraph)
					currentParagraph = nil
				end
			end
		end
	end

	if currentParagraph then
		table.insert(lines, currentParagraph)
	end

	return lines
end

--- Parses the given text into a list of lines
function MarkdownParser:Parse()
	local lines = self:GetLines()

	lines = self:ParseList(lines)
	lines = self:ParseHeaders(lines)
	lines = self:ParseParagraphs(lines) -- do this last

	return lines
end

return MarkdownParser