From b59ef914da404625caae3deca97cb030dc9ac1b1 Mon Sep 17 00:00:00 2001 From: Mark Wissink Date: Wed, 9 Sep 2026 10:24:27 -0400 Subject: [PATCH] Remove non-TLS support --- assets/boot.html | 79 ++++++++++------------------------ assets/js/app.js | 37 +++++----------- assets/js/render.js | 35 +++++++-------- assets/sw.js | 38 ++++++---------- assets/templates/bookmark.njk | 23 +++------- assets/templates/reference.njk | 5 +-- assets/templates/version.njk | 7 --- server.py | 30 +++++++------ utils/compile_bible.py | 5 +-- 9 files changed, 88 insertions(+), 171 deletions(-) diff --git a/assets/boot.html b/assets/boot.html index e736026..6d680ff 100644 --- a/assets/boot.html +++ b/assets/boot.html @@ -19,13 +19,22 @@ The pages on disk are fragments and the shell is a template, and it is the worker that puts them together. So this page has one job: register the worker and reload once it is running, which lands on the real app at the - address that was asked for. It is only ever seen once per device. --> + address that was asked for. It is only ever seen once per device. + + There is no fallback for a device that cannot install one. There used to + be -- this page loaded the renderer itself and composed the page in the + browser -- and it existed for one case: the app served over plain http:// + from a LAN address, which is not a secure context, so no worker can + register. This app is served over TLS, where that case cannot arise, and + the fallback was a second way of building every page that nothing + exercised. What is left when registration fails is a sentence saying so, + because there is nothing honest to show instead. -->

Preparing the offline copy…

+ pages on the device and needs JavaScript.

diff --git a/assets/js/app.js b/assets/js/app.js index 02c4a56..7341f81 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -1,7 +1,7 @@ // Page startup. // -// Pages arrive whole -- composed by the service worker, or by boot.html on the -// visit before there is one -- so there is nothing here that builds a page. +// Pages arrive whole -- the service worker composes every one of them -- so +// there is nothing here that builds a page. // What is left is the three things a composed document cannot do for itself: // put a swapped-in page where it belongs before it is painted, land the // reference picker where the reader asked to go, and tell the chrome when a @@ -94,11 +94,10 @@ } } - // A worker-composed page is an ordinary document and the browser scrolls to - // the anchor itself. One composed by boot.html is not: it replaced a - // document the browser had already finished with, so the fragment identifier - // has been spent. Repeating it costs nothing in the first case and is what - // makes a link to GEN#v1_1 land on the verse in the second. + // The browser scrolls to the anchor itself on a document it navigated to, + // so this is for the one it does not: a reload that landed on boot.html and + // was reloaded again into the real page. Costs nothing when the browser has + // already been there. function scrollToHash() { var el = hashTarget(); if (el) jumpTo(el); @@ -166,25 +165,12 @@ // // Toggling the class rather than the style because Bootstrap declares // .d-none !important, which an inline display would lose to. - // - // Only the digest line is missing on a page boot.html composed -- there was - // no worker to name a version -- so the element itself is always here. function showVersion() { var el = document.getElementById('app-version'); if (!el) return; el.classList.toggle('d-none', !document.querySelector('#content .index')); } - // api/bookmark has no origin server -- it is answered by the worker -- so - // there is nothing to ask until the worker is controlling this page. - // controller, not ready: ready can resolve a tick before clients.claim() - // takes effect, and a request sent in that gap reaches the network and 404s. - function whenControlled(fn) { - if (!('serviceWorker' in navigator)) return; - if (navigator.serviceWorker.controller) return fn(); - navigator.serviceWorker.addEventListener('controllerchange', fn, { once: true }); - } - // Deferred scripts run before DOMContentLoaded fires, so this always lands, // and it lands after htmx has processed the shell. document.addEventListener('DOMContentLoaded', function () { @@ -192,15 +178,12 @@ showVersion(); // Registered from the page it is going to serve, not from a page of its - // own: there is nothing to wait for and nothing to reload. This load is - // already the real app -- the worker installs alongside it, and takes over - // composing, the bookmark and the offline download from the next - // navigation on. + // own: this load is already the real app, composed by the worker that is + // controlling it. What this catches is the copy on disk having changed + // since -- the browser refetches sw.js, sees different bytes, and installs + // the new one alongside, which takes over from the next navigation on. if ('serviceWorker' in navigator) { navigator.serviceWorker.register('sw.js').catch(function () {}); } - whenControlled(function () { - document.body.dispatchEvent(new CustomEvent('worker-ready')); - }); }); })(); diff --git a/assets/js/render.js b/assets/js/render.js index 3d07404..44052cf 100644 --- a/assets/js/render.js +++ b/assets/js/render.js @@ -1,17 +1,15 @@ -// The renderer, shared by the two things that ever build a page: the service -// worker, which composes every navigation once it is installed, and boot.html, -// which composes the one navigation that arrives before there is a worker to -// do it. +// The renderer: the templates in templates/, and the two things sw.js does +// with them -- compose a fragment into the shell, and stand a notice in for a +// page that could not be delivered. // -// Sharing it is the whole point. A shell only the worker could build is what -// made a first visit show a spinner and reload; with the same templates and -// the same code reachable from the page, the first visit is already the app -// and the worker is what makes the second one fast and the hundredth one -// offline. +// A file of its own rather than more of sw.js because it is the half with +// nothing to do with the network: no routes, no caches, no requests. It was +// loaded by boot.html as well once, which composed pages in the browser for a +// device that could not install a worker; nothing but the worker builds a page +// now. // -// Loaded as a plain script by both -- importScripts in the worker, a