typescript - Erweiterung der JavaScript-Syntax im Monaco Editor mit vollständiger Integration
Ich versuche, den Monaco Editor zu erweitern, um Benutzern zu ermöglichen, in einer Mischung aus JavaScript und einer anderen Sprache zu schreiben, wobei Trennzeichen verwendet werden, um sie innerhalb derselben Datei zu trennen, ähnlich wie Markdown das Schreiben mehrerer Sprachen mithilfe von Codeblöcken erlaubt.
Der Unterschied ist, dass ich alle anderen IDE-Funktionen, die Monaco für JavaScript eingebaut hat, beibehalten möchte, wie zum Beispiel Linting (durch Diagnosen), intelligente automatische Vervollständigung, Gehe-zu-Definition, automatische Formatierungshilfen und jede andere IDE-Funktion, die mit Monacos integriertem JavaScript-Modus geliefert wird. Ich möchte, dass diese Funktionen weiterhin im JavaScript-Teil des Codes funktionieren, den Monaco bearbeitet, und für den Teil der Unter-Sprache deaktiviert werden.
Mein erster Versuch bestand darin, setMonarchTokensProvider aufzurufen und eine modifizierte Version der Tokenizer-Regeln von TypeScript zu übergeben. Konkret konnte ich den Anfangsgrenzwert-Delimiter zur Root-Regel hinzufügen und eine neue Regel für die Unter-Sprache auf die gleiche Weise erstellen, wie es die Dokumentation für Monarch (Monacos Syntax-Highlighter) beschreibt, unter Verwendung von @nextEmbedded. (Zu Testzwecken habe ich CSS als eingebettete Sprache fest codiert.)
Wenn ich setMonarchTokensProvider so für die Sprache "javascript" aufrufe, ignoriert es diesen Syntax-Highlighting-Tokenizer vollständig und markiert die Code-Fences von CSS als ungültiges JavaScript, was darauf hinweist, dass man den eingebauten JavaScript-Modus auf diese Weise nicht überschreiben kann.
Wenn ich setMonarchTokensProvider mit einer neuen Sprache aufrufe (z. B. „mylang“) und den Editor so einstelle, dass er diese Sprache verwendet, liefert er korrektes Syntax-Highlighting (!) für diese CSS-in-JS-Hybridsprache. Aber alle anderen erweiterten Funktionen, die im JavaScript-Modus vorhanden waren, sind nicht mehr verfügbar. Der Editor hatte keine intelligente Autovervollständigung für Methoden, die in Klassen in derselben Datei definiert sind, keine interne Fehleranzeige für ungültige Syntax und keine seiner bekannten JavaScript-IDE-Funktionen.
Also war mein nächster Versuch, die vorinstallierte TypeScript-Definition des Monaco-Codes zu ändern, um meine eigenen Regeln für die Syntaxhervorhebung einzuschließen. Dies markierte meinen CSS-in-JS-Code vollständig korrekt (!), wenn die Sprache auf „typescript“ eingestellt war, und ließ alle anderen Funktionen unverändert (!) einschließlich der Diagnoseberichte (Live-Validierung und Unterstreichung von Fehlern), Auto-Vervollständigung, einfach alles! (Ich habe es nicht mit „javascript“ ausprobiert, aber es ist sicher anzunehmen, dass es wahrscheinlich funktioniert oder trivial zum Laufen zu bringen ist, da JavaScript tatsächlich als Variantenkonfiguration des TypeScript-Modus in Monaco implementiert ist.)
Leider betrachtete es auch den gesamten CSS-Teil davon, einschließlich des Zauns darum, als ungültigen JavaScript-Code.
Ich weiß, dass dies theoretisch machbar ist, weil man im HTML-Modus CSS oder JS mit voller Unterstützung für ordnungsgemäße Validierung und Auto-Vervollständigung sowie allen anderen IDE-Funktionen einbetten kann; im Grunde funktioniert jede Untersprache in einer HTML-Datei so, als wäre sie in ihrer eigenen Datei: HTML-Funktionen im Root der Datei, CSS-Funktionen innerhalb von style-Tags, JS-Funktionen innerhalb von script-Tags.
Aber wenn man in die Implementierung des TypeScript-Plugins innerhalb von Monaco eintaucht, ist es nicht klar, wo man damit beginnen sollte, dies zu bearbeiten, weder als Benutzer der Bibliothek Monaco, noch durch Forken und Patchen, wo es nötig ist. Ich begann damit, zu versuchen, den DiagnostcsAdapter [sic] zu modifizieren und nachzuverfolgen, wo er tatsächlich implementiert ist, aber ich blieb zwei Funktionsaufrufe tief stecken, wo es scheint, dass ein Promise zur Syntaxprüfung übergeben wird, das einen Wert zurückgibt, der später verwendet wird, aber die Implementierung von getSyntacticDiagnostics überlässt die Arbeit einfach einer anderen Implementierung, die ich nirgendwo sonst im Repository, noch im monaco-languages Repository oder im vscode Repository finden kann.
Antwort #1
Ich mache etwas Ähnliches. Meine Lösung ist, nicht-JS-Code innerhalb eines Blockkommentars zu platzieren:
regularJsCode()
/*
[your-syntax-identifying-start-token]
place any syntax you want here
[your-syntax-identifying-end-token]
*/
regularJsCode()
Dann können Sie es mit Ihren Werkzeugen, Parsern, IDE-Erweiterungen usw. verarbeiten. Und das Coolste ist, dass Sie VSCode dazu bringen können, es nach Wunsch syntaxmäßig zu markieren, sodass es nicht wie ein Hack aussieht.
Dieser Ansatz ist vorzuziehen, weil Ihre JS-Datei weiterhin eine zu 100 % gültige JS-Datei bleibt.
Wenn Sie immer noch nicht Ihre Syntax in Kommentare setzen möchten, dann sollten Sie Ihre eigene Dateierweiterung wie .jsx/.tsx erstellen. In praktischen VSCode-Begriffen bedeutet dies, dass Sie eine VSCode-Erweiterung mit Sprachserver und so weiter erstellen müssen. Das ist nicht so einfach, aber die Dokumentation ist gut. Sie könnten Ihren eigenen JS-Hervorhebungscode innerhalb Ihrer VSCode-Erweiterung unter Verwendung des Sprachservers zusammenstellen: https://github.com/sourcegraph/javascript-typescript-langserver
Antwort #2
Laut dem Schöpfer von Monaco:
Architektonisch können Sie Folgendes tun:
- verwenden Sie monaco-editor-core direkt
- definiere eine neue Sprache für den Editor
- Forken Sie monaco-typescript und ändern Sie es so, dass es mit Ihrer neu definierten Sprach-ID funktioniert. Ändern Sie dann den TS-Sprachhost-Code so, dass die ursprünglichen Modelle nicht an TypeScript übergeben werden, sondern zunächst eine Vorverarbeitung ausgeführt wird, die Ihre benutzerdefinierte Sprache aus dem Text entfernt, und dann nur gültiges TypeScript an den TS-Compiler weitergegeben wird. Eine Idee ist, jedes entfernte Zeichen durch ein Leerzeichen zu ersetzen. Dadurch bleibt die gesamte Positions-/Offset-Berechnung ohne Aufwand auf Ihrer Seite erhalten.
Viel Glück!
