@@ -28,23 +28,58 @@ export async function getStaticPaths() {
2828 });
2929 }
3030
31+ // Pre-compute sorted chapter list per title for cross-chapter nav
32+ const titleChapters = new Map <number , number []>();
33+ for (const [key] of byTitleChapter ) {
34+ const [titleStr, chapterStr] = key .split (' -' );
35+ const titleNum = parseInt (titleStr ?? ' 0' , 10 );
36+ const chapterNum = parseInt (chapterStr ?? ' 0' , 10 );
37+ if (! titleChapters .has (titleNum )) titleChapters .set (titleNum , []);
38+ titleChapters .get (titleNum )! .push (chapterNum );
39+ }
40+ for (const [, chapters] of titleChapters ) {
41+ chapters .sort ((a , b ) => a - b );
42+ }
43+
3144 return entries .map ((entry ) => {
3245 const key = ` ${entry .data .usc_title }-${entry .data .chapter } ` ;
3346 const chapterSiblings = byTitleChapter .get (key ) ?? [];
47+ const titleNum = entry .data .usc_title ;
48+ const chapterNum = entry .data .chapter ;
49+ const chapters = titleChapters .get (titleNum ) ?? [];
50+ const chapterIdx = chapters .indexOf (chapterNum );
51+
52+ // Cross-chapter boundary links
53+ let prevChapterLast: typeof entry | null = null ;
54+ let nextChapterFirst: typeof entry | null = null ;
55+
56+ if (chapterIdx > 0 ) {
57+ const prevCh = chapters [chapterIdx - 1 ];
58+ const prevEntries = byTitleChapter .get (` ${titleNum }-${prevCh } ` ) ?? [];
59+ prevChapterLast = prevEntries .length > 0 ? prevEntries [prevEntries .length - 1 ] ?? null : null ;
60+ }
61+ if (chapterIdx < chapters .length - 1 ) {
62+ const nextCh = chapters [chapterIdx + 1 ];
63+ const nextEntries = byTitleChapter .get (` ${titleNum }-${nextCh } ` ) ?? [];
64+ nextChapterFirst = nextEntries .length > 0 ? nextEntries [0 ] ?? null : null ;
65+ }
66+
3467 return {
3568 params: { slug: entry .id },
36- props: { entry , chapterSiblings },
69+ props: { entry , chapterSiblings , prevChapterLast , nextChapterFirst },
3770 };
3871 });
3972}
4073
41- const { entry, chapterSiblings } = Astro .props ;
74+ const { entry, chapterSiblings, prevChapterLast, nextChapterFirst } = Astro .props ;
4275const { Content } = await render (entry );
4376
44- // Compute prev/next section links
77+ // Compute prev/next section links (with cross-chapter fallback)
4578const currentIdx = chapterSiblings .findIndex ((s : typeof entry ) => s .id === entry .id );
46- const prevSection = currentIdx > 0 ? chapterSiblings [currentIdx - 1 ] : null ;
47- const nextSection = currentIdx < chapterSiblings .length - 1 ? chapterSiblings [currentIdx + 1 ] : null ;
79+ const prevSection = currentIdx > 0 ? chapterSiblings [currentIdx - 1 ] : prevChapterLast ;
80+ const nextSection = currentIdx < chapterSiblings .length - 1 ? chapterSiblings [currentIdx + 1 ] : nextChapterFirst ;
81+ const prevIsCrossChapter = currentIdx === 0 && !! prevChapterLast ;
82+ const nextIsCrossChapter = currentIdx === chapterSiblings .length - 1 && !! nextChapterFirst ;
4883
4984const { usc_title, usc_section, chapter, classification, current_through, generated_at } = entry .data ;
5085
@@ -314,14 +349,14 @@ const readingTimeMin = Math.max(1, Math.round(wordCount / 200));
314349 <nav class =" not-prose mt-8 flex items-center justify-between border-t border-gray-200 pt-4 font-sans dark:border-gray-800" aria-label =" Section navigation" >
315350 { prevSection ? (
316351 <a href = { ` ${base }statute/${prevSection .id }/ ` } class = " flex flex-col gap-0.5 rounded-lg px-3 py-2 transition-colors hover:bg-warm-gray dark:hover:bg-gray-800 max-w-[45%]" >
317- <span class = " text-[11px] text-gray-400" >← Previous</span >
352+ <span class = " text-[11px] text-gray-400" >← Previous{ prevIsCrossChapter ? ` (Ch. ${ prevSection . data . chapter }) ` : ' ' } </span >
318353 <span class = " text-sm font-medium text-teal" >§ { prevSection .data .usc_section } </span >
319354 <span class = " truncate text-xs text-gray-500" >{ prevSection .data .title .replace (/ ^ Section \S + - / , ' ' )} </span >
320355 </a >
321356 ) : <span ></span >}
322357 { nextSection ? (
323358 <a href = { ` ${base }statute/${nextSection .id }/ ` } class = " flex flex-col items-end gap-0.5 rounded-lg px-3 py-2 transition-colors hover:bg-warm-gray dark:hover:bg-gray-800 max-w-[45%] ml-auto text-right" >
324- <span class = " text-[11px] text-gray-400" >Next → </span >
359+ <span class = " text-[11px] text-gray-400" >Next{ nextIsCrossChapter ? ` (Ch. ${ nextSection . data . chapter }) ` : ' ' } → </span >
325360 <span class = " text-sm font-medium text-teal" >§ { nextSection .data .usc_section } </span >
326361 <span class = " truncate text-xs text-gray-500" >{ nextSection .data .title .replace (/ ^ Section \S + - / , ' ' )} </span >
327362 </a >
0 commit comments