@hutusi/amytis 1.14.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/.github/workflows/ci.yml +1 -1
  2. package/.github/workflows/publish.yml +2 -2
  3. package/CHANGELOG.md +42 -0
  4. package/CLAUDE.md +90 -219
  5. package/README.md +33 -1
  6. package/README.zh.md +33 -1
  7. package/TODO.md +10 -0
  8. package/bun.lock +205 -539
  9. package/content/books/sample-book/index.mdx +3 -0
  10. package/content/posts/code-block-features-showcase.mdx +223 -0
  11. package/content/series/rst-legacy/deeper-notes/images/test.svg +4 -0
  12. package/content/series/rst-legacy/deeper-notes/index.rst +15 -0
  13. package/content/series/rst-legacy/getting-started.rst +24 -0
  14. package/content/series/rst-legacy/index.rst +9 -0
  15. package/content/series/rst-readme/README.rst +9 -0
  16. package/content/series/rst-readme/readme-index-post.rst +10 -0
  17. package/content/series/rst-toctree/first-post.rst +6 -0
  18. package/content/series/rst-toctree/index.rst +10 -0
  19. package/content/series/rst-toctree/second-post.rst +6 -0
  20. package/content/series/rst-toctree-precedence/first-post.rst +6 -0
  21. package/content/series/rst-toctree-precedence/index.rst +12 -0
  22. package/content/series/rst-toctree-precedence/second-post.rst +6 -0
  23. package/docs/ALERTS.md +112 -0
  24. package/docs/ARCHITECTURE.md +239 -8
  25. package/docs/CODE-BLOCKS.md +238 -0
  26. package/docs/CONTRIBUTING.md +36 -0
  27. package/docs/guides/README.md +11 -0
  28. package/docs/guides/importing-vuepress-books.md +178 -0
  29. package/eslint.config.mjs +20 -6
  30. package/next.config.ts +2 -2
  31. package/package.json +52 -24
  32. package/packages/create-amytis/package.json +1 -1
  33. package/packages/create-amytis/src/index.test.ts +43 -1
  34. package/packages/create-amytis/src/index.ts +64 -8
  35. package/public/next-image-export-optimizer-hashes.json +14 -73
  36. package/scripts/build-pagefind.ts +172 -0
  37. package/scripts/copy-assets.ts +246 -56
  38. package/scripts/generate-code-group-icons.ts +79 -0
  39. package/scripts/generate-knowledge-graph.ts +2 -1
  40. package/scripts/render-rst.py +923 -0
  41. package/scripts/run-with-rst-python.ts +42 -0
  42. package/scripts/sync-vuepress-book.ts +499 -0
  43. package/src/app/[slug]/[postSlug]/page.tsx +20 -10
  44. package/src/app/[slug]/page/[page]/page.tsx +15 -0
  45. package/src/app/books/[slug]/{[chapter] → [...chapter]}/page.tsx +32 -10
  46. package/src/app/books/[slug]/page.tsx +67 -32
  47. package/src/app/globals.css +639 -94
  48. package/src/app/page.tsx +1 -1
  49. package/src/app/series/[slug]/page/[page]/page.tsx +74 -6
  50. package/src/app/series/[slug]/page.tsx +11 -13
  51. package/src/app/series/page.tsx +3 -3
  52. package/src/app/sitemap.ts +3 -3
  53. package/src/components/ArticleCopyCleaner.tsx +64 -0
  54. package/src/components/AuthorCard.tsx +25 -16
  55. package/src/components/BookMobileNav.tsx +44 -50
  56. package/src/components/BookSidebar.tsx +0 -0
  57. package/src/components/CodeBlock.test.tsx +93 -8
  58. package/src/components/CodeBlock.tsx +39 -101
  59. package/src/components/CodeBlockToolbar.tsx +88 -0
  60. package/src/components/CodeGroup.tsx +81 -0
  61. package/src/components/CoverImage.tsx +6 -2
  62. package/src/components/ExternalLinkIcon.tsx +15 -0
  63. package/src/components/FeaturedStoriesSection.tsx +3 -3
  64. package/src/components/GithubAlert.tsx +97 -0
  65. package/src/components/MarkdownRenderer.test.tsx +30 -4
  66. package/src/components/MarkdownRenderer.tsx +148 -24
  67. package/src/components/Mermaid.tsx +32 -1
  68. package/src/components/PostList.tsx +1 -1
  69. package/src/components/PostNavigation.tsx +13 -2
  70. package/src/components/PostSidebar.tsx +13 -2
  71. package/src/components/RstRenderer.test.tsx +93 -0
  72. package/src/components/RstRenderer.tsx +157 -0
  73. package/src/components/Search.tsx +18 -4
  74. package/src/components/SeriesCatalog.tsx +1 -1
  75. package/src/components/ShareBar.tsx +5 -0
  76. package/src/components/TocPanel.tsx +10 -2
  77. package/src/i18n/translations.ts +2 -0
  78. package/src/layouts/BookLayout.tsx +35 -4
  79. package/src/layouts/PostLayout.tsx +10 -2
  80. package/src/layouts/SimpleLayout.tsx +10 -3
  81. package/src/lib/code-group-icons.test.ts +78 -0
  82. package/src/lib/code-group-icons.ts +148 -0
  83. package/src/lib/image-utils.test.ts +19 -0
  84. package/src/lib/image-utils.ts +11 -0
  85. package/src/lib/markdown.test.ts +195 -14
  86. package/src/lib/markdown.ts +928 -254
  87. package/src/lib/normalize-vuepress-math.ts +118 -0
  88. package/src/lib/rehype-fence-meta.ts +22 -0
  89. package/src/lib/rehype-image-metadata.ts +2 -2
  90. package/src/lib/remark-book-chapter-links.ts +106 -0
  91. package/src/lib/remark-code-group.ts +54 -0
  92. package/src/lib/remark-github-alerts.test.ts +83 -0
  93. package/src/lib/remark-github-alerts.ts +65 -0
  94. package/src/lib/remark-vuepress-containers.ts +130 -0
  95. package/src/lib/rst-renderer.test.ts +355 -0
  96. package/src/lib/rst-renderer.ts +629 -0
  97. package/src/lib/rst.test.ts +350 -0
  98. package/src/lib/rst.ts +674 -0
  99. package/src/lib/series-redirects.ts +42 -0
  100. package/src/lib/shiki-rst.ts +185 -0
  101. package/src/lib/shiki.test.ts +153 -0
  102. package/src/lib/shiki.ts +292 -0
  103. package/src/lib/urls.ts +57 -0
  104. package/src/test-utils/render.ts +23 -0
  105. package/tests/fixtures/sync-vuepress-book/docs/.vuepress/config.js +43 -0
  106. package/tests/fixtures/sync-vuepress-book/docs/intro/welcome.md +7 -0
  107. package/tests/fixtures/sync-vuepress-book/docs/maths/linear/assets/diagram.png +1 -0
  108. package/tests/fixtures/sync-vuepress-book/docs/maths/linear/matrices.md +7 -0
  109. package/tests/fixtures/sync-vuepress-book/docs/maths/linear/vectors.md +9 -0
  110. package/tests/helpers/env.ts +19 -0
  111. package/tests/integration/book-chapter-links.test.ts +107 -0
  112. package/tests/integration/books-nested-toc.test.ts +176 -0
  113. package/tests/integration/books.test.ts +3 -2
  114. package/tests/integration/code-block-features.test.ts +188 -0
  115. package/tests/integration/code-group.test.ts +183 -0
  116. package/tests/integration/code-notation.test.ts +97 -0
  117. package/tests/integration/feed-utils.test.ts +13 -0
  118. package/tests/integration/github-alerts.test.ts +82 -0
  119. package/tests/integration/markdown-external-links.test.ts +103 -0
  120. package/tests/integration/normalize-vuepress-math.test.ts +149 -0
  121. package/tests/integration/reading-time-headings.test.ts +12 -14
  122. package/tests/integration/series-draft.test.ts +12 -5
  123. package/tests/integration/series.test.ts +93 -0
  124. package/tests/integration/sync-vuepress-book.test.ts +240 -0
  125. package/tests/integration/vuepress-containers.test.ts +107 -0
  126. package/tests/tooling/build-pagefind.test.ts +66 -0
  127. package/tests/tooling/new-post.test.ts +1 -1
  128. package/tests/unit/static-params.test.ts +166 -13
@@ -18,7 +18,7 @@ jobs:
18
18
  - name: Setup Bun
19
19
  uses: oven-sh/setup-bun@v1
20
20
  with:
21
- bun-version: latest
21
+ bun-version: 1.3.11
22
22
 
23
23
  - name: Install dependencies
24
24
  run: bun install --frozen-lockfile
@@ -19,7 +19,7 @@ jobs:
19
19
 
20
20
  - uses: oven-sh/setup-bun@v1
21
21
  with:
22
- bun-version: latest
22
+ bun-version: 1.3.11
23
23
 
24
24
  - run: bun install --frozen-lockfile
25
25
 
@@ -43,7 +43,7 @@ jobs:
43
43
 
44
44
  - uses: oven-sh/setup-bun@v1
45
45
  with:
46
- bun-version: latest
46
+ bun-version: 1.3.11
47
47
 
48
48
  - run: bun install --frozen-lockfile
49
49
 
package/CHANGELOG.md CHANGED
@@ -5,6 +5,48 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.16.0] - 2026-06-01
9
+
10
+ ### Added
11
+ - **VuePress Book Pipeline**: Books are now first-class with nested chapter ids and TOCs, a catch-all chapter route, collapsible sections in the chapter sidebar, book-level LaTeX/math, VuePress `:::container` admonitions, and inter-chapter links. Includes a new `bun run sync-vuepress-book` importer that handles frontmatter-less chapters and stale `.md` references gracefully.
12
+ - **Shiki Syntax Highlighting**: Replaced `react-syntax-highlighter`/Prism with a build-time Shiki pipeline across both Markdown/MDX and rST. Unknown fence languages now degrade to plaintext with a build-log warning instead of crashing the build, and any bundled Shiki language is lazy-loaded on demand.
13
+ - **Code-Group Tabs**: New `:::code-group` (Markdown) and `.. code-group::` (rST) directives render fenced blocks as switchable tabs, with auto-detected icons for languages, package managers, and config files.
14
+ - **Shiki Notation Comments**: Inline `// [!code focus]`, `[!code error]`, `[!code warning]`, `[!code highlight]`, and diff markers render with visual indicators inside code blocks.
15
+ - **GitHub-Flavored Alert Blockquotes**: `> [!NOTE]`, `> [!TIP]`, `> [!IMPORTANT]`, `> [!WARNING]`, `> [!CAUTION]` render as styled callouts in both Markdown and rST (admonition visual parity).
16
+ - **Reading Meta**: Word count appears alongside reading time on post and chapter headers, with Chinese localization (`5 分钟阅读`).
17
+ - **External Link Affordance**: Outward-arrow icon on external links, opened in a new tab.
18
+ - **Code Block Polish**: Real tab icons via Iconify for code-group headers, proper-case language labels, a more prominent highlighted-line background, and rST `:linenos:` / `:emphasize-lines:` / `:caption:` support.
19
+
20
+ ### Changed
21
+ - **Mermaid Diagrams** now render frameless by default — no outer border, padding, background, or shadow. Diagram SVGs use the full column width.
22
+ - **`showChapterExcerpt`** defaults to `false` on books; opt back in per-book.
23
+ - **Markdown Rendering Fidelity**: Single-line `$$ x $$` block math now expands and parses as display math; block math centers via `.katex-display`; VuePress inline `<img>` styling is preserved through import; KaTeX `unicodeTextInMathMode` warnings (noise on CJK math labels) are scoped-silenced.
24
+ - **Dependency Refresh**: TypeScript 5.9 → 6.0, ESLint 9 → 10 (config rewritten without `eslint-config-next`), Next.js + safe minor/patch sweep, `@types/node` 24 → 25, `pdf-to-img` 5 → 6.
25
+
26
+ ### Fixed
27
+ - **Hydration Mismatches**: Locale-bound text in `TocPanel`, `PostNavigation`, `PostSidebar`, and `ShareBar` no longer logs a hydration error on first paint for users whose stored locale differs from `siteConfig.i18n.defaultLocale`. Mermaid's mutation-prone wrapper is likewise marked.
28
+ - **Table Padding**: Restored horizontal padding on prose table cells (the earlier `:where()`-based override was silently stripped by Tailwind v4 / Lightning CSS; replaced with a plain descendant selector that survives compilation).
29
+ - **rST Fallback Parser**: Added rendering for `.. figure::`, line blocks, admonitions (including custom `.. cnote::` with caption), `:doc:` / `:ref:` / `:numref:` roles; suppresses `.. toctree::` from rendered body; normalizes escaped whitespace in inline rST.
30
+ - **React 19 Warnings**: Resolved `react-hooks/set-state-in-effect` warnings and silenced image-preload warnings for local images. Eager `CoverImage` variants are no longer deprioritized.
31
+ - **Copy-Paste UX**: Stripped per-paragraph backgrounds on article copy to prevent "striping" when pasting into rich-text editors. Clipboard-API guard before `preventDefault`.
32
+ - **Misc**: `<summary>` styled as an interactive link; code-group icon lookups via `Object.hasOwn`; shiki dedup state reset in `finally`; `<style>` element scoping for shiki output; book import edge cases (URI decode, Vue component warnings, fenced blocks in container normalizer, chapter image paths relative to parent dir).
33
+
34
+ ## [1.15.0] - 2026-04-12
35
+
36
+ ### Added
37
+ - **First-Class rST Support**: Added robust reStructuredText post and series support through the Python/docutils pipeline, including README-based series indexes and better handling of legacy rST metadata and content structure.
38
+ - **Legacy rST Link Resolution**: Added support for legacy `:doc:` references, including same-series and cross-series links, so migrated rST content can keep its internal navigation intact.
39
+
40
+ ### Changed
41
+ - **rST Rendering Fidelity**: Improved rST rendering parity with Markdown for links, tables, code blocks, images, and general article presentation, making legacy content feel native inside Amytis.
42
+ - **Series Ordering Accuracy**: Series listing pages now sort by the real newest post date in each series instead of assuming the first rendered post is the latest one.
43
+ - **Build Performance**: Significantly reduced rebuild cost by caching rendered rST output, preserving nested image optimizer caches, tightening asset sync behavior, reducing generated image width buckets, and skipping Pagefind work when exported HTML is unchanged.
44
+
45
+ ### Fixed
46
+ - **Legacy rST Edge Cases**: Fixed broken rST image rendering, restored docutils-based runtime rendering, accepted legacy single-digit date formats, improved adjacency/order handling for manually ordered rST series, and kept rST excerpts explicit when metadata omits them.
47
+ - **Image Optimizer Compatibility**: Prevented broken optimized URLs for local `.avif` and `.webp` sources by bypassing `next-image-export-optimizer` for those files in shared image renderers.
48
+ - **Create Amytis on Windows**: Fixed `create-amytis` scaffolding on Windows for releases containing Unicode paths by switching the Windows extraction path to ZIP + PowerShell. The scaffold package was also released separately as `create-amytis@0.1.2`.
49
+
8
50
  ## [1.14.0] - 2026-04-05
9
51
 
10
52
  ### Added
package/CLAUDE.md CHANGED
@@ -1,231 +1,102 @@
1
1
  # CLAUDE.md
2
2
 
3
- This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
3
+ Guidance for Claude Code in this repo. Rules, gotchas, and pointers not reference material.
4
4
 
5
- ## Project Overview
5
+ ## Project
6
6
 
7
- Amytis is a static "digital garden" blog built with Next.js 15+ (App Router), React 19, and Tailwind CSS v4. Content is authored in MDX/Markdown files and statically generated at build time. Features include series support, multi-language (i18n), configurable themes, and comments integration.
7
+ Amytis: static digital-garden blog (Next.js 16 App Router, React 19, Tailwind v4, static export). Content in MDX / Markdown (primary), rST (legacy support); everything resolves at build time. Package manager: bun.
8
8
 
9
- ## Commands
9
+ ## Essential commands
10
10
 
11
11
  ```bash
12
- # Development
13
- bun dev # Start dev server at localhost:3000
14
- bun run lint # Run ESLint
15
-
16
- # Testing
17
- bun test # Run all tests
18
- bun run test:unit # Run unit tests (src/)
19
- bun run test:int # Run integration tests
20
- bun run test:e2e # Run end-to-end tests
21
- bun run test:mobile # Run Playwright mobile compatibility tests (requires dev server)
22
- bun test path/to/file.test.ts # Run a single test file
23
-
24
- # Build
25
- bun run build # Full production build (copies assets, builds Next.js, optimizes images)
26
- bun run build:dev # Development build (no image optimization, faster) — also regenerates Pagefind search index in public/pagefind/
27
- bun run clean # Remove .next, out, public/posts directories
28
-
29
- # Deploy
30
- bun run deploy # Deploy out/ to Linux/nginx server via rsync+sshpass (reads .env.local)
31
-
32
- # Content creation
33
- bun run new "Post Title" # Create new post
34
- bun run new-series "Series Name" # Create new series
35
- bun run new-from-pdf doc.pdf # Create post from PDF
36
- bun run new-from-images ./photos # Create post from image folder
37
- bun run new-flow # Create today's flow note
38
- bun run add-series-redirects # Add redirectFrom to all series posts (for autoPaths migration)
39
- bun run add-series-redirects <series-slug> # Add redirectFrom to one series only
40
- bun run add-series-redirects --dry-run # Preview without writing
41
- bun run new-flow-from-chat # Import all new files from imports/chats/
42
- bun run sync-book # Sync chapters list for all books from disk
43
- bun run sync-book <slug> # Sync chapters list for one book
12
+ bun dev # dev server (Turbopack, http://localhost:3000)
13
+ bun run lint # ESLint
14
+ bun test # all tests
15
+ bun run build # production build (image optimization + Pagefind)
16
+ bun run build:dev # faster build; regenerates public/pagefind/ for search-in-dev
17
+ bun run clean # nuke .next, out, public/posts when caches misbehave
44
18
  ```
45
19
 
46
- ## Design Principles
47
-
48
- - **Strict build over silent runtime failure.** This is a statically exported site — all misconfiguration must be caught at build time. Prefer `throw` in `generateStaticParams` and similar build-time functions over silent skips or `console.warn`. Examples: `validateSeriesAutoPaths` throws on slug collisions; `redirectFrom` alias conflicts should throw rather than silently producing broken redirects.
49
-
50
- ## Architecture
51
-
52
- ### Data Flow
53
-
54
- 1. **Content source**: MDX/Markdown files in `content/posts/` and `content/series/`
55
- 2. **Data layer**: `src/lib/markdown.ts` - reads files with Node `fs`, parses frontmatter with `gray-matter`, validates with Zod
56
- 3. **Static generation**: Routes use `generateStaticParams` to pre-render at build time
57
- 4. **Rendering**: `react-markdown` with remark/rehype plugins for GFM, math (KaTeX), syntax highlighting, and Mermaid diagrams
58
-
59
- ### Key Files
60
-
61
- - `site.config.ts` - Site configuration (nav, social, pagination, themes, i18n, analytics, comments)
62
- - `src/lib/markdown.ts` - Data access layer with all content query functions
63
- - `src/lib/urls.ts` - Central URL helpers (`getPostUrl`, `getPostsBasePath`, `getSeriesCustomPaths`, etc.) — always use these instead of hardcoding `/posts/[slug]`
64
- - `src/lib/search-utils.ts` - Pure search utilities (URL type detection, date extraction, title cleaning, markdown stripping) shared by `Search` and the search index route
65
- - `src/app/globals.css` - Theme CSS variables and color palettes
66
- - `src/components/MarkdownRenderer.tsx` - MDX rendering with all plugins
67
- - `src/i18n/translations.ts` - Language strings for i18n
68
-
69
- ### Route Structure
70
-
71
- - `/` - Homepage with hero, featured series, featured posts, latest writing
72
- - `/posts/[slug]` - Individual post pages
73
- - `/posts/page/[page]` - Paginated post listing
74
- - `/series` - All series overview
75
- - `/series/[slug]` - Single series with its posts
76
- - `/series/[slug]/page/[page]` - Series pagination
77
- - `/tags` - Tag cloud with post counts
78
- - `/tags/[tag]` - Posts filtered by tag
79
- - `/authors/[author]` - Posts filtered by author
80
- - `/archive` - Chronological listing grouped by year/month
81
- - `/books` - All books overview
82
- - `/books/[slug]` - Single book with chapter listing
83
- - `/books/[slug]/[chapter]` - Individual chapter page
84
- - `/flows` - Flow notes listing (paginated)
85
- - `/flows/page/[page]` - Paginated flow listing
86
- - `/flows/[year]` - Flows filtered by year
87
- - `/flows/[year]/[month]` - Flows filtered by month
88
- - `/flows/[year]/[month]/[day]` - Single flow detail page
89
- - `/[slug]` - Static pages (about, subscribe, etc.) and custom posts/series listing pages
90
- - `/[prefix]/[slug]` - Posts at custom URL prefixes (e.g. `/articles/my-post`, `/weeklies/my-post`)
91
- - `/[prefix]/page/[page]` - Paginated listing at custom URL prefixes
92
-
93
- ### Content Structure
94
-
95
- **Posts** support two formats:
96
- - **Flat file**: `content/posts/my-post.mdx`
97
- - **Nested folder**: `content/posts/my-post/index.mdx` (allows co-located images in `./images/`)
98
-
99
- **Series** live in `content/series/[slug]/index.mdx` with optional `images/` folder for cover images.
100
-
101
- **Books** live in `content/books/[slug]/` with `index.mdx` for metadata and separate `.mdx` files per chapter. The `index.mdx` frontmatter defines chapter ordering with an optional parts structure.
102
-
103
- **Flows** (daily notes) live in `content/flows/YYYY/MM/DD.md` (or `.mdx`). Each flow has a date, title, excerpt, tags, and markdown content.
104
-
105
- Date-prefixed filenames (`2026-01-01-my-post.mdx`) extract dates automatically.
106
-
107
- ## Config Files
108
-
109
- There are two config files that must be kept in sync:
110
-
111
- - **`site.config.ts`** — the live config for this repo (i18n enabled; locale-aware fields use `{ en: '...', zh: '...' }` objects)
112
- - **`site.config.example.ts`** — single-language starter template shipped via `create-amytis`; locale-aware fields use plain strings; optional features (books, flow) default to disabled
113
-
114
- **Rule:** Any schema change to `site.config.ts` (new field, renamed field, type change) must be mirrored in `site.config.example.ts`. Locale-aware values (`string | Record<string, string>`) should use plain strings in the example.
115
-
116
- ## Configuration (`site.config.ts`)
117
-
118
- Key configuration options:
119
- - `nav` - Navigation links with weights
120
- - `social` - GitHub, Twitter, email links for footer
121
- - `series.navbar` - Series slugs to show in navbar dropdown
122
- - `series.customPaths` - Per-series custom URL prefix e.g. `{ 'weeklies': 'weeklies' }` → posts at `/weeklies/[slug]`
123
- - `pagination.posts`, `pagination.series` - Items per page
124
- - `themeColor` - 'default' | 'blue' | 'rose' | 'amber'
125
- - `hero` - Homepage hero title and subtitle
126
- - `i18n` - Default locale and supported locales
127
- - `featured.series` - Scrollable series: `scrollThreshold` (default: 2), `maxItems` (default: 6)
128
- - `featured.stories` - Scrollable stories: `scrollThreshold` (default: 1), `maxItems` (default: 5)
129
- - `analytics.providers` - array of enabled providers: `['umami', 'google']`; `[]` disables analytics
130
- - `comments.provider` - 'giscus' | 'disqus' | null
131
- - `feed.format` - 'rss' | 'atom' | 'both'
132
- - `feed.content` - 'full' | 'excerpt'
133
- - `feed.maxItems` - max feed items (0 = unlimited)
134
- - `footer.bottomLinks` - custom links in the footer bottom bar (ICP, cookie policy, etc.); `text` accepts plain string or `{ en, zh }` locale map
135
- - `posts.basePath` - Custom URL prefix for all posts (default: `'posts'`); e.g. `'articles'` → posts at `/articles/[slug]`
136
- - `posts.authors.default` - Fallback authors when a post has none set in frontmatter
137
- - `posts.authors.showInHeader` - Show author byline below post title (default: true)
138
- - `posts.authors.showAuthorCard` - Show author card at end of post (default: true)
139
- - `posts.excludeFromListing` - Series slugs whose posts are hidden from `/posts` listing pages
140
- - `authors` - Per-author profiles: `bio`, `avatar` (image path), `social` (array of `{ image, description }`)
141
-
142
- ## Content Frontmatter
143
-
144
- ### Posts
145
-
146
- ```yaml
147
- ---
148
- title: "Post Title"
149
- subtitle: "Optional subtitle line" # Rendered below the title in italic
150
- date: "2026-01-01"
151
- excerpt: "Optional summary (auto-generated if omitted)"
152
- category: "Category Name"
153
- tags: ["tag1", "tag2"]
154
- authors: ["Author Name"]
155
- series: "series-slug" # Link to a series
156
- draft: true # Hidden in production
157
- featured: true # Show in featured section
158
- pinned: true # Always shown in featured section; never shuffled away (hero = most recent pinned)
159
- coverImage: "./images/cover.jpg" # Local or external URL
160
- latex: true # Enable KaTeX math
161
- toc: false # Hide table of contents
162
- layout: "simple" # Use simple layout (default: "post")
163
- externalLinks: # Links to external discussions
164
- - name: "Hacker News"
165
- url: "https://news.ycombinator.com/item?id=12345"
166
- - name: "V2EX"
167
- url: "https://v2ex.com/t/123456"
168
- redirectFrom: # Old URLs that should redirect to this post (prefix changes only)
169
- - /posts/my-old-slug
170
- - /old-series/my-old-slug
171
- ---
172
- ```
20
+ Content-creation scripts, test layout, validate pipeline → `docs/CONTRIBUTING.md`.
173
21
 
174
- ### Series (`content/series/[slug]/index.mdx`)
175
-
176
- ```yaml
177
- ---
178
- title: "Series Title"
179
- excerpt: "Series description"
180
- date: "2026-01-01"
181
- coverImage: "./images/cover.jpg"
182
- featured: true # Show in featured series
183
- draft: true # Hidden in production (default: false)
184
- sort: "date-asc" # 'date-asc' | 'date-desc' | 'manual'
185
- posts: ["post-1", "post-2"] # Manual post ordering (optional)
186
- ---
187
- ```
22
+ ## Architecture map
188
23
 
189
- ### Books (`content/books/[slug]/index.mdx`)
190
-
191
- ```yaml
192
- ---
193
- title: "Book Title"
194
- excerpt: "Book description"
195
- date: "2026-01-01"
196
- coverImage: "text:DG" # Cover image or text placeholder
197
- featured: true # Show in featured books
198
- draft: false
199
- authors: ["Author Name"]
200
- chapters:
201
- - part: "Part I: Getting Started" # Optional part grouping
202
- chapters:
203
- - title: "Chapter Title"
204
- id: "chapter-file" # Maps to chapter-file.mdx or chapter-file/index.mdx
205
- - part: "Part II: Advanced"
206
- chapters:
207
- - title: "Another Chapter"
208
- id: "another-chapter"
209
- ---
210
- ```
24
+ Quick "where do routes live" lookup. Full reference: `docs/ARCHITECTURE.md`.
25
+
26
+ - Standard routes follow folder names under `src/app/`: `/posts`, `/series`, `/tags`, `/notes`, `/books`, `/authors`, `/archive`, `/graph`, `/flows/[year]/[month]/[day]`.
27
+ - **Top-level `[slug]` and `[slug]/[postSlug]`** resolve `redirectFrom` aliases and `series.customPaths` — highest-risk dynamic surface; touch with care.
28
+ - Feeds at `feed.xml` / `feed.atom` / `all.xml` / `all.atom` / `flows/feed.{xml,atom}`; sitemap at `sitemap.ts`; search index at `search.json`.
29
+ - Rendering pipeline lives in `src/lib/`: Shiki (`shiki.ts`, `shiki-rst.ts`), remark/rehype plugins (`remark-github-alerts`, `remark-wikilinks`, `remark-code-group`, `rehype-fence-meta`, `rehype-image-metadata`), redirects (`series-redirects.ts`), feeds/JSON-LD (`feed-utils.ts`, `json-ld.ts`).
30
+
31
+ ## Design principles
32
+
33
+ - **Strict build over silent runtime failure.** Static export means misconfiguration must fail at build time. Use `throw` in `generateStaticParams` and similar — never silent skips or `console.warn`. Precedent: `validateSeriesAutoPaths` throws on slug collisions; `redirectFrom` alias conflicts (reserved slug or duplicate) should also throw, not produce broken redirects.
34
+ - **Exception**: fence-language resolution in `src/lib/shiki.ts` deliberately degrades to `plaintext` + a deduped `console.warn` instead of throwing. Authors can't reliably predict Shiki's alias coverage, and "typo" vs "legitimate community alias" are indistinguishable from our side, so production deploys shouldn't fail on a single unhighlighted code block. Real typos still surface via the warn output in local/CI build logs.
35
+ - **Validate author input at build time; keep content portable.** Frontmatter via Zod; slug / redirect conflicts throw. Files on disk stay valid `.md` / `.mdx` / `.rst` — no Amytis-specific syntax that breaks other tools.
36
+
37
+ ## Integration-point rules (always go through X)
38
+
39
+ - **URLs:** always `getPostUrl()` / `getPostsBasePath()` / `getSeriesCustomPaths()` from `src/lib/urls.ts`. Never hardcode `/posts/[slug]` — posts may live at `/articles/[slug]`, custom prefixes (`series.customPaths`), or under `posts.basePath`.
40
+ - **Content reads:** always via `src/lib/markdown.ts` (`getAllPosts`, `getPostBySlug`, `getSeriesData`, etc.). Frontmatter validation belongs in its Zod schemas, not in route files.
41
+ - **Search utilities:** pure helpers (URL type detection, date extraction, title cleaning, markdown stripping) live in `src/lib/search-utils.ts` and are shared by the `Search` component and the search-index route. Don't duplicate them.
42
+ - **i18n strings:** add to `src/i18n/translations.ts`. Locale-aware config fields are `string | Record<string, string>`; resolve via `resolveLocale()` / `resolveLocaleValue()` from `src/lib/i18n.ts`.
43
+
44
+ ## Config sync
45
+
46
+ `site.config.ts` (this repo — i18n object form, `{ en, zh }`) and `site.config.example.ts` (shipped via `create-amytis` — plain strings, single-locale, optional features default disabled) must stay in sync. Any schema change to one must be mirrored in the other.
47
+
48
+ ## Gotchas (things Claude will get wrong on first try)
49
+
50
+ - **`turbopackIgnore` on fs reads.** Any `fs.readFileSync()` path expression must be preceded by `/* turbopackIgnore: true */` (see `src/lib/markdown.ts`, `src/lib/rehype-image-metadata.ts`). Missing it causes incorrect bundling.
51
+ - **No AVIF for `coverImage`.** Upstream bug in `next-image-export-optimizer` emits `.webp` files but a `srcset` pointing at `.avif` → 404 in prod. Use `.jpg` / `.png` / `.webp`. See `docs/TROUBLESHOOTING.md`.
52
+ - **Unicode slugs.** Dynamic route pages call `safeDecodeParam()` and try decoded / raw / NFC / NFD variants — don't shortcut with bare `decodeURIComponent()` (it throws on malformed input). When touching dynamic routes, verify both ASCII and Unicode slugs.
53
+ - **`generateStaticParams` returns raw values.** Don't `encodeURIComponent` route params; Next.js handles encoding. Don't link to placeholder routes like `/posts/[slug]` — always link to concrete URLs.
54
+ - **Series format is locked.** A series index can be `index.md` / `.mdx` / `README.md` / `README.mdx` / `index.rst` / `README.rst` (first match wins). All child posts must match. Mixing formats is a build error.
55
+ - **rST needs Python `docutils`.** Set `AMYTIS_RST_PYTHON=/path/to/python` if not on `$PATH`. Without it, falls back to a lower-fidelity built-in parser.
56
+ - **Pagefind index.** `bun run build:dev` regenerates `public/pagefind/`; search returns stale results until you rerun it after content changes.
57
+ - **`trailingSlash: true` is load-bearing.** Lets co-located post assets (`posts/slug/images/`) coexist with `posts/slug/index.html`. Don't flip it in `next.config.ts`.
58
+ - **Shiki highlighter is a `globalThis` singleton.** Never instantiate it per render — `createHighlighter` loads Oniguruma WASM + grammars (~1–2 s). See `src/lib/shiki.ts`.
59
+ - **rST sanitize-html allowlist must keep `style` + `data-*` on `pre`/`code`/`span`/`div`.** Stripping any of these silently kills Shiki output (monochrome text in prod, looks fine locally because dev rST isn't sanitized). See `src/components/RstRenderer.tsx`.
60
+ - **Bump `RST_RENDERER_DISK_CACHE_VERSION` (`src/lib/rst-renderer.ts`) on highlighter-output changes.** Stale on-disk caches in `.cache/rst-renderer/` will serve old markup otherwise. Run `rm -rf .cache/rst-renderer` after pulling such a change.
61
+ - **Fence meta needs `rehype-fence-meta` BEFORE `rehype-raw`.** `mdast-util-to-hast` stores fence meta on `node.data.meta`, which `rehype-raw` drops during HTML round-trip. The plugin copies it to a real `data-meta` attribute first. Order matters in `MarkdownRenderer.tsx`.
62
+ - **Code-group tabs add `<input type="radio">` + `<label>` to the rST sanitize-html allowlist.** Keep the `transformTags` guard in `RstRenderer.tsx` that strips any `<input>` whose `type !== "radio"` — that's the defense against an rST author injecting password/file/etc. inputs through raw HTML.
63
+ - **GitHub alerts (`> [!NOTE]`, etc.) need the custom `remarkGithubAlerts` plugin.** `remark-gfm` v4 does NOT transform `[!TYPE]` blockquotes — they pass through as plain blockquotes with the literal marker visible. The custom plugin in `src/lib/remark-github-alerts.ts` is what detects them and routes to `<GithubAlert>`. If a future remark-gfm adds native alert support, that's a regression to watch for (covered by an integration test).
64
+ - **Single-line block math `$$ x $$` is silently inline.** `micromark-extension-math` (under `remark-math` v6) requires the `$$` markers on their own lines — single-line collapses to *inline* math (no `katex-display` wrapper, no centering, no display margin) and looks like a subtly under-styled formula. `src/lib/normalize-vuepress-math.ts` expands single-line `$$ x $$` to opener / body / closer before parsing, so authored content stays portable. If a chapter formula stops centering, suspect the normalizer's regex first.
65
+
66
+ ## Development workflow
67
+
68
+ - **Don't push or open PRs unless asked.** Local commits are fine; anything touching the remote needs explicit go-ahead.
69
+ - **Commit in focused slices.** Keep `bun run validate` green at each commit so the branch stays bisectable.
70
+ - **Tests + docs in the same change.** Update `docs/ARCHITECTURE.md` / `docs/CONTRIBUTING.md` / `docs/TROUBLESHOOTING.md` alongside seam/workflow/invariant changes — not as a follow-up.
71
+ - **Commits** follow Conventional Commits: `feat | fix | refactor | perf | chore | docs | test | release`. Subject under ~70 chars; body explains *why*.
72
+ - **Branches:** `<type>/<kebab-slug>` matching commit prefixes.
73
+ - **No Claude attribution.** Do not add `Co-Authored-By: Claude ...` trailers to commit messages or the `🤖 Generated with [Claude Code]` footer to PR descriptions. The default templates in the harness include both — strip them.
74
+
75
+ ## Verifying a change
76
+
77
+ - **Default verify loop: `bun run lint && bun run test` only.** Stop here.
78
+ - **Do NOT run `bun run build:dev` (or `bun run build` / `bun run validate`) unless the user asks OR it is genuinely needed.** It takes ~1–2 minutes (Turbopack compile + 800+ static pages + Pagefind index) and the cost adds up fast across many small steps. None of these are "needed" on their own: markdown pipeline edits, schema changes, route moves, branch tip, pre-PR readiness, "just to be safe."
79
+ - "Genuinely needed" means lint+test **cannot** catch the failure mode you're worried about — e.g. a strict-build invariant that only fires during static export (a `throw` in `generateStaticParams`, a `redirectFrom` collision, a Zod-schema failure that only triggers on real content). If unsure, prefer asking over running.
80
+ - `bun run validate` chains lint + test + build:dev; same rule — same bar.
81
+ - Touched `src/lib/markdown.ts`, `src/lib/urls.ts`, or `site.config.ts`? Add an integration test under `tests/integration/`.
82
+ - Touched any dynamic route? Verify both ASCII and Unicode slugs render.
83
+
84
+ ## Context compression hints
85
+
86
+ When compressing history, preserve in priority order:
87
+
88
+ 1. **Build-time invariants touched** — strict-build/throw boundaries, Zod schemas, `site.config.ts` shape, helpers in `src/lib/urls.ts` / `src/lib/markdown.ts`.
89
+ 2. **Modified files and why** — file list with one-line reasons, not the diff.
90
+ 3. **Verification status** — `bun run lint && bun test` (and `build:dev` if run) pass/fail.
91
+ 4. **Cache version bumps** — `RST_RENDERER_DISK_CACHE_VERSION` etc.; easy to lose after compression.
92
+ 5. **Open TODOs and rollback notes.**
93
+ 6. **Tool output**: drop; keep pass/fail summary only.
94
+
95
+ ## Where to find more
211
96
 
212
- ## Key Components
213
-
214
- - `PostLayout` / `SimpleLayout` - Post page layouts with TOC, series sidebar, external links, comments
215
- - `Hero` - Configurable homepage hero section with collapsible intro
216
- - `HorizontalScroll` - Scrollable container with navigation arrows for featured content
217
- - `PostList` - Card-based post listing with thumbnails, metadata, excerpts, and tags
218
- - `SeriesCatalog` - Timeline-style series post listing with numbered entries and progress indicator
219
- - `SeriesSidebar` - Series navigation sidebar with progress bar and color-coded states
220
- - `SeriesList` - Mobile-optimized series navigation matching sidebar design
221
- - `Search` - Full-text search (Cmd/Ctrl+K) powered by Pagefind (build-time index); features type filter tabs (All/Post/Flow/Book), recent searches, keyboard navigation (arrows + number keys), debounced input, body scroll lock, focus trap, ARIA accessibility, and search syntax tips (`"phrase"`, `-exclude`)
222
- - `TableOfContents` - Sticky TOC with scroll tracking, reading progress, and back-to-top
223
- - `MarkdownRenderer` - MDX rendering with GFM, math, syntax highlighting, diagrams
224
- - `CoverImage` - Optimized image component with WebP support
225
- - `Comments` - Giscus or Disqus integration (theme-aware)
226
- - `Analytics` - Umami, Plausible, or Google Analytics integration
227
- - `FlowContent` - Client wrapper for flow pages with tag filtering state management
228
- - `FlowCalendarSidebar` - Calendar sidebar with date navigation, browse panel, and clickable tag filters
229
- - `FlowTimelineEntry` - Individual flow entry in timeline list
230
- - `LanguageSwitch` - i18n language selector
231
- - `ThemeToggle` - Light/dark mode toggle
97
+ - `docs/ARCHITECTURE.md` — route map, content model, components, data layer, frontmatter schemas, full configuration reference
98
+ - `docs/CONTRIBUTING.md` — full command list, test layout, content-creation scripts
99
+ - `docs/TROUBLESHOOTING.md` known issues (AVIF, dev-mode browser-extension CSP/SharedStorage noise)
100
+ - `docs/deployment.md` production deploy steps
101
+ - `docs/guides/` — task-oriented walkthroughs (e.g. `importing-vuepress-books.md`)
102
+ - `site.config.ts` live config (read it directly; don't infer from this file)
package/README.md CHANGED
@@ -44,6 +44,8 @@ Further reading: [How to Get AI to Write Better Code](https://hutusi.com/weeklie
44
44
  - **Full-text Search:** Fast, static client-side search across all content (Cmd/Ctrl+K) powered by Pagefind.
45
45
  - **Structured Content:**
46
46
  - **Series:** Multi-part content organization with manual or automatic ordering.
47
+ - **Legacy rST Series:** A series can opt into reStructuredText by using `index.rst` or `README.rst`; mixed Markdown and rST files in the same series fail the build.
48
+ - **Docutils-backed rST Rendering:** When `docutils` is available, rST series render through the Python/docutils path instead of the lightweight fallback parser.
47
49
  - **Books:** Long-form content with explicit chapters, parts, and a dedicated reading interface.
48
50
  - **Notes:** Atomic, evergreen concepts for personal knowledge management.
49
51
  - **Flows:** Stream-style daily notes or micro-blogging for quick thoughts.
@@ -213,6 +215,8 @@ Amytis is built around Next.js static export with `output: "export"` and `traili
213
215
  - Posts default to `/<posts.basePath>/<slug>` and `posts.basePath` defaults to `/posts`.
214
216
  - If `series.autoPaths` is enabled, series posts move to `/<series-slug>/<post-slug>`.
215
217
  - If `series.customPaths` is configured, those custom prefixes override `autoPaths`.
218
+ - Frontmatter `redirectFrom` entries are exported as static redirect pages so legacy URLs can keep working.
219
+ - Prefer URL helpers over hardcoded post paths, because a canonical post URL may live under `/posts`, a series slug, or a custom prefix depending on config.
216
220
  - Before moving series posts off the default posts path, run `bun run add-series-redirects --dry-run` and then `bun run add-series-redirects` so legacy URLs still resolve.
217
221
 
218
222
  ## Writing Content
@@ -236,11 +240,39 @@ Create daily notes in `content/flows/YYYY/MM/DD.md` or `.mdx`.
236
240
 
237
241
  ### Series
238
242
 
239
- Create a directory in `content/series/<slug>/` with an `index.mdx`, then add posts as sibling files or folders.
243
+ Create a directory in `content/series/<slug>/` with either:
244
+
245
+ - `index.mdx` or `index.md` for a Markdown series
246
+ - `index.rst` or `README.rst` for an rST series
247
+
248
+ `README.mdx` and `README.md` are also accepted as Markdown series indexes. Then add posts as sibling files or folders using the same format as the series index. Mixed Markdown and rST files in one series are rejected at build time.
240
249
 
241
250
  - CLI: `bun run new-series "Series Name"`
242
251
  - You can also create a post directly inside an existing series with `bun run new "Post Title" --series <series-slug>`
243
252
 
253
+ #### rST / docutils workflow
254
+
255
+ For full-fidelity rST rendering, install `docutils` in a Python environment that the project can execute:
256
+
257
+ ```bash
258
+ python3 -m pip install docutils pygments
259
+ ```
260
+
261
+ If you want Amytis to use a specific interpreter, point `AMYTIS_RST_PYTHON` at it:
262
+
263
+ ```bash
264
+ export AMYTIS_RST_PYTHON=/absolute/path/to/python
265
+ ```
266
+
267
+ Current behavior:
268
+
269
+ - `index.rst` or `README.rst` makes the whole series rST-only.
270
+ - For rST series ordering, explicit `:posts:` metadata takes precedence. If `:posts:` is absent, Amytis uses simple local `.. toctree::` entry order from the series index. If neither exists, the series falls back to the existing date-based sort.
271
+ - rST assets such as `.. image::` and `.. figure::` are resolved relative to the source file and rewritten to the site asset paths.
272
+ - Supported legacy roles such as `:doc:`, `:ref:`, `:numref:`, `:math:`, and `:dtag:` are either rendered directly or degraded into readable inline output instead of docutils error blocks.
273
+ - Top-of-file docinfo metadata is parsed into Amytis metadata, but it is not rendered at the top of blog-style article HTML.
274
+ - If Python/docutils is unavailable, Amytis falls back to the lightweight built-in rST compatibility path. That path keeps series loading working, but it has lower fidelity than the docutils-backed renderer.
275
+
244
276
  ### Books
245
277
 
246
278
  Books are long-form structured content under `content/books/<slug>/`.
package/README.zh.md CHANGED
@@ -44,6 +44,8 @@ Amytis 围绕一条从碎片想法到精炼知识的路径来帮助个人或组
44
44
  - **全文搜索:** 基于 Pagefind 的快速静态客户端全文搜索,支持 Cmd/Ctrl+K。
45
45
  - **结构化内容体系:**
46
46
  - **Series:** 支持手动或自动排序的多篇内容组织方式。
47
+ - **Legacy rST Series:** 当系列入口文件使用 `index.rst` 或 `README.rst` 时,该系列会按 reStructuredText 解析;同一系列中混用 Markdown 和 rST 会在构建时直接失败。
48
+ - **基于 docutils 的 rST 渲染:** 当环境中可用 `docutils` 时,rST 系列会走 Python/docutils 渲染路径,而不是轻量回退解析器。
47
49
  - **Books:** 支持明确章节、分部以及专用阅读界面的长篇内容。
48
50
  - **Notes:** 面向个人知识管理的原子化常青概念。
49
51
  - **Flows:** 用于快速记录想法的流式日记或微博客。
@@ -219,6 +221,8 @@ Amytis 基于 Next.js 静态导出构建,关键配置为 `output: "export"`
219
221
  - 文章默认路径为 `/<posts.basePath>/<slug>`,其中 `posts.basePath` 默认值为 `/posts`。
220
222
  - 启用 `series.autoPaths` 后,系列文章会移动到 `/<series-slug>/<post-slug>`。
221
223
  - 如果配置了 `series.customPaths`,则会以这些自定义前缀覆盖 `autoPaths`。
224
+ - frontmatter 中的 `redirectFrom` 会在导出时生成静态跳转页,用于保留旧链接。
225
+ - 不要硬编码文章路径,优先使用 URL helper,因为规范 URL 可能位于 `/posts`、系列 slug 或自定义前缀之下。
222
226
  - 在把系列文章从默认的 posts 路径迁走之前,先运行 `bun run add-series-redirects --dry-run`,再执行 `bun run add-series-redirects`,以确保旧链接仍然可访问。
223
227
 
224
228
  ## 内容写作
@@ -242,11 +246,39 @@ Amytis 基于 Next.js 静态导出构建,关键配置为 `output: "export"`
242
246
 
243
247
  ### Series
244
248
 
245
- 在 `content/series/<slug>/` 下创建目录和 `index.mdx`,然后将系列文章作为同级文件或文件夹加入其中。
249
+ 在 `content/series/<slug>/` 下创建目录,并选择以下其中一种入口文件:
250
+
251
+ - `index.mdx` 或 `index.md`,表示 Markdown 系列
252
+ - `index.rst` 或 `README.rst`,表示 rST 系列
253
+
254
+ `README.mdx` 和 `README.md` 也可作为 Markdown 系列入口。随后使用与入口文件一致的格式添加同级文章文件或子目录。同一系列中混用 Markdown 和 rST 会在构建时被拒绝。
246
255
 
247
256
  - CLI: `bun run new-series "Series Name"`
248
257
  - 也可以直接将文章创建到已有系列中: `bun run new "Post Title" --series <series-slug>`
249
258
 
259
+ #### rST / docutils 工作流
260
+
261
+ 如果希望获得更完整的 rST 渲染效果,请在一个可执行的 Python 环境中安装 `docutils`:
262
+
263
+ ```bash
264
+ python3 -m pip install docutils pygments
265
+ ```
266
+
267
+ 如果需要显式指定解释器,可设置 `AMYTIS_RST_PYTHON`:
268
+
269
+ ```bash
270
+ export AMYTIS_RST_PYTHON=/absolute/path/to/python
271
+ ```
272
+
273
+ 当前行为:
274
+
275
+ - `index.rst` 或 `README.rst` 会让整个系列进入 rST 模式。
276
+ - 对于 rST 系列文章顺序,显式的 `:posts:` 元数据优先级最高;如果没有 `:posts:`,Amytis 会使用系列入口文件中简单本地 `.. toctree::` 条目的顺序;如果两者都没有,则回退到现有的基于日期排序。
277
+ - `.. image::`、`.. figure::` 等资源路径会相对源文件解析,并重写为站点可用的静态资源路径。
278
+ - `:doc:`、`:ref:`、`:numref:`、`:math:`、`:dtag:` 等常见 legacy role 会尽量直接渲染;无法完整支持时也会降级为可读的内联输出,而不是 docutils 报错块。
279
+ - 文件顶部的 docinfo 元数据会被解析为 Amytis 元数据,但不会再渲染为文章顶部的作者/版本信息块。
280
+ - 如果 Python/docutils 不可用,Amytis 会回退到内置的轻量 rST 兼容路径。这样仍可加载系列,但渲染保真度会低于 docutils 路径。
281
+
250
282
  ### Books
251
283
 
252
284
  书籍是位于 `content/books/<slug>/` 下的长篇结构化内容。
package/TODO.md CHANGED
@@ -22,6 +22,15 @@
22
22
  - [ ] **Link Validator**: Script to check for broken internal wiki-links and external URLs.
23
23
  - [ ] **Content Porter**: Tool to import/export notes from Obsidian or Notion.
24
24
  - [ ] **Optimization**: Automatically compress and resize co-located images during build.
25
+ - [ ] **Build Performance**: Profile `build:dev`, clean stale export/search outputs before indexing, and consider a lighter local build path that skips expensive full-site indexing when not needed.
26
+
27
+ ## 📚 rST Follow-up
28
+ - [ ] **Fixture Coverage**: Add more compatibility fixtures from legacy rST series, including nested lists, tables, directives, images, and internal links.
29
+ - [ ] **Parser Diagnostics**: Improve rST build errors with clearer file context, line numbers where possible, and actionable unsupported-syntax messages.
30
+ - [ ] **Syntax Contract**: Document the exact supported rST subset and explicitly list unsupported or partial constructs.
31
+ - [ ] **Asset & Link Handling**: Harden relative asset resolution and add validation for broken local rST links and image references.
32
+ - [ ] **Reading Time**: Reuse the shared mixed-CJK reading-time rules for rST content so Chinese, Japanese, and Korean text are counted consistently.
33
+ - [ ] **Advanced Constructs**: Evaluate the highest-value next rST features from real imported content, such as footnotes, simple tables, and selected directives.
25
34
 
26
35
  ## ✅ Completed Highlights
27
36
  - [x] **JSON-LD Structured Data**: `BlogPosting`, `Book`, and `Article` schemas for Google rich results.
@@ -33,3 +42,4 @@
33
42
  - [x] **Robust Engineering**: Zero hydration mismatches, Zod validation, and 64+ automated tests.
34
43
  - [x] **Refined UI**: High-contrast typography, four color palettes, and horizontal scroll featured sections.
35
44
  - [x] **Sub-features**: Newsletter/Subscribe page, Reading Progress, and Author Ecosystem.
45
+ - [x] **Series-scoped rST Support**: Strict rST series detection, README-based indexes, Unicode-safe static params, and legacy redirect handling.