local a = require "lego.html.attribute" local html = {} ---@alias lego.HtmlNode lego._HtmlNote|string ---@class lego._HtmlNote ---@field tag string ---@field attributes lego.HtmlAttribute[] ---@field children lego._HtmlNote[] ---@param tag string ---@param attributes lego.HtmlAttribute[] ---@param children lego.HtmlNode[] ---@return lego.HtmlNode function html.el(tag, attributes, children) local attrs = {} for _, attr_table in ipairs(attributes or {}) do for k, v in pairs(attr_table) do attrs[k] = v end end return { tag = tag, attributes = attrs, children = children or {}, } end ---@param text string ---@return lego.HtmlNode function html.text(text) return text end ---@param html_str string ---@return lego.HtmlNode function html.raw(html_str) return html_str end ---@param txts string[] ---@return string[] function html.tt(txts) local tt = vim .iter(txts) :map(function(txt) return { txt, " " } end) :flatten() :totable() if tt[#tt] == " " then table.remove(tt, #tt) end return tt end local _self_closing_tags = { area = {}, base = {}, br = {}, col = {}, embed = {}, hr = {}, img = {}, input = {}, -- link = {}, -- ignored because it needed for rss meta = {}, source = {}, track = {}, wbr = {}, } ---@param node lego.HtmlNode ---@return string function html.render(node) if type(node) == "string" then return node elseif type(node) == "table" and node.tag then local attr_keys = {} for k in pairs(node.attributes or {}) do table.insert(attr_keys, k) end table.sort(attr_keys) local attrs_str = "" for _, v in pairs(attr_keys) do attrs_str = attrs_str .. string.format(' %s="%s"', v, node.attributes[v]) end if _self_closing_tags[node.tag] then return string.format("<%s%s>", node.tag, attrs_str) end local children_str = "" for _, child in ipairs(node.children or {}) do children_str = children_str .. html.render(child) end return string.format("<%s%s>%s", node.tag, attrs_str, children_str, node.tag) end return "" end function html.render_page(node) return "" .. html.render(node) end -- --- COMMON ELEMENTS -- stylua: ignore start ---@param attributes lego.HtmlAttribute[] ---@param children lego.HtmlNode[] function html.div(attributes, children) return html.el("div", attributes, children) end ---@param attributes lego.HtmlAttribute[] ---@param children lego.HtmlNode[] function html.main(attributes, children) return html.el("main", attributes, children) end ---@param attributes lego.HtmlAttribute[] function html.meta(attributes) return html.el("meta", attributes, {}) end ---@param attributes lego.HtmlAttribute[] ---@param children lego.HtmlNode[] function html.span(attributes, children) return html.el("span", attributes, children) end ---@param attributes lego.HtmlAttribute[] ---@param children lego.HtmlNode[] function html.p(attributes, children) return html.el("p", attributes, children) end ---@param attributes lego.HtmlAttribute[] ---@param children lego.HtmlNode[] function html.a(attributes, children) return html.el("a", attributes, children) end ---@param attributes lego.HtmlAttribute[] ---@param children lego.HtmlNode[] function html.ul(attributes, children) return html.el("ul", attributes, children) end ---@param attributes lego.HtmlAttribute[] ---@param children lego.HtmlNode[] function html.li(attributes, children) return html.el("li", attributes, children) end ---@param attributes lego.HtmlAttribute[] ---@param children lego.HtmlNode[] function html.title(attributes, children) return html.el("title", attributes, children) end ---@param attributes lego.HtmlAttribute[] function html.link(attributes) return html.el("link", attributes, {}) end ---@param attributes lego.HtmlAttribute[] ---@param children lego.HtmlNode[] function html.h1(attributes, children) return html.el("h1", attributes, children) end ---@param attributes lego.HtmlAttribute[] ---@param children lego.HtmlNode[] function html.h2(attributes, children) return html.el("h2", attributes, children) end ---@param attributes lego.HtmlAttribute[] ---@param children lego.HtmlNode[] function html.nav(attributes, children) return html.el("nav", attributes, children) end function html.br() return html.el("br", {}, {}) end ---@param datetime string function html.time(datetime) return html.el("time", { a.attr("datetime", datetime) }, { html.text(datetime)}) end -- stylua: ignore end return html