Files
chan/CLAUDE.md
2026-08-11 16:17:49 +08:00

95 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
项目:缠论研习社——缠中说禅《教你炒股票》原文与杂文的沉浸式阅读站。
## 命令
```bash
pnpm install # 安装依赖(需 Node 20+ 与 pnpm
pnpm dev # 开发服务器 → http://localhost:5173vite open 自动开浏览器)
pnpm build # vue-tsc -b 类型检查 + vite 生产构建
pnpm build:only # 跳过类型检查,仅 vite build
pnpm typecheck # 仅 vue-tsc -b 类型检查(改完 TS/Vue 先跑这个)
pnpm preview # 预览生产构建
```
本机 pnpm v11 用 `pnpm-workspace.yaml``allowBuilds`(不是 `onlyBuiltDependencies`)放行 esbuild / vue-demi 的构建脚本;新增带构建脚本的 devDep 时需在此手动放行,否则安装会被拦。
## 样式约定(重要)
### 每个用 Tailwind 写的元素必须带一个「标记类名」
用 Tailwind 工具类写样式时,**必须给每个有独立含义的元素加一个语义化的标记 class并放在 class 列表最前面**。这样用户在对话里能精确指代「改哪个 div」。
```vue
<!-- 不要纯工具类堆叠用户无法指代 -->
<div class="flex items-center gap-2 rounded-md bg-surface px-3 py-2">
<!-- 标记类名打头组件名__部位kebab-case -->
<div class="article-card__lesson flex items-center gap-2 rounded-md bg-surface px-3 py-2">
```
命名规则:`<组件或区块名>__<部位>`,如 `home-hero__title``reader-meta``article-card__tags`。一个 `.vue` 文件内的标记类名以该组件的功能名为前缀,保证跨组件不撞。
> 现存组件(如 `ArticleCard.vue`)尚未遵循此约定;**新建或重写元素时一律补上**,改动既有元素时顺手补。
### 颜色必须走设计 Token禁止裸色值
所有颜色用 `src/style.css``@theme inline` 定义的语义类,**不要写 `bg-white` / `text-gray-500` / `#fff` 这类**
- 背景:`bg-app`(应用底)/ `bg-background`(卡片)/ `bg-surface` / `bg-surface-2` / `bg-hover`
- 文本:`text-foreground` / `text-muted` / `text-subtle` / `text-faint`
- 品牌/语义:`text-primary` / `bg-primary-soft` / `text-success` / `text-warning` / `text-danger`
- 边框:`border-line` / `border-line-strong` / `border-line-card`
- 圆角用 `rounded-xs/sm/md/lg/xl/2xl`4/8/12/16/20/24阴影用 `shadow-xs/sm/soft/md/lg/xl`
亮/暗主题切换靠 `<html class="dark">`,所有语义色自动适配——**只要用 Token就不用单独写 dark: 变体**。
### class 合并用 `cn()`
`src/utils/cn.ts``cn()` = clsx条件+ tailwind-merge冲突后写覆盖前写`px-2 px-4 → px-4`)。有条件 class 或动态拼接时用它,别手写字符串拼接。
## 架构(需要跨文件理解的)
**技术栈**Vue 3 `<script setup>` + Vite 6 + Tailwind v4CSS-first `@theme`+ TS strict + Pinia + Vue Router 4 + markdown-it + lucide-vue-next。`@` 别名 → `src/`
### 数据层是完全解耦的(核心设计)
页面不直接读数据文件,而是通过 `src/composables/useArticles.ts`:它把 `chanlunLessons``data/chanlun.ts`)和 `essays``data/essays.ts`)合并,提供 `chanlun / essaysList / latest / featured / find() / neighbors() / search()`
- 接入真实抓取数据时:只改数据源(替换 `data/*.ts`)或把 `useArticles.ts` 内的静态数组改成异步请求,**页面和组件无需改动**。
- 文章正文是 **markdown 字符串**`Article.content`,见 `types/article.ts`)。抓取的 HTML 入库时转 markdown或扩展 `useMarkdown.ts` 直接渲染 HTML。
### 文章正文排版 = `.prose-chan`(不要手写)
正文区一律挂 `prose-chan` 类(定义在 `style.css``@layer components`),它已处理 h2/h3/p/blockquote/code/table/列表等全部排版。字号/字体不写死,而是通过 `data-size``sm|base|lg|xl`)和 `data-font``serif|sans`)属性驱动,值来自 reading store。
### 两个 Pinia store 驱动全局体验
- `stores/theme.ts``light | dark | system`,持久化到 `localStorage['chan-theme']`,靠给 `<html>``.dark` 生效。
- `stores/reading.ts`:字号 / 字体 / 专注模式,分别持久化。
- **防闪烁FOUC**`index.html` 里有段内联脚本在 Vue 挂载前同步读 `chan-theme``.dark`。改主题存储 key 时,`index.html` 脚本和 `stores/theme.ts` 必须**同步改**,否则首屏会闪。
### 路由与布局
5 个 view两种 layout
- `DefaultLayout``/`):顶栏 + 侧栏 + 内容 + 页脚,包 home / chanlun / articles / about。
- `ReaderLayout``/read/:category/:slug`):沉浸阅读,含阅读进度、阅读设置、上下篇导航。
- markdown 的 h2/h3 会被 `useMarkdown.ts` 注入 `id`slug 来自 `utils/slug.ts`),便于锚点跳转。
### 现存组件缺标记类名
`components/ui/`BaseButton/Badge/Card/SearchInput`components/layout/`AppHeader/AppSidebar/AppFooter`ArticleCard` 等目前是纯工具类。改动它们时按上面的「标记类名」约定补齐。
## 其他约定
- TS strict 且开了 `noUnusedLocals` / `noUnusedParameters`**未用的 import / 变量会直接让 `pnpm build` 失败**,删代码时记得清干净。
- `<script setup lang="ts">` + Composition API。
- 图标:默认用 `lucide-vue-next`Vue 组件,按需 tree-shake。另装了 **Remix Icon**webfont补 lucide 缺的图标,品牌 Logo 即用 `ri-line-chart-line`
- CSS 已在 `main.ts` 全局引入 `remixicon/fonts/remixicon.css`,直接用 `<i class="ri-xxx-line" aria-hidden="true"></i>`
- webfont 字号靠 `text-*`font-size 驱动,不用 `size-*`);颜色继承 `currentColor`,所以放在 `text-white` 的容器里就是白色。
- 图标名查 https://remixicon.comv4.9,无 candlestick走势/图表类可用 `ri-line-chart-line` / `ri-bar-chart-line` / `ri-stock-line` / `ri-funds-line`)。
- `verbatimModuleSyntax: true`:类型 import 必须写 `import type { ... }`