' .. EscapeHtml(post.title) .. '
' .. '' .. '' .. EscapeHtml(summary) .. '
' .. '' .. tags_html .. '-- ui.lua — shared HTML component builders. -- -- Pure functions: data in, HTML string out. No DB access here; route -- handlers query and pass rows in. local web = require "web" local M = {} -- ── Tag pills ───────────────────────────────────────────────────────── -- Render tag pills for a list of tag strings. -- kind scopes the filter link to that section ("blog" filters on the feed at /). -- htmx=true → include hx-get/hx-target/hx-swap for list pages (where #post-list exists) -- htmx=false → plain href links only, for detail pages (no #post-list in DOM) function M.tag_pills(tags_list, kind, htmx) if #tags_list == 0 then return "" end -- Blog tag filters live on the front-page feed; wiki keeps its section page. local base = (kind == "blog") and "/" or ("/" .. kind) local search_path = "/" .. kind .. "/search" local sep = (base == "/") and "?" or "?" local pills = {} for _, tag in ipairs(tags_list) do local pill = '' .. EscapeHtml(tag) .. '' pills[#pills+1] = pill end return table.concat(pills, " ") end -- Render the tag cloud for a list page (with active-tag state). -- tags_list is the output of db.list_tags(kind). function M.tag_cloud(tags_list, kind, active_tag) if #tags_list == 0 then return "" end local base = (kind == "blog") and "/" or ("/" .. kind) local search_path = "/" .. kind .. "/search" local pills = {} for _, t in ipairs(tags_list) do local is_active = t.tag == active_tag local cls = is_active and "tag-pill tag-pill-active" or "tag-pill" -- Active tag: clicking clears the filter. local qs = "tag=" .. EscapePath(t.tag) local href = is_active and base or (base .. "?" .. qs) local hx_get = is_active and search_path or (search_path .. "?" .. qs) pills[#pills+1] = '' .. EscapeHtml(t.tag) .. '' end return '
' .. EscapeHtml(summary) .. '
' .. '' .. tags_html .. '