
桌面应用CLI【免费下载链接】MiaoYan⛷ Lightweight Markdown app to help you write great sentences.项目地址https://gitcode.com/gh_mirrors/mi/MiaoYan点击查看免费下载本篇技术指南围绕妙言MiaoYan开源仓库中的 .claude/rules/swift.md 开发规范展开系统讲解这款 macOS Markdown 编辑器在 Swift 工程中必须遵守的三类项目特有规则AppKit 与 SwiftUI 的框架边界、面向大文档的线程纪律以及易被 review 忽略的 CJK 全角标点与 CRLF 文本处理。读者将不仅理解每条规则的为什么还能在 Helpers/TypographyCleaner.swift、Business/NoteVersionManager.swift 等源码与 MiaoYanTests 测试中找到可复现、可验证的落地实现直接用于自己的 Swift/macOS 开发实践。规范的定位只写妙言特有的部分MiaoYan 的 Swift 规则文档有一个明确前提只约束 MiaoYan 特有的部分。通用的 Swift 内存管理与线程纪律如MainActor的 UI 约束、值类型与引用类型的取舍、ARC 循环引用等属于语言常识不在此文档中重复文档聚焦的是本项目长期实践中踩过的坑与既定的技术方向共四类AppKit vs SwiftUI主编辑器热路径与新增独立面板的技术选型边界Threading大笔记场景下哪些任务必须离开主线程CJK 文本处理全角标点在源码中的书写方式unicode 转义而非字面量CRLF 文本处理\r\n作为单个 grapheme 带来的匹配陷阱。理解这一只写特有部分的定位很重要它意味着下面每条规则都是经过真实故障检验的约束而不是泛泛的最佳实践。AppKit 与 SwiftUI 的边界热路径保持 AppKit独立面板可挂 SwiftUI必须保持 AppKit 的部分macOS 主 app 的以下核心模块不重写、不迁移持续使用AppKit NSViewController/NSWindowController编辑器核心对应 Views/EditTextView.swift是笔记正文的 NSTextView 封装预览管线对应 Views/MPreviewView.swift 及其扩展如 Extensions/MPreviewViewExport.swift承载 HTML 预览与导出既有窗口与 storyboard 场景对应 Resources/Localization/Base.lproj/Main.storyboard 与 Resources/Localization/Base.lproj/ContentViewController.xib以及 Controllers/MainWindowController.swift、Controllers/ViewController.swift 等控制层。从源码结构可以印证这一边界编辑与预览热路径上的核心类都是NSViewController/NSView体系例如版本历史面板 Controllers/VersionHistoryViewController.swift 中final class VersionHistoryViewController: NSViewController项目级开发约定 AGENTS.md 第 138 行也明确写着保持 macOS 编辑器核心、预览管线和既有 storyboard 场景在 AppKit 上。新增独立面板允许 SwiftUI规范留出了一个明确的下一代方向边界新增的独立面板——如版本 diff 视图version diff、quick-open 快速打开、大纲侧栏这类自包含 UI——允许通过NSHostingView挂载 SwiftUI。这是维护者在 2026-07 定下的方向。但边界必须守住不得以此为由把 SwiftUI 渗进 EditTextView / MPreviewView / ViewController 热路径。也就是说场景技术选型原因编辑器核心、预览管线、既有窗口/storyboardAppKit不重写成熟稳定避免热路径重写风险版本 diff、quick-open、大纲侧栏等新独立面板NSHostingView SwiftUI自包含、低耦合作为下一代 UI 方向试点EditTextView / MPreviewView / ViewController禁止渗入 SwiftUI保持热路径可预期、可调试落地建议如果要在新面板中使用 SwiftUI把NSHostingView挂在面板自身的 view 层级上面板通过协议或回调与 AppKit 侧通信而不是把SwiftUI.View直接塞进EditTextView等类的内部实现。线程纪律大文档场景下哪些任务必须离开主线程四条明确的后台队列任务规范规定以下四类工作必须走后台队列文件 IO读盘、写盘、版本快照落盘等版本历史版本目录扫描、比较、修剪Mermaid 渲染图表渲染是重活绝不能在主线程执行PDF 导出分页与页面快照涉及大量排版计算。同时有一条硬性约束大笔记 / 大预览不允许在主线程同步读。源码级印证Business/NoteVersionManager.swift 是这条纪律的典型实现第 10 行创建了专用串行队列DispatchQueue(label: com.tw93.miaoyan.versions)第 30–31 行把版本目录创建、内容比较、快照写入全部放进queue.async只在结束时通过DispatchQueue.main.async回调主线程通知 UI。规范中的版本历史走后台队列、UI 更新回主线程在这里完整落地。Mermaid 与 PDF 导出同样遵循该原则MiaoYanTests/MermaidExportTests.swift 围绕 WebView 中mermaid.min.js的异步渲染编写了等待逻辑waitForMermaid并在 Helpers/PdfExportController.swift 中等待code.language-mermaid全部挂上data-processed标记后才进入打印避免图表未渲染完成即导出PDF 入口 Controllers/ViewControllerExport.swift 中case PDF分支也是先启用预览、等待加载完成再调用 Extensions/MPreviewViewExport.swift 的exportPdf()。实践建议大文档的读入、清洗、高亮等重操作同样应放在后台主线程只做 UI 提交与轻量计算涉及 NSTextStorage 等 UI 对象时用DispatchQueue.main.async切回主线程再写回。CJK 文本处理全角标点必须用 unicode 转义书写规则原文Swift 源码和测试里写全角标点——凡是存在半角孪生兄弟的字符如,;:!?()等——一律使用\u{FF0C}这类 unicode 转义禁止写字面量。原因是字面量在生成/编辑过程中极易退化成半角而 review 时肉眼几乎看不出来差异。文档还记录了一个真实事故TypographyCleaner 的字符集合里曾混入半角逗号导致英文句子的空格被误删。这个坑是这条规则的直接由来。无半角孪生的字符如。「」……可以写字面量因为它们不存在退化成半角的风险。源码与测试中的落地形态在 Helpers/TypographyCleaner.swift 中可以看到这条规则的实际执行第 508–511 行normalizePunctuationWidth的宽度映射表全部用转义书写let mapping: [Character: Character] [ ,: \u{FF0C}, ;: \u{FF1B}, :: \u{FF1A}, !: \u{FF01}, ?: \u{FF1F}, .: \u{3002}, ]键半角用字面量、值全角用转义二者对照一目了然review 时不会看混。第 539–541 行全角标点字符集同样用转义构造private static let fullwidthPunctuation SetCharacter(\u{FF0C}\u{3002}\u{FF01}\u{FF1F}\u{FF1B}\u{FF1A}\u{3001})测试侧同样遵守MiaoYanTests/TypographyCleanerTests.swift 第 29 行断言你好,世界清洗后等于你好\u{FF0C}世界期望值用转义、输入值用半角字面量测试意图因此非常清晰。结合功能入口理解TypographyCleaner 的实际调用入口在 Controllers/ViewControllerEditor.swift 第 940 行起的cleanTypography动作读取整个文档 →TypographyCleaner.clean(content)→ 若内容有变化则通过 text view 的编辑路径整文重写进入 undo 栈→ 保存并刷新预览。规范第 16 行关于集合里混入半角逗号导致英文句子空格被误删的描述与测试中testPureEnglishUntouched纯英文文本保持不动互为印证一旦全角字符集合里混入半角逗号,就会命中英文句子的逗号并触发错误的全角化/空格重排逻辑。CRLF 文本处理\r\n是单个 grapheme规则原文与陷阱处理可能含 CRLF 的文本时必须记住\r\n是单个 grapheme字素簇。因此content[i] \n逐字符比较匹配不到它range(of: \n...)这类按单个\n的 needle 搜索同样匹配不到。规范给出的解法是显式加\r\n分支或使用双 needle 搜索即同时搜索\n与\r\n两种结尾。TypographyCleaner 中的 CRLF 兼容实现Helpers/TypographyCleaner.swift 完整演示了如何安全处理 CRLF 文档第 23 行frontmatter 起始判断同时接受---与---\r第 30 行行内容统一用trimmingCharacters(in: .whitespacesAndNewlines)修剪这样\r会被一并去掉后续的 fence、frontmatter 结束判断不会因尾随\r失效源码注释明确说明这是为了让 CRLF 文档正确闭合 frontmatter 与代码围栏第 134–137 行的测试testCRLFDocumentStillCleaned直接覆盖了该场景输入---\r\ntitle: x\r\n---\r\n正文,好abc期望输出---\r\ntitle: x\r\n---\r\n正文\u{FF0C}好 abc——CRLF 行尾被完整保留正文清洗照常进行。这个案例说明处理 CRLF 时不要只盯着\n要么在边界判断中显式处理\r要么用双 needle 搜索同时覆盖两种行尾否则会产生看似匹配成功、实际漏掉的隐性 bug。综合检查清单把四类规则整理成可直接对照的清单适用于妙言工程内的代码评审与新增代码UI 框架边界编辑核心、预览管线、既有窗口与 storyboard 场景未改写成 SwiftUI新增独立面板如使用 SwiftUI仅通过NSHostingView挂载未渗入EditTextView/MPreviewView/ViewController热路径线程纪律文件 IO、版本历史、Mermaid 渲染、PDF 导出均在后队列执行大笔记/大预览未在主线程同步读取后台任务完成后通过主队列回调更新 UI参考 Business/NoteVersionManager.swiftCJK 标点书写有半角孪生的全角字符一律使用\u{FF0C}类转义不写字面量参考 Helpers/TypographyCleaner.swift 第 508–511、539–541 行无半角孪生的字符。「」……可按字面量书写CRLF 处理涉及行尾判断时显式包含\r\n分支或使用双 needle 搜索边界匹配前用trimmingCharacters(in: .whitespacesAndNewlines)去除尾随\r这四条规则共同构成了妙言 Swift 开发中与通用最佳实践不重叠的那部分约束。理解其背后的故障案例半角逗号混入 TypographyCleaner、CRLF 匹配漏判后你不仅能在妙言仓库中写出符合规范的代码也能把这些经验迁移到任何需要长期维护的 macOS Swift 项目中——尤其是那些要处理中英混排文本与多行尾格式的编辑器类应用。赞分享桌面应用CLI【免费下载链接】MiaoYan⛷ Lightweight Markdown app to help you write great sentences.项目地址https://gitcode.com/gh_mirrors/mi/MiaoYan点击查看免费下载相关推荐c-ares部署策略生产环境中的配置优化与监控方案c ares部署策略生产环境中的配置优化与监控方案 c ares是一个用于异步DNS请求的C语言库在生产环境中部署时需要进行合理的配置优化和监控方案设计以网络通信妙言MiaoYan完整开发路线图2025年新功能预告与未来规划妙言MiaoYan完整开发路线图2025年新功能预告与未来规划 妙言MiaoYan作为一款轻量级的Markdown笔记本应用凭借其纯本地使用、安全可靠的特点桌面应用CLIPowerToys AI 贡献者指南构建纪律、测试规范与工程边界的完整实践PowerToys AI 贡献者指南构建纪律、测试规范与工程边界的完整实践 本文以 PowerToys 仓库根目录的 AGENTS.md https://li桌面应用开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考