Markdown 語言伺服器簡介
2022 年 8 月 16 日,作者:Matt Bierner,@MattBierner
Markdown 支援是我在 2016 年加入 Visual Studio Code 時負責的第一個功能。哇,真的已經六年了嗎?不過,這真是絕佳的搭配。我使用 Markdown 的時間夠久了,以至於我經常發現自己希望能在 Twitter、Outlook 以及幾乎所有游標停駐的文字方塊中輸入反引號和星號。多年來,能夠不斷擴展 VS Code 內建的 Markdown 支援,並看到我們的 Markdown 擴充功能如何直接和間接地塑造了 Webview 和筆記本等核心功能,這真的非常有成就感。
這就是為什麼我很興奮地分享一個我過去半年來默默努力的專案,以及一個我認為代表 VS Code Markdown 工具下一步的專案:Markdown 語言伺服器。透過這個語言伺服器,我們將 VS Code 大部分內建的 Markdown 語言工具(從文件大綱到智慧摺疊,再到路徑完成)提供給其他編輯器和工具使用。我們的目標是利用通常與程式語言相關聯的智慧功能,推動 Markdown 工具向前發展。
Markdown 語言伺服器的開發工作分為兩個新的(且名稱相似!)開放原始碼程式庫
-
Markdown 語言服務 - 一個 TypeScript 程式庫,提供用於處理 Markdown 的工具。
-
Markdown 語言伺服器 - 一個使用語言服務建置的 Markdown 語言伺服器。
雖然這些程式庫仍處於早期階段,但 VS Code 1.70+ 已經在使用它們(希望您甚至沒有注意到 :-))。我們甚至從這次切換中看到了一些好處,例如將 Markdown 工具移至單獨的程序,使其不會阻礙其他擴充功能。
但在我過於超前之前,您可能想知道:為什麼需要 Markdown 語言伺服器?老實說,我也花了這六年才想通。這也記錄了我從一開始將 Markdown 簡單地視為帶有一些星號、括號和井字號的純文字,到後來將 Markdown 理解為一種標記語言,並且可以從我們為 TypeScript 或 Python 等程式語言提供的許多相同工具中受益的演變過程。
深入了解 Markdown 工具
在發現 VS Code 之前,我主要使用簡單的文字編輯器編碼。這意味著我必須記住符號名稱,並在每次想使用它們時都將其輸入出來。如果我想重新命名變數,我會執行文字尋找/取代,並希望我的單元測試能夠捕捉到不可避免的名稱輸入錯誤或損壞的情況。這是一種緩慢且不可靠的工作方式,但我很滿足,因為我不知道情況可能會更好。直到我最終接觸到更智慧的工具後,我才真正理解我的工作流程有多麼原始。
最近,我對 Markdown 也有了同樣的體會。多年來,我一直很滿意使用 VS Code 相對簡單的 Markdown 編輯器。我對語法醒目提示和內建的 Markdown 預覽感到滿意。文件大綱和可點擊的編輯器連結只是額外的好處。我已經習慣手動寫出連結。我已經接受了如果我更改標題名稱,我需要執行文字搜尋來更新所有指向該標題的連結。而且由於我將 Markdown 視為僅僅是花俏的純文字,我甚至無法想像會有更好的方法。
但有一天,在感覺像是第一百次輸錯圖片路徑後,我終於意識到:這不好玩!我為什麼要浪費生命手動輸入和驗證這些連結?工具就是為此而生的!我知道我不想要任何工具,我想要一個可以幫助我以文字形式閱讀和撰寫 Markdown,而不是將 Markdown 原始碼隱藏在某些 WYSIWYG 風格的 UI 魔術背後的工具。這非常符合 VS Code 的精神以及我們對程式語言支援的看法。為什麼我們為傳統程式語言提供的許多相同智慧功能不適用於 Markdown 呢?我隔天就開始研究連結完成功能。
連結完成功能提供建議,協助您撰寫連結到目前檔案內標題或工作區中其他檔案的連結。我甚至新增了支援,可以完成連結到其他 Markdown 檔案內標題的連結。很棒!這只是一個小小的補充,但對我的生產力產生了巨大的影響。很快我就無法想像沒有它我過去是怎麼生活的。
沉浸在 Markdown 完成功能的成功中,我陶醉地想像著接下來我可以為 Markdown 帶來哪些其他語言智慧功能。我夢想著自信地在標題上按下 F2 鍵以安全地重新命名它們。我夢想著紅色的波浪線從混濁的文字海洋中射出,以幫助識別無效的連結。這一切似乎都是如此顯而易見!為什麼我幾年前沒有想到呢?我開始將 Markdown 理解為結構化文字,而不僅僅是純文字,而且更優質的 Markdown 工具的可能性似乎是無窮無盡的。
Markdown 語言功能
我不會用每個新功能背後的故事來煩擾您,也不會深入探討所有實作細節。簡而言之,我採取了漸進式方法,這使得所有努力都能在我有限的時間內投入到 VS Code 的 Markdown 支援中成為可能。例如,我沒有直接跳到建置重新命名支援,而是首先獲得了穩定版本的尋找所有參考並使其正常運作(因為如果您想重新命名符號,您首先需要知道所有參考它的位置)。漸進式地工作並在每個功能的基礎上建置新功能也幫助我在實作新功能時測試舊功能。例如,在連結上實作重新命名功能幫助我抓住了大量連結偵測錯誤。(這種方法的唯一缺點是意識到您已經在一些非常複雜的正規表示式之上建置了您的「喔,如此優雅」的高塔)。
在春末推出報告無效檔案/圖片連結的實驗性支援時,我退後一步檢視我的工作。現在的 Markdown 語言功能集包括
- 文件大綱
- 工作區符號
- 文件連結
- 智慧摺疊
- 智慧選取
- 完成
- 重新命名
- 尋找所有參考
- 前往定義
- 無效連結診斷
- 移動/重新命名檔案時更新連結
我知道這些新工具將使 Markdown 工作更快速、更安全。但是,當我檢視這個程式語言常見的功能列表時,一個想法不斷地困擾著我。幾個月前我還認為這很荒謬,但現在,當我再次思考時,我意識到也許終於到了推出 Markdown 語言伺服器的時機了。
伺服器為您服務?
到 2022 年春末,VS Code 的所有 Markdown 工具仍在使用正常的擴充功能 API 執行。雖然我想探索將所有這些工具移至適當的語言伺服器,但進行變更將產生實際的工程成本。我需要確保這將是值得的。
我為此來回思考了一個多月。即使現有的程式碼狀況良好,仍然有很多未知數。如果我進行到一半才意識到它行不通怎麼辦?我以前甚至從未認真研究過語言伺服器。
當我爭論這一切時,我讓自己忙於重構 Markdown 擴充功能的原始碼,彷彿它即將被移至語言伺服器。我嘗試隔離對 VS Code 擴充功能 API 的依賴性,我將更多邏輯切換為使用服務注入,並且我確保測試不依賴檔案系統。這樣,即使我從未冒險嘗試語言伺服器,至少我也在清理程式碼庫。
一些考量最終讓我確信 Markdown 語言伺服器是正確的下一步。首先是一個相當平凡的考量:我發現為 Markdown 檔案有效率地實作連結診斷非常具有挑戰性。在像 vscode-docs 這樣的大型 Markdown 工作區中,我一直不小心將擴充功能主機阻塞了幾百毫秒。這可不好。另一方面,語言伺服器作為自己的程序執行。不僅如此,語言伺服器現在還有一種新的提取模型用於診斷,我很興奮能嘗試一下。
然後還有更崇高的理由。例如,Markdown 語言伺服器對其他編輯器和工具也會很有用。這包括 VS Code 團隊推出的另一個編輯器:Monaco!更不用說像 Markdown CLI 工具這樣的可能性了。如果我沒有時間自己建置這樣的工具,也許其他人可以使用語言伺服器作為起點。我已經在 VS Code 的 Markdown 工具上投入了大量工作,如果所有這些工作也能造福他人,那就太好了。
透過提供新的語言伺服器,我也許能夠啟動圍繞改善 Markdown 工具的共同努力。VS Code 既是開放原始碼軟體的豐碩生產者,也是使用者,我已經看到了這些類型的專案提供的明顯好處。開放原始碼 Markdown 語言伺服器將有助於其他編輯器,但反過來也會邀請貢獻,最終將有助於 VS Code!語言伺服器可以將開發人員聚集在一起,共同致力於一個更大的專案,這將使所有人受益,而不是讓每個編輯器/工具重複實作自己的 Markdown 支援。
如果沒有實際建置語言伺服器的計畫,所有這些宏偉的思考都是無關緊要的。即使在我進行了所有重構之後,將程式碼移至語言伺服器仍然需要大量工作!這似乎令人難以承受,直到我意識到我不必一次完成所有工作。我可以漸進式地建置伺服器,一次從 VS Code Markdown 擴充功能移動一個功能到新的 Markdown 語言伺服器。如果我做得對,我可以簽入每個小的漸進式遷移,以便使用者在建置新的語言伺服器時對其進行測試。理想情況下,使用者永遠不會注意到功能何時從擴充功能移至語言伺服器。
也許這很明顯,但我已經成為這種針對大型程式碼變更的漸進式方法的忠實信徒。沒有十萬行程式碼的 PR 或持續數月(或數年!)的大型功能分支。相反,對 main
進行一堆小的、安全的變更。如果一切按計畫進行,那麼完成所有這些工作的提交應該是反高潮的。這就是我們逐步在整個 VS Code 程式碼庫中使用嚴格 Null 檢查 的方法,這也是我認為我可以快速且盡可能順利地將 VS Code 的所有 Markdown 工具移至新的語言伺服器的方法。
劇透警告:它成功了!我一次移動一個語言功能。我在過程中學習,並在清楚需要時進行重構。診斷是最後一個移動的功能,因為我不僅將它們移動到語言伺服器,而且還重寫了它們,以使用語言伺服器新的提取診斷模型。整個工作的最後一次提交主要是刪除了 Markdown 擴充功能中現在未使用的程式碼。因此,今天,如果您使用的是 VS Code 1.70+,幾乎所有 Markdown 語言功能都使用新的語言伺服器。
共同打造更優質的 Markdown 工具
在許多方面,過去六個月 VS Code Markdown 工具的進展比我過去六年在這個領域的工作還要多。今天,我們正在發布許多新工具,其中一些工具以前從未適用於 Markdown。這些功能中的許多功能使最普通的 Markdown 讀者和作者受益,而其他功能只有進階使用者才會欣賞。然而,儘管取得了所有這些進展,但我知道我們才剛剛開始探索 Markdown 工具的潛力。
真正讓我對 Markdown 語言伺服器感到興奮的是,現在這個專案比僅僅是 VS Code 更大了。透過使我們的 Markdown 工具易於使用,我希望我們能夠幫助推動所有人的 Markdown 工具向前發展。這些開放原始碼專案是幫助共同建構 Markdown 工具未來的邀請。如果您有興趣做出貢獻,請查看新專案,看看您可以使用它們創建什麼。您可以提交錯誤報告和功能請求,甚至可以提交 PR!還有許多我甚至還沒有夢想過的智慧 Markdown 語言功能。讓我們一起建構它們吧!
如果您有興趣查看原始碼或做出貢獻,可以在 GitHub 和 npm 上找到 Markdown 語言服務和伺服器
-
Markdown 語言服務 - 一個 TypeScript 程式庫,提供用於處理 Markdown 的工具。
-
Markdown 語言伺服器 - 一個使用語言服務建置的 Markdown 語言伺服器。
編碼愉快!
Matt Bierner,@MattBierner