Skip to content

Commit 7db0816

Browse files
authored
Merge pull request #15 from juwenzhang/feat/markdown-parser-package
Feat/markdown parser package
2 parents ffd8d75 + f8c7387 commit 7db0816

File tree

127 files changed

+15056
-85
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

127 files changed

+15056
-85
lines changed

.codebuddy/memory/2026-04-06.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# 2026-04-06 Session Log
2+
3+
## 修复 mermaid 依赖策略
4+
5+
### 问题
6+
- `md-parser-core` 把 mermaid 声明为 `peerDependencies`(optional),但 core 只在 worker 里 dynamic import
7+
- `md-parser-react``md-parser-vue` 把 mermaid 放在 `dependencies`,但构建时已 external 不打包
8+
- 导致消费者安装库包时被迫拉取 mermaid 整棵巨大依赖树
9+
10+
### 修改
11+
三个库包的 mermaid 全部改为 `devDependencies`(仅构建时类型解析用),两个 demo 应用自行在 `dependencies` 中安装 mermaid。
12+
13+
### 文件变更
14+
- `packages/md-parser-core/package.json` — 删除 peerDependencies,mermaid 移到 devDependencies
15+
- `packages/md-parser-react/package.json` — mermaid 从 dependencies 移到 devDependencies
16+
- `packages/md-parser-vue/package.json` — mermaid 从 dependencies 移到 devDependencies
17+
- `demo/react-app/package.json` — 新增 mermaid 到 dependencies
18+
- `demo/vue-app/package.json` — mermaid 从 devDependencies 移到 dependencies
19+
20+
### 验证
21+
- `pnpm install`
22+
- `pnpm run build` 全量构建通过 ✅
23+
24+
---
25+
26+
## 创建 md-parser-theme 样式包 — 样式与逻辑分离
27+
28+
### 决策
29+
将 CSS 样式从 React/Vue 包中完全抽离到独立的 `@luhanxin/md-parser-theme` 包,实现样式与逻辑分离。
30+
31+
### 修复的问题
32+
1. **类名不一致**:Mermaid 类名从 camelCase(`mermaidDiagram`)统一为 kebab-case(`mermaid-diagram`
33+
2. **`.skeleton` vs `.markdown-skeleton` 不匹配**:React CSS 定义 `.skeleton` 但 JSX 用 `.markdown-skeleton`,导致 loading 状态无样式
34+
3. **Vue 样式双重维护**:每个组件有 scoped CSS,MarkdownRenderer 又用 `:deep()` 重复定义一遍
35+
4. **KaTeX 类名**`.katexDisplay` 改为 `.katex-display`
36+
37+
### 文件变更
38+
#### 新增
39+
- `packages/md-parser-theme/package.json` — 新包配置
40+
- `packages/md-parser-theme/src/index.css` — 统一样式(475行,全 kebab-case)
41+
- `packages/md-parser-theme/README.md` — 使用文档
42+
43+
#### 修改
44+
- `packages/md-parser-react/src/components/MermaidDiagram.tsx` — 类名改 kebab-case
45+
- `packages/md-parser-react/package.json` — 移除 style 导出
46+
- `packages/md-parser-react/tsup.config.ts` — 不再打包 CSS
47+
- `packages/md-parser-vue/src/components/MermaidDiagram.vue` — 类名改 kebab-case,删除 scoped CSS
48+
- `packages/md-parser-vue/src/components/CustomContainer.vue` — 删除 scoped CSS
49+
- `packages/md-parser-vue/src/components/CodeBlock.vue` — 删除 scoped CSS
50+
- `packages/md-parser-vue/src/components/Mention.vue` — 删除 scoped CSS
51+
- `packages/md-parser-vue/src/components/Hashtag.vue` — 删除 scoped CSS
52+
- `packages/md-parser-vue/src/MarkdownRenderer.vue` — 删除全部 scoped/:deep() CSS
53+
- `packages/md-parser-vue/package.json` — 移除 style 导出
54+
- `demo/react-app/package.json` — 添加 theme 依赖
55+
- `demo/react-app/src/main.tsx` — 改用 `import '@luhanxin/md-parser-theme'`
56+
- `demo/vue-app/package.json` — 添加 theme 依赖
57+
- `demo/vue-app/src/main.ts` — 改用 `import '@luhanxin/md-parser-theme'`
58+
59+
#### 删除
60+
- `packages/md-parser-react/src/styles/markdown.css` — 旧 CSS 文件
61+
- `packages/md-parser-react/src/styles/` — 空目录
62+
63+
### 验证
64+
- typecheck: React ✅ Vue ✅
65+
- `pnpm run build` 全量构建通过 ✅
66+
- React demo (localhost:5173) 启动验证 ✅
67+
- Vue demo (localhost:5175) 启动验证 ✅
68+
- theme CSS 零 camelCase 残留 ✅
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
---
2+
name: fix-md-parser-build-errors
3+
overview: 修复 `pnpm run build` 中所有构建错误,涵盖 md-parser-react 路径错误、CodeBlock dompurify 依赖、Vue demo 模板字符串转义问题、缺失的 env.d.ts、以及未使用导入清理。
4+
todos:
5+
- id: fix-react-renderer-imports
6+
content: 修复 md-parser-react MarkdownRenderer.tsx 的 3 个错误相对路径(../ 改为 ./),移除 CodeBlock.tsx 的 dompurify 依赖
7+
status: completed
8+
- id: cleanup-unused-imports
9+
content: 清理所有包的未使用导入:React MarkdownProvider/useActiveHeading/ErrorBoundary,Vue MarkdownProvider
10+
status: completed
11+
- id: fix-vue-demo-template
12+
content: 修复 demo/vue-app App.vue 模板字符串反引号转义,清理 demo/react-app App.tsx 未使用的 useMarkdown 导入
13+
status: completed
14+
- id: verify-build
15+
content: 执行 pnpm run build 验证所有包构建通过
16+
status: completed
17+
dependencies:
18+
- fix-react-renderer-imports
19+
- cleanup-unused-imports
20+
- fix-vue-demo-template
21+
---
22+
23+
## 用户需求
24+
25+
修复 `pnpm run build` 的全部构建错误,使项目能够完整通过编译。
26+
27+
## 产品概述
28+
29+
当前 md-parser 三个包(core/react/vue)和两个 demo 应用在执行 `pnpm run build` 时存在多处构建阻断错误,需要逐一修复。
30+
31+
## 核心问题
32+
33+
1. **md-parser-react 路径错误**: `MarkdownRenderer.tsx` 使用 `../context/``../hooks/` 引用同级目录,应为 `./context/``./hooks/`
34+
2. **md-parser-react CodeBlock 冗余依赖**: `CodeBlock.tsx` 引入了 `dompurify`,但未声明依赖且 core 已内置 rehype-sanitize,属于冗余二次清理
35+
3. **demo/vue-app 模板字符串转义**: `App.vue` 中反引号被错误转义为 `\`` 导致 JS 语法解析失败
36+
4. **多处未使用导入**: React/Vue 包和 demo 中存在未使用的 import(`RenderLevel``useCallback``React``useMarkdown` 等)
37+
5. **demo/react-app 隐式 any**: EventHandlers 回调参数隐式 any,是上游包未构建的连锁反应
38+
39+
## 技术栈
40+
41+
- 前端构建: tsup (md-parser-react) / vite lib mode (md-parser-vue) / vite (demo apps)
42+
- TypeScript: strict mode, bundler moduleResolution
43+
- 包管理: pnpm workspace, workspace:* 引用
44+
45+
## 实现方案
46+
47+
修复策略按构建依赖链从上游到下游逐步修复:
48+
49+
```
50+
md-parser-core (已通过)
51+
-> md-parser-react (修复路径 + 移除 dompurify + 清理未使用导入)
52+
-> demo/react-app (清理未使用导入)
53+
-> md-parser-vue (清理未使用导入)
54+
-> demo/vue-app (修复模板字符串转义)
55+
```
56+
57+
### 关键技术决策
58+
59+
**CodeBlock.tsx 的 DOMPurify 处理 -- 选择移除而非保留**:
60+
61+
- md-parser-core 已内置 `rehype-sanitize` 做完整的 XSS 防护,Shiki 高亮输出在 pipeline 中已经过 sanitize
62+
- CodeBlock 组件接收的 `highlightedHtml` 来自 core 渲染结果,已是安全 HTML
63+
- 移除 DOMPurify 可以减少包体积 + 消除对额外依赖的需求
64+
- 移除后直接使用 `highlightedHtml` 赋值给 `dangerouslySetInnerHTML`
65+
66+
## 实现细节
67+
68+
### 1. md-parser-react/src/MarkdownRenderer.tsx -- 路径修复
69+
70+
- `../context/MarkdownProvider` -> `./context/MarkdownProvider`
71+
- `../hooks/useEventDelegation` -> `./hooks/useEventDelegation`
72+
- `../hooks/useMarkdown` -> `./hooks/useMarkdown`
73+
74+
### 2. md-parser-react/src/components/CodeBlock.tsx -- 移除 dompurify
75+
76+
- 删除 `import DOMPurify from 'dompurify'`
77+
- 删除 `useMemo` 中的 `DOMPurify.sanitize()` 调用
78+
- 直接使用 `highlightedHtml` 传入 `dangerouslySetInnerHTML`
79+
- 若仍需 `useMemo`(无需,因为 `highlightedHtml` 本身已是 prop),可简化为直接使用
80+
81+
### 3. md-parser-react/src/context/MarkdownProvider.tsx -- 清理导入
82+
83+
- 移除未使用的 `RenderLevel` 类型导入
84+
85+
### 4. md-parser-react/src/hooks/useActiveHeading.ts -- 清理导入
86+
87+
- 移除未使用的 `useCallback`
88+
89+
### 5. md-parser-react/src/components/MarkdownErrorBoundary.tsx -- 清理导入
90+
91+
- `import React, { Component, ... }` -> `import { Component, ... }`(react-jsx transform 不需要显式 React 导入)
92+
93+
### 6. md-parser-vue/src/context/MarkdownProvider.ts -- 清理导入
94+
95+
- 移除未使用的 `RenderLevel` 类型导入
96+
97+
### 7. demo/vue-app/src/App.vue -- 模板字符串转义修复
98+
99+
- 将所有 `\`` 还原为正常反引号
100+
- 将所有 `\${` 还原为正常 `${` 模板插值
101+
- 移除未使用的 `computed` 导入
102+
103+
### 8. demo/react-app/src/App.tsx -- 清理导入
104+
105+
- 移除未使用的 `useMarkdown` 导入
106+
- EventHandlers 回调参数的隐式 any 会在上游 md-parser-react 修复后自动解决
107+
108+
## 目录结构
109+
110+
```
111+
packages/
112+
├── md-parser-react/src/
113+
│ ├── MarkdownRenderer.tsx # [MODIFY] 修复 3 个 import 路径 ../->./
114+
│ ├── components/
115+
│ │ ├── CodeBlock.tsx # [MODIFY] 移除 dompurify,简化 sanitize 逻辑
116+
│ │ └── MarkdownErrorBoundary.tsx # [MODIFY] 移除未使用的 React 导入
117+
│ ├── context/
118+
│ │ └── MarkdownProvider.tsx # [MODIFY] 移除未使用的 RenderLevel 导入
119+
│ └── hooks/
120+
│ └── useActiveHeading.ts # [MODIFY] 移除未使用的 useCallback 导入
121+
├── md-parser-vue/src/
122+
│ └── context/
123+
│ └── MarkdownProvider.ts # [MODIFY] 移除未使用的 RenderLevel 导入
124+
demo/
125+
├── react-app/src/
126+
│ └── App.tsx # [MODIFY] 移除未使用的 useMarkdown 导入
127+
└── vue-app/src/
128+
└── App.vue # [MODIFY] 修复模板字符串反引号转义
129+
```
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
---
2+
name: fix-md-parser-packages
3+
overview: 系统性修复 md-parser-core/react/vue 三个包及两个 demo 中存在的类名不一致、导出缺失、安全配置不一致、CSS 命名错误、README 过时等问题。
4+
todos:
5+
- id: fix-react-components
6+
content: 修复 React 包:CustomContainer/CodeBlock 类名改为 kebab-case,index.ts 添加 MermaidDiagram 导出
7+
status: completed
8+
- id: fix-react-css
9+
content: React CSS 文件 markdown.module.css 重命名为 markdown.css,更新 tsup.config.ts 入口路径,修复响应式媒体查询类名,清理空 types 目录
10+
status: completed
11+
- id: fix-vue-components
12+
content: 修复 Vue 包:CustomContainer/CodeBlock 类名和 scoped CSS 改为 kebab-case,MermaidDiagram securityLevel 改为 strict
13+
status: completed
14+
- id: fix-readmes
15+
content: 更新 React/Vue 包 README,将 DOMPurify 描述替换为 rehype-sanitize + mermaid strict
16+
status: completed
17+
- id: verify-all
18+
content: 执行 pnpm run typecheck 和 pnpm run build 全量验证所有修复
19+
status: completed
20+
dependencies:
21+
- fix-react-components
22+
- fix-react-css
23+
- fix-vue-components
24+
- fix-readmes
25+
---
26+
27+
## 用户需求
28+
29+
全面审查并修复 md-parser-core、md-parser-react、md-parser-vue 三个包及两个 demo 应用中的所有代码质量问题。
30+
31+
## 核心修复内容
32+
33+
### 高优先级
34+
35+
1. React 包 index.ts 缺少 MermaidDiagram 组件导出
36+
2. React CustomContainer.tsx 组件类名与 Core 输出不一致(camelCase vs kebab-case)
37+
3. React CodeBlock.tsx 组件类名与 Core 输出不一致
38+
4. Vue MermaidDiagram.vue securityLevel 为 'loose',应改为 'strict'
39+
5. Vue CustomContainer.vue 和 CodeBlock.vue 类名与 Core 不一致
40+
41+
### 中优先级
42+
43+
6. React CSS 响应式媒体查询中 `.markdownBody` 应为 `.markdown-body`
44+
7. CSS 文件名 `markdown.module.css` 误导,实际不作为 CSS Module 使用,应改为 `markdown.css`
45+
8. React/Vue README 仍提及已移除的 DOMPurify
46+
47+
### 低优先级
48+
49+
9. React `src/types/` 空目录清理
50+
10. 修复完成后执行全量 typecheck + build 验证
51+
52+
## 技术栈
53+
54+
- md-parser-core: tsup 构建,输出 kebab-case 类名(`custom-container``code-block-wrapper`
55+
- md-parser-react: tsup 构建,React 18,CSS 作为独立入口打包
56+
- md-parser-vue: vite lib 模式构建,Vue 3 + scoped CSS
57+
- demo: vite dev/build
58+
59+
## 实现方案
60+
61+
### 核心思路
62+
63+
Core 包的 `hast-handlers.ts``rehype-code-meta.ts` 定义了 HTML 输出的类名(kebab-case),是整个系统的**唯一真相源**。React 和 Vue 的独立组件(CustomContainer、CodeBlock)的类名必须与 Core 输出保持一致,这样:
64+
65+
1. CSS 样式能同时命中 `dangerouslySetInnerHTML/v-html` 渲染的 core 输出和独立组件
66+
2. 用户自定义样式只需写一套选择器
67+
68+
### 修复策略
69+
70+
- **React 独立组件**:将 className 从 camelCase 改为 kebab-case,与 Core 和已修改的 CSS 文件保持一致
71+
- **Vue 独立组件**:同样修改模板和 scoped CSS 中的类名为 kebab-case
72+
- **CSS 文件重命名**`markdown.module.css``markdown.css`,同步更新 tsup.config.ts 入口路径
73+
- **securityLevel 统一**:Vue MermaidDiagram 从 `'loose'` 改为 `'strict'`
74+
75+
## 实现注意事项
76+
77+
- CSS 文件重命名后必须更新 `tsup.config.ts` 中的入口路径
78+
- Vue scoped CSS 的类名修改需同时修改 `<template>``<style scoped>` 两处
79+
- README 中 DOMPurify 的描述需替换为实际使用的安全机制(rehype-sanitize + mermaid securityLevel:strict
80+
- 修复完成后执行 `pnpm run typecheck``pnpm run build` 全量验证
81+
82+
## 目录结构
83+
84+
```
85+
packages/md-parser-react/
86+
├── src/
87+
│ ├── index.ts # [MODIFY] 添加 MermaidDiagram 导出
88+
│ ├── components/
89+
│ │ ├── CustomContainer.tsx # [MODIFY] 类名 camelCase → kebab-case
90+
│ │ └── CodeBlock.tsx # [MODIFY] 类名 camelCase → kebab-case
91+
│ ├── styles/
92+
│ │ └── markdown.module.css → markdown.css # [RENAME] 去掉 .module 后缀
93+
│ └── types/ # [DELETE] 空目录
94+
├── tsup.config.ts # [MODIFY] CSS 入口路径更新
95+
└── README.md # [MODIFY] DOMPurify 描述修正
96+
97+
packages/md-parser-vue/
98+
├── src/
99+
│ ├── components/
100+
│ │ ├── CustomContainer.vue # [MODIFY] 类名 + scoped CSS kebab-case
101+
│ │ ├── CodeBlock.vue # [MODIFY] 类名 + scoped CSS kebab-case
102+
│ │ └── MermaidDiagram.vue # [MODIFY] securityLevel: 'loose' → 'strict'
103+
└── README.md # [MODIFY] DOMPurify 描述修正
104+
```

0 commit comments

Comments
 (0)