Markdown 語言伺服器簡介
2022 年 8 月 16 日,作者:Matt Bierner,@MattBierner
當我 2016 年加入 Visual Studio Code 時,Markdown 支援是我負責的第一個功能。哇,真的已經六年了嗎?不過這真是天作之合。我使用 Markdown 的時間夠久了,以至於我經常發現自己下意識地在 Twitter、Outlook 以及幾乎所有游標停駐的文字框中輸入反引號和星號。多年來,能看到 VS Code 內建的 Markdown 支援不斷成長,並看到我們的 Markdown 擴充功能如何直接和間接地塑造了網頁檢視和 Notebooks 等核心功能,這真的讓我感到非常有成就感。
這就是為什麼我很高興分享一個我過去半年來默默努力的專案,以及一個我認為代表 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 語言伺服器。
Coding 愉快!
Matt Bierner,@MattBierner