update api to use "blocks" for future protocols

This commit is contained in:
2026-02-13 21:40:08 -05:00
parent ac30aea1fa
commit 4bd920b09f
4 changed files with 246 additions and 510 deletions

View File

@@ -1,195 +1,130 @@
local M = {}
function M.element(tag, attrs, content)
local out = { "<", tag }
M.proto = "http"
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
local function isHttp()
return M.proto == "http"
end
local function isGemini()
return M.proto == "gemini"
end
local function esc(s)
s = s or ""
s = s:gsub("&", "&amp;")
s = s:gsub("<", "&lt;")
s = s:gsub(">", "&gt;")
return s
end
M.p = function(s)
s = s or ""
if isHttp() then
return "<p>" .. esc(s) .. "</p>"
elseif isGemini() then
return s
end
end
M.h = function(level, s)
level = tonumber(level) or 1
if level < 1 then level = 1 end
if level > 6 then level = 6 end
s = s or ""
if isHttp() then
return "<h" .. level .. ">" .. esc(s) .. "</h" .. level .. ">"
elseif isGemini() then
return string.rep("#", level) .. " " .. s
end
end
M.codeblock = function(s)
s = s or ""
if isHttp() then
return "<pre><code>" .. esc(s) .. "</code></pre>"
elseif isGemini() then
return "```\n" .. s .. "\n```"
end
end
M.inline = function(s)
s = s or ""
if isHttp() then
return "<code>" .. esc(s) .. "</code>"
elseif isGemini() then
return "`" .. s .. "`"
end
end
M.link = function(text, url)
text = text or ""
url = url or ""
if isHttp() then
return "<a href=\"" .. esc(url) .. "\">" .. esc(text) .. "</a>"
elseif isGemini() then
return "=> " .. url .. " " .. text
end
end
M.list = function(items, ordered)
items = items or {}
if isHttp() then
local tag = ordered and "ol" or "ul"
local out = "<" .. tag .. ">"
for _, v in ipairs(items) do
out = out .. "<li>" .. esc(v) .. "</li>"
end
out = out .. "</" .. tag .. ">"
return out
elseif isGemini() then
local out = {}
for i, v in ipairs(items) do
if ordered then
table.insert(out, i .. ". " .. v)
else
table.insert(out, "* " .. v)
end
end
return table.concat(out, "\n")
end
end
if content == nil then
out[#out + 1] = " />"
return table.concat(out)
M.blockquote = function(s)
s = s or ""
if isHttp() then
return "<blockquote>" .. esc(s) .. "</blockquote>"
elseif isGemini() then
return "> " .. s
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)
M.rule = function()
if isHttp() then
return "<hr />"
elseif isGemini() then
return "---"
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)
M.image = function(alt, src)
alt = alt or ""
src = src or ""
if isHttp() then
return "<img src=\"" .. esc(src) .. "\" alt=\"" .. esc(alt) .. "\" />"
elseif isGemini() then
return "=> " .. src .. " " .. alt
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)
M.file = function(text, url)
text = text or ""
url = url or ""
if isHttp() then
return "<a href=\"" .. esc(url) .. "\" download>" .. esc(text) .. "</a>"
elseif isGemini() then
return "=> " .. url .. " " .. text
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