Shpigford/clearly

GitHub: Shpigford/clearly

Clearly 是一款适用于 Mac 和 iOS 的原生 Markdown 编辑器,提供语法高亮、实时预览和丰富的格式化功能,无需订阅且无遥测。

Stars: 1004 | Forks: 70

Clearly icon

Clearly

一款适用于 Mac 和 iPhone 的原生 Markdown 编辑器。

Mac App Store · 直接下载 · 网站 · @Shpigford

Clearly — markdown editor with live preview

打开 `.md` 文件。享受带有语法高亮的书写体验。一键切换至预览。就这么简单。原生支持 macOS 和 iOS,没有 Electron,无需订阅,没有遥测。 ## 功能 ### 书写 - **语法高亮** — 标题、粗体、斜体、链接、代码块、表格,边打字边高亮 - **格式快捷键** — ⌘B 粗体,⌘I 斜体,⌘K 链接,以及完整的“格式”菜单 - **扩展 Markdown** — ==高亮==,^上标^,~下标~,:emoji: 简码,`[TOC]` 生成 - **文档大纲** — 每个文档的标题树,点击跳转 - **查找与替换** — ⌘F,支持正则表达式和区分大小写选项 - **速记板** — 带全局热键的菜单栏浮动笔记 ### 预览 - **GFM 渲染** — 表格、任务列表、脚注、删除线 - **KaTeX 数学公式** — 行内和块级公式 - **Mermaid 图表** — 从代码块生成的流程图、时序图 - **代码块** — 语法高亮、行号、diff 高亮、一键复制 - **标注** — NOTE、TIP、WARNING 等 15 种以上类型,可折叠 - **交互性** — 切换复选框、缩放图片、悬停脚注、双击跳转至源码 ### 集成 - **QuickLook** — 在 Finder 中按空格键预览 `.md` 文件 - **PDF 导出** — 导出或打印,自动处理分页 - **iOS** — 相同的渲染器,相同的语法高亮器,可从“文件” App 打开任何 `.md` 文件 ## 截图

## 前置条件 - Mac App 需要运行 **macOS 15** (Sequoia) 或更高版本 - iPhone App 需要运行 **iOS 17** 或更高版本 - **Xcode 16+** 及其命令行工具 (`xcode-select --install`) - **Homebrew** ([brew.sh](https://brew.sh)) - **xcodegen** — `brew install xcodegen` 依赖项 (cmark-gfm, Sparkle, KeyboardShortcuts) 会由 Xcode 通过 Swift Package Manager 自动拉取。 ## 快速开始 ``` git clone https://github.com/Shpigford/clearly.git cd clearly brew install xcodegen # skip if already installed xcodegen generate # generates Clearly.xcodeproj from project.yml open Clearly.xcodeproj # opens in Xcode ``` 然后按下 **⌘R** 构建并运行。 ### CLI 构建 ``` xcodebuild -scheme Clearly -configuration Debug build xcodebuild -scheme Clearly-iOS -destination 'generic/platform=iOS Simulator' build ``` ## 项目结构 ``` Clearly/ ├── ClearlyApp.swift # @main — DocumentGroup + menu commands (⌘1/⌘2) ├── MarkdownDocument.swift # FileDocument conformance for .md files (Mac + iOS) ├── ContentView.swift # Per-document scene root (Mac) ├── EditorView.swift # NSViewRepresentable wrapping NSTextView ├── ClearlyTextView.swift # Subclassed NSTextView with formatting actions ├── PreviewView.swift # NSViewRepresentable wrapping WKWebView ├── ScratchpadManager.swift # Menu-bar floating scratchpad windows ├── SettingsView.swift # General + About preferences └── iOS/ ├── ClearlyApp_iOS.swift # @main — DocumentGroup, system Files browser ├── DocumentDetailBody.swift # Per-document scene root (iOS) ├── EditorView_iOS.swift # UIViewRepresentable wrapping UITextView ├── ClearlyUITextView.swift # TextKit 1 UITextView subclass └── PreviewView_iOS.swift # UIViewRepresentable wrapping WKWebView ClearlyQuickLook/ ├── PreviewProvider.swift # QLPreviewProvider for Finder previews └── Info.plist Packages/ClearlyCore/ # Local SwiftPM package, platform-agnostic └── Sources/ClearlyCore/ ├── Rendering/ # MarkdownRenderer, syntax highlighter, theme, mermaid/math/table support ├── State/ # OpenDocument, OutlineState, FindState, JumpToLineState, StatusBarState ├── Editor/ # ImagePasteService, ImageDownloader ├── Diagnostics/ # DiagnosticLog, BugReportURL ├── Stats/ # MarkdownStats (word counts) └── Platform/ # PlatformFont/Color/Image typealiases Shared/Resources/ # Bundled JS/CSS (KaTeX, Mermaid, Highlight.js), demo.md website/ # Static site deployed to clearly.md scripts/ # Release pipeline project.yml # xcodegen config (source of truth) ``` ## 架构 **SwiftUI + AppKit/UIKit**,双平台均基于文档架构。 ### Targets 1. **Clearly** (Mac) — 包含 `MarkdownDocument` 的 `DocumentGroup`。AppKit 的 `NSTextView` 编辑器 + `WKWebView` 预览,两者均通过 `NSViewRepresentable` 进行桥接。包含一个用于浮动速记板的菜单栏 `MenuBarExtra`。 2. **Clearly-iOS** — `DocumentGroup`。UIKit 的 `UITextView` 编辑器 + `WKWebView` 预览,通过 `UIViewRepresentable` 进行桥接。系统“文件”浏览器是入口点。 3. **ClearlyQuickLook** — 用于按空格键预览 `.md` 文件的 Finder 扩展,与 `ClearlyCore` 共享 `MarkdownRenderer`。 ### 编辑器 通过 `NSViewRepresentable` / `UIViewRepresentable` 封装平台原生文本视图(Mac 上的 `NSTextView`,iOS 上的 `UITextView`)。这提供了原生的撤销/重做、系统查找 UI,以及基于 `NSTextStorageDelegate` 在每次敲击键盘时触发的语法高亮。iOS 依然使用 TextKit 1,因为 TextKit 2 会让 `textStorage` 实际上失效。 ### 预览 `PreviewView` (Mac) 和 `PreviewView_iOS` 均封装了 `WKWebView`,并通过 `MarkdownRenderer` (cmark-gfm) 渲染 HTML。后处理流水线:数学公式 → 高亮标记 → 上标/下标 → emoji → 标注 → TOC → 表格 → 代码高亮。 ### 依赖项 | Package | Purpose | |---------|---------| | [cmark-gfm](https://github.com/brokenhandsio/cmark-gfm) | GitHub Flavored Markdown 转 HTML | | [Sparkle](https://sparkle-project.org) | 自动更新(仅限直接下载分发版) | | [KeyboardShortcuts](https://github.com/sindresorhus/KeyboardShortcuts) | 用于菜单栏速记板的全局热键 | ### 关键决策 - **AppKit/UIKit 桥接** — 在 `TextEditor` 之上使用平台原生文本视图,以实现撤销、查找和 `NSTextStorageDelegate` 语法高亮 - **动态主题** — 所有颜色均通过 `Theme.swift` 并使用 `NSColor(name:)` 实现自动浅色/深色模式切换 - **共享渲染** — `MarkdownRenderer` 和 `PreviewCSS` 位于 `ClearlyCore` 中,并编译进 Mac、iOS 和 QuickLook - **双重分发** — 直接下载版使用 Sparkle,App Store 版不用。所有 Sparkle 代码均封装在 `#if canImport(Sparkle)` 中 - **不使用 `.insitor()`** — 由于全屏安全区 bug,大纲面板使用 `HStack` ## 常见开发任务 ### 修改语法高亮 编辑 `Packages/ClearlyCore/Sources/ClearlyCore/Rendering/MarkdownSyntaxHighlighter.swift`。匹配模式按顺序应用——先是代码块,然后是其他所有内容。 ### 修改预览样式 编辑 `Packages/ClearlyCore/Sources/ClearlyCore/Rendering/PreviewCSS.swift`。App 内预览和 QuickLook 均会使用此文件。需保持与 `Theme.swift` 的颜色同步。基础样式必须放在 `@media (prefers-color-scheme: dark)` 覆盖之前。 ### 添加预览功能 遵循 `MathSupport`/`MermaidSupport` 的模式:在 `ClearlyCore/Rendering/` 中创建一个 `*Support.swift` 枚举,其中包含一个返回 `