javascript - 通过完全集成在 Monaco Editor 中扩展 JavaScript 语法

标签 javascript typescript plugins ide monaco-editor

我正在尝试扩展 Monaco Editor允许用户使用 JavaScript 和另一种语言的混合编写,在同一个文件中使用定界符将它们分隔开,类似于 Markdown 允许使用围栏代码块编写多种语言的方式。

区别在于我想保留 Monaco 为 JavaScript 内置的所有其他 IDE 功能,例如 linting(通过 diagnostics 完成)、smart auto-completion , jump-to-definition , auto-formatting helpers ,以及 Monaco 内置 JavaScript 模式附带的所有其他 IDE 功能。我希望这些功能在 Monaco 正在编辑的代码的 JavaScript 部分仍然有效,并在子语言部分被禁用。

我的第一次尝试是调用 setMonarchTokensProvider ,传入 TypeScript's tokenizer rules 的修改版本.具体来说,我能够将开始分隔符添加到 root rule并以与 Monarch (Monaco's syntax highligher) 的文档相同的方式为子语言创建新规则描述,using @nextEmbedded . (出于测试目的,我一直将 CSS 硬编码为嵌入式语言。)

当我像这样为 the language "javascript" 调用 setMonarchTokensProvider 时,它完全忽略了这种语法高亮分词器,并将 CSS 的代码栅栏标记为无效的 JavaScript,表明您不能通过这种方式覆盖内置 JavaScript 模式。

当我使用一种新语言(例如“mylang”)调用 setMonarchTokensProvider 并将编辑器设置为使用该语言时,它会为这种 CSS-in-JS 混合语言提供正确的语法高亮显示 (!)。但是在 JavaScript 模式中找到的所有其他高级功能都不再存在。对于在同一文件中的类上定义的方法,编辑器没有任何智能自动完成功能,也没有针对无效语法的任何编辑器内错误报告,或其任何商标 JavaScript IDE features .

因此,我的下一次尝试是修改预捆绑的 Monaco 代码的 TypeScript 定义,以包含我的自定义语法突出显示规则。这正确地完全突出了我的 CSS-in-JS 代码(!),当将语言设置为“ typescript ”时,保持所有其他功能不变(!),包括诊断报告(实时验证和下划线错误),自动完成,全部! (我没有用“javascript”尝试过它,但可以安全地假设它可能工作或者让它工作是微不足道的,因为 JavaScript is actually implemented as a variant configuration of the TypeScript mode in Monaco 。)

不幸的是,它还认为它的整个 CSS 部分,包括它周围的栅栏,都是无效的 JavaScript 代码。

The thing almost working.

我知道这在理论上是可行的,因为在 HTML 模式下,您可以嵌入 CSS 或 JS,并完全支持正确的验证和自动完成以及所有其他 IDE 功能;基本上,HTML 文件中的每个子语言都像在其自己的文件中一样工作:文件根目录中的 HTML 功能、样式标签中的 CSS 功能、脚本标签中的 JS 功能。

但是深入研究 TypeScript 插件在 Monaco 中的实现,不清楚从哪里开始编辑它,作为 Monaco 库的用户,或者通过 fork 它并在必要时修补它。我开始尝试修改 DiagnostcsAdapter [原文如此] 并跟踪它实际实现的位置,但我陷入了两个函数调用深处,它似乎插入了一个 promise of syntax validation。返回 a value that's used later , 但是 the implementation of getSyntacticDiagnostics只是将工作打包到我找不到的其他实现中 anywhere else in the repo , 也不在 monaco-languages repovscode repo .

最佳答案

我做过类似的东西。我的解决方案是将非 JS 代码放在 block 注释中:

regularJsCode()
/* 
[your-syntax-identifying-start-token]
place any syntax you want here
[your-syntax-identifying-end-token]
*/
regularJsCode()

然后你可以使用你的工具、解析器、IDE 扩展等来处理它。最酷的部分是你可以让 VSCode 像你想要的那样对其进行语法高亮显示,这样它就不会看起来像一些 hack。

这种方法是可取的,因为你的 JS 文件仍然是 100% 有效的 JS 文件。

如果您仍然不想将语法放入注释中,那么您应该创建自己的文件扩展名,例如 .jsx/.tsx。实际上,VSCode 术语这意味着您需要使用语言服务器和其他东西创建 VSCode 扩展。这不是那么容易,但是文档很好。您可以使用语言服务器在您的 VSCode 扩展中组装您自己的 JS 突出显示代码:https://github.com/sourcegraph/javascript-typescript-langserver

关于javascript - 通过完全集成在 Monaco Editor 中扩展 JavaScript 语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52672353/

相关文章:

java - 使用 UI 创建 Android Studio 插件

javascript - ‘this’ vs. 'bind.(this)' vs. 将事件传递给事件处理程序,React JS vs. vanilla JavaScript

javascript - 无法在 TypeScript 中设置未定义的属性 XXX

使用下一代插件的 java 小程序

typescript - 为什么 Typescript 会忽略超出已知大小的元组内容?

typescript - 是否可以避免 Typescript 上的长相对导入路径?

javascript - jQuery 命名空间和使用 "this"

javascript - 从 View 中修改 ng-model

javascript - 使用jquery生成html表时设置下拉选择值

javascript - 大量的JavaScript,219个字节中的多个问题( Canvas ,按位,…)