Markdown To Web
将本地 Markdown 笔记目录“一键”编译为可部署的静态 React 网站。
此仓库会读取 public/mengyanote/ 下的所有 Markdown 文件,生成 JSON 数据,并在前端通过 React + react-markdown 渲染,最终可直接构建成 纯静态站点(可部署到 GitHub Pages / Netlify / Vercel / 任意 Nginx / OSS 等)。
本 README(中文)包含:项目定位、特性说明、运行与构建、内部工作原理、目录结构、忽略与定制、部署方式、常见问题(FAQ)与未来计划(Roadmap)。
如需英文版本,请查看 README.en.md。
✨ 主要特性
- 🚀 一键生成数据:脚本自动递归扫描
public/mengyanote,提取目录树、文件内容与统计信息。 - 📦 纯静态输出:构建阶段就准备好全部数据,无需后端 / Serverless API。
- 🧭 动态目录树:可展开/折叠,每个节点保留唯一
path与id。 - 📝 Markdown 全面支持:GFM(表格 / 任务列表 / 删除线)、换行、数学公式(KaTeX)、代码块高亮(Highlight.js)。
- 🧮 数学公式渲染:
remark-math+rehype-katex。 - 💡 代码体验增强:复制按钮、语言标签、自动高亮。
- 📚 面包屑导航:基于文件路径实时生成。
- 🧱 可定制渲染组件:可移除/替换任意 remark/rehype 插件,或覆写组件(如链接、图片、表格、代码块)。
- 🕶 深色风格(可自定义):CSS 易修改,可换成“极简/原味/图片优先”布局。
- 🔍 预生成数据多路径兜底:前端运行时尝试从
/data或/src/data加载,兼容不同构建/部署结构。 - 🧯 忽略机制:支持
ignore.json自定义排除目录 / 文件。 - 📊 统计信息:生成文件总数、文件夹总数、生成时间等元数据。
该项目适合:知识库发布、学习笔记归档、团队内部静态文档、离线备份网页化。
🛠 技术栈
- 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)
- 安装依赖
npm install
- 本地开发(会先生成静态数据)
npm run dev
这会先执行 node scripts/generateData.js 从 public/mengyanote 读取 Markdown 并生成 src/data 下的 directoryTree.json / fileContents.json / stats.json,然后启动 Vite 开发服务器。
- 生成生产构建
npm run build
- 预览构建产物
npm run preview
- 单独生成数据(不启动服务器)
npm run generate-data
- 代码检查
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 中的渲染类名/元素结构。
✍️ 如何编辑/添加笔记
- 在
public/mengyanote下增加或修改.md文件,保持目录组织即可。 - 运行
npm run generate-data(或npm run dev)以重新生成src/data。 - 刷新浏览器查看最新内容。
忽略机制
- 默认忽略:
.obsidian、.trash、.git、node_modules、所有以.开头的文件或目录。 - 自定义忽略:在
public/mengyanote/ignore.json中加入:
{
"ignore": ["临时", "草稿.md", "private"]
}
ignore.json 位于源根目录(
public/mengyanote),脚本运行时会打印“已加载忽略配置”。
🚢 部署建议
- 静态站点:
npm run build会在dist/生成静态文件,适合部署到 GitHub Pages、Netlify、Vercel、或任意静态文件托管服务。 - GitHub Pages:构建后将
dist/的内容发布到 gh-pages 分支或通过 GitHub Actions 自动发布。
示例(手工):
- 构建
npm run build
- 将
dist/内容上传到你的静态托管服务或 gh-pages 分支。
如果需要,我可以为你添加一个自动部署到 GitHub Pages 的 GitHub Actions 工作流(deploy.yml)。示例工作流会:
- 触发条件:
push到main或手动触发 - 安装依赖 & 运行
npm run build - 发布
dist/到gh-pages分支
(如需请开 Issue 或在 PR 中请求)
其他托管方式
| 平台 | 方式 | 备注 |
|---|---|---|
| GitHub Pages | gh-pages 分支 / Action | 需启用 Pages |
| Netlify | 直接连接仓库 | Build 命令:npm run build,Publish:dist |
| Vercel | 导入项目 | 自动识别 Vite |
| OSS / Nginx | 上传 dist | 纯静态即可 |
基础 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/...。
渲染组件要点
- 代码块组件:支持复制、语言标签、降尾换行处理
- 图片:包裹
<figure>+<figcaption> - 标题:自动生成
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 变更)。