Lazy loaded image
技术分享
🔖Joint MD:把零散 Markdown 变成一篇可以认真读的文档
字数 2446阅读时长≈ 7 分钟
2026-8-12
2026-8-12
一款本地优先的 Markdown 合并与阅读工具:把多个 Markdown 文件按顺序拼成一个 Merged Document,实时预览、沉浸阅读。
我平时会把笔记、技术资料和阶段性记录拆成很多个 Markdown 文件。拆分有利于维护,但当我想完整阅读一组内容,或者把它交给别人时,往往还要手动复制、调整顺序、补分隔线,再另存一份文件。Joint MD 就是为这个过程做的一个小工具。
Joint MD 适合这些相对明确的任务:
  • 把一组章节 Markdown 按指定顺序合成一篇文档。
  • 阅读多个 Markdown 文件组成的长文档,并通过目录快速跳转。
  • 将 Markdown 合并结果下载为一个 .md 文件。
  • 在不上传源文件的前提下,临时整理一批个人资料。

界面演示

notion image
notion image

如何运行

项目要求 Node.js 20 或更高版本。拉取项目后,在根目录执行:
开发服务器通常会运行在:
如果需要验证生产构建或安装 PWA,即在本地按照浏览器应用启动项,可以执行:
项目还提供了几个常用脚本:
Joint MD 也可以作为 PWA 安装到桌面或应用列表中。不过开发模式不会启用 PWA,应该用 build 加 preview 的方式验证安装流程。

Markdown 使用流程

1. 添加源文件

打开 Joint MD 后,左侧是 源文件队列。可以把 .md 或 .markdown 文件拖进投放区,也可以通过文件选择器添加。
这里有一个有意保持简单的规则:一个会话内只能处理一种文件类型。Markdown 文件不能和 EPUB 混在同一个队列里;如果要切换类型,需要先清空当前队列。
Markdown 单文件大小上限是 5 MB。文件会通过浏览器 File API 读取,当前版本不做内容上传。

2. 调整文件顺序

文件队列的顺序就是合并后的顺序。每一行文件都支持拖动排序,也可以使用上移、下移和移除操作。
点击某个文件名,还可以让右侧预览平滑滚动到该源文件在 Merged Document 中的起始位置。这个小交互很适合检查章节顺序,尤其是文件数量较多时,不需要在长文档里反复搜索。

3. 选择 Join Mode

左侧的“拼接与导出”区域提供三种 Join Mode:
  • Plain:文件之间只保留空行,适合内容本身已经有清晰标题的资料。
  • Rule:文件之间插入 Markdown 水平线 --,适合区分独立文章或章节。默认模式就是它。
  • Filename Heading:在每个源文件前生成一个 H1,标题来自文件名并去掉扩展名,适合文件名本身就是章节标题的情况。
Join Mode 改变后,Merged Document、目录、阅读进度标识以及导出内容都会随之更新,不需要额外点击“开始合并”。

4. 设置 Export Name

Export Name 是导出文件的基础名称,不需要手动输入扩展名。例如输入 frontend-notes,下载的 Markdown 文件会使用 frontend-notes.md;打印流程也会使用这个名称作为窗口标题。

5. 阅读和导出

右侧是实时的 GFM Preview。它支持 GitHub Flavored Markdown 常见能力,包括表格、代码块、引用、任务列表和删除线等。
确认内容后,可以选择:
  • Export Markdown:下载合并后的原始 Markdown 文本。
  • Print to PDF:打开浏览器打印流程,在目标打印机中选择“另存为 PDF”。
PDF 并不是由服务器或额外 PDF 引擎生成,而是使用浏览器现成的打印能力。这样做的好处是正文仍然是可选择的文本,不会退化成截图式 PDF。

EPUB 阅读模式

除了 Markdown,Joint MD 还可以导入 .epub 文件。EPUB 会在浏览器中解析,章节和内嵌资源会被整理后用于页面预览。EPUB 单文件大小上限是 50 MB。
EPUB 模式更接近一个本地阅读队列:可以按章节浏览,也可以使用字号、纸张色和 Reader Mode。Print to PDF 同样可用,但 Export Markdown 在 EPUB 模式下会被禁用,因为项目当前不承担 EPUB 到 Markdown 的转换和重新排版。

整体 UI 说明

这个项目里没有采用常见的“顶部导航 + 一堆功能卡片”的布局,而是把整个界面收敛成一个双栏 Workbench。它的重点不是展示功能,而是能够实时看到文件当前排在哪里,以及合并后的正文现在是什么样。

左侧:可操作的 File Queue

左侧控制面板负责所有输入和组织动作:
  • 顶部显示当前队列类型和文件数量。
  • 中间是明显的拖放区域,降低添加文件的操作成本。
  • 文件列表使用紧凑行布局,方便在多个文件之间进行排序、定位和移除。
  • 底部集中放置 Export Name 与 Join Mode,避免设置散落在页面各处。

右侧:实时的 Merged Document

右侧预览区由标题栏、正文和底部导出栏组成。标题栏会显示当前文档名、文件数量和字符数,并提供几个低干扰的阅读工具:
  • 打开或关闭 H1-H3 目录。
  • 减小或增大字号。
  • 切换柔和纸张色。
从当前 Merged Document 中提取出来的 H1 到 H3 标题。因此当 Join Mode 使用 Filename Heading 时,文件名生成的标题也会自然出现在目录中。
底部导出栏把最终动作固定在阅读区下方。没有源文件时,按钮会保持不可用;EPUB 模式下,Markdown 下载按钮也会明确处于禁用状态。状态提示则放在同一位置,用来反馈导入和导出结果。

Reader Mode:把工作台收成阅读器

当我不再需要调整文件,而是准备从头阅读时,可以点击顶部的“阅读模式”。这不是一次路由跳转,而是 Workbench 的布局状态变化:
  • 左侧 File Queue 隐藏。
  • 正文区域居中,阅读宽度收窄到更适合长文阅读的范围。
  • 内容左右留出更充足的边距。
  • 行距变得更舒展,减少长段落阅读时的视觉拥挤。
阅读模式的价值不在于增加一个新页面,而在于让同一份文档在“整理”和“阅读”之间快速切换,避免用户丢失当前上下文。

阅读进度与隐私

Joint MD 对浏览器存储的使用分成两类:
  • Reader Preferences:字号和柔和纸张色等跨文档偏好会保存在浏览器中。
  • Reading Progress:特定 Merged Document 的阅读位置会根据文档内容指纹记录,之后再次打开同一份内容时尝试恢复。
源文件正文不写入这些存储。刷新或关闭页面后,当前 File Queue 和源文件内容会清空;偏好设置和阅读进度可能继续保留。PWA 的 Service Worker 也只缓存应用壳,也就是 HTML、JavaScript、CSS、字体和图标,不会缓存用户导入的文件正文。
对个人笔记、内部资料和临时整理任务来说,这个边界很重要:工具能提供便利,但不会默认替用户建立一份云端副本。

当前版本的边界

为了让工具保持可理解,v1 暂时不做这些事情:
  • PDF 转 Markdown 和 OCR。
  • 云端存储、账号和多人协作。
  • 服务端处理用户文件。
  • 根据每个 Markdown 源文件原来的路径解析相对图片或链接。
  • EPUB 导出为 Markdown,或完整的 EPUB 编辑和重新打包。
因此,Joint MD 更像一个“本地文档工作台”:它把已有文件整理成连续的阅读对象,帮助我快速检查、阅读和交付,而不是试图替代编辑器、知识库或发布系统。

项目的总结

Joint MD 最有价值的地方,不是把很多格式和按钮堆在一起,而是把一个具体动作做得足够完整:将一组本地 Markdown 文件按顺序组织起来,实时得到 Merged Document,再从阅读状态自然过渡到导出。
如果你的资料已经以 Markdown 为主,常常需要合并章节、整理学习笔记,或者希望在不上传文件的情况下快速生成可读版本,这个工具提供了一条很短的路径:拖入文件,排好顺序,选择 Join Mode,打开目录阅读,最后导出 Markdown 或打印成 PDF。
上一篇
Conda基础学习笔记
下一篇
dount