ist jetzt verfügbar! Lesen Sie über die neuen Funktionen und Fehlerbehebungen vom November.

Einführung des Markdown Language Servers

16. August 2022 von Matt Bierner, @MattBierner

Die Markdown-Unterstützung war die erste Funktion, die ich im Jahr 2016 übernommen habe, als ich zu Visual Studio Code kam. Wow, sind das wirklich schon sechs Jahre? Es war jedoch eine großartige Kombination. Ich habe so lange mit Markdown gearbeitet, dass ich mich oft dabei erwische, wie ich hoffnungsvoll Backticks und Sternchen in Twitter, Outlook und fast jedes Textfeld tippe, in das mein Cursor landet. Es war unglaublich lohnend, die integrierte Markdown-Unterstützung von VS Code im Laufe der Jahre auszubauen und zu sehen, wie unsere Markdown-Erweiterung Kernfunktionen wie Webviews und Notebooks direkt und indirekt geprägt hat.

Deshalb freue ich mich, ein Projekt vorstellen zu können, an dem ich in den letzten sechs Monaten im Stillen gearbeitet habe und das meiner Meinung nach den nächsten Schritt für die Markdown-Tools von VS Code darstellt: einen Markdown Language Server. Mit diesem Language Server machen wir die meisten integrierten Markdown-Sprachwerkzeuge von VS Code – alles von Dokumentgliederungen über intelligentes Falten bis hin zu Pfadvervollständigungen – für andere Editoren und Tools verfügbar. Unser Ziel ist es, die Markdown-Tools mit der Art von Intelligenz voranzutreiben, die man eher mit Programmiersprachen in Verbindung bringt.

Die Arbeit am Markdown Language Server ist in zwei neue (und ähnlich benannte!) Open-Source-Bibliotheken aufgeteilt

Obwohl sich diese Bibliotheken noch im Anfangsstadium befinden, werden sie bereits von VS Code 1.70+ verwendet (und hoffentlich haben Sie es nie bemerkt :-)). Wir haben sogar einige Vorteile aus diesem Wechsel gezogen, wie z. B. die Auslagerung der Markdown-Tools in einen separaten Prozess, sodass sie andere Erweiterungen nicht blockieren.

Aber bevor ich mich zu weit aus dem Fenster lehne, fragen Sie sich vielleicht: Warum wird ein Markdown Language Server benötigt? Und ehrlich gesagt, es hat mich diese sechs Jahre gekostet, um selbst zu diesem Punkt zu gelangen. Das spiegelt auch meine Entwicklung wider: von der Ansicht von Markdown als einfachem Klartext mit ein paar Sternchen, Klammern und Rautenzeichen, um es aufzulockern, hin zum Verständnis von Markdown als Auszeichnungssprache, die von vielen der gleichen Werkzeuge profitieren kann, die wir für Programmiersprachen wie TypeScript oder Python anbieten.

Sich mit Markdown-Tools auseinandersetzen

Bevor ich VS Code entdeckte, programmierte ich hauptsächlich mit einem einfachen Texteditor. Das bedeutete, dass ich mir Symbolnamen merken und sie jedes Mal eintippen musste, wenn ich sie verwenden wollte. Wenn ich eine Variable umbenennen wollte, führte ich eine Textsuche/-ersetzung durch und hoffte, dass meine Unit-Tests die unvermeidlichen Fälle abfangen würden, in denen ein Name entweder falsch geschrieben oder verunstaltet wurde. Es war eine langsame und unzuverlässige Arbeitsweise, aber ich war zufrieden, weil ich nicht wusste, dass es besser gehen könnte. Ich habe erst wirklich begriffen, wie primitiv mein Workflow war, nachdem ich endlich intelligentere Werkzeuge in die Hände bekam.

Diese Erkenntnis machte ich kürzlich auch mit Markdown. Jahrelang kam ich mit dem relativ einfachen Markdown-Editor von VS Code gut zurecht. Ich war mit der Syntaxhervorhebung und der integrierten Markdown-Vorschau zufrieden. Dokumentgliederungen und klickbare Editor-Links waren nur Boni. Ich hatte mich daran gewöhnt, Links von Hand zu schreiben. Ich hatte akzeptiert, dass ich, wenn ich einen Header-Namen änderte, eine Textsuche durchführen müsste, um alle Links zu diesem Header zu aktualisieren. Und weil ich Markdown kaum mehr als schickem Klartext sah, konnte ich mir nicht einmal vorstellen, dass es einen besseren Weg gab.

Aber eines Tages, nachdem ich zum gefühlt hundertsten Mal einen Bildpfad falsch eingegeben hatte, traf es mich: **Das macht keinen Spaß**! Warum verschwende ich mein Leben damit, diese Links manuell einzutippen und zu validieren? Dafür sind Werkzeuge da! Ich wusste, dass ich nicht irgendein Werkzeug wollte, sondern eines, das mir hilft, mein Markdown als Text zu lesen und zu schreiben, anstatt die Markdown-Quelle hinter einer WYSIWYG-ähnlichen UI-Magie zu verstecken. Das entspricht sehr dem Ethos von VS Code und unserer Denkweise über die Unterstützung von Programmiersprachen. Warum sollten nicht viele der gleichen intelligenten Funktionen, die wir für traditionelle Programmiersprachen anbieten, auch für Markdown gelten? Am nächsten Tag begann ich mit der Arbeit an Link-Vervollständigungen.

Link-Vervollständigungen sind Vorschläge, die Ihnen helfen, Links zu Headern innerhalb der aktuellen Datei oder zu anderen Dateien im Arbeitsbereich zu schreiben. Ich habe sogar die Unterstützung für die Vervollständigung von Links zu Headern in anderen Markdown-Dateien hinzugefügt. Nett! Es war eine kleine Ergänzung, die aber einen großen Unterschied in meiner Produktivität machte. Bald konnte ich mir nicht mehr vorstellen, wie ich jemals ohne sie gelebt hatte.

Berauscht vom Erfolg der Markdown-Vervollständigungen schwelgte ich in der Vorstellung, welche anderen Sprachintelligenzen ich als Nächstes in Markdown einbringen könnte. Ich stellte mir vor, wie ich F2 auf Headern drückte, um sie sicher umzubenennen. Ich träumte davon, rote Wellenlinien, die sich durch trübe Textmeere schlängeln, um ungültige Links zu identifizieren. Es schien alles so offensichtlich! Warum war ich nicht schon vor Jahren darauf gekommen? Ich begann, Markdown als strukturierten Text und nicht nur als einfachen Text zu verstehen, und die Möglichkeiten für bessere Markdown-Tools schienen endlos.

Markdown-Sprachfeatures

Ich werde Sie nicht mit der Geschichte hinter jeder neuen Funktion langweilen oder alle Details der Implementierung verraten. Es genügt zu sagen, dass ich einen inkrementellen Ansatz verfolgte, der all die Anstrengungen mit der begrenzten Zeit ermöglichte, die ich für die Markdown-Unterstützung von VS Code aufwenden konnte. Anstatt direkt mit der Implementierung der Umbenennungsunterstützung zu beginnen, habe ich zuerst eine solide Version von **Alle Referenzen finden** zum Laufen gebracht (denn wenn Sie ein Symbol umbenennen möchten, müssen Sie zuerst alle Stellen kennen, an denen es referenziert wird). Durch die inkrementelle Arbeit und den schrittweisen Aufbau jeder Funktion konnte ich alte Funktionen testen, während ich neue implementierte. Zum Beispiel half mir die Implementierung der Umbenennung von Links, Unmengen von Fehlern bei der Linkerkennung zu finden. (Der einzige Nachteil dieses Ansatzes ist die Erkenntnis, dass Sie Ihren "so eleganten" Turm auf ein paar sehr haarigen regulären Ausdrücken gebaut haben).

Als im späten Frühjahr experimentelle Unterstützung für die Meldung ungültiger Datei-/Bildlinks eingeführt wurde, trat ich einen Schritt zurück, um meine Arbeit zu überprüfen. Die Menge der Markdown-Sprachfeatures umfasste nun

  • Dokumentgliederungen
  • Arbeitsbereichssymbole
  • Dokumentlinks
  • Intelligentes Falten
  • Intelligente Auswahl
  • Vervollständigungen
  • Umbenennen
  • Alle Referenzen finden
  • Zur Definition springen
  • Diagnosen für defekte Links
  • Aktualisierung von Links bei Dateiverschiebungen/-umbenennungen

Ich wusste, dass diese neuen Werkzeuge die Arbeit mit Markdown schneller und sicherer machen würden. Aber als ich diese Liste von Features, die für Programmiersprachen üblich sind, durchging, drängte sich mir eine Idee auf. Ich hatte sie vor ein paar Monaten noch als lächerlich abgetan, aber jetzt, als ich sie wieder durchdachte, erkannte ich, dass es vielleicht endlich Zeit für einen Markdown Language Server war.

Werden Sie bedient?

Bis zum späten Frühjahr 2022 liefen alle Markdown-Tools von VS Code noch über die normalen Erweiterungs-APIs. Obwohl ich die Umstellung all dieser Werkzeuge auf einen richtigen Language Server erkunden wollte, wäre die Änderung mit erheblichen technischen Kosten verbunden. Ich musste sicherstellen, dass es sich lohnen würde.

Ich habe diesen Gedanken mehr als einen Monat lang hin und her gewälzt. Obwohl der bestehende Code in einem ordentlichen Zustand war, gab es viele Unbekannte. Was, wenn ich einen Teil des Weges zurücklegen und dann feststellen würde, dass es nicht funktionieren würde? Ich hatte noch nie ernsthaft an einem Language Server gearbeitet.

Während ich das alles abwog, hielt ich mich damit beschäftigt, den Quellcode der Markdown-Erweiterung so zu refaktorieren, als ob er in einen Language Server verschoben werden sollte. Ich versuchte, Abhängigkeiten von den VS Code-Erweiterungs-APIs zu isolieren, verlagerte mehr Logik auf Service-Injection und stellte sicher, dass Tests nicht vom Dateisystem abhängig waren. So konnte ich, selbst wenn ich nie den Sprung zum Language Server wagte, zumindest den Code aufräumen.

Einige Überlegungen überzeugten mich letztendlich, dass ein Markdown Language Server der richtige nächste Schritt war. Erstens, eine eher banale: Ich fand es sehr schwierig, Link-Diagnosen für Markdown-Dateien effizient zu implementieren. In einem großen Markdown-Arbeitsbereich wie vscode-docs blockierte ich immer wieder versehentlich den Extension Host für ein paar hundert Millisekunden. Nicht gut. Ein Language Server hingegen läuft als eigener Prozess. Nicht nur das, sondern Language Server hatten jetzt auch ein neues Pull-Modell für Diagnosen, das ich gerne ausprobieren wollte.

Dann gab es edlere Gründe. Zum Beispiel wäre ein Markdown Language Server für andere Editoren und Tools nützlich. Dazu gehört auch der andere Editor, den das VS Code-Team anbietet: Monaco! Ganz zu schweigen von den Möglichkeiten eines CLI-Tools für Markdown. Wenn ich keine Zeit hätte, ein solches Werkzeug selbst zu bauen, könnte es vielleicht jemand anderes tun und den Language Server als Ausgangspunkt nutzen. Ich hatte viel Arbeit in die Markdown-Tools von VS Code gesteckt und es wäre großartig, wenn diese Arbeit anderen zugute käme.

Durch die Bereitstellung eines neuen Language Servers könnte ich auch eine gemeinsame Anstrengung zur Verbesserung der Markdown-Tools anstoßen. VS Code ist sowohl ein produktiver Erzeuger als auch Nutzer von Open-Source-Software, und ich hatte die klaren Vorteile solcher Projekte gesehen. Ein Open-Source-Markdown-Language-Server würde anderen Editoren helfen, aber im Gegenzug auch Beiträge einladen, die letztendlich VS Code helfen würden! Anstatt dass jeder Editor/jedes Tool den Aufwand für die Implementierung seiner eigenen Markdown-Unterstützung dupliziert, könnte ein Language Server Entwickler zusammenbringen, um an einem größeren Projekt zu arbeiten, das allen zugute käme.

All diese großen Überlegungen waren irrelevant, wenn kein Plan vorhanden war, wie der Language Server tatsächlich gebaut werden sollte. Selbst nach all meinem Refactoring wäre die Verlagerung des Codes in einen Language Server noch viel Arbeit gewesen! Es schien überwältigend, bis mir klar wurde, dass ich es nicht alles auf einmal machen musste. Ich konnte den Server schrittweise aufbauen und eine Funktion nach der anderen von der VS Code Markdown-Erweiterung zum neuen Markdown Language Server verlagern. Und wenn ich es richtig machte, konnte ich jede kleine inkrementelle Migration einchecken, so dass die Benutzer den neuen Language Server testen würden, während er gebaut wurde. Idealerweise würden die Benutzer nie bemerken, wann eine Funktion von der Erweiterung zum Language Server wechselte.

Vielleicht ist das offensichtlich, aber ich bin ein großer Verfechter dieser Art von inkrementellem Ansatz für große Codeänderungen. Keine hunderttausend Zeilen Code-PRs oder riesigen Feature-Branches, die monate- (oder jahrelang) bestehen bleiben! Stattdessen kleine, sichere Änderungen an `main`. Wenn alles wie geplant läuft, sollte der Commit, der all diese Arbeit abschließt, unspektakulär sein. Dies ist der Ansatz, den wir verfolgt haben, um die strict null check im gesamten VS Code-Codebase schrittweise einzuführen, und so habe ich das Gefühl, dass ich alle Markdown-Tools von VS Code schnell und mit möglichst wenig Aufwand auf einen neuen Language Server verschieben konnte.

Und Spoiler-Alarm: Es hat funktioniert! Ich habe die Sprachfeatures einzeln verschoben. Ich habe dabei gelernt und refaktorisiert, wenn es nötig erschien. Diagnosen waren die letzte Funktion, die verschoben wurde, da ich sie nicht nur zum Language Server verlagert, sondern auch neu geschrieben habe, um das neue Pull-Diagnose-Modell des Language Servers zu nutzen. Der letzte Commit der gesamten Aktion bestand hauptsächlich darin, den nun ungenutzten Code aus der Markdown-Erweiterung zu löschen. Und so nutzen heute, wenn Sie VS Code 1.70+ verwenden, fast alle Markdown-Sprachfeatures den neuen Language Server.

Gemeinsam bessere Markdown-Tools entwickeln

In vielerlei Hinsicht gab es in den letzten sechs Monaten mehr Fortschritte bei den Markdown-Tools von VS Code als in den letzten sechs Jahren, in denen ich in diesem Bereich tätig war. Heute liefern wir viele neue Werkzeuge aus, von denen einige für Markdown bisher nicht verfügbar waren. Viele dieser Features kommen den gelegentlichen Lesern und Schreibern von Markdown zugute, während andere nur von fortgeschrittenen Benutzern geschätzt werden. Trotz all dieser Fortschritte weiß ich, dass wir erst am Anfang der Erforschung dessen stehen, was bei Markdown-Tools möglich ist.

Was mich am Markdown Language Server wirklich begeistert, ist, dass das Projekt jetzt größer ist als nur VS Code. Indem wir unsere Markdown-Tools einfach nutzbar machen, hoffe ich, dass wir die Markdown-Tools für alle voranbringen können. Diese Open-Source-Projekte sind Einladungen, gemeinsam an der Zukunft der Markdown-Tools zu bauen. Wenn Sie daran interessiert sind, beizutragen, schauen Sie sich die neuen Projekte an und sehen Sie, was Sie damit erstellen können. Sie können Fehlerberichte und Funktionswünsche einreichen, vielleicht sogar einen PR! Es gibt unzählige intelligente Markdown-Sprachfeatures, von denen ich noch nicht einmal geträumt habe. Bauen wir sie gemeinsam!

Wenn Sie sich den Quellcode ansehen oder dazu beitragen möchten, finden Sie den Markdown Language Service und Server auf GitHub und npm

Viel Spaß beim Programmieren!

Matt Bierner, @MattBierner

© . This site is unofficial and not affiliated with Microsoft.