# 萌芽笔记 🌱 一个优雅的 Markdown 笔记 Web 应用,支持实时预览和 GitHub 风格渲染。 > **🎉 v2.0 重要更新 (2025-12-19)** > - ✅ 完全移除 localStorage 依赖,解决浏览器权限弹窗问题 > - ✅ 完美支持移动端浏览器(微信、Safari iOS 等) > - ✅ 隐私模式/无痕模式下正常工作 > - ✅ 添加错误边界和友好的错误提示 > - ✅ 优化网络请求,支持相对路径部署 > - 📖 详细说明请查看 [前端优化说明.md](前端优化说明.md) ## ✨ 特性 - 📝 **Markdown 渲染**: 使用 `react-markdown` 提供强大的渲染能力 - 🎨 **GitHub 风格**: 标准的 GitHub Markdown 样式 - 🔤 **霞鹜文楷字体**: 全站使用 LXGW WenKai Mono 等宽字体 - 📂 **文件树导航**: 直观的侧边栏目录结构 - 🚀 **快速响应**: FastAPI 后端 + React 前端 - 💡 **代码高亮**: 支持多种编程语言的语法高亮 - 🧮 **数学公式**: KaTeX 数学公式渲染支持 - 📱 **响应式设计**: 完美适配桌面和移动设备 - 🌐 **跨浏览器兼容**: 支持所有主流浏览器和移动端 - 🔒 **隐私模式支持**: 在隐私/无痕模式下正常工作 ## 🛠 技术栈 ### 后端 - **Python 3.8+** - **FastAPI** - 现代、快速的 Web 框架 - **Uvicorn** - ASGI 服务器 ### 前端 - **React 19** - 用户界面库 - **Vite 7** - 极速构建工具 - **react-markdown** - Markdown 渲染 - **github-markdown-css** - GitHub 风格样式 - **rehype/remark 插件** - 扩展 Markdown 功能 - GFM (GitHub Flavored Markdown) - 代码高亮 (highlight.js) - 数学公式 (KaTeX) - HTML 支持 ## 🚀 快速开始 ### 方式一:使用批处理脚本(Windows推荐) #### 启动后端 双击运行 `启动后端.bat` #### 启动前端 双击运行 `启动前端.bat` ### 方式二:手动启动 #### 1. 启动后端服务 ```bash # 进入后端目录 cd mengyanote-backend # 安装依赖(首次运行) pip install -r requirements.txt # 启动服务 python main.py ``` 后端将在 `http://localhost:8000` 运行 #### 2. 启动前端服务 ```bash # 进入前端目录 cd mengyanote-frontend # 安装依赖(首次运行) npm install # 启动开发服务器 npm run dev ``` 前端将在 `http://localhost:5173` 运行 ## 📁 项目结构 ``` mengyanote/ ├── mengyanote-backend/ # 后端服务 │ ├── main.py # FastAPI 应用入口 │ ├── requirements.txt # Python 依赖 │ └── mengyanote/ # Markdown 文件存储目录 │ ├── 编程语言/ │ ├── 计算机科普/ │ ├── 计算机网络/ │ └── ... │ ├── mengyanote-frontend/ # 前端应用 │ ├── src/ │ │ ├── components/ # React 组件 │ │ │ ├── Sidebar.jsx # 侧边栏组件 │ │ │ ├── MarkdownRenderer.jsx # Markdown 渲染器 │ │ │ └── ... │ │ ├── context/ # React Context │ │ ├── utils/ # 工具函数 │ │ ├── App.jsx # 主应用组件 │ │ └── main.jsx # 应用入口 │ ├── public/ # 静态资源 │ │ └── LXGWWenKaiMono-Medium.ttf # 字体文件 │ ├── package.json # 前端依赖 │ └── vite.config.js # Vite 配置 │ ├── 启动后端.bat # 后端启动脚本 ├── 启动前端.bat # 前端启动脚本 ├── 启动说明.md # 详细启动说明 └── README.md # 项目说明 ``` ## 🎯 功能说明 ### 后端 API - `GET /api/tree` - 获取文件树结构 - `GET /api/file?path={path}` - 获取指定文件内容 - `GET /api/health` - 健康检查 - `GET /docs` - API 文档(Swagger UI) ### 前端功能 - **文件导航**: 点击左侧文件树浏览笔记 - **Markdown 渲染**: 自动渲染 GitHub 风格的 Markdown - **代码高亮**: 自动识别并高亮代码块 - **数学公式**: 支持行内和块级数学公式 - **图片支持**: 点击图片可放大查看 - **外链处理**: 外部链接自动在新标签页打开 ## 🎨 字体配置 项目使用 **霞鹜文楷等宽体 (LXGW WenKai Mono)** 作为全站字体。 字体文件位置:`mengyanote-frontend/public/LXGWWenKaiMono-Medium.ttf` 如果字体文件缺失,系统会自动回退到默认字体。 ## 🔧 环境变量 ### 前端环境变量(可选) 在 `mengyanote-frontend` 目录创建 `.env` 文件: ```env VITE_API_BASE=http://localhost:8000 ``` ## 📦 构建生产版本 ### 前端构建 ```bash cd mengyanote-frontend npm run build ``` 构建产物在 `dist` 目录,可部署到任何静态托管服务。 ## 🐛 故障排除 ### 前端无法连接后端 1. 确认后端服务正在运行(访问 http://localhost:8000/api/health) 2. 检查浏览器控制台的网络请求错误 3. 确认后端端口为 8000 ### 字体未加载 1. 确认 `LXGWWenKaiMono-Medium.ttf` 存在于 `public` 目录 2. 检查浏览器开发者工具的网络面板 3. 清除浏览器缓存重试 ### Markdown 渲染异常 1. 检查文件编码是否为 UTF-8 2. 查看浏览器控制台错误信息 3. 确认 react-markdown 相关依赖已正确安装 ## 📝 开发建议 1. **IDE**: 推荐使用 VS Code 2. **代码规范**: 前端使用 ESLint 进行代码检查 3. **热重载**: 后端和前端都支持热重载,修改代码自动刷新 4. **调试**: 使用 Chrome DevTools 进行前端调试 --- **Made with ❤️ by 树萌芽** ## 🛠 技术栈 - React 19 + Hooks + Context - Vite 构建 - react-markdown + remark / rehype 插件: - `remark-gfm`(扩展语法) - `remark-math`(数学公式) - `remark-breaks`(软换行) - `rehype-raw`(允许原始 HTML 渲染) - `rehype-katex`(数学公式渲染) - `rehype-highlight`(代码高亮) - Highlight.js 默认主题(可替换) - KaTeX 样式(按需可移除) 所有数据生成逻辑在 **Node 脚本层** 完成,前端只做纯渲染,部署安全轻量。 ## ⚡ 快速开始(Windows / cmd.exe) 1. 安装依赖 ``` npm install ``` 2. 本地开发(会先生成静态数据) ``` npm run dev ``` 这会先执行 `node scripts/generateData.js` 从 `public/mengyanote` 读取 Markdown 并生成 `src/data` 下的 `directoryTree.json` / `fileContents.json` / `stats.json`,然后启动 Vite 开发服务器。 3. 生成生产构建 ``` npm run build ``` 4. 预览构建产物 ``` npm run preview ``` 5. 单独生成数据(不启动服务器) ``` npm run generate-data ``` 6. 代码检查 ``` npm run lint ``` ## 🧬 项目结构(重要文件/目录) - `public/mengyanote/` - 源 Markdown 笔记目录(请把你的 .md 文件放在这里以纳入站点)。 - `scripts/generateData.js` - 将 Markdown 文件读取并生成 `src/data` 的脚本。 - `src/data/` - 由脚本生成的 JSON 数据(目录树、文件内容、统计信息)。 - `src/components/MarkdownRenderer.jsx` - Markdown 渲染组件(样式与功能定制点)。 - `src/components/MarkdownRenderer.css` - Markdown 渲染相关样式(可在此处简化或替换为你喜欢的样式)。 - `src/components/Sidebar.jsx` - 侧边栏目录树组件。 - `src/context/AppContext.jsx` - 全局上下文与路由状态。 - `scripts/` - 工具脚本(目前包含 `generateData.js`)。 示例:如果你想让 Markdown 渲染更简洁(“换成我图片那种”样式),可以编辑 `src/components/MarkdownRenderer.css` 或直接修改 `MarkdownRenderer.jsx` 中的渲染类名/元素结构。 ## ✍️ 如何编辑/添加笔记 1. 在 `public/mengyanote` 下增加或修改 `.md` 文件,保持目录组织即可。 2. 运行 `npm run generate-data`(或 `npm run dev`)以重新生成 `src/data`。 3. 刷新浏览器查看最新内容。 ### 忽略机制 - 默认忽略:`.obsidian`、`.trash`、`.git`、`node_modules`、所有以 `.` 开头的文件或目录。 - 自定义忽略:在 `public/mengyanote/ignore.json` 中加入: ```jsonc { "ignore": ["临时", "草稿.md", "private"] } ``` > ignore.json 位于源根目录(`public/mengyanote`),脚本运行时会打印“已加载忽略配置”。 ## 🚢 部署建议 - 静态站点:`npm run build` 会在 `dist/` 生成静态文件,适合部署到 GitHub Pages、Netlify、Vercel、或任意静态文件托管服务。 - GitHub Pages:构建后将 `dist/` 的内容发布到 gh-pages 分支或通过 GitHub Actions 自动发布。 示例(手工): 1. 构建 ``` npm run build ``` 2. 将 `dist/` 内容上传到你的静态托管服务或 gh-pages 分支。 如果需要,我可以为你添加一个自动部署到 GitHub Pages 的 GitHub Actions 工作流(`deploy.yml`)。示例工作流会: 1. 触发条件:`push` 到 `main` 或手动触发 2. 安装依赖 & 运行 `npm run build` 3. 发布 `dist/` 到 `gh-pages` 分支 (如需请开 Issue 或在 PR 中请求) ### 其他托管方式 | 平台 | 方式 | 备注 | |------|------|------| | GitHub Pages | gh-pages 分支 / Action | 需启用 Pages | | Netlify | 直接连接仓库 | Build 命令:`npm run build`,Publish:`dist` | | Vercel | 导入项目 | 自动识别 Vite | | OSS / Nginx | 上传 dist | 纯静态即可 | ### 基础 Nginx 配置示例 ```nginx server { listen 80; server_name example.com; root /var/www/markdown-to-web/dist; location / { try_files $uri /index.html; } add_header Cache-Control "public, max-age=31536000"; } ``` ## 🎨 定制渲染样式 如果你觉得当前 Markdown 美化太重并想改回更简洁的“图片优先”或原始样式: - 编辑 `src/components/MarkdownRenderer.css`:移除或覆盖过度的样式(字体、背景、代码块高亮等)。 - 编辑 `src/components/MarkdownRenderer.jsx`:调整渲染器的 className、元素包装或忽略某些 remark/rehype 插件。 ### 常见修改点 | 需求 | 修改位置 | 说明 | |------|----------|------| | 去掉公式支持 | `MarkdownRenderer.jsx` | 移除 `remark-math` / `rehype-katex` 并删 CSS 引入 | | 去掉代码高亮 | `MarkdownRenderer.jsx` | 移除 `rehype-highlight` 与对应样式 | | 禁用内联代码特殊样式 | 已内置 | 自定义插件 `remarkDisableInlineCode` 已将 inlineCode 转普通文本 | | 改图片最大宽度 | `MarkdownRenderer.css` | 调整 `.markdown-image img` | | 更换高亮主题 | 安装新主题 | 引入其他 highlight.js CSS | | 调整面包屑 | `fileUtils.generateBreadcrumbs` | 可改分隔符或格式 | ### 架构 / 数据流程简述 ``` ┌──────────────┐ 扫描/过滤 ┌────────────────┐ JSON写入 ┌───────────────┐ │ public/mengya │ ─────────────▶ │ generateData.js │ ───────────▶ │ src/data/*.json │ │ note/ (原始MD)│ ignore.json │ (Node脚本) │ public/data │ (目录/内容/统计)│ └──────────────┘ └────────────────┘ └───────────────┘ │ ▼ 前端 (React 渲染) ``` 前端加载策略:尝试按顺序 fetch:`/data/...` → `/src/data/...` → `./data/...`。 ### 渲染组件要点 - 代码块组件:支持复制、语言标签、降尾换行处理 - 图片:包裹 `
` + `
` - 标题:自动生成 `id` + 锚点链接 - 链接:区分内部/外部,`[[wikilink]]` 保留为文本标签(可扩展) - 表格:外层包裹 div 实现横向滚动容器 ### 性能提示 - Markdown 数量巨大时,可按需拆分 lazy-load(目前为一次性加载全部 JSON) - 可拓展为:构建阶段拆分单文件 JSON,运行时按需请求 - 可增加 Service Worker 缓存静态 JSON ## ❓ 常见问题(FAQ) **Q: 为什么我新增文件后页面没有显示?** A: 需要重新运行 `npm run generate-data` 或 `npm run dev` 让脚本再生成数据。 **Q: 想忽略某个目录但它还是出现?** A: 确认 `ignore.json` 位于 `public/mengyanote/` 根目录,键名是 `ignore`,数组项不要写路径前缀。 **Q: 能否按需加载而不是一次性加载所有内容?** A: 当前实现为构建期大 JSON。可拓展为“每文件单独 JSON + 动态 fetch”。 **Q: 是否支持搜索?** A: 目前未实现。可通过构建阶段生成反向索引(lunr / minisearch)再前端搜索。 **Q: 图片如何放大预览?** A: 可在 `MarkdownRenderer.jsx` 中为 `img` 包裹 Lightbox 组件或添加点击事件。 **Q: 可以改成多语言站点?** A: 可在数据生成脚本中区分语言目录(如 `en/`、`zh/`),渲染层添加语言切换上下文。 ## 🧭 Roadmap(计划) - [ ] 全文搜索(可选:关键词高亮) - [ ] 按需加载:文件内容拆分 - [ ] 文件更新 diff / 最近更新列表 - [ ] Tag/Frontmatter 支持(YAML 解析) - [ ] RSS / JSON Feed 输出 - [ ] 导出 PDF / 打印优化 - [ ] Service Worker 缓存加速 - [ ] GitHub Actions 自动部署工作流示例 欢迎在 Issue 中补充你的需求。 ## 🤝 贡献与许可 欢迎提交 Issue 或 Pull Request。仓库包含 `LICENSE`(请查看该文件以确认许可证类型)。 为了保持项目干净: - 新功能请先创建 issue 讨论。 - 提交 PR 时附带简短说明和相关截图(如果是 UI 变更)。