diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-07-23 15:00:17 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-07-23 15:00:17 +0200 |
| commit | aa6c9dad764089a3f0e287b5f90937e97dde3921 (patch) | |
| tree | 213f7f56bf3c5ca1db82f0eee7c482886fa9ce43 /internal/web/render_test.go | |
| parent | 66a17fda33e44e9022d6724f850323f754715259 (diff) | |
| download | lectio-aa6c9dad764089a3f0e287b5f90937e97dde3921.tar.gz lectio-aa6c9dad764089a3f0e287b5f90937e97dde3921.zip | |
web: horizontal/vertical/interlinear display modes + web_display config
Adds a display-layout option to lectio-web alongside the existing colour
themes:
- config: WebDisplay field (toml web_display), default "horizontal",
normalized on load via the new exported config.NormalizeDisplay
(unknown -> "horizontal", same lenient style as the other web_* fields).
- render: extracts the citation/ToEnglishRef resolution shared by
GatherVersion into an unexported resolveRef helper (GatherVersion's
signature/behavior unchanged) and adds GatherVerses(version, sec,
lectionary) returning raw bible.Verse structs plus a versified flag, for
column/interlinear alignment.
- web/render: RenderReadings gains a display parameter. "horizontal" is
the original stacked layout, byte-for-byte the same code path as
before. "vertical" reuses the same per-version column data in a
.display-vertical/.vcol grid (the CLI compare view, browser-side).
"interlinear" maps versions through render.OfflineVersions' pl->wuj
substitution (pl has no verse numbers), gathers GatherVerses per
version, and interleaves them by chapter:verse into .ilverse/.illine
blocks (ordered union of keys, first versified version's order first).
- server: adds a display <select> to the top bar wired into the existing
#controls HTMX form; a resolveQuery(cfg, r) helper replaces the
duplicated date/lectionary/all/versions(+now display) resolution in
indexHandler and readingsHandler.
- fold-in from the B2 review: indexHandler now populates indexData.Lookup
via a shared renderLookup(ref, versions) helper (also used by
lookupHandler), so a bookmarked "/?ref=...&v=..." link shows its
lookup result instead of an empty pane.
- base.css: layout-only rules for the two new modes (no colours; themes
stay colour-only).
go test ./..., go vet ./..., gofmt clean; go build ./cmd/lectio-web ok.
Diffstat (limited to 'internal/web/render_test.go')
| -rw-r--r-- | internal/web/render_test.go | 58 |
1 files changed, 56 insertions, 2 deletions
diff --git a/internal/web/render_test.go b/internal/web/render_test.go index 7ee666a..974c6f1 100644 --- a/internal/web/render_test.go +++ b/internal/web/render_test.go @@ -11,7 +11,7 @@ import ( func TestRenderReadings(t *testing.T) { secs := []liturgy.Section{{Heading: "Ewangelia (J 20, 1. 11-18)", PartID: "ewangelia"}} - html := string(RenderReadings(secs, []string{"wuj"}, "new")) + html := string(RenderReadings(secs, []string{"wuj"}, "new", "horizontal")) if !strings.Contains(html, "Ewangelia") || !strings.Contains(html, "class=") { t.Errorf("reading pane missing heading/classes: %q", html[:min(200, len(html))]) } @@ -45,7 +45,7 @@ func TestRenderReadingsEscapesScriptText(t *testing.T) { PartID: "pierwsze_czytanie", Paragraphs: [][]string{{"<script>alert(1)</script>"}}, }} - html := string(RenderReadings(secs, []string{"pl"}, "new")) + html := string(RenderReadings(secs, []string{"pl"}, "new", "horizontal")) if strings.Contains(html, "<script>alert(1)</script>") { t.Errorf("raw <script> leaked into rendered output: %q", html) } @@ -54,6 +54,60 @@ func TestRenderReadingsEscapesScriptText(t *testing.T) { } } +func TestRenderReadingsVertical(t *testing.T) { + secs := []liturgy.Section{{Heading: "Ewangelia (J 20, 1. 11-18)", PartID: "ewangelia"}} + html := string(RenderReadings(secs, []string{"wuj", "vul"}, "new", "vertical")) + if !strings.Contains(html, "display-vertical") { + t.Errorf("vertical output missing display-vertical container: %q", html[:min(300, len(html))]) + } + if !strings.Contains(html, "vcol") { + t.Errorf("vertical output missing vcol columns: %q", html[:min(300, len(html))]) + } + if !strings.Contains(html, "Wujek") || !strings.Contains(html, "Wulgata") { + t.Errorf("vertical output missing both version labels: %q", html[:min(300, len(html))]) + } +} + +func TestRenderReadingsInterlinear(t *testing.T) { + secs := []liturgy.Section{{Heading: "Ewangelia (J 20, 1. 11-18)", PartID: "ewangelia"}} + html := string(RenderReadings(secs, []string{"wuj", "vul"}, "new", "interlinear")) + if !strings.Contains(html, "ilverse") { + t.Errorf("interlinear output missing ilverse: %q", html[:min(300, len(html))]) + } + if !strings.Contains(html, `class="vnum"`) { + t.Errorf("interlinear output missing vnum: %q", html[:min(300, len(html))]) + } + // The first ilverse block should group both version labels under one key. + // Bound it by the next vnum span (each ilverse carries exactly one). + i := strings.Index(html, `class="vnum"`) + block := html[i:] + if j := strings.Index(html[i+1:], `class="vnum"`); j != -1 { + block = html[i : i+1+j] + } + if !strings.Contains(block, "Wujek") || !strings.Contains(block, "Wulgata") { + t.Errorf("first interlinear verse block missing both version labels: %q", block) + } +} + +func TestRenderReadingsInterlinearExcludesPL(t *testing.T) { + secs := []liturgy.Section{{Heading: "Ewangelia (J 20, 1. 11-18)", PartID: "ewangelia"}} + html := string(RenderReadings(secs, []string{"pl", "vul"}, "new", "interlinear")) + if strings.Contains(html, "Polski (niedziela.pl)") { + t.Errorf("interlinear output should substitute wuj for pl, not carry pl's label: %q", html[:min(300, len(html))]) + } + if !strings.Contains(html, "Wujek") { + t.Errorf("interlinear output should substitute wuj for pl: %q", html[:min(300, len(html))]) + } +} + +func TestRenderReadingsInterlinearNoVersifiedNote(t *testing.T) { + secs := []liturgy.Section{{Heading: "Bez odwoĊania", PartID: "ewangelia"}} + html := string(RenderReadings(secs, []string{"wuj"}, "new", "interlinear")) + if strings.Contains(html, "ilverse") { + t.Errorf("expected no ilverse blocks when nothing resolves: %q", html) + } +} + func TestUserTheme(t *testing.T) { dir := t.TempDir() t.Setenv("XDG_CONFIG_HOME", dir) |
