You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在VSCode CustomTextEditor扩展中集成Monaco Editor并启用典型功能?

在VS Code Custom Text Editor扩展中集成Monaco Editor(带行号、概览功能)

嘿,我刚好折腾过把Monaco集成到Custom Text Editor里,完全能实现你要的增强版编辑器效果。下面是从零开始的完整步骤:

1. 初始化Custom Text Editor扩展项目

首先用Yeoman生成器创建基础扩展结构:

  • 全局安装Yeoman和VS Code扩展生成器:npm install -g yo generator-code
  • 运行yo code,选择New Custom Text Editor,按提示填项目信息(比如命名为monaco-enhanced-editor

生成项目后,安装专门适配VS Code扩展的Monaco包:

npm install @vscode/monaco-editor --save

2. 配置package.json

确保你的package.json里正确注册自定义编辑器的基础信息,重点关注contributes.customEditorsactivationEvents

{
  "activationEvents": [
    "onCustomEditor:monaco-enhanced-editor.customEditor"
  ],
  "contributes": {
    "customEditors": [
      {
        "viewType": "monaco-enhanced-editor.customEditor",
        "displayName": "Enhanced Monaco Editor",
        "selector": [
          {
            "filenamePattern": "*.monaco"
          }
        ],
        "priority": "default"
      }
    ]
  }
}

这里我们指定.monaco后缀的文件默认用这个自定义编辑器打开。

3. 实现Custom Editor Provider(核心逻辑)

打开生成的src/extension.ts,修改CustomTextEditorProvider类,核心是在resolveCustomTextEditor方法中创建WebView并加载Monaco:

先导入必要模块:

import * as vscode from 'vscode';
import { Uri } from 'vscode';
import { getMonacoEnvironment } from '@vscode/monaco-editor';

然后修改resolveCustomTextEditor方法,处理WebView配置和内容同步:

async resolveCustomTextEditor(
  document: vscode.TextDocument,
  webviewPanel: vscode.WebviewPanel,
  _token: vscode.CancellationToken
): Promise<void> {
  // 配置WebView权限,允许脚本和访问扩展资源
  webviewPanel.webview.options = {
    enableScripts: true,
    localResourceRoots: [
      this.context.extensionUri,
      Uri.joinPath(this.context.extensionUri, 'node_modules', 'monaco-editor')
    ]
  };

  // 设置WebView的HTML内容,加载Monaco并初始化编辑器
  webviewPanel.webview.html = this.getWebviewContent(webviewPanel.webview, document);

  // 监听VS Code文档变化,同步到Monaco编辑器
  const changeDocumentSubscription = vscode.workspace.onDidChangeTextDocument(e => {
    if (e.document.uri.toString() === document.uri.toString()) {
      webviewPanel.webview.postMessage({
        type: 'updateDocument',
        content: e.document.getText()
      });
    }
  });

  // 监听Monaco编辑器内容变化,同步回VS Code文档
  webviewPanel.webview.onDidReceiveMessage(async message => {
    if (message.type === 'updateContent') {
      const edit = new vscode.WorkspaceEdit();
      edit.replace(
        document.uri,
        new vscode.Range(0, 0, document.lineCount, 0),
        message.content
      );
      await vscode.workspace.applyEdit(edit);
    }
  });

  // 面板关闭时清理订阅
  webviewPanel.onDidDispose(() => {
    changeDocumentSubscription.dispose();
  });
}

接下来实现getWebviewContent方法,生成加载Monaco的HTML:

private getWebviewContent(webview: vscode.Webview, document: vscode.TextDocument): string {
  // 获取Monaco资源的WebView URI
  const monacoUri = webview.asWebviewUri(
    Uri.joinPath(this.context.extensionUri, 'node_modules', 'monaco-editor')
  );
  const env = getMonacoEnvironment(monacoUri);

  return `
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <style>
        body, html { margin: 0; padding: 0; height: 100vh; overflow: hidden; }
        #container { width: 100%; height: 100%; }
      </style>
    </head>
    <body>
      <div id="container"></div>

      <script>
        // 配置Monaco环境
        self.MonacoEnvironment = ${JSON.stringify(env)};
      </script>
      <script src="${monacoUri}/min/vs/loader.js"></script>
      <script>
        require.config({ paths: { 'vs': '${monacoUri}/min/vs' } });

        require(['vs/editor/editor.main'], () => {
          // 初始化Monaco编辑器,配置行号、概览等核心功能
          const editor = monaco.editor.create(document.getElementById('container'), {
            value: ${JSON.stringify(document.getText())},
            language: 'javascript', // 可根据需求修改语言
            lineNumbers: 'on', // 显示左侧行号
            overviewRulerLanes: 2, // 右侧概览标尺车道数
            overviewRulerBorder: true, // 显示概览标尺边框
            scrollBeyondLastLine: false,
            minimap: { enabled: true }, // 启用迷你地图(和概览配合)
            theme: 'vs-dark' // 可选:深色主题,也可用'vs'或'hc-black'
          });

          // 监听编辑器内容变化,同步回VS Code
          editor.onDidChangeModelContent(() => {
            window.vscode.postMessage({
              type: 'updateContent',
              content: editor.getValue()
            });
          });

          // 监听VS Code文档更新,同步到编辑器
          window.addEventListener('message', event => {
            if (event.data.type === 'updateDocument') {
              const currentValue = editor.getValue();
              if (currentValue !== event.data.content) {
                editor.setValue(event.data.content);
              }
            }
          });
        });
      </script>
    </body>
    </html>
  `;
}

4. 配置高级功能(可选)

如果需要更多增强效果,可以在编辑器初始化的options里添加:

  • lineNumbersMinChars: 设置行号的最小宽度
  • overviewRulerColor: 自定义概览标尺颜色
  • scrollbar: 配置滚动条样式,比如scrollbar: { vertical: 'visible', horizontal: 'visible' }
  • 代码高亮、智能提示:需要配置Monaco对应的语言服务

5. 测试扩展

  • 按F5启动扩展开发宿主窗口
  • 创建一个test.monaco文件,双击打开就能看到带行号和右侧概览的Monaco编辑器
  • 编辑内容会实时同步到文件,修改文件内容也会同步到编辑器

内容的提问来源于stack exchange,提问作者FireFuro99

火山引擎 最新活动