DotMD:一款基于 Go + Wails 的轻量开源 Markdown 桌面编辑器
Markdown 写作,应该像喝水一样简单。
一、引言
Markdown 是一种极简的标记语言,用简单的符号就能写出结构清晰、排版美观的文档,早已成为技术写作、笔记管理、博客发布的事实标准。
但一个顺手的 Markdown 编辑器并不好找:
- 在线编辑器依赖网络,隐私与体验都打折扣;
- 重量级 IDE功能繁杂,启动慢、内存占用高,写篇笔记杀鸡用牛刀;
- 商业软件需要付费订阅,且不开放源码。
DotMD 就是为了解决这些问题而生------一款开源、免费、轻量、本地运行的桌面 Markdown 查看与编辑器。它开箱即用,下载一个单文件 exe 双击就能运行,无需安装、无需联网。
📸 界面预览
打开示例文档 doc/demo.md 的实际效果(分屏编辑 + 实时预览):




二、为什么会有 DotMD
DotMD 的诞生源于一个朴素的需求:想要一个"刚刚好"的 Markdown 编辑器。
- 要快:启动迅速,编辑流畅,不卡顿;
- 要全:实时预览、数学公式、图表、代码高亮一个都不能少;
- 要轻:不引入复杂的插件生态,界面干净不打扰;
- 要自由:开源、免费、数据都在本地,想怎么用就怎么用。
于是作者用 Go + Wails v2 + React 自己动手做了 DotMD,并把它开源出来,希望能帮到同样喜欢 Markdown 的人。
三、核心特性
📂 目录树管理
打开任意文件夹,左侧自动生成目录树,.md 文档一目了然。支持新建文件、新建文件夹、重命名、删除(右键菜单),写多文档项目时非常顺手。
🖊️ 流畅的编辑体验
基于 CodeMirror 6 的源码编辑器,自带 Markdown 语法高亮、行号、代码折叠和自动补全。三种视图模式随意切换:
- 编辑:专注写作;
- 分屏:左侧编辑、右侧实时预览(默认推荐);
- 预览:只读渲染,适合展示。
🔄 编辑与预览精确对齐
分屏模式下,编辑器与预览按源码行号精确对齐双向同步------滚动左侧源码,右侧预览自动跳到对应内容;滚动右侧预览,左侧源码同步跟随。基于每个块级元素标注的源码行号实现,而不是简单的比例滚动,真正做到"看到哪里、写到哪里"。
🧮 数学公式(KaTeX)
支持行内公式 $...$ 与块级公式 $$...$$,渲染基于 KaTeX,速度快、质量高。写技术文章、论文笔记都不在话下:
E = m c 2 , e i π + 1 = 0 E = mc^2, \quad e^{i\pi} + 1 = 0 E=mc2,eiπ+1=0
📊 图表(Mermaid)
内嵌 Mermaid,直接书写图表代码即可渲染出流程图、时序图、甘特图等。技术架构图、流程说明,一行代码搞定:
#mermaid-svg-kdGwJoQxe9x3Z792{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-kdGwJoQxe9x3Z792 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kdGwJoQxe9x3Z792 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kdGwJoQxe9x3Z792 .error-icon{fill:#552222;}#mermaid-svg-kdGwJoQxe9x3Z792 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kdGwJoQxe9x3Z792 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kdGwJoQxe9x3Z792 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kdGwJoQxe9x3Z792 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kdGwJoQxe9x3Z792 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kdGwJoQxe9x3Z792 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kdGwJoQxe9x3Z792 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kdGwJoQxe9x3Z792 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kdGwJoQxe9x3Z792 .marker.cross{stroke:#333333;}#mermaid-svg-kdGwJoQxe9x3Z792 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kdGwJoQxe9x3Z792 p{margin:0;}#mermaid-svg-kdGwJoQxe9x3Z792 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-kdGwJoQxe9x3Z792 .cluster-label text{fill:#333;}#mermaid-svg-kdGwJoQxe9x3Z792 .cluster-label span{color:#333;}#mermaid-svg-kdGwJoQxe9x3Z792 .cluster-label span p{background-color:transparent;}#mermaid-svg-kdGwJoQxe9x3Z792 .label text,#mermaid-svg-kdGwJoQxe9x3Z792 span{fill:#333;color:#333;}#mermaid-svg-kdGwJoQxe9x3Z792 .node rect,#mermaid-svg-kdGwJoQxe9x3Z792 .node circle,#mermaid-svg-kdGwJoQxe9x3Z792 .node ellipse,#mermaid-svg-kdGwJoQxe9x3Z792 .node polygon,#mermaid-svg-kdGwJoQxe9x3Z792 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kdGwJoQxe9x3Z792 .rough-node .label text,#mermaid-svg-kdGwJoQxe9x3Z792 .node .label text,#mermaid-svg-kdGwJoQxe9x3Z792 .image-shape .label,#mermaid-svg-kdGwJoQxe9x3Z792 .icon-shape .label{text-anchor:middle;}#mermaid-svg-kdGwJoQxe9x3Z792 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kdGwJoQxe9x3Z792 .rough-node .label,#mermaid-svg-kdGwJoQxe9x3Z792 .node .label,#mermaid-svg-kdGwJoQxe9x3Z792 .image-shape .label,#mermaid-svg-kdGwJoQxe9x3Z792 .icon-shape .label{text-align:center;}#mermaid-svg-kdGwJoQxe9x3Z792 .node.clickable{cursor:pointer;}#mermaid-svg-kdGwJoQxe9x3Z792 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kdGwJoQxe9x3Z792 .arrowheadPath{fill:#333333;}#mermaid-svg-kdGwJoQxe9x3Z792 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kdGwJoQxe9x3Z792 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kdGwJoQxe9x3Z792 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kdGwJoQxe9x3Z792 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kdGwJoQxe9x3Z792 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kdGwJoQxe9x3Z792 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kdGwJoQxe9x3Z792 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kdGwJoQxe9x3Z792 .cluster text{fill:#333;}#mermaid-svg-kdGwJoQxe9x3Z792 .cluster span{color:#333;}#mermaid-svg-kdGwJoQxe9x3Z792 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-kdGwJoQxe9x3Z792 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kdGwJoQxe9x3Z792 rect.text{fill:none;stroke-width:0;}#mermaid-svg-kdGwJoQxe9x3Z792 .icon-shape,#mermaid-svg-kdGwJoQxe9x3Z792 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kdGwJoQxe9x3Z792 .icon-shape p,#mermaid-svg-kdGwJoQxe9x3Z792 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kdGwJoQxe9x3Z792 .icon-shape .label rect,#mermaid-svg-kdGwJoQxe9x3Z792 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kdGwJoQxe9x3Z792 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kdGwJoQxe9x3Z792 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kdGwJoQxe9x3Z792 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 数学
图表
代码
编写 Markdown
实时预览
KaTeX
Mermaid
highlight.js
导出 HTML / PDF
💻 代码高亮
highlight.js 驱动,支持几十种编程语言,技术文档中的代码块赏心悦目。
🖼️ 本地图片预览
文档中相对路径引用的本地图片 可以直接在预览中显示(如 ),无需上传图床、无需外链。打开任意含本地图片的 Markdown 文档,所见即所得。
📁 文件管理
- 新建文件 / 新建文件夹 / 重命名 / 删除(右键菜单);
- 拖放打开 :把
.md文件直接拖到窗口任意位置即可打开; - 未保存提示:关闭窗口或切换文件时,若有未保存更改会自动提示,避免误丢内容。
📤 导出
- HTML:生成独立可打开的文件,样式、公式、代码高亮全部内联,无需任何环境;
- PDF:一键导出,适合存档与分享。
🔗 系统集成
.md文件关联 :打开程序时自动检测.md关联;未关联到 DotMD(含关联到其他程序)时会提示一键关联,关联后双击.md文件即可用 DotMD 打开;- 右键/双击打开 :右键
.md→ 打开方式 → DotMD,或双击关联文件,自动打开; - 单实例运行:重复打开文件自动转发到已运行实例,不重复启动;
- 版本信息:关于弹窗动态显示当前程序版本号。
⌨️ 常用快捷键
| 快捷键 | 功能 |
|---|---|
Ctrl+S |
保存 |
Ctrl+B / Ctrl+I |
加粗 / 斜体 |
Ctrl+F |
查找 |
Ctrl+Alt+F |
替换 |
F3 / Ctrl+G |
查找下一个 |
Shift+F3 / Ctrl+Shift+G |
查找上一个 |
Esc |
关闭搜索面板 / 弹窗 |
四、技术架构
DotMD 采用 Go 后端 + Web 前端 的桌面应用架构,通过 Wails v2 桥接。
#mermaid-svg-iLj8sYTxlJRQUKbZ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-iLj8sYTxlJRQUKbZ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-iLj8sYTxlJRQUKbZ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-iLj8sYTxlJRQUKbZ .error-icon{fill:#552222;}#mermaid-svg-iLj8sYTxlJRQUKbZ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-iLj8sYTxlJRQUKbZ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-iLj8sYTxlJRQUKbZ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-iLj8sYTxlJRQUKbZ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-iLj8sYTxlJRQUKbZ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-iLj8sYTxlJRQUKbZ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-iLj8sYTxlJRQUKbZ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-iLj8sYTxlJRQUKbZ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-iLj8sYTxlJRQUKbZ .marker.cross{stroke:#333333;}#mermaid-svg-iLj8sYTxlJRQUKbZ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-iLj8sYTxlJRQUKbZ p{margin:0;}#mermaid-svg-iLj8sYTxlJRQUKbZ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-iLj8sYTxlJRQUKbZ .cluster-label text{fill:#333;}#mermaid-svg-iLj8sYTxlJRQUKbZ .cluster-label span{color:#333;}#mermaid-svg-iLj8sYTxlJRQUKbZ .cluster-label span p{background-color:transparent;}#mermaid-svg-iLj8sYTxlJRQUKbZ .label text,#mermaid-svg-iLj8sYTxlJRQUKbZ span{fill:#333;color:#333;}#mermaid-svg-iLj8sYTxlJRQUKbZ .node rect,#mermaid-svg-iLj8sYTxlJRQUKbZ .node circle,#mermaid-svg-iLj8sYTxlJRQUKbZ .node ellipse,#mermaid-svg-iLj8sYTxlJRQUKbZ .node polygon,#mermaid-svg-iLj8sYTxlJRQUKbZ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-iLj8sYTxlJRQUKbZ .rough-node .label text,#mermaid-svg-iLj8sYTxlJRQUKbZ .node .label text,#mermaid-svg-iLj8sYTxlJRQUKbZ .image-shape .label,#mermaid-svg-iLj8sYTxlJRQUKbZ .icon-shape .label{text-anchor:middle;}#mermaid-svg-iLj8sYTxlJRQUKbZ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-iLj8sYTxlJRQUKbZ .rough-node .label,#mermaid-svg-iLj8sYTxlJRQUKbZ .node .label,#mermaid-svg-iLj8sYTxlJRQUKbZ .image-shape .label,#mermaid-svg-iLj8sYTxlJRQUKbZ .icon-shape .label{text-align:center;}#mermaid-svg-iLj8sYTxlJRQUKbZ .node.clickable{cursor:pointer;}#mermaid-svg-iLj8sYTxlJRQUKbZ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-iLj8sYTxlJRQUKbZ .arrowheadPath{fill:#333333;}#mermaid-svg-iLj8sYTxlJRQUKbZ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-iLj8sYTxlJRQUKbZ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-iLj8sYTxlJRQUKbZ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iLj8sYTxlJRQUKbZ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-iLj8sYTxlJRQUKbZ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iLj8sYTxlJRQUKbZ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-iLj8sYTxlJRQUKbZ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-iLj8sYTxlJRQUKbZ .cluster text{fill:#333;}#mermaid-svg-iLj8sYTxlJRQUKbZ .cluster span{color:#333;}#mermaid-svg-iLj8sYTxlJRQUKbZ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-iLj8sYTxlJRQUKbZ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-iLj8sYTxlJRQUKbZ rect.text{fill:none;stroke-width:0;}#mermaid-svg-iLj8sYTxlJRQUKbZ .icon-shape,#mermaid-svg-iLj8sYTxlJRQUKbZ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iLj8sYTxlJRQUKbZ .icon-shape p,#mermaid-svg-iLj8sYTxlJRQUKbZ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-iLj8sYTxlJRQUKbZ .icon-shape .label rect,#mermaid-svg-iLj8sYTxlJRQUKbZ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iLj8sYTxlJRQUKbZ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-iLj8sYTxlJRQUKbZ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-iLj8sYTxlJRQUKbZ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 后端 Go
前端 WebView2
Wails Binding
React 19 + Vite
CodeMirror 6 编辑器
marked + DOMPurify 渲染
KaTeX 公式
Mermaid 图表
highlight.js 高亮
编辑/预览精确对齐
Wails v2 Runtime
文件系统 / 对话框
注册表文件关联
本地资源服务
PDF 导出
技术栈总览
| 层 | 技术 |
|---|---|
| 桌面框架 | Wails v2(Go + WebView2) |
| 后端 | Go 1.25(文件系统、注册表关联、本地资源服务) |
| 前端 | React 19 + Vite + TypeScript |
| 编辑器 | CodeMirror 6 |
| Markdown 渲染 | marked + DOMPurify |
| 公式 | KaTeX |
| 图表 | Mermaid |
| 代码高亮 | highlight.js |
| PDF 导出 | html2canvas + jsPDF |
这套组合的好处是:后端小而稳 (Go 编译为单一可执行文件),前端生态丰富 (复用成熟 Web 组件),最终产物是一个自包含的 exe ,分发部署极其简单。文档里引用的本地图片则通过后端提供的本地资源服务(assetserver Handler)在预览中加载,无需外部依赖。
五、快速上手
- 获取 :从仓库下载
dotmd.exe(免安装单文件,Windows 10/11 x64); - 运行 :双击
dotmd.exe,无需安装、无需联网; - 打开方式 (任选其一):
- 点击「打开文件夹」,选择 Markdown 文档所在目录;
- 点击「打开文件」选择单个文档;
- 把
.md文件拖到窗口任意位置; - 双击 已关联的
.md文件(首次启动按提示一键关联);
- 开始写作:进入编辑,右侧实时预览,滚动自动对齐;
- 导出:工具栏一键导出 HTML / PDF。
提示:若系统缺少 WebView2 运行时(一般 Win10/11 自带),按提示安装即可。
六、适用场景
- ✍️ 技术写作:公式、图表、代码高亮全覆盖,一篇技术博客一次写完;
- 📒 个人笔记:目录树管理,多文档切换顺手,数据 100% 留在本地;
- 📚 文档整理:README、说明文档、接口文档,导出 HTML/PDF 方便分享;
- 🎓 学习记录:Markdown 语法练习、公式笔记、流程图草图;
- 🖼️ 图文笔记:本地图片直接显示,配合目录树管理图片素材。
七、与同类产品对比
| 对比项 | DotMD | Typora | Mark Text | VS Code |
|---|---|---|---|---|
| 开源免费 | ✅ | ❌ 付费 | ✅ | ✅ |
| 免安装单文件 | ✅ | ❌ | ✅ | ❌ |
| 实时预览 | ✅ | ✅ | ✅ | ✅(需插件) |
| 精确对齐同步滚动 | ✅ | ✅ | ✅ | ✅ |
| 本地图片预览 | ✅ | ✅ | ✅ | ✅ |
| 数学公式 | ✅ KaTeX | ✅ | ✅ | 需插件 |
| Mermaid 图表 | ✅ | ✅ | 部分 | 需插件 |
| 拖放打开文件 | ✅ | ✅ | ❌ | ✅ |
| 启动轻量 | ✅ | ✅ | ✅ | ❌ 偏重 |
| 目录树 | ✅ | ✅ | ❌ | ✅ |
DotMD 的定位是轻量、专注、开箱即用:不需要插件、不需要配置,装上就能舒服地写 Markdown。
八、获取与支持
- 📦 源码仓库 :https://gitcode.com/itopit/dotmd(欢迎 Star ⭐)
- 🖥️ 运行环境:Windows 10 / 11(x64)
- 🏷️ 当前版本:v1.0.0
- 📄 开源协议:MIT,可自由使用、修改、商用
九、结语
Markdown 编辑器很多,但"刚刚好"的那一个需要用心打磨。DotMD 坚持轻量、开源、免费、本地优先,不断打磨编辑体验------精确对齐的同步滚动、开箱即用的文件关联、顺手的拖放打开、本地图片直显。
打开它,写下第一行 # Hello, DotMD! 吧。
本文由 DotMD 编写,打开 doc/demo.md 可体验全部渲染能力。