local M = {}

function M.element(tag, attrs, content)
	local out = { "<", tag }

	if attrs then
		for k, v in pairs(attrs) do
			if v ~= false and v ~= nil then
				if v == true then
					out[#out + 1] = " " .. k
				else
					out[#out + 1] = " " .. k .. "=\"" .. tostring(v) .. "\""
				end
			end
		end
	end

	if content == nil then
		out[#out + 1] = " />"
		return table.concat(out)
	end

	out[#out + 1] = ">"
	out[#out + 1] = tostring(content)
	out[#out + 1] = "</"
	out[#out + 1] = tag
	out[#out + 1] = ">"

	return table.concat(out)
end

function M.a(link, str)
	link = link or "https://example.com"
	str = str or link
	return M.element("a", { href = link }, str)
end

function M.download(link, str, downloadName)
	link = link or "."
	str = str or link
	return M.element("a", { href = link, download = downloadName }, str)
end

function M.ha(link, str)
	link = link or "https://example.com"
	str = str or link
	return M.element("a", { href = link, class = "hidden" }, str)
end

function M.external(link, str)
	return M.element("a", { href = link, target = "_blank" }, str)
end

function M.note(str)
	return M.element("div", { class = "note" }, str)
end

function M.muted(str)
	return M.element("div", { class = "muted" }, str)
end

function M.callout(str)
	return M.element("div", { class = "callout" }, str)
end

function M.h1(str)
	return M.element("h1", nil, str or "")
end

function M.h2(str)
	return M.element("h2", nil, str or "")
end

function M.h3(str)
	return M.element("h3", nil, str or "")
end

function M.h4(str)
	return M.element("h4", nil, str or "")
end

function M.h5(str)
	return M.element("h5", nil, str or "")
end

function M.h6(str)
	return M.element("h6", nil, str or "")
end

function M.p(str)
	return M.element("p", nil, str or "")
end

function M.pre(str)
	return M.element("pre", nil, str or "")
end

function M.code(str)
	return M.element("pre", nil, M.element("code", nil, str or ""))
end

function M.ul(items)
	items = items or {}
	local out = {}
	for _, item in ipairs(items) do
		out[#out + 1] = M.element("li", nil, item)
	end
	return M.element("ul", nil, table.concat(out))
end

function M.ol(items)
	items = items or {}
	local out = {}
	for _, item in ipairs(items) do
		out[#out + 1] = M.element("li", nil, item)
	end
	return M.element("ol", nil, table.concat(out))
end

function M.tl(items)
	items = items or {}
	local out = {}
	for _, item in ipairs(items) do
		out[#out + 1] = M.element("li", nil, item)
	end
	return M.element("ul", { class = "tl" }, table.concat(out))
end

function M.blockquote(str)
	return M.element("blockquote", nil, str or "")
end

function M.hr()
	return M.element("hr")
end

function M.img(src, alt)
	return M.element("img", { src = src or "", alt = alt or "" })
end

function M.strong(str)
	return M.element("strong", nil, str or "")
end

function M.em(str)
	return M.element("em", nil, str or "")
end

function M.br()
	return M.element("br")
end

function M.div(content, class)
	return M.element("div", class and { class = class } or nil, content or "")
end

function M.span(content, class)
	return M.element("span", class and { class = class } or nil, content or "")
end

function M.escape(str)
	str = tostring(str or "")
	str = str:gsub("&", "&amp;")
	str = str:gsub("<", "&lt;")
	str = str:gsub(">", "&gt;")
	str = str:gsub('"', "&quot;")
	str = str:gsub("'", "&#39;")
	return str
end

function M.highlight(str)
	return M.element("span", { class = "highlight" }, str or "")
end

function M.banner(str)
	return M.element("div", { class = "banner" }, str or "")
end

function M.center(str)
	return M.element("div", { class = "center" }, str or "")
end

function M.nav(link, str)
	link = link or "example.com"
	str = str or link
	return M.element("a", { href = link, class = "nav" }, str)
end

function M.rl(r, l)
	return
		M.element("span", { class = "left" }, r or "") ..
		M.element("span", { class = "right" }, l or "")
end

return M
