展開(kāi)發(fā)實(shí)戰(zhàn):Clearly如何讓Finder精美預(yù)覽Markdown(附3個(gè)LaunchServices陷阱))
【免費(fèi)下載鏈接】clearlyMarkdown editor for Mac, iOS and iPadOS項(xiàng)目地址https://gitcode.com/gh_mirrors/cle/clearly點(diǎn)擊查看免費(fèi)下載Clearly 是一款面向 Mac、iOS 與 iPadOS 的原生 Markdown 編輯器。它的亮點(diǎn)之一是隨主應(yīng)用附帶的QuickLook 擴(kuò)展在 Finder 中選中任意.md文件按下空格就能看到代碼高亮、數(shù)學(xué)公式、Mermaid 圖表一應(yīng)俱全的精美預(yù)覽而不是干巴巴的原始文本。這篇文章拆解 Clearly 的 QuickLook 擴(kuò)展是怎么做出來(lái)的并附上項(xiàng)目團(tuán)隊(duì)踩過(guò)的3 個(gè) LaunchServices 陷阱——它們會(huì)讓你的 Markdown 預(yù)覽靜默退化回純文本且不報(bào)任何錯(cuò)。 QuickLook 能帶來(lái)什么空格一鍵預(yù)覽QuickLook 是 macOS/iOS 系統(tǒng)級(jí)的文件預(yù)覽機(jī)制。裝好 Clearly 后你獲得兩個(gè)體驗(yàn)升級(jí)Finder 空格預(yù)覽選中.md文件按空格全屏浮層直接展示渲染后的 Markdown分欄視圖預(yù)覽Finder 列式視圖中瀏覽筆記目錄時(shí)右側(cè)預(yù)覽欄同步顯示排版內(nèi)容且自動(dòng)切換更小的字體以適配窄欄。預(yù)覽效果與 Clearly 應(yīng)用內(nèi)的預(yù)覽面板完全同源——同一套渲染管線多端一致? 架構(gòu)一覽一個(gè) app-extension 目標(biāo) 共享渲染核心在 project.ymlxcodegen 配置中QuickLook 擴(kuò)展是一個(gè)獨(dú)立的app-extension構(gòu)建目標(biāo)ClearlyQuickLook其配置見(jiàn) project.yml擴(kuò)展 Bundle IDcom.sabotage.clearly.quicklook隨主應(yīng)用以embed: true方式打包進(jìn) app資源上復(fù)用主應(yīng)用的Shared/Resources/KaTeX、Mermaid、highlight.js 及字體保證離線可用核心渲染邏輯不復(fù)制、不重寫(xiě)而是依賴本地 Swift 包ClearlyCore。這正是 Clearly 多端架構(gòu)的關(guān)鍵決策M(jìn)arkdownRenderer和PreviewCSS放在ClearlyCore中同時(shí)編譯進(jìn) Mac 主應(yīng)用、iOS 應(yīng)用和 QuickLook 擴(kuò)展三個(gè)目標(biāo)。應(yīng)用內(nèi)預(yù)覽改一個(gè)樣式Finder 預(yù)覽自動(dòng)同步完整的渲染上下文應(yīng)用內(nèi)預(yù)覽 / QuickLook / PDF 導(dǎo)出說(shuō)明見(jiàn) docs/markdown-rendering-architecture.md。 核心實(shí)現(xiàn)不到 50 行的 PreviewProviderQuickLook 預(yù)覽擴(kuò)展的入口是 ClearlyQuickLook/PreviewProvider.swift整個(gè)文件只有 40 多行。核心邏輯是標(biāo)準(zhǔn)四步實(shí)現(xiàn)QLPreviewingController協(xié)議系統(tǒng)把待預(yù)覽文件 URL 交給preparePreviewOfFile(at:completionHandler:)以 UTF-8 讀取 Markdown 文本調(diào)用 MarkdownRenderer.renderHTML底層是 cmark-gfm支持表格、刪除線、任務(wù)列表等 GFM 語(yǔ)法轉(zhuǎn)成 HTML拼上 PreviewCSS.swift 生成的樣式表以及數(shù)學(xué)公式KaTeX、表格、Mermaid、代碼高亮的注入腳本交給一個(gè)WKWebView加載webView.loadHTMLString(html, baseURL: MermaidSupport.resourceBaseURL) handler(nil)注意這里的輕量級(jí)QuickLook 擴(kuò)展本身幾乎不寫(xiě)業(yè)務(wù)代碼全部復(fù)用主應(yīng)用已有的渲染棧。擴(kuò)展真正的差異化配置集中在 ClearlyQuickLook/Info.plistNSExtensionPointIdentifier聲明為com.apple.quicklook.previewQLSupportedContentTypes列出支持的 UTI內(nèi)容類型標(biāo)識(shí)開(kāi)啟QLSupportsSearchableItems讓 Finder 快速預(yù)覽中支持文字查找。沙盒權(quán)限則非??酥埔?jiàn) ClearlyQuickLook/ClearlyQuickLook.entitlements——只開(kāi)了app-sandbox和network.clientQuickLook 進(jìn)程以 XPC 形式運(yùn)行不能碰主應(yīng)用之外的東西。?? 3 個(gè) LaunchServices 陷阱為什么你的預(yù)覽只是原始文本這是全文最值錢的部分。.md的 QuickLook 預(yù)覽、Finder 分欄預(yù)覽、.md 的默認(rèn)打開(kāi)方式三者共享同一套 LaunchServices 路由任何一環(huán)配置錯(cuò)誤系統(tǒng)都靜默回退到原生純文本預(yù)覽器Text.qlgenerator日志里幾乎找不到報(bào)錯(cuò)。以下是 Clearly 團(tuán)隊(duì)記錄在 CLAUDE.md 中的三個(gè)必須同時(shí)滿足的不變量陷阱 1必須用UTExportedTypeDeclarations而不是UTImportedTypeDeclarationsClearly 在 Clearly/Info.plist 中用導(dǎo)出Exported聲明來(lái)認(rèn)領(lǐng)net.daringfireball.markdown這個(gè)內(nèi)容類型并聲明md、markdown等擴(kuò)展名屬于它。如果你用UTImportedTypeDeclarations很多教程示例都這么寫(xiě)當(dāng)系統(tǒng)上沒(méi)有其他應(yīng)用權(quán)威導(dǎo)出該類型時(shí)LaunchServices 會(huì)把這個(gè)導(dǎo)入聲明標(biāo)記為inactive imported untrusted結(jié)果quicklookd直接放棄你的擴(kuò)展回退到純文本預(yù)覽。導(dǎo)出聲明則意味著這個(gè)類型由我說(shuō)了算。陷阱 2LSHandlerRank必須是Owner同一份 Clearly/Info.plist 的CFBundleDocumentTypes里.md文檔類型的LSHandlerRank寫(xiě)的是Owner。原因如果用默認(rèn)的Default其他以O(shè)wner級(jí)別認(rèn)領(lǐng) Markdown 的應(yīng)用某些代碼編輯器、寫(xiě)作工具就會(huì)在默認(rèn)打開(kāi)程序的競(jìng)爭(zhēng)中獲勝——哪怕它們的內(nèi)容類型聲明更弱。這會(huì)導(dǎo)致 Finder 雙擊.md打開(kāi)的不是你的編輯器。陷阱 3QLSupportedContentTypes必須同時(shí)包含兩個(gè) Markdown UTI這是最隱蔽的一個(gè)。macOS Spotlight 在文件首次被索引時(shí)會(huì)粘性地給它定型當(dāng)時(shí)系統(tǒng)上哪個(gè) Markdown UTI 是權(quán)威的文件就被標(biāo)成那個(gè)類型。結(jié)果就是曾經(jīng)裝過(guò) iA Writer或任何導(dǎo)出net.ia.markdown的應(yīng)用的用戶磁盤(pán)上約一半的.md文件會(huì)被定型為net.ia.markdown——即使那個(gè)應(yīng)用早已卸載。而 QuickLook 系統(tǒng)只調(diào)用QLSupportedContentTypes里列出的 UTI 對(duì)應(yīng)的擴(kuò)展。所以 ClearlyQuickLook/Info.plist 里老老實(shí)實(shí)寫(xiě)了兩行keyQLSupportedContentTypes/key array stringnet.daringfireball.markdown/string stringnet.ia.markdown/string /array少寫(xiě)任何一個(gè)另一批用戶的文件就會(huì)永久停留在原始文本預(yù)覽。? 附贈(zèng)驗(yàn)證環(huán)節(jié)的隱藏深坑修好配置只是開(kāi)始怎么驗(yàn)證本身還有坑同樣記錄在 CLAUDE.mdqlmanage命令行不可信在 macOS 26 上它對(duì).appex預(yù)覽擴(kuò)展會(huì)直接崩潰qlmanage -m plugins也只列出舊式.qlgenerator插件空結(jié)果屬于正?,F(xiàn)象。唯一的可靠測(cè)試方式是Finder 里按空格未公證的擴(kuò)展不被quicklookd調(diào)用新系統(tǒng)要求父應(yīng)用完成公證notarization staple 后擴(kuò)展才會(huì)生效。所以本地驗(yàn)證發(fā)布產(chǎn)物時(shí)要走完整的公證 →staple→qlmanage -r刷緩存流程舊注冊(cè)會(huì)污染本機(jī) LaunchServices大量 DerivedData / 并行工作目錄里的開(kāi)發(fā)版應(yīng)用會(huì)留下成百上千條陳舊注冊(cè)且新版 macOS 已移除lsregister -kill只能按路徑逐條lsregister -u清理。 iOS 側(cè)預(yù)覽擴(kuò)展 自定義縮略圖Mac 之外Clearly 在 iOS/iPadOS 上還做了兩件事配置思路完全一致1. QuickLook 預(yù)覽擴(kuò)展Clearly/iOS/PreviewExtension/PreviewViewController.swift邏輯與 Mac 版幾乎相同但多了一步——注冊(cè)了LocalImageSchemeHandler處理本地圖片并把baseURL設(shè)為文件所在目錄讓相對(duì)路徑圖片能在預(yù)覽中正常顯示。2. 自定義縮略圖擴(kuò)展Clearly/iOS/ThumbnailExtension/ThumbnailProvider.swift在文件App 列表視圖里給.md文件畫(huà)出標(biāo)題 前幾行正文的定制縮略圖。它的做法很聰明——只讀文件前 4096 字節(jié)readSample提取第一個(gè)#標(biāo)題和最多 12 行正文來(lái)繪制縮略圖生成快且不拖慢文件系統(tǒng)列表寬度小于 64pt 時(shí)干脆畫(huà)空白讓系統(tǒng)自己貼文檔角標(biāo)。 細(xì)節(jié)深色模式一行都不用改因?yàn)闃邮饺縼?lái)自共享的PreviewCSS它內(nèi)部用media (prefers-color-scheme: dark)自動(dòng)適配深色模式。QuickLook 預(yù)覽跟著系統(tǒng)外觀切換主應(yīng)用零成本獲得同樣的體驗(yàn) 總結(jié)你的 QuickLook 擴(kuò)展檢查清單從 Clearly 的實(shí)現(xiàn)中可以提煉出這份可復(fù)用的檢查清單#檢查項(xiàng)Clearly 對(duì)應(yīng)文件1擴(kuò)展目標(biāo)獨(dú)立、隨主應(yīng)用內(nèi)嵌Bundle ID 用獨(dú)立后綴project.yml2渲染邏輯放共享包擴(kuò)展只做膠水MarkdownRenderer.swift3用UTExportedTypeDeclarations聲明內(nèi)容類型Clearly/Info.plist4LSHandlerRank設(shè)為OwnerClearly/Info.plist5QLSupportedContentTypes覆蓋所有歷史UTIClearlyQuickLook/Info.plist6驗(yàn)證用 Finder 空格別信qlmanageCLAUDE.mdQuickLook 擴(kuò)展的代碼量小得驚人——難點(diǎn)全在配置與系統(tǒng)路由。照著這份清單走你的 Markdown 文件在 Finder 里按下空格的那一刻就該是一篇排版精美的文章。贊分享【免費(fèi)下載鏈接】clearlyMarkdown editor for Mac, iOS and iPadOS項(xiàng)目地址https://gitcode.com/gh_mirrors/cle/clearly點(diǎn)擊查看免費(fèi)下載相關(guān)推薦Go-Chassis 服務(wù)發(fā)現(xiàn)與注冊(cè)集成 ServiceComb 與 Kubernetes 完整指南Go Chassis 服務(wù)發(fā)現(xiàn)與注冊(cè)集成 ServiceComb 與 Kubernetes 完整指南 Go Chassis 是一款云原生應(yīng)用框架專為 GoQuickLook5個(gè)超實(shí)用技巧讓你3分鐘精通Windows文件預(yù)覽神器QuickLook5個(gè)超實(shí)用技巧讓你3分鐘精通Windows文件預(yù)覽神器 你是否曾在整理項(xiàng)目文件時(shí)為了查看一個(gè)圖片內(nèi)容而不得不啟動(dòng)Photoshop或者在桌面應(yīng)用插件系統(tǒng)如何免費(fèi)使用 Markdown Viewer瀏覽器擴(kuò)展完全指南讓 Markdown 預(yù)覽更高效 如何免費(fèi)使用 Markdown Viewer瀏覽器擴(kuò)展完全指南讓 Markdown 預(yù)覽更高效 Markdown Viewer 是一款強(qiáng)大的瀏覽器擴(kuò)展前端文檔創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考