/** * src/lib/nav-href.ts — pure route-href resolver (#80 multi-book navigation). * * No `astro:content` import (mirrors chapter-sort.ts) so tsup can include it in * the DTS bundle without dragging Astro virtual modules into the build graph. * The nav components (Sidebar, ChapterNav, NavContent, …) call these helpers * instead of hardcoding the single-book `/chapters//` URL shape — so ONE set * of components serves both a single-book site (the default pattern) and a * multi-book consumer whose chapters render at `///`. * * Patterns are base-relative TOKEN STRINGS (a resolver *function* could not * survive the book-config virtual module's `JSON.stringify`, so the config * surface is a declarative string resolved here): * :id → entry.id verbatim, slashes preserved e.g. 'kg/01-intro' * :book → the entry's book name (see `bookField`), or '' e.g. 'kg' * :slug → entry.id with a leading '/' stripped e.g. '01-intro' * BASE_URL is applied here, so patterns are written base-relative (lead '/'). * * Defaults reproduce the single-book behavior BYTE-FOR-BYTE: * chapterRoute = '/chapters/:id/' → `${base}chapters/${id}/` * bookField = 'book' (academic/tools schemas have no `book` → bookOf * returns null → "show all chapters", today's nav) * apparatusRoute = '/:route/' → `${base}/` */ /** Minimal shape the resolver needs from a chapter collection entry. */ interface ChapterLike { id: string; data: Record; } /** * Normalize a base URL to exactly one trailing slash (`''`/`undefined` → `'/'`). * * v4.27.0 (#182): promoted from this module's private helper to THE shared * normalizer — 18 `.astro` files previously inlined the same normalization in * three regex idioms. Astro does not guarantee a trailing slash on `base` * (`'/foo'` is a documented form), so every `import.meta.env.BASE_URL` read * must pass through here before href composition: `${normalizeBase(...)}chapters/`. * Takes the base as a PARAMETER because src/lib ships pre-compiled in dist/, * where Vite's import.meta.env replacement cannot reach (see exam-manifest.ts). */ declare function normalizeBase(baseUrl: string | undefined): string; /** * The composing variant (#182): strip ALL trailing slashes (`'/'` → `''`, * `'/foo/'` → `'/foo'`) for `${baseNoSlash(...)}/answers`-style templates * where the literal supplies the slash (Rationale.astro's route detection). */ declare function baseNoSlash(baseUrl: string | undefined): string; /** * The entry's book name from `data[bookField]`, or `null` when absent/blank. * Single-book schemas (academic/tools/minimal) have no such field → `null`, * which callers read as "this is the only book — show every chapter". */ declare function bookOf(entry: ChapterLike, bookField?: string): string | null; /** `entry.id` with a leading `'/'` stripped (multi-book) or unchanged. */ declare function slugOf(entry: ChapterLike, bookField?: string): string; /** Resolve a chapter entry to a base-prefixed href via the `chapterRoute` pattern. */ declare function chapterHref(entry: ChapterLike, pattern?: string, baseUrl?: string, bookField?: string): string; /** * Resolve a per-book apparatus route (glossary / practice-exam / flashcards / * answers) to a base-prefixed href via the `apparatusRoute` pattern. */ declare function apparatusHref(route: string, book: string | null, pattern?: string, baseUrl?: string): string; /** Whether `entry` is the page at `currentPath` (trailing-slash tolerant). */ declare function isCurrentChapter(entry: ChapterLike, currentPath: string, pattern?: string, baseUrl?: string, bookField?: string): boolean; export { type ChapterLike, apparatusHref, baseNoSlash, bookOf, chapterHref, isCurrentChapter, normalizeBase, slugOf };