From 98c4fd331df0aa312329d66619bea95e9c1ad595 Mon Sep 17 00:00:00 2001 From: marvin Date: Tue, 15 Sep 2026 00:18:29 -0400 Subject: [PATCH] Add a live preview pane to Gateway Defaults for the themed page and Custom HTML (v0.11.91) --- package.json | 2 +- src/public/features.js | 26 ++++++++++++++++++++++++++ src/public/index.html | 19 ++++++++++++++----- src/public/styles.css | 2 +- 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 0cf5ddd..5ce587b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "site-gateway", - "version": "0.11.90", + "version": "0.11.91", "private": true, "description": "Site Gateway: simple self-hosted website publishing, reverse proxying, and automatic HTTPS.", "type": "module", diff --git a/src/public/features.js b/src/public/features.js index f29e9a1..9339f71 100644 --- a/src/public/features.js +++ b/src/public/features.js @@ -47,8 +47,34 @@ function renderDefaultSettings() { if (!document.querySelector("#default-site-help")) { const help = document.createElement("p"); help.id = "default-site-help"; help.className = "muted"; help.textContent = "The Default Site handles unknown HTTP hostnames. HTTPS requests still require a matching host and certificate."; form.prepend(help); } for (const key of ["mode","title","message","redirectUrl","redirectCode","customHtml"]) if (form.elements[key] && value[key] !== undefined) form.elements[key].value = value[key]; form.elements.preservePath.checked = value.preservePath !== false; + renderDefaultSitePreview(); } +// Keep this HTML template in sync with the themed-page literal inside renderDefaultSiteHtml() +// in src/server.js -- duplicated here so the live preview below renders instantly, without a +// round trip to the server, on every keystroke. If the server template ever changes, this must +// be updated to match or the preview will silently drift from what visitors actually see. +function defaultSiteThemedHtml(title, message) { + const safeTitle = extendedEscape(title); + const safeMessage = extendedEscape(message); + return `${safeTitle}
SG
Site Gateway

${safeTitle}

${safeMessage}

Host. Proxy. Secure.
`; +} + +function renderDefaultSitePreview() { + const form = document.querySelector("#default-site-form"), frame = document.querySelector("#default-site-preview-frame"), note = document.querySelector("#default-site-preview-note"); + if (!form || !frame || !note) return; + const mode = form.elements.mode.value; + if (mode === "abort") { frame.closest(".default-site-preview-frame-wrap").classList.add("hidden"); note.classList.remove("hidden"); note.textContent = "No page is shown for this mode \u2014 the connection is closed immediately."; return; } + if (mode === "redirect") { frame.closest(".default-site-preview-frame-wrap").classList.add("hidden"); note.classList.remove("hidden"); const destination = form.elements.redirectUrl.value.trim(); note.textContent = destination ? `No page is shown for this mode \u2014 visitors are redirected to ${destination}.` : "No page is shown for this mode \u2014 enter a redirect destination above."; return; } + frame.closest(".default-site-preview-frame-wrap").classList.remove("hidden"); note.classList.add("hidden"); + if (mode === "custom") { frame.srcdoc = form.elements.customHtml.value || "

Enter Custom HTML above to preview it here.

"; return; } + const title = form.elements.title.value || (mode === "welcome" ? "Gateway ready" : "Route not found"); + const message = form.elements.message.value || "The gateway is responding, but this address has not been configured."; + frame.srcdoc = defaultSiteThemedHtml(title, message); +} +document.querySelector("#default-site-form")?.addEventListener("input", renderDefaultSitePreview); +document.querySelector("#default-site-form")?.addEventListener("change", renderDefaultSitePreview); + function renderHealthSettings() { if (!state.settings) return; const form = document.querySelector("#health-settings-form"), value = state.settings.certificateHealth || {}; for (const key of ["warningDays","criticalDays","staleMinutes"]) if (value[key] !== undefined) form.elements[key].value = value[key]; diff --git a/src/public/index.html b/src/public/index.html index 303c605..0bbea2d 100644 --- a/src/public/index.html +++ b/src/public/index.html @@ -7,7 +7,7 @@ Site Gateway - +