@@ -282,7 +282,7 @@ const copy = {
282282 brandLine : "AI Coding 工程工作流手册" ,
283283 plannerMode : "学习清单" ,
284284 scheduleMode : "学习计划" ,
285- readerMode : "章节阅读 " ,
285+ readerMode : "全文阅读 " ,
286286 navKicker : "Feynman Loop" ,
287287 navTitle : "19 章 · 36 天费曼间隔练习" ,
288288 navCopy : "每天一个新章,到期旧章按 2-3-5-7 间隔短复述。" ,
@@ -393,7 +393,7 @@ const copy = {
393393 brandLine : "AI coding engineering workflow" ,
394394 plannerMode : "Checklist" ,
395395 scheduleMode : "Plan" ,
396- readerMode : "Chapter Reader" ,
396+ readerMode : "Reader" ,
397397 navKicker : "Feynman Loop" ,
398398 navTitle : "19 Chapters · 36-Day Feynman Spacing" ,
399399 navCopy : "One new chapter per day; due reviews return on a 2-3-5-7 cadence." ,
@@ -1048,12 +1048,16 @@ function focusedChapterSection() {
10481048}
10491049
10501050function readerVisibleHeadings ( ) {
1051- const headings = state . headings . filter ( ( heading ) => heading . depth === 2 || heading . depth === 3 ) ;
1052- const section = focusedChapterSection ( ) ;
1053- if ( ! section ) return headings ;
1051+ return state . headings . filter ( ( heading ) => heading . depth === 2 || heading . depth === 3 ) ;
1052+ }
10541053
1055- const nodes = new Set ( section . nodes ) ;
1056- return headings . filter ( ( heading ) => nodes . has ( heading . element ) ) ;
1054+ function headingChapterIndex ( heading ) {
1055+ const section = state . chapterSections . find ( ( candidate ) => candidate . nodes . includes ( heading . element ) ) ;
1056+ return section ?. chapterIndex || null ;
1057+ }
1058+
1059+ function headingById ( id ) {
1060+ return state . headings . find ( ( heading ) => heading . id === id ) || null ;
10571061}
10581062
10591063function chapterPageText ( index ) {
@@ -2230,6 +2234,11 @@ function renderToc() {
22302234 const link = document . createElement ( "a" ) ;
22312235 link . href = `#${ heading . id } ` ;
22322236 link . className = `depth-${ heading . depth } ` ;
2237+ link . dataset . tocTarget = heading . id ;
2238+ const chapterIndex = headingChapterIndex ( heading ) ;
2239+ if ( chapterIndex ) {
2240+ link . dataset . tocChapter = String ( chapterIndex ) ;
2241+ }
22332242 link . textContent = heading . text ;
22342243
22352244 if ( query && ! heading . text . toLowerCase ( ) . includes ( query ) ) {
@@ -2243,7 +2252,7 @@ function renderToc() {
22432252
22442253function observeHeadings ( ) {
22452254 state . observer ?. disconnect ( ) ;
2246- const links = new Map ( [ ...els . toc . querySelectorAll ( "a" ) ] . map ( ( link ) => [ link . hash . slice ( 1 ) , link ] ) ) ;
2255+ const links = new Map ( [ ...els . toc . querySelectorAll ( "a" ) ] . map ( ( link ) => [ link . dataset . tocTarget || link . hash . slice ( 1 ) , link ] ) ) ;
22472256
22482257 state . observer = new IntersectionObserver (
22492258 ( entries ) => {
@@ -2287,6 +2296,25 @@ async function openChapter(chapterIndex) {
22872296 } , 40 ) ;
22882297}
22892298
2299+ async function openTocTarget ( id ) {
2300+ if ( state . guidePromise ) {
2301+ await state . guidePromise . catch ( ( ) => { } ) ;
2302+ }
2303+
2304+ const heading = headingById ( id ) ;
2305+ if ( ! heading ) return ;
2306+
2307+ const chapterIndex = headingChapterIndex ( heading ) ;
2308+ if ( chapterIndex ) {
2309+ setReaderFocus ( chapterIndex ) ;
2310+ }
2311+ setMode ( "reader" ) ;
2312+
2313+ window . setTimeout ( ( ) => {
2314+ heading . element . scrollIntoView ( { behavior : "smooth" , block : "start" } ) ;
2315+ } , 40 ) ;
2316+ }
2317+
22902318function showError ( error ) {
22912319 console . error ( error ) ;
22922320 const text = copy [ state . lang ] ;
@@ -2364,6 +2392,13 @@ document.addEventListener("click", (event) => {
23642392 return ;
23652393 }
23662394
2395+ const tocLink = event . target . closest ( "#toc-list a[href^='#']" ) ;
2396+ if ( tocLink ) {
2397+ event . preventDefault ( ) ;
2398+ openTocTarget ( tocLink . dataset . tocTarget || tocLink . hash . slice ( 1 ) ) ;
2399+ return ;
2400+ }
2401+
23672402 const link = event . target . closest ( "a[href]" ) ;
23682403 if ( ! link ) return ;
23692404 const href = link . getAttribute ( "href" ) ;
0 commit comments