阐明
- 为了让 monaco 应用 vscode 的主题
尝试实现(弯路)
主题的间接转换
- 刚开始本认为是两者主题的格局不同, 尝试转换后发现还是不能失常应用
- 后果发现两者的 token 基本不同, 也就是宰割代码每一部分的命名不同
monarch 转换 textmate
- 发现 monaco 应用的是本人设计的 monarch 来实现语法高亮, 然而 vscode 应用的是 textmate 的格局
textmate 是苹果的那种
- 于是想到如果实现一种转换逻辑, 将 textmate->monarch, 那么 monaco 就能够应用 vscode 的主题了(因为 token 一样了)
- 当学完单方的逻辑后, 钻研了 posix 与 pcre 正则的转换, 进行事件时, 发现一个致命问题..monach 无奈实现后行断言(
(?<=})
), 这就导致了一般的转换根本无法实现.(简单的 … 可能有生之年系列吧)
最终解决方案
- 应用 vscode-textmate 代替原 monarch
- 其实这个在开始钻研的时候就有了, 然而网上说因为不能间接调用 c, 所以应用 wasm 的效率比桌面端低, 所以并没有无限思考(有点自卑了 …)
- 最终性能这块, 看到了
vscode-textmate
有benchmark
, 测试了一波. 发现除了 js 的解析比桌面端慢两倍, 其余的甚至比桌面端快 … 有点费解了(不晓得本人有没有钻研错, 如果有说的不对请拍砖)
jQuery v2.0.3
TOKENIZING 250971 lines using grammar source.js
Oniguruma: 550 ms., Onigasm: 381 ms. (1.4x faster)
Bootstrap CSS v3.1.1
TOKENIZING 127005 lines using grammar source.css
Oniguruma: 217 ms., Onigasm: 91 ms. (2.4x faster)
vscode.d.ts
TOKENIZING 264938 lines using grammar source.ts
Oniguruma: 356 ms., Onigasm: 191 ms. (1.9x faster)
JSON
TOKENIZING 103784 lines using grammar source.ts
Oniguruma: 312 ms., Onigasm: 185 ms. (1.7x faster)
Bootstrap CSS v3.1.1 minified
TOKENIZING 99967 lines using grammar source.css
Oniguruma: 231 ms., Onigasm: 167 ms. (1.4x faster)
jQuery v2.0.3 minified
TOKENIZING 83618 lines using grammar source.js
Oniguruma: 254 ms., Onigasm: 480 ms. (1.9x slower)
Bootstrap with multi-byte minified
TOKENIZING 116201 lines using grammar source.css
Oniguruma: 248 ms., Onigasm: 196 ms. (1.3x faster)
实现原理
- 这个计划是从 monaco-tm 中得来的, 然而最终欠缺了主题应用, 能够从 vscode 中无缝移植主题, 欠缺了语言插件, 能够从 vscode 无缝迁徙 tmLanguage 的插件, 并且反对语言点注入
- grammar 是用来解析语法的, 会在调用这个语言的时候, 加载对应的语法文件
具体须要实现
monaco.languages.EncodedTokensProvider
接口传给setTokensProvider
做参数
setTokensProvider
代替了setMonarchTokensProvider
- configuration 是用来配置一些折叠, 括号, 正文等货色 … 和原来的 monaco 一样
- theme 就是用来申请加载主题的
因为语法的解析变成了 vscode-textmate, 所以不能应用传统的形式来加载主题, 须要从
Registry
中拿到ColorMap
而后定义给主题
- 最初通过监听应用语言时加载对应的语法解析文件
应用
- ng 下曾经封装好了依赖包的应用, 非 ng 框架也能够稍作批改应用
- 包地址 cyia-ngx-common
- 引入模块
CyiaMonacoTextmateModule
, 组件中通过依赖注入拿到CyiaMonacoTextmateService
服务
this.service.setMonaco(monaco);
this.service.init().then(async () => {const themeList = await this.service.getThemeList();
this.themeList = themeList;
this.selectedTheme = themeList[1];
const name = await this.service.defineTheme(this.selectedTheme);
this.instance = monaco.editor.create(
this.containerElement?.nativeElement,
{
theme: name,
value: `let a=6;`,
language: this.selectedLanguage,
minimap: {enabled: false,},
automaticLayout: true,
}
);
});
// 切换主题
async change(e) {const name = await this.service.defineTheme(e);
monaco.editor.setTheme(name);
}
相干地址
- 演示地址
- 演示地址源码
- 调用包源码