From 4bd920b09f8f33a6e3f6da980407409d14f34aa1 Mon Sep 17 00:00:00 2001 From: vx-clutch Date: Fri, 13 Feb 2026 21:40:08 -0500 Subject: [PATCH] update api to use "blocks" for future protocols --- lib/fes.lua | 462 +++++++++++-------------------------- lib/std.lua | 285 +++++++++-------------- lib/util.lua | 7 - modules/version/version.go | 2 +- 4 files changed, 246 insertions(+), 510 deletions(-) diff --git a/lib/fes.lua b/lib/fes.lua index 3b37930..f4cd0a3 100644 --- a/lib/fes.lua +++ b/lib/fes.lua @@ -4,7 +4,111 @@ local symbol = require("lib.symbol") local M = {} M.__index = M -function M.fes(header, footer) +local default_html_header = [[ + + + + + +{{FAVICON}} +{{TITLE}} + + + +
+]] + +local default_html_footer = [[ + +
+ + +]] + +local default_gemini_header = [[ +]] + +local default_gemini_footer = [[ +=> https://git.vxserver.dev/fSD/fes Fes Powered +=> https://www.lua.org Lua Powered +=> https://git.vxserver.dev/fSD/fes/src/branch/main/LICENSE ISC Licensed +{{COPYRIGHT}} +]] + +function M.fes(proto, header, footer) + proto = proto or "http" + std.proto = proto + local config = {} local site_config = {} local fes_mod = package.loaded.fes @@ -15,8 +119,22 @@ function M.fes(header, footer) end end - if site_config.favicon then - site_config.favicon = '' + if proto == "http" and site_config.favicon then + site_config.favicon = + '' + end + + local default_header + local default_footer + + if proto == "http" then + default_header = default_html_header + default_footer = default_html_footer + elseif proto == "gemini" then + default_header = default_gemini_header + default_footer = default_gemini_footer end local self = { @@ -24,348 +142,38 @@ function M.fes(header, footer) title = site_config.title, copyright = site_config.copyright, favicon = site_config.favicon, - header = header or [[ - - - - - -{{FAVICON}} -{{TITLE}} - - - -
-]], - footer = footer or [[ - -
- - -]], + header = header or default_header, + footer = footer or default_footer, parts = {}, + proto = proto, } return setmetatable(self, M) end -function M:g(str) - table.insert(self.parts, str) - return self -end - -function M:extend(name, tbl) - if type(name) ~= "string" then - error("First argument to extend must be a string (namespace name)") - end - if type(tbl) ~= "table" then - error("Second argument to extend must be a table of functions") - end - self[name] = {} - for k, v in pairs(tbl) do - if type(v) ~= "function" then - error("Extension values must be functions, got " .. type(v) .. " for key " .. k) - end - self[name][k] = function(...) - return v(self, ...) - end - end +function M:raw(str) + table.insert(self.parts, (str or "") .. "\n") return self end for name, func in pairs(std) do if type(func) == "function" then M[name] = function(self, ...) - local result = func(...) - table.insert(self.parts, result) + table.insert(self.parts, func(...)) return self end end end function M:build() - local header = self.header - header = header:gsub("{{TITLE}}", self.title or "Document") - local favicon_html = self.favicon and ('') - header = header:gsub( - "{{FAVICON}}", - favicon_html - or - [[]] - ) - local footer = self.footer:gsub("{{COPYRIGHT}}", - self.copyright or symbol.legal.copyright .. "The Copyright Holder") - return header .. table.concat(self.parts, "\n") .. footer + if self.proto == "http" then + local header = self.header:gsub("{{TITLE}}", self.title or "Document") + local favicon_html = self.favicon or '' + header = header:gsub("{{FAVICON}}", favicon_html) + local footer = self.footer:gsub("{{COPYRIGHT}}", self.copyright or symbol.legal.copyright .. "The Copyright Holder") + return header .. table.concat(self.parts, "\n") .. footer + end + return table.concat(self.parts, "\n") end M.__tostring = function(self) diff --git a/lib/std.lua b/lib/std.lua index 7d59e49..64fc5d5 100644 --- a/lib/std.lua +++ b/lib/std.lua @@ -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("&", "&") + s = s:gsub("<", "<") + s = s:gsub(">", ">") + return s +end + +M.p = function(s) + s = s or "" + if isHttp() then + return "

" .. esc(s) .. "

" + 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 "" .. esc(s) .. "" + elseif isGemini() then + return string.rep("#", level) .. " " .. s + end +end + +M.codeblock = function(s) + s = s or "" + if isHttp() then + return "
" .. esc(s) .. "
" + elseif isGemini() then + return "```\n" .. s .. "\n```" + end +end + +M.inline = function(s) + s = s or "" + if isHttp() then + return "" .. esc(s) .. "" + elseif isGemini() then + return "`" .. s .. "`" + end +end + +M.link = function(text, url) + text = text or "" + url = url or "" + if isHttp() then + return "" .. esc(text) .. "" + 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 .. "
  • " .. esc(v) .. "
  • " + end + out = out .. "" + 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 "
    " .. esc(s) .. "
    " + elseif isGemini() then + return "> " .. s end - - out[#out + 1] = ">" - out[#out + 1] = tostring(content) - 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 "
    " + 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 "\""" + 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 "" .. esc(text) .. "" + 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("&", "&") - str = str:gsub("<", "<") - str = str:gsub(">", ">") - str = str:gsub('"', """) - str = str:gsub("'", "'") - 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 diff --git a/lib/util.lua b/lib/util.lua index 63a5832..c53ad86 100644 --- a/lib/util.lua +++ b/lib/util.lua @@ -1,16 +1,9 @@ -local std = require("lib.std") -local symbol = require("lib.symbol") - local M = {} function M.cc(tbl, sep) return table.concat(tbl, sep or "") end -function M.copyright(link, holder) - return symbol.legal.copyright .. " " .. std.external(link, holder) -end - function M.ls(dir) local p = io.popen('ls -A -1 -- ' .. string.format('%q', dir)) if not p then diff --git a/modules/version/version.go b/modules/version/version.go index e4cec3a..036018e 100644 --- a/modules/version/version.go +++ b/modules/version/version.go @@ -9,7 +9,7 @@ var gitCommit string = "devel" const PROGRAM_NAME string = "fes" const PROGRAM_NAME_LONG string = "fes/fSD" -const VERSION string = "1.2.0" +const VERSION string = "2.0.0" func Version() { fmt.Printf("%s version %s\n", PROGRAM_NAME_LONG, VERSION)