resolve sequences from the directory tree

A bundle nested under another bundle is a member of that series (ADR-0033), so
`Site.Sequence` walks up to the nearest bundle ancestor and back down to its
members: ordered by `order` where set, then by name. Members resolve through the
language fallback, so a chapter with no Bengali variant still holds its place in
Bengali reading order instead of breaking prev/next.

One `.Sequence` field carries both shapes a theme needs. A landing page renders
`.Members` as an archive; a chapter renders `.Prev`/`.Next`, which are pointers
into `.Members` so `{{with}}` yields nothing at the ends. `Index == 0` is what
tells the two apart.

`Query` was deliberately not extended. A series ascends where `Run` descends, and
an order knob on `Query` is the config knob rule 6 bans; instead `Site.keys()`
came out so both iterate the index one way, deleting `Run`'s own dedupe map.

`draft` is not honoured: no bundle carries the field and nothing else excludes
drafts, so entry 19 adds it in both places at once. Recorded in content-model.md
rather than left implied.

state.md also corrects six inventory rows that had drifted before this change —
three LOC figures, the test total, `go.mod`, and two lines that were flatly wrong
("Dependencies: none", "goldmark is not yet imported"). The coupling gate proves
state.md changed with the code; it cannot prove the numbers are right.
This commit is contained in:
2026-08-01 02:23:35 +06:00
parent 50f3bd1942
commit 7789242185
10 changed files with 427 additions and 41 deletions
+5 -5
View File
@@ -17,7 +17,7 @@ func TestBundleRendersMarkdownIntoTheTheme(t *testing.T) {
if err != nil {
t.Fatal(err)
}
out, err := r.Bundle(b, "en", []string{"en"})
out, err := r.Bundle(b, "en", []string{"en"}, nil)
if err != nil {
t.Fatal(err)
}
@@ -41,7 +41,7 @@ func TestBundleWithoutTitleFallsBackToKey(t *testing.T) {
if err != nil {
t.Fatal(err)
}
out, err := r.Bundle(b, "en", []string{"en"})
out, err := r.Bundle(b, "en", []string{"en"}, nil)
if err != nil {
t.Fatal(err)
}
@@ -62,7 +62,7 @@ func TestSiteOverridesOneBlockAndInheritsTheRest(t *testing.T) {
if err != nil {
t.Fatal(err)
}
out, err := r.Bundle(b, "en", []string{"en"})
out, err := r.Bundle(b, "en", []string{"en"}, nil)
if err != nil {
t.Fatal(err)
}
@@ -90,7 +90,7 @@ func TestAListingOverrideDoesNotLeakIntoBundlePages(t *testing.T) {
if err != nil {
t.Fatal(err)
}
out, err := r.Bundle(b, "en", nil)
out, err := r.Bundle(b, "en", nil, nil)
if err != nil {
t.Fatal(err)
}
@@ -106,7 +106,7 @@ func TestSiteStylesheetReplacesTheReferenceOne(t *testing.T) {
t.Fatal(err)
}
b, _ := content.Parse("pages/x.md", []byte("hi\n"))
out, err := r.Bundle(b, "en", nil)
out, err := r.Bundle(b, "en", nil, nil)
if err != nil {
t.Fatal(err)
}