Skip to content

Commit 7430cb1

Browse files
committed
Adjust reader TOC and chapter navigation
1 parent fdc7535 commit 7430cb1

3 files changed

Lines changed: 51 additions & 21 deletions

File tree

assets/site.js

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

10501050
function 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

10591063
function 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

22442253
function 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+
22902318
function 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");

assets/styles.css

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,17 +1186,12 @@ button:disabled {
11861186
}
11871187

11881188
.chapter-pager {
1189-
position: sticky;
1190-
top: calc(var(--topbar-offset) + var(--sidebar-offset) + 0.6rem);
1191-
z-index: 30;
11921189
display: grid;
11931190
grid-template-columns: repeat(2, minmax(0, 1fr));
11941191
gap: 0.75rem;
1195-
margin: 1rem 0 0;
1196-
padding: 0.65rem 0;
1197-
border-bottom: 1px solid var(--line);
1198-
background: rgb(246 250 248 / 92%);
1199-
backdrop-filter: blur(14px);
1192+
margin-top: 2rem;
1193+
padding-top: 1rem;
1194+
border-top: 1px solid var(--line);
12001195
}
12011196

12021197
.chapter-page-button {

index.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@
1919
<meta name="twitter:card" content="summary" />
2020
<link rel="canonical" href="https://lling0000.github.io/Vibe_coding_guide/" />
2121
<title>Vibe Coding Guide | AI Coding 工程工作流手册</title>
22-
<link rel="stylesheet" href="./assets/styles.css?v=20260617-schedule-pdf" />
22+
<link rel="stylesheet" href="./assets/styles.css?v=20260617-reader-bottom-nav" />
2323
<script defer src="https://cdn.jsdelivr.net/npm/dompurify@3.2.6/dist/purify.min.js"></script>
2424
<script defer src="https://cdn.jsdelivr.net/npm/marked@15.0.12/marked.min.js"></script>
2525
<script defer src="https://cdn.jsdelivr.net/npm/mermaid@11.4.1/dist/mermaid.min.js"></script>
2626
<script defer src="https://cdn.jsdelivr.net/npm/lucide@0.475.0/dist/umd/lucide.min.js"></script>
27-
<script defer src="./assets/site.js?v=20260617-schedule-pdf"></script>
27+
<script defer src="./assets/site.js?v=20260617-reader-bottom-nav"></script>
2828
</head>
2929
<body data-mode="planner">
3030
<div class="site-progress" aria-hidden="true">
@@ -52,7 +52,7 @@
5252
</button>
5353
<button type="button" class="segmented-button" data-mode="reader" aria-pressed="false">
5454
<i data-lucide="book-open-text" aria-hidden="true"></i>
55-
<span id="reader-mode-label">章节阅读</span>
55+
<span id="reader-mode-label">全文阅读</span>
5656
</button>
5757
</div>
5858

@@ -252,6 +252,8 @@ <h1 id="reader-title">把 AI Coding 变成可复用的工程工作流。</h1>
252252

253253
<div class="reader-shell">
254254
<div class="reader-column">
255+
<article id="guide-content" class="prose" aria-live="polite"></article>
256+
255257
<nav class="chapter-pager" id="chapter-pager" aria-label="Chapter navigation">
256258
<button type="button" class="chapter-page-button" id="prev-chapter-button">
257259
<i data-lucide="chevron-left" aria-hidden="true"></i>
@@ -268,8 +270,6 @@ <h1 id="reader-title">把 AI Coding 变成可复用的工程工作流。</h1>
268270
<i data-lucide="chevron-right" aria-hidden="true"></i>
269271
</button>
270272
</nav>
271-
272-
<article id="guide-content" class="prose" aria-live="polite"></article>
273273
</div>
274274

275275
<aside class="annotation-panel" id="annotation-panel" aria-labelledby="annotation-title">

0 commit comments

Comments
 (0)