' local function page_title(title) return EscapeHtml(title) .. " \226\128\148 " .. EscapeHtml(config.get("site_title")) end --- Return a complete HTML document wrapping body_html in the site shell. --- Always returns a full page; callers check GetHeader("HX-Request") and --- call render.partial() instead when only a fragment is needed. function M.layout(title, body_html) local site_title = config.get("site_title") local safe_title = page_title(title) return "\n" .. '\n' .. "\n" .. '\n' .. '\n' .. "" .. safe_title .. "\n" .. '\n' .. THEME_INIT .. "\n" .. '\n' .. '\n' .. '\n' .. '\n' .. (radio_html() ~= "" and '\n' or "") .. "\n" .. "\n" .. nav_html() .. "\n" -- hx-boost on
makes every internal link inside page content -- (post cards, pagination, back-links, links in markdown) swap only -- #content, so the radio player
\n" .. footer_html() .. "\n" .. radio_html() .. "\n" .. "\n" .. "" end --- Return the fragment as-is for HTMX partial responses. function M.partial(fragment_html) return fragment_html end --- Smart dispatch: return the right response for the request type. --- --- Three cases: --- 1. Direct browser navigation → full layout (no HX-Request header) --- 2. Boosted navigation → a plus the replacement --- #content element only (HX-Request + HX-Boosted). htmx swaps it --- via outerHTML and picks the <title> out of the response; nav, --- footer, and the radio player are left untouched. --- 3. True HTMX fragment request → bare partial (HX-Request, no --- HX-Boosted; e.g. nav search input, editor preview, tag pills) --- --- All page-returning handlers should call this instead of checking --- GetHeader("HX-Request") themselves. function M.respond(title, body_html) if GetHeader("HX-Request") then if GetHeader("HX-Boosted") then return "<title>" .. page_title(title) .. "\n" .. MAIN_OPEN .. "\n" .. body_html .. "\n