01Native macOS app · Swift + PythonmacOS 原生应用 · Swift + Python

MD_reader

A quiet Markdown reader for the Mac: a native window around an offline renderer, with code, diagrams, math, search and keyboard navigation.一个安静的 Mac Markdown 阅读器:原生窗口里装着离线渲染,支持代码、流程图、公式、全文搜索和键盘导航。

My role我的角色
Sole author. I designed and built it end to end.独立作者。从设计到实现,都由我一个人完成。
Status状态
Private repo · personal tool私有仓库 · 自用工具
MD_reader reading a sample document in the dark theme: toolbar capsules, breadcrumb, a centred column with headings and a quote.
11page template, no dashboard个页面模板,没有仪表盘
00network requests while reading阅读时的网络请求
77single-key shortcuts个单键快捷键

01The problem问题

Reading notes shouldn’t need an editor.读笔记,不该非得打开编辑器。

Editors are for writing编辑器是用来写的

Opening a folder of Markdown notes in a code editor shows source, tabs and a file tree, not a page you want to read for an hour.用代码编辑器打开一文件夹的 Markdown 笔记,看到的是源码、标签页和文件树,而不是一个能安心读一小时的页面。

Renderers need the internet渲染器要联网

Most previewers load highlighting, diagrams and math from a CDN, so they break offline and leak what you read.大多数预览工具从 CDN 加载高亮、流程图和公式,离线就坏,而且会暴露你在读什么。

Mac first先照顾 Mac

It should open like any Mac app: double-click, drag a folder onto the window, or “Open With” from Finder.它应该像普通 Mac 应用一样打开:双击、把文件夹拖到窗口上,或者在访达里用「打开方式」。

02What I built我做了什么

A native window around a tiny local reader.原生窗口,包着一个很小的本地阅读器。

A Swift app opens a native window with a transparent title bar and a WKWebView, and starts a bundled Python engine on a free local port. The engine lists files, searches them, and serves one reading page.一个 Swift 应用打开带透明标题栏的原生窗口和 WKWebView,并在一个空闲的本地端口上启动内置的 Python 引擎。引擎负责列文件、搜索,以及提供唯一的阅读页面。

  • Fully offline: marked, highlight.js, Mermaid and KaTeX are vendored, so nothing loads from the network.完全离线:marked、highlight.js、Mermaid 和 KaTeX 都打包在应用里,不从网络加载任何东西。
  • Code blocks with a language label and one-click copy; Mermaid diagrams; inline and display math; relative images and cross-document links.代码块带语言标签和一键复制;Mermaid 流程图;行内和独立公式;相对路径图片和跨文档链接。
  • Single-key navigation: / search, \ file tree, D outline, [ and ] previous and next, T theme, Esc close.单键导航:/ 搜索,\ 文件树,D 目录,[ 和 ] 上一篇和下一篇,T 切换主题,Esc 关闭。
  • Light and dark themes follow the system; text size A−/A+ is remembered; a reading-progress bar.明暗主题跟随系统;字号 A−/A+ 会被记住;带阅读进度条。
  • Its own design.md: type scale, list and table rules, and anti-patterns such as “no dashboard home page”.有自己的 design.md:字号层级、列表和表格规则,以及「不做仪表盘首页」这样的反模式。

03How it works怎么做的

Two small programs, one job each.两个小程序,各干一件事。

  1. STEP 01

    Finder or drag-and-drop访达或拖放

    A .md file or folder arrives at the Swift app.一个 .md 文件或文件夹交给 Swift 应用。

  2. STEP 02

    Swift shellSwift 外壳

    Picks a free port and starts the bundled Python engine.选一个空闲端口,启动内置的 Python 引擎。

  3. STEP 03

    Python enginePython 引擎

    /api/list, /api/file, /api/search over localhost only.只在本机提供 /api/list、/api/file、/api/search。

  4. STEP 04

    WKWebView pageWKWebView 页面

    Renders with vendored marked, highlight.js, Mermaid, KaTeX.用内置的 marked、highlight.js、Mermaid、KaTeX 渲染。

04Interface and details界面与细节

Everything is one key away.所有东西都只差一个键。

  1. Code blocks with language labels and copy buttons.
    01 / 05

    Code reads like code代码就该像代码

    Each block is a rounded card with its language and a copy button. The highlight theme matches the reader’s own dark theme.每个代码块都是圆角卡片,带语言名和复制按钮。高亮配色和阅读器自己的深色主题一致。

  2. A Mermaid flowchart and a hairline table.
    02 / 05

    Diagrams and tables, offline流程图和表格,离线也能看

    Mermaid draws flowcharts from text. Tables are cards with horizontal hairlines only, a rule written into the design doc.Mermaid 用文字画流程图。表格是只有横向发丝线的卡片,这条规则写在设计文档里。

  3. Display math rendered with KaTeX, and a local image.
    03 / 05

    Math and local images公式和本地图片

    KaTeX renders inline and display math. Relative image paths resolve against the document’s own folder.KaTeX 渲染行内和独立公式。相对路径的图片按文档自己所在的文件夹解析。

  4. The search overlay listing matches across documents.
    04 / 05

    Press / to search everything按 / 搜索所有文档

    Full-text search across the folder, with arrow keys to choose and Enter to open at the match.在整个文件夹里全文搜索,方向键选择,回车直接跳到匹配处。

  5. The light theme with a table and a task list.
    05 / 05

    Light when the Mac is lightMac 是浅色,它也是浅色

    Both themes are designed, not inverted: the code theme, the table head and the accent dots all change together.两套主题都是设计出来的,不是简单反色:代码配色、表头和强调色圆点一起变化。

05Tech used用到的技术

What it’s made of.用什么做的。

App应用
  • Swift
  • AppKit
  • WKWebView
  • swiftc
Engine引擎
  • Python 3
  • http.server
  • no dependencies无第三方依赖
Rendering渲染
  • marked
  • highlight.js
  • Mermaid
  • KaTeX
Languages语言占比
  • Python 83%
  • Swift 16%
  • Shell 1%

06What I learned我学到了什么

Lessons I’ll keep.会一直记得的几件事。

  1. Small tools deserve a design doc too. Writing down “no dashboard, one column, hairline tables” settled arguments before they started.小工具也值得一份设计文档。先写下「不做仪表盘、单栏、发丝线表格」,很多争论还没开始就结束了。
  2. Let each language do what it’s best at. Swift owns the window and the Mac behaviours; Python owns files and text. Neither had to be clever.让每种语言做它最擅长的事。Swift 管窗口和 Mac 的行为,Python 管文件和文字。两边都不需要耍聪明。
  3. Check with real screenshots. The first build looked fine in code review but every library 404’d; a screenshot check caught it in one round.用真实截图检查。第一版在代码审查时看起来没问题,但所有渲染库都 404;截图检查一轮就发现了。