PPysolate SpineREAD THE CODE · UNDERSTAND THE SYSTEM
课程与章节
源码索引 / CURRENT IMPLEMENTATION

site/src/pages/[slug].astro

23 行 · 点击行号可定位;函数链接随声明位置更新,不手填行号。

---
import { getCollection, render } from 'astro:content';
import Layout from '../layouts/Docs.astro';
import nav from '../../.generated/navigation.json'; import { lessons } from '../lessons/catalog'; import { readingLinks } from '../components/lesson-player/validate.mjs';
export async function getStaticPaths() {
  return (await getCollection('docs')).map(entry=>({params:{slug:entry.id},props:{entry}}));
}
const { entry } = Astro.props;
const { Content, headings } = await render(entry);
const group = nav.filter(p=>p.section===entry.data.section);
const index = group.findIndex(p=>p.slug===entry.id); const audioLessons=lessons.filter(lesson=>readingLinks(lesson.episode).some(link=>link.href.split('#')[0]===`/${entry.id}/`));
const previous = group[index-1], next = group[index+1];
---
<Layout title={entry.data.title} description={entry.data.description} headings={headings}>
  <div class="eyebrow">{entry.data.section==='deep'?'DEEP DIVE':entry.data.section==='patterns'?'GO PATTERNS':entry.data.section==='reading'?'CODE READING':entry.data.section==='basics'?'FOUNDATIONS':entry.data.section==='research'?'RESEARCH EXPLORATION':'IMPLEMENTATION'} / {String(entry.data.section==='implementation'?index+1:index).padStart(2,'0')}</div>
  <h1>{entry.data.title}</h1><p class="lede">{entry.data.description}</p>
  <details class="page-jump"><summary>本章目录</summary><nav>{headings.filter(h=>h.depth===2).map(h=><a href={`#${h.slug}`}>{h.text}</a>)}</nav></details>
  {audioLessons.length>0 && <details class="notice" aria-label="对应饭点课"><summary>配套饭点图解 · {audioLessons.length} 节(按需展开)</summary><ul>{audioLessons.map(({episode})=><li><a href={`/listen/${episode.id}/`}>{episode.kind==='flow'?'流程课':'知识小点'} · {episode.title}</a></li>)}</ul></details>}<article class="prose"><Content /></article>
  <nav class="page-steps" aria-label="章节顺序">
    {previous && <a href={`/${previous.slug}/`}><small>← 上一章</small><strong>{previous.title}</strong></a>}
    {next && <a href={`/${next.slug}/`}><small>下一章 →</small><strong>{next.title}</strong></a>}
  </nav>
</Layout>