aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-07-24 13:16:57 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-07-24 13:16:57 +0200
commit4c23ae5107690a77a4253eaecbb7dfa822bdffc3 (patch)
tree2935b0a534df0e189c49c9fad533bb79d096a636 /internal
parenta675a983424f1f8d103fc12d55ef4f7129a92d62 (diff)
downloadlectio-4c23ae5107690a77a4253eaecbb7dfa822bdffc3.tar.gz
lectio-4c23ae5107690a77a4253eaecbb7dfa822bdffc3.zip
web reader: fix chapter arrows (drive chap select) + mono (move #pane out of controls form)
Diffstat (limited to 'internal')
-rw-r--r--internal/web/server_test.go34
-rw-r--r--internal/web/templates/reader.html16
2 files changed, 44 insertions, 6 deletions
diff --git a/internal/web/server_test.go b/internal/web/server_test.go
index 77dfe74..638eb2b 100644
--- a/internal/web/server_test.go
+++ b/internal/web/server_test.go
@@ -406,3 +406,37 @@ func TestChooseListener(t *testing.T) {
}
})
}
+
+// TestReaderPaneOutsideForm guards the mono fix: #pane must render AFTER the
+// controls </form> so its reading text inherits body's --font-reading (which
+// the mono toggle flips) instead of the form's --font-ui.
+func TestReaderPaneOutsideForm(t *testing.T) {
+ srv := NewServer(config.Default())
+ rec := httptest.NewRecorder()
+ srv.ServeHTTP(rec, httptest.NewRequest("GET", "/reader", nil))
+ b := rec.Body.String()
+ f := strings.Index(b, "</form>")
+ p := strings.Index(b, `id="pane"`)
+ if f < 0 || p < 0 || p < f {
+ t.Errorf("#pane must render after </form> (form@%d pane@%d)", f, p)
+ }
+}
+
+// TestReaderArrowsDriveChapSelect guards the chapter-nav fix: the arrows drive
+// the chap <select> (single source of truth) rather than a competing hx-vals
+// "chap" param, and the server renders the requested book+chapter.
+func TestReaderArrowsDriveChapSelect(t *testing.T) {
+ srv := NewServer(config.Default())
+ rec := httptest.NewRecorder()
+ srv.ServeHTTP(rec, httptest.NewRequest("GET", "/reader?book=Luke&chap=12", nil))
+ b := rec.Body.String()
+ if !strings.Contains(b, "select[name=chap]") {
+ t.Errorf("chapter arrows should drive the chap <select>")
+ }
+ if strings.Contains(b, `hx-vals='{"chap"`) {
+ t.Errorf("chapter arrows must not use a competing hx-vals chap param")
+ }
+ if !strings.Contains(b, "Luke 12") {
+ t.Errorf("server did not render the requested Luke 12")
+ }
+}
diff --git a/internal/web/templates/reader.html b/internal/web/templates/reader.html
index c82d08e..921016a 100644
--- a/internal/web/templates/reader.html
+++ b/internal/web/templates/reader.html
@@ -27,16 +27,17 @@
</select>
</label>
+ {{/* Arrows drive the chapter <select> (the single source of truth) and
+ fire its change, so navigation always carries the CURRENT book +
+ target chapter -- no duplicate "chap" param from a competing hx-vals. */}}
<span class="chap-nav">
- <button type="button" hx-get="/reader" hx-target="#reader-root" hx-select="#reader-root"
- hx-swap="outerHTML" hx-vals='{"chap":"{{.PrevChap}}"}'>&larr;</button>
+ <button type="button" onclick="var s=this.closest('.controls').querySelector('select[name=chap]');s.value='{{.PrevChap}}';s.dispatchEvent(new Event('change',{bubbles:true}));">&larr;</button>
<label>{{.L.WebChapter}}
<select name="chap">
{{range .ChapOpts}}<option value="{{.N}}" {{if .Selected}}selected{{end}}>{{.N}}</option>{{end}}
</select>
</label>
- <button type="button" hx-get="/reader" hx-target="#reader-root" hx-select="#reader-root"
- hx-swap="outerHTML" hx-vals='{"chap":"{{.NextChap}}"}'>&rarr;</button>
+ <button type="button" onclick="var s=this.closest('.controls').querySelector('select[name=chap]');s.value='{{.NextChap}}';s.dispatchEvent(new Event('change',{bubbles:true}));">&rarr;</button>
</span>
{{range .VersionOpts}}
@@ -50,9 +51,12 @@
<option value="interlinear" {{if eq .Display "interlinear"}}selected{{end}}>{{.L.OptInterlinear}}</option>
</select>
</label>
-
- <div id="pane">{{.Reading}}</div>
</form>
+
+ {{/* #pane is OUTSIDE the form so its reading text inherits body's
+ --font-reading (mono-responsive), not the form's --font-ui. It stays
+ inside #reader-root so an hx-select swap re-renders it with the controls. */}}
+ <div id="pane">{{.Reading}}</div>
</div>
<label class="theme-picker">{{.L.Theme}}