diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml
new file mode 100644
index 0000000..d5fffe5
--- /dev/null
+++ b/.github/workflows/deploy-pages.yml
@@ -0,0 +1,56 @@
+name: Deploy to GitHub Pages
+
+on:
+ push:
+ branches:
+ - main
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: pages
+ cancel-in-progress: true
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup Pages
+ uses: actions/configure-pages@v5
+
+ - name: Setup Node
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20
+ cache: npm
+
+ - name: Install Dependencies
+ run: npm ci
+
+ - name: Build Site
+ env:
+ VITE_BASE_PATH: /${{ github.event.repository.name }}/
+ run: npm run build
+
+ - name: Upload Pages Artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: dist
+
+ deploy:
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ needs: build
+ runs-on: ubuntu-latest
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/.gitignore b/.gitignore
index e43b0f9..bf56190 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
.DS_Store
+node_modules/
+dist/
diff --git a/README.md b/README.md
index cd80cbf..88a437f 100644
--- a/README.md
+++ b/README.md
@@ -2,21 +2,11 @@
# 解码 Agent Harness
-### Claude Code 架构深度剖析
-**不做使用教程,不列 Prompt 技巧——拆解 Agent 的骨架与神经。**
-
-[](https://github.com/lintsinghua/claude-code-book/stargazers)
-[](https://lintsinghua.github.io/)
-[](LICENSE)
-[]()
-[]()
-
-### [在线阅读 →](https://lintsinghua.github.io/)
+### [在线阅读 →](https://gugugugun.github.io/claude-code-book)
-
## 这本书讲什么
@@ -30,7 +20,7 @@
> **⚠️ 声明**
> 本书基于对 Claude Code 公开文档和产品行为的架构分析编写,**未引用、未使用任何未公开或未授权的源码**。Claude Code 为 Anthropic PBC 产品,本书不隶属于、未获授权于、也不代表 Anthropic。
----
+本项目基于原仓库 [lintsinghua/claude-code-book](https://github.com/lintsinghua/claude-code-book) 进行二次开发,目标是提供更友好的网页阅读体验。
## 为什么值得读
@@ -125,7 +115,6 @@
| 对 Agent 工程感兴趣的 **研究者** | 从实现角度理解 Agent 系统的运作方式 |
| 希望最大化利用 Claude Code 的 **实践者** | 理解设计意图,用得更准、调得更深 |
----
## 约定
@@ -133,11 +122,61 @@
- 每章结构:**学习目标 → 核心概念 → 架构图 → 实战练习 → 关键要点**
- 示例代码为说明设计模式的示意代码,非产品源码
-## 背景
+- 章节树导航:按书籍结构展示全部章节
+- Markdown 渲染:实时加载并渲染各章节内容
+- 上一篇/下一篇:支持连续阅读
+- 主题切换:支持明暗主题偏好
+- 阅读记忆:自动记录最近阅读章节
+
+## 项目结构
+
+```text
+.
+├─ src/
+│ ├─ main.js
+│ ├─ style.css
+│ └─ bookManifest.js
+├─ 第一部分-基础篇/
+├─ 第二部分-核心系统篇/
+├─ 第三部分-高级模式篇/
+├─ 第四部分-工程实践篇/
+├─ 附录/
+├─ index.html
+├─ vite.config.js
+└─ package.json
+```
+
+## 快速开始
-2026 年 3 月 31 日,安全研究员 [Chaofan Shou (@Fried_rice)](https://x.com/Fried_rice) 发现 Anthropic 发布在 npm registry 中的 `@anthropic-ai/claude-code` 包存在构建配置失误:source map 文件引用了未设访问控制的 Cloudflare R2 存储桶。披露推文获得超 1700 万次浏览,引发了技术社区对 Agent 架构的空前讨论。Anthropic 随后修补了该配置。
+### 1. 安装依赖
+
+```bash
+npm install
+```
+
+### 2. 本地开发
+
+```bash
+npm run dev
+```
-本书写作的初衷正是受到这场讨论的启发——当 Agent 架构成为开发者社区的热门话题,我们意识到需要一本系统性的书来讲解 Agent Harness 的设计原理。
+### 3. 生产构建
+
+```bash
+npm run build
+```
+
+### 4. 本地预览构建产物
+
+```bash
+npm run preview
+```
+
+## 内容维护说明
+
+- 书籍内容来源于仓库内各 Markdown 章节文件
+- 章节目录由 `src/bookManifest.js` 统一维护
+- 新增章节时,请同步更新 `src/bookManifest.js`
## 贡献
@@ -146,13 +185,13 @@
## 致谢
[Linux.Do](https://linux.do/) 社区
+[lintsinghua/claude-code-book](https://github.com/lintsinghua/claude-code-book)
+[](https://creativecommons.org/licenses/by-nc-sa/4.0/)
-## Star History
-
-[](https://star-history.com/#lintsinghua/claude-code-book&Date)
-## License
+## 友链
+- 灌注L站喵,https://linux.do/
-[](https://creativecommons.org/licenses/by-nc-sa/4.0/)
+## 许可证
-本书内容采用 [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) 协议发布——可自由分享和改编,但须署名、非商业使用、并以相同协议共享。
+书籍内容与相关版权遵循原项目及其许可证约定;如需转载或二次发布,请先阅读并遵守原仓库许可条款。
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..ee21fe9
--- /dev/null
+++ b/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+ Claude Code Book 在线阅读
+
+
+
+
+
+
+
+
+
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..08d816f
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,1136 @@
+{
+ "name": "claude-code-book-web-reader",
+ "version": "0.1.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "claude-code-book-web-reader",
+ "version": "0.1.0",
+ "dependencies": {
+ "dompurify": "^3.2.6",
+ "marked": "^15.0.7"
+ },
+ "devDependencies": {
+ "vite": "^7.1.3"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.4.tgz",
+ "integrity": "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.27.4.tgz",
+ "integrity": "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.27.4.tgz",
+ "integrity": "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.27.4.tgz",
+ "integrity": "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz",
+ "integrity": "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.27.4.tgz",
+ "integrity": "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.4.tgz",
+ "integrity": "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.4.tgz",
+ "integrity": "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.27.4.tgz",
+ "integrity": "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.27.4.tgz",
+ "integrity": "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.27.4.tgz",
+ "integrity": "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.27.4.tgz",
+ "integrity": "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.4.tgz",
+ "integrity": "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.4.tgz",
+ "integrity": "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.4.tgz",
+ "integrity": "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.27.4.tgz",
+ "integrity": "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.27.4.tgz",
+ "integrity": "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.4.tgz",
+ "integrity": "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.4.tgz",
+ "integrity": "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.4.tgz",
+ "integrity": "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.4.tgz",
+ "integrity": "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.4.tgz",
+ "integrity": "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.27.4.tgz",
+ "integrity": "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.27.4.tgz",
+ "integrity": "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.27.4.tgz",
+ "integrity": "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.27.4.tgz",
+ "integrity": "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz",
+ "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz",
+ "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz",
+ "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz",
+ "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz",
+ "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz",
+ "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz",
+ "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz",
+ "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz",
+ "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz",
+ "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz",
+ "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz",
+ "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz",
+ "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz",
+ "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz",
+ "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz",
+ "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz",
+ "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz",
+ "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz",
+ "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-openbsd-x64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz",
+ "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz",
+ "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz",
+ "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz",
+ "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz",
+ "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz",
+ "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/dompurify": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-3.3.3.tgz",
+ "integrity": "sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==",
+ "license": "(MPL-2.0 OR Apache-2.0)",
+ "optionalDependencies": {
+ "@types/trusted-types": "^2.0.7"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.27.4.tgz",
+ "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.27.4",
+ "@esbuild/android-arm": "0.27.4",
+ "@esbuild/android-arm64": "0.27.4",
+ "@esbuild/android-x64": "0.27.4",
+ "@esbuild/darwin-arm64": "0.27.4",
+ "@esbuild/darwin-x64": "0.27.4",
+ "@esbuild/freebsd-arm64": "0.27.4",
+ "@esbuild/freebsd-x64": "0.27.4",
+ "@esbuild/linux-arm": "0.27.4",
+ "@esbuild/linux-arm64": "0.27.4",
+ "@esbuild/linux-ia32": "0.27.4",
+ "@esbuild/linux-loong64": "0.27.4",
+ "@esbuild/linux-mips64el": "0.27.4",
+ "@esbuild/linux-ppc64": "0.27.4",
+ "@esbuild/linux-riscv64": "0.27.4",
+ "@esbuild/linux-s390x": "0.27.4",
+ "@esbuild/linux-x64": "0.27.4",
+ "@esbuild/netbsd-arm64": "0.27.4",
+ "@esbuild/netbsd-x64": "0.27.4",
+ "@esbuild/openbsd-arm64": "0.27.4",
+ "@esbuild/openbsd-x64": "0.27.4",
+ "@esbuild/openharmony-arm64": "0.27.4",
+ "@esbuild/sunos-x64": "0.27.4",
+ "@esbuild/win32-arm64": "0.27.4",
+ "@esbuild/win32-ia32": "0.27.4",
+ "@esbuild/win32-x64": "0.27.4"
+ }
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/marked": {
+ "version": "15.0.12",
+ "resolved": "https://registry.npmmirror.com/marked/-/marked-15.0.12.tgz",
+ "integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==",
+ "license": "MIT",
+ "bin": {
+ "marked": "bin/marked.js"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.8",
+ "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.8.tgz",
+ "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.60.1.tgz",
+ "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.8"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.60.1",
+ "@rollup/rollup-android-arm64": "4.60.1",
+ "@rollup/rollup-darwin-arm64": "4.60.1",
+ "@rollup/rollup-darwin-x64": "4.60.1",
+ "@rollup/rollup-freebsd-arm64": "4.60.1",
+ "@rollup/rollup-freebsd-x64": "4.60.1",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.60.1",
+ "@rollup/rollup-linux-arm-musleabihf": "4.60.1",
+ "@rollup/rollup-linux-arm64-gnu": "4.60.1",
+ "@rollup/rollup-linux-arm64-musl": "4.60.1",
+ "@rollup/rollup-linux-loong64-gnu": "4.60.1",
+ "@rollup/rollup-linux-loong64-musl": "4.60.1",
+ "@rollup/rollup-linux-ppc64-gnu": "4.60.1",
+ "@rollup/rollup-linux-ppc64-musl": "4.60.1",
+ "@rollup/rollup-linux-riscv64-gnu": "4.60.1",
+ "@rollup/rollup-linux-riscv64-musl": "4.60.1",
+ "@rollup/rollup-linux-s390x-gnu": "4.60.1",
+ "@rollup/rollup-linux-x64-gnu": "4.60.1",
+ "@rollup/rollup-linux-x64-musl": "4.60.1",
+ "@rollup/rollup-openbsd-x64": "4.60.1",
+ "@rollup/rollup-openharmony-arm64": "4.60.1",
+ "@rollup/rollup-win32-arm64-msvc": "4.60.1",
+ "@rollup/rollup-win32-ia32-msvc": "4.60.1",
+ "@rollup/rollup-win32-x64-gnu": "4.60.1",
+ "@rollup/rollup-win32-x64-msvc": "4.60.1",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.15",
+ "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.15.tgz",
+ "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/vite": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmmirror.com/vite/-/vite-7.3.1.tgz",
+ "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.27.0",
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3",
+ "postcss": "^8.5.6",
+ "rollup": "^4.43.0",
+ "tinyglobby": "^0.2.15"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "lightningcss": "^1.21.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..c917148
--- /dev/null
+++ b/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "claude-code-book-web-reader",
+ "private": true,
+ "version": "0.1.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "dompurify": "^3.2.6",
+ "marked": "^15.0.7"
+ },
+ "devDependencies": {
+ "vite": "^7.1.3"
+ }
+}
diff --git a/src/bookManifest.js b/src/bookManifest.js
new file mode 100644
index 0000000..2d2ce35
--- /dev/null
+++ b/src/bookManifest.js
@@ -0,0 +1,86 @@
+export const bookTree = [
+ {
+ title: "前言",
+ path: "00-前言.md"
+ },
+ {
+ title: "第一部分 基础篇",
+ children: [
+ { title: "01 智能体编程的新范式", path: "第一部分-基础篇/01-智能体编程的新范式.md" },
+ { title: "02 对话循环 Agent的心跳", path: "第一部分-基础篇/02-对话循环-Agent的心跳.md" },
+ { title: "03 工具系统 Agent的双手", path: "第一部分-基础篇/03-工具系统-Agent的双手.md" },
+ { title: "04 权限管线 Agent的护栏", path: "第一部分-基础篇/04-权限管线-Agent的护栏.md" }
+ ]
+ },
+ {
+ title: "第二部分 核心系统篇",
+ children: [
+ { title: "05 设置与配置 Agent的基因", path: "第二部分-核心系统篇/05-设置与配置-Agent的基因.md" },
+ { title: "06 记忆系统 Agent的长期记忆", path: "第二部分-核心系统篇/06-记忆系统-Agent的长期记忆.md" },
+ { title: "07 上下文管理 Agent的工作记忆", path: "第二部分-核心系统篇/07-上下文管理-Agent的工作记忆.md" },
+ { title: "08 钩子系统 Agent的生命周期扩展点", path: "第二部分-核心系统篇/08-钩子系统-Agent的生命周期扩展点.md" }
+ ]
+ },
+ {
+ title: "第三部分 高级模式篇",
+ children: [
+ { title: "09 子智能体与 Fork 模式", path: "第三部分-高级模式篇/09-子智能体与Fork模式.md" },
+ { title: "10 协调器模式 多智能体编排", path: "第三部分-高级模式篇/10-协调器模式-多智能体编排.md" },
+ { title: "11 技能系统与插件架构", path: "第三部分-高级模式篇/11-技能系统与插件架构.md" },
+ { title: "12 MCP 集成与外部协议", path: "第三部分-高级模式篇/12-MCP集成与外部协议.md" }
+ ]
+ },
+ {
+ title: "第四部分 工程实践篇",
+ children: [
+ { title: "13 流式架构与性能优化", path: "第四部分-工程实践篇/13-流式架构与性能优化.md" },
+ { title: "14 Plan 模式与结构化工作流", path: "第四部分-工程实践篇/14-Plan模式与结构化工作流.md" },
+ { title: "15 构建你自己的 Agent Harness", path: "第四部分-工程实践篇/15-构建你自己的Agent-Harness.md" }
+ ]
+ },
+ {
+ title: "附录",
+ children: [
+ { title: "A 源码导航地图", path: "附录/A-源码导航地图.md" },
+ { title: "B 工具完整清单", path: "附录/B-工具完整清单.md" },
+ { title: "C 功能标志速查表", path: "附录/C-功能标志速查表.md" },
+ { title: "D 术语表", path: "附录/D-术语表.md" }
+ ]
+ }
+];
+
+export function flattenBook(tree = bookTree) {
+ const result = [];
+
+ function visit(node) {
+ if (node.path) {
+ result.push({ title: node.title, path: node.path });
+ return;
+ }
+
+ for (const child of node.children || []) {
+ visit(child);
+ }
+ }
+
+ for (const item of tree) {
+ visit(item);
+ }
+
+ return result;
+}
+
+export function findNodeByPath(path, tree = bookTree) {
+ for (const node of tree) {
+ if (node.path === path) {
+ return node;
+ }
+ if (node.children) {
+ const hit = findNodeByPath(path, node.children);
+ if (hit) {
+ return hit;
+ }
+ }
+ }
+ return null;
+}
diff --git a/src/main.js b/src/main.js
new file mode 100644
index 0000000..f1e4ecc
--- /dev/null
+++ b/src/main.js
@@ -0,0 +1,447 @@
+import './style.css';
+import { marked } from 'marked';
+import DOMPurify from 'dompurify';
+import { bookTree, flattenBook, findNodeByPath } from './bookManifest.js';
+
+const STORAGE_THEME_KEY = 'book.reader.theme';
+const STORAGE_LAST_PAGE_KEY = 'book.reader.last-page';
+const STORAGE_SIDEBAR_COLLAPSED_KEY = 'book.reader.sidebar-collapsed';
+
+const markdownModules = import.meta.glob('/**/*.md', {
+ query: '?raw',
+ import: 'default'
+});
+
+const flatBook = flattenBook(bookTree);
+
+marked.setOptions({
+ gfm: true,
+ breaks: false
+});
+
+const app = document.querySelector('#app');
+
+app.innerHTML = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+const elements = {
+ nav: document.querySelector('#bookNav'),
+ article: document.querySelector('#article'),
+ articleTitle: document.querySelector('#articleTitle'),
+ searchInput: document.querySelector('#searchInput'),
+ themeToggle: [...document.querySelectorAll('.theme-toggle-btn')],
+ sidebarToggle: document.querySelector('#sidebarToggle'),
+ mobileMenuBtn: document.querySelector('#mobileMenuBtn'),
+ sidebarBackdrop: document.querySelector('#sidebarBackdrop'),
+ prevBtn: document.querySelector('#prevBtn'),
+ nextBtn: document.querySelector('#nextBtn'),
+ toc: document.querySelector('#toc'),
+ tocToggle: document.querySelector('#tocToggle'),
+ floatingTocBtn: document.querySelector('#floatingTocBtn'),
+ progressBar: document.querySelector('#progressBar')
+};
+
+let currentPath = null;
+
+function isMobileViewport() {
+ return window.matchMedia('(max-width: 960px)').matches;
+}
+
+function applySidebarCollapsed(collapsed) {
+ document.body.classList.toggle('sidebar-collapsed', collapsed);
+ localStorage.setItem(STORAGE_SIDEBAR_COLLAPSED_KEY, String(collapsed));
+}
+
+function setSidebarOpen(open) {
+ document.body.classList.toggle('sidebar-open', open);
+}
+
+function initSidebarState() {
+ const collapsed = localStorage.getItem(STORAGE_SIDEBAR_COLLAPSED_KEY) === 'true';
+ applySidebarCollapsed(collapsed);
+}
+
+function normalizePath(path) {
+ return path.startsWith('/') ? path : `/${path}`;
+}
+
+function renderThemeIcon(isDark) {
+ const html = isDark
+ ? ``
+ : ``;
+ elements.themeToggle.forEach(btn => btn.innerHTML = html);
+}
+
+function applyTheme(theme) {
+ const value = theme === 'dark' ? 'dark' : 'light';
+ document.documentElement.dataset.theme = value;
+ localStorage.setItem(STORAGE_THEME_KEY, value);
+ renderThemeIcon(value === 'dark');
+}
+
+function initTheme() {
+ const stored = localStorage.getItem(STORAGE_THEME_KEY);
+ if (stored) {
+ applyTheme(stored);
+ return;
+ }
+
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
+ applyTheme(prefersDark ? 'dark' : 'light');
+}
+
+function slugify(text) {
+ return text
+ .toLowerCase()
+ .trim()
+ .replace(/[^\w\u4e00-\u9fa5\-\s]/g, '')
+ .replace(/\s+/g, '-');
+}
+
+function renderToc() {
+ const headings = [...elements.article.querySelectorAll('h1, h2, h3, h4')];
+ if (!headings.length) {
+ elements.toc.innerHTML = '本页暂无目录
';
+ return;
+ }
+
+ elements.toc.innerHTML = `
+
+ ${headings
+ .map((heading) => {
+ if (!heading.id) {
+ heading.id = slugify(heading.textContent || 'section');
+ }
+ return `- ${heading.textContent}
`;
+ })
+ .join('')}
+
+ `;
+}
+
+function updateReadingProgress() {
+ const doc = document.documentElement;
+ const total = doc.scrollHeight - doc.clientHeight;
+ const ratio = total > 0 ? Math.min(1, Math.max(0, window.scrollY / total)) : 0;
+ elements.progressBar.style.transform = `scaleX(${ratio})`;
+}
+
+function getCurrentIndex() {
+ return flatBook.findIndex((item) => item.path === currentPath);
+}
+
+function updatePager() {
+ const index = getCurrentIndex();
+ elements.prevBtn.disabled = index <= 0;
+ elements.nextBtn.disabled = index < 0 || index >= flatBook.length - 1;
+}
+
+function renderNav(filterText = '') {
+ const keyword = filterText.trim().toLowerCase();
+
+ function renderNodes(nodes, level = 0) {
+ const items = [];
+
+ for (const node of nodes) {
+ if (node.path) {
+ const match = !keyword || node.title.toLowerCase().includes(keyword);
+ if (!match) continue;
+ const isActive = node.path === currentPath;
+ items.push(`
+
+
+
+ `);
+ } else {
+ const childHtml = renderNodes(node.children || [], level + 1);
+ if (!childHtml) continue;
+ items.push(`
+
+ ${node.title}
+
+
+ `);
+ }
+ }
+
+ return items.join('');
+ }
+
+ const html = renderNodes(bookTree);
+ elements.nav.innerHTML = html ? `` : '没有匹配章节
';
+}
+
+async function loadMarkdown(path) {
+ const normalized = normalizePath(path);
+ const loader = markdownModules[normalized];
+
+ if (!loader) {
+ throw new Error(`未找到 Markdown 文件: ${normalized}`);
+ }
+
+ const markdown = await loader();
+ return markdown;
+}
+
+async function openArticle(path, fromHistory = false) {
+ currentPath = path;
+
+ const node = findNodeByPath(path);
+ elements.articleTitle.textContent = node ? node.title : path;
+
+ elements.article.style.animation = 'none';
+ elements.article.offsetHeight; /* trigger reflow */
+ elements.article.style.animation = null;
+
+ try {
+ const markdown = await loadMarkdown(path);
+ const rawHtml = marked.parse(markdown);
+ const safeHtml = DOMPurify.sanitize(rawHtml);
+ elements.article.innerHTML = safeHtml;
+ renderToc();
+ renderNav(elements.searchInput.value);
+ updatePager();
+ updateReadingProgress();
+
+ const hash = `#${encodeURIComponent(path)}`;
+ if (!fromHistory && window.location.hash !== hash) {
+ history.pushState({ path }, '', hash);
+ }
+
+ localStorage.setItem(STORAGE_LAST_PAGE_KEY, path);
+ window.scrollTo({ top: 0, behavior: 'smooth' });
+ } catch (error) {
+ elements.article.innerHTML = `加载失败:${error.message}
`;
+ }
+}
+
+function bindEvents() {
+ elements.nav.addEventListener('click', (event) => {
+ const target = event.target.closest('button[data-path]');
+ if (!target) return;
+
+ openArticle(target.dataset.path);
+ if (isMobileViewport()) {
+ setSidebarOpen(false);
+ }
+ });
+
+ elements.article.addEventListener('click', (event) => {
+ const link = event.target.closest('a');
+ if (!link) return;
+
+ const href = link.getAttribute('href');
+ if (href && href.startsWith('#')) {
+ event.preventDefault();
+ const targetId = href.substring(1);
+ let targetEl = document.getElementById(targetId);
+ if (!targetEl) {
+ try { targetEl = document.getElementById(decodeURIComponent(targetId)); } catch(e) {}
+ }
+ if (targetEl) {
+ targetEl.scrollIntoView({ behavior: 'smooth' });
+ }
+ }
+ });
+
+ elements.searchInput.addEventListener('input', () => {
+ renderNav(elements.searchInput.value);
+ });
+
+ elements.themeToggle.forEach(btn => {
+ btn.addEventListener('click', () => {
+ const next = document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark';
+ applyTheme(next);
+ });
+ });
+
+ elements.sidebarToggle.addEventListener('click', () => {
+ const nextCollapsed = !document.body.classList.contains('sidebar-collapsed');
+ applySidebarCollapsed(nextCollapsed);
+ });
+
+ if (elements.mobileMenuBtn) {
+ elements.mobileMenuBtn.addEventListener('click', () => {
+ setSidebarOpen(!document.body.classList.contains('sidebar-open'));
+ });
+ }
+
+ elements.sidebarBackdrop.addEventListener('click', () => {
+ setSidebarOpen(false);
+ });
+
+ elements.prevBtn.addEventListener('click', () => {
+ const index = getCurrentIndex();
+ if (index > 0) openArticle(flatBook[index - 1].path);
+ });
+
+ elements.nextBtn.addEventListener('click', () => {
+ const index = getCurrentIndex();
+ if (index >= 0 && index < flatBook.length - 1) openArticle(flatBook[index + 1].path);
+ });
+
+ if (elements.toc) {
+ elements.toc.addEventListener('click', (event) => {
+ const link = event.target.closest('a[data-target]');
+ if (!link) return;
+
+ event.preventDefault();
+ const targetId = link.getAttribute('data-target');
+ if (targetId) {
+ let targetEl = document.getElementById(targetId);
+ if (!targetEl) {
+ try {
+ targetEl = document.getElementById(decodeURIComponent(targetId));
+ } catch(e) {}
+ }
+
+ if (targetEl) {
+ targetEl.scrollIntoView({ behavior: 'smooth' });
+ }
+ }
+ });
+ }
+
+ if (elements.tocToggle) {
+ elements.tocToggle.addEventListener('click', () => {
+ document.body.classList.add('toc-collapsed');
+ });
+ }
+
+ if (elements.floatingTocBtn) {
+ elements.floatingTocBtn.addEventListener('click', () => {
+ document.body.classList.remove('toc-collapsed');
+ });
+ }
+
+ window.addEventListener('scroll', updateReadingProgress, { passive: true });
+ window.addEventListener('resize', () => {
+ if (!isMobileViewport()) {
+ setSidebarOpen(false);
+ }
+ });
+
+ window.addEventListener('popstate', (event) => {
+ const target = event.state?.path;
+ if (target) {
+ openArticle(target, true);
+ return;
+ }
+
+ const fromHash = decodeURIComponent(window.location.hash.replace(/^#/, ''));
+ if (fromHash) {
+ openArticle(fromHash, true);
+ }
+ });
+}
+
+function resolveInitialPath() {
+ const fromHash = decodeURIComponent(window.location.hash.replace(/^#/, ''));
+ if (flatBook.some((item) => item.path === fromHash)) return fromHash;
+
+ const lastPage = localStorage.getItem(STORAGE_LAST_PAGE_KEY);
+ if (lastPage && flatBook.some((item) => item.path === lastPage)) return lastPage;
+
+ return flatBook[0]?.path;
+}
+
+async function bootstrap() {
+ initTheme();
+ initSidebarState();
+ bindEvents();
+ renderNav();
+
+ const initialPath = resolveInitialPath();
+ if (initialPath) {
+ await openArticle(initialPath, true);
+ }
+}
+
+bootstrap();
diff --git a/src/style.css b/src/style.css
new file mode 100644
index 0000000..7360e46
--- /dev/null
+++ b/src/style.css
@@ -0,0 +1,635 @@
+:root {
+ /* Warm, parchment-like light mode palette */
+ --bg: #F9F5EC;
+ --surface: rgba(253, 248, 237, 0.75);
+ --surface-solid: #FDF8ED;
+ --text: #3E3124;
+ --heading: #2C2219;
+ --muted: #7E6C56;
+ --line: #E8DDCA;
+ --accent: #D35400;
+ --accent-hover: #A04000;
+ --accent-soft: rgba(211, 84, 0, 0.08);
+ --accent-glow: rgba(211, 84, 0, 0.15);
+
+ --radius-sm: 8px;
+ --radius-md: 12px;
+ --radius-lg: 16px;
+ --shadow-sm: 0 1px 2px 0 rgba(70, 50, 30, 0.05);
+ --shadow-md: 0 4px 6px -1px rgba(70, 50, 30, 0.08), 0 2px 4px -1px rgba(70, 50, 30, 0.04);
+ --shadow-glow: 0 0 20px var(--accent-glow);
+ --glass-blur: blur(12px);
+}
+
+:root[data-theme='dark'] {
+ /* Warm dark/sepia mode palette for reading */
+ --bg: #1E1A17;
+ --surface: rgba(43, 38, 33, 0.7);
+ --surface-solid: #2B2621;
+ --text: #CFC3AD;
+ --heading: #EAE2D1;
+ --muted: #8E8271;
+ --line: #453E35;
+ --accent: #D98850;
+ --accent-hover: #ED9A5E;
+ --accent-soft: rgba(217, 136, 80, 0.12);
+ --accent-glow: rgba(217, 136, 80, 0.15);
+
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.4);
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.5), 0 2px 4px -1px rgba(0, 0, 0, 0.3);
+}
+
+* { box-sizing: border-box; }
+html, body {
+ margin: 0; min-height: 100vh;
+}
+body {
+ background-color: var(--bg);
+ background-image:
+ radial-gradient(circle at 15% 50%, var(--accent-glow), transparent 25%),
+ radial-gradient(circle at 85% 30%, var(--accent-glow), transparent 25%);
+ background-attachment: fixed;
+ color: var(--text);
+ font-family: 'Outfit', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
+ line-height: 1.6;
+ -webkit-font-smoothing: antialiased;
+ transition: background-color 0.4s ease, color 0.4s ease;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ font-family: 'ZCOOL XiaoWei', 'STKaiti', serif;
+ color: var(--heading);
+ margin-top: 0;
+}
+
+.site-shell {
+ display: flex;
+ min-height: 100vh;
+}
+
+
+.sidebar {
+ width: 300px;
+ flex-shrink: 0;
+ border-right: 1px solid var(--line);
+ background: var(--surface);
+ backdrop-filter: var(--glass-blur);
+ -webkit-backdrop-filter: var(--glass-blur);
+ padding: 24px 20px;
+ position: sticky;
+ top: 0;
+ max-height: 100vh;
+ overflow-y: auto;
+ overflow-x: hidden;
+ display: flex;
+ flex-direction: column;
+ transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1), padding 0.3s ease;
+ will-change: width, transform;
+ transform: translateZ(0); /* force GPU acceleration */
+ z-index: 40;
+}
+
+.sidebar::-webkit-scrollbar { width: 4px; }
+.sidebar::-webkit-scrollbar-track { background: transparent; }
+.sidebar::-webkit-scrollbar-thumb { background: var(--line); border-radius: 4px; }
+.sidebar:hover::-webkit-scrollbar-thumb { background: var(--muted); }
+
+.sidebar-top-actions {
+ display: flex;
+ justify-content: flex-end;
+ margin-bottom: 20px;
+}
+
+.icon-btn {
+ background: transparent;
+ border: 1px solid transparent;
+ color: var(--muted);
+ width: 36px;
+ height: 36px;
+ border-radius: var(--radius-sm);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ padding: 0;
+}
+.icon-btn svg { width: 20px; height: 20px; fill: currentColor; }
+
+.icon-btn:hover {
+ background: var(--surface-solid);
+ border-color: var(--line);
+ color: var(--accent);
+ transform: translateY(-1px);
+ box-shadow: var(--shadow-sm);
+}
+
+body.sidebar-collapsed .sidebar {
+ width: 80px;
+ padding: 24px 12px;
+ align-items: center;
+}
+
+body.sidebar-collapsed .brand h1,
+body.sidebar-collapsed .brand-kicker,
+body.sidebar-collapsed .sidebar-actions,
+body.sidebar-collapsed .book-nav {
+ display: none;
+}
+
+.brand {
+ margin-bottom: 24px;
+}
+.brand-kicker {
+ margin: 0 0 4px;
+ font-size: 0.75rem;
+ text-transform: uppercase;
+ letter-spacing: 0.15em;
+ color: var(--accent);
+ font-weight: 700;
+}
+.brand h1 {
+ margin: 0;
+ line-height: 1.2;
+ font-size: 1.75rem;
+ background: linear-gradient(135deg, var(--heading) 0%, var(--muted) 100%);
+ -webkit-background-clip: text;
+ background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.sidebar-actions {
+ display: flex;
+ gap: 8px;
+ margin-bottom: 24px;
+}
+
+.search-wrapper {
+ position: relative;
+ flex: 1;
+}
+.search-wrapper svg {
+ position: absolute;
+ left: 12px;
+ top: 50%;
+ transform: translateY(-50%);
+ width: 16px;
+ height: 16px;
+ fill: var(--muted);
+}
+input[type="search"] {
+ width: 100%;
+ background: var(--surface-solid);
+ border: 1px solid var(--line);
+ color: var(--text);
+ border-radius: var(--radius-sm);
+ padding: 10px 12px 10px 36px;
+ font: inherit;
+ font-size: 0.9rem;
+ transition: all 0.2s ease;
+ outline: none;
+}
+input[type="search"]:focus {
+ border-color: var(--accent);
+ box-shadow: 0 0 0 3px var(--accent-soft);
+}
+
+.book-nav ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+.group-title {
+ margin: 16px 0 8px;
+ font-size: 0.8rem;
+ color: var(--muted);
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+ font-weight: 600;
+ padding-left: calc(var(--level, 0) * 12px + 12px);
+}
+.nav-item {
+ width: 100%;
+ text-align: left;
+ border: none;
+ background: transparent;
+ color: var(--text);
+ border-radius: var(--radius-sm);
+ padding: 8px 12px;
+ padding-left: calc(12px + var(--level, 0) * 12px);
+ margin: 2px 0;
+ font-size: 0.95rem;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ position: relative;
+ display: flex;
+ align-items: center;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.nav-item::before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 50%;
+ transform: translateY(-50%) scaleY(0);
+ width: 3px;
+ height: 16px;
+ background: var(--accent);
+ border-radius: 0 4px 4px 0;
+ transition: transform 0.2s ease;
+}
+.nav-item:hover {
+ background: var(--accent-soft);
+ color: var(--accent);
+}
+.nav-item.active {
+ background: var(--accent-soft);
+ color: var(--accent);
+ font-weight: 600;
+}
+.nav-item.active::before {
+ transform: translateY(-50%) scaleY(1);
+}
+
+.content {
+ padding: 0;
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+ min-width: 0; /* Prevents flex flex grow bug */
+}
+
+.reading-progress {
+ position: sticky;
+ top: 0;
+ z-index: 50;
+ height: 3px;
+ background: transparent;
+ width: 100%;
+}
+.reading-progress span {
+ display: block;
+ width: 100%;
+ height: 100%;
+ transform-origin: left center;
+ transform: scaleX(0);
+ background: linear-gradient(90deg, var(--accent), #10B981);
+ box-shadow: 0 0 10px var(--accent-glow);
+ transition: transform 0.1s linear;
+}
+
+.content-inner {
+ padding: clamp(24px, 5vw, 60px);
+ max-width: 900px;
+ width: 100%;
+ margin: 0 auto;
+ flex: 1;
+}
+
+.article-toolbar {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-end;
+ border-bottom: 1px solid var(--line);
+ padding-bottom: 20px;
+ margin-bottom: 32px;
+ gap: 16px;
+}
+.kicker {
+ margin: 0 0 8px;
+ font-size: 0.8rem;
+ text-transform: uppercase;
+ letter-spacing: 0.1em;
+ color: var(--muted);
+ font-weight: 500;
+}
+.article-toolbar h2 {
+ margin: 0;
+ font-size: clamp(2rem, 4vw, 2.75rem);
+ line-height: 1.1;
+}
+
+.pager { display: flex; gap: 12px; }
+.btn-secondary {
+ background: var(--surface-solid);
+ border: 1px solid var(--line);
+ color: var(--text);
+ padding: 8px 16px;
+ border-radius: var(--radius-sm);
+ font-size: 0.9rem;
+ font-weight: 500;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+.btn-secondary:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ transform: none;
+}
+.btn-secondary:not(:disabled):hover {
+ background: var(--surface);
+ border-color: var(--accent);
+ color: var(--accent);
+ transform: translateY(-1px);
+ box-shadow: var(--shadow-sm);
+}
+
+.article {
+ font-size: 1.1rem;
+ line-height: 1.8;
+ color: var(--text);
+ animation: fade-up 0.5s cubic-bezier(0.16, 1, 0.3, 1) forwards;
+ opacity: 0;
+ transform: translateY(10px);
+}
+.article h1, .article h2, .article h3, .article h4 {
+ color: var(--heading);
+ font-weight: 700;
+ margin-top: 2em;
+ margin-bottom: 0.75em;
+ scroll-margin-top: 80px;
+}
+.article h2 { font-size: 1.8rem; border-bottom: 1px solid var(--line); padding-bottom: 0.5em; }
+.article h3 { font-size: 1.4rem; }
+.article h4 { font-size: 1.2rem; }
+
+.article p {
+ margin-top: 0;
+ margin-bottom: 1.5em;
+}
+.article a {
+ color: var(--accent);
+ text-decoration: none;
+ font-weight: 500;
+ border-bottom: 1px solid transparent;
+ transition: border-color 0.2s;
+}
+.article a:hover {
+ border-color: var(--accent);
+}
+
+.article ul, .article ol {
+ margin-top: 0;
+ margin-bottom: 1.5em;
+ padding-left: 1.5em;
+}
+.article li { margin-bottom: 0.5em; }
+
+.article blockquote {
+ margin: 1.5em 0;
+ padding: 1rem 1.5rem;
+ border-left: 4px solid var(--accent);
+ background: var(--accent-soft);
+ border-radius: 0 var(--radius-md) var(--radius-md) 0;
+ color: var(--text);
+ font-style: italic;
+}
+.article blockquote p:last-child { margin-bottom: 0; }
+
+.article code {
+ font-family: 'JetBrains Mono', 'Fira Code', Consolas, monospace;
+ background: var(--surface-solid);
+ border: 1px solid var(--line);
+ padding: 0.2em 0.4em;
+ border-radius: 4px;
+ font-size: 0.85em;
+ color: var(--accent);
+}
+
+.article pre {
+ margin: 1.5em 0;
+ padding: 1.25rem;
+ background: #0f172a;
+ color: #e2e8f0;
+ border-radius: var(--radius-lg);
+ overflow-x: auto;
+ box-shadow: inset 0 0 0 1px rgba(255,255,255,0.1), var(--shadow-md);
+}
+.article pre code {
+ background: transparent;
+ border: none;
+ padding: 0;
+ color: inherit;
+ font-size: 0.9em;
+}
+
+.article img {
+ max-width: 100%;
+ height: auto;
+ border-radius: var(--radius-md);
+ box-shadow: var(--shadow-md);
+ margin: 1.5em auto;
+ display: block;
+}
+
+.article table {
+ width: 100%;
+ border-collapse: collapse;
+ margin: 1.5em 0;
+}
+.article th, .article td {
+ border: 1px solid var(--line);
+ padding: 0.75rem 1rem;
+ text-align: left;
+}
+.article th {
+ background: var(--surface-solid);
+ color: var(--heading);
+ font-weight: 600;
+}
+
+.toc-panel {
+ position: fixed;
+ top: 100px;
+ right: max(20px, calc((100vw - 320px - 900px) / 2 - 280px));
+ width: 260px;
+ max-height: calc(100vh - 140px);
+ background: var(--surface);
+ backdrop-filter: var(--glass-blur);
+ -webkit-backdrop-filter: var(--glass-blur);
+ border: 1px solid var(--line);
+ border-radius: var(--radius-md);
+ padding: 16px 20px;
+ box-shadow: var(--shadow-md);
+ overflow-y: auto;
+ z-index: 30;
+ transition: opacity 0.3s, transform 0.3s;
+}
+
+.toc-head {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 12px;
+ padding-bottom: 8px;
+ border-bottom: 1px solid var(--line);
+}
+.toc-title {
+ margin: 0;
+ font-size: 0.75rem;
+ font-weight: 700;
+ text-transform: uppercase;
+ letter-spacing: 0.1em;
+ color: var(--muted);
+}
+.toc-empty {
+ color: var(--muted);
+ font-size: 0.9rem;
+ font-style: italic;
+}
+
+body.toc-collapsed .toc-panel {
+ transform: translateX(calc(100% + 40px));
+ opacity: 0;
+ pointer-events: none;
+}
+
+.floating-toc-btn {
+ position: fixed;
+ bottom: 30px;
+ right: 30px;
+ width: 48px;
+ height: 48px;
+ border-radius: 50%;
+ background: var(--accent);
+ color: white;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: var(--shadow-md), var(--shadow-glow);
+ cursor: pointer;
+ border: none;
+ z-index: 29;
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ opacity: 0;
+ pointer-events: none;
+ transform: scale(0.8);
+}
+.floating-toc-btn svg { width: 24px; height: 24px; fill: currentColor; }
+body.toc-collapsed .floating-toc-btn {
+ opacity: 1;
+ pointer-events: auto;
+ transform: scale(1);
+}
+.floating-toc-btn:hover {
+ transform: scale(1.1);
+ background: var(--accent-hover);
+}
+
+.toc ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+.toc li {
+ margin: 8px 0;
+ font-size: 0.9rem;
+ line-height: 1.4;
+}
+.toc a {
+ color: var(--muted);
+ text-decoration: none;
+ display: block;
+ transition: color 0.2s, transform 0.2s;
+ border-left: 2px solid transparent;
+ padding-left: 8px;
+}
+.toc a:hover {
+ color: var(--accent);
+ border-left-color: var(--accent);
+ transform: translateX(2px);
+}
+
+.lv-h2 { margin-left: 0; font-weight: 500; }
+.lv-h3 { margin-left: 12px; font-size: 0.85rem; }
+.lv-h4 { margin-left: 24px; font-size: 0.8rem; }
+
+.mobile-header {
+ display: none;
+}
+.sidebar-backdrop {
+ display: none;
+}
+
+@keyframes fade-up {
+ 0% { opacity: 0; transform: translateY(15px); }
+ 100% { opacity: 1; transform: translateY(0); }
+}
+
+@media (max-width: 1280px) {
+ .toc-panel {
+ display: none;
+ }
+}
+
+@media (max-width: 960px) {
+ .site-shell {
+ grid-template-columns: 1fr;
+ }
+ body.sidebar-collapsed .site-shell {
+ grid-template-columns: 1fr;
+ }
+
+ .sidebar {
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ width: 320px;
+ transform: translateX(-100%);
+ box-shadow: var(--shadow-md);
+ border-right: none;
+ background: var(--surface-solid);
+ }
+ body.sidebar-open .sidebar {
+ transform: translateX(0);
+ }
+
+ .sidebar-backdrop {
+ position: fixed;
+ inset: 0;
+ z-index: 35;
+ background: rgba(0, 0, 0, 0.4);
+ backdrop-filter: blur(4px);
+ -webkit-backdrop-filter: blur(4px);
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.3s;
+ display: block;
+ }
+ body.sidebar-open .sidebar-backdrop {
+ opacity: 1;
+ pointer-events: auto;
+ }
+
+ .mobile-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 12px 20px;
+ background: var(--surface);
+ backdrop-filter: var(--glass-blur);
+ -webkit-backdrop-filter: var(--glass-blur);
+ border-bottom: 1px solid var(--line);
+ position: sticky;
+ top: 0;
+ z-index: 30;
+ }
+
+ .content-inner {
+ padding: 24px 20px;
+ }
+ .article-toolbar {
+ flex-direction: column;
+ align-items: flex-start;
+ }
+ .article-toolbar h2 {
+ font-size: 1.8rem;
+ }
+}
diff --git a/vite.config.js b/vite.config.js
new file mode 100644
index 0000000..39ec092
--- /dev/null
+++ b/vite.config.js
@@ -0,0 +1,5 @@
+import { defineConfig } from 'vite';
+
+export default defineConfig({
+ base: process.env.VITE_BASE_PATH || '/'
+});