monaco-editor 实现SQL编辑器

原文链接:https://www.yuque.com/sxd_panda/antv/editor

安装

yarn add monaco-editor
或
npm install monaco-editor

配置

看网上的教程需要添加vite配置,但是我的项目没有对vite进行配置,打包出来的也是可以用的,具体看你们的场景

vite.config.js配置

安装 vite-plugin-monaco-editor
javascript 复制代码
import monacoEditorPlugin from 'vite-plugin-monaco-editor'

plugins: [
  monacoEditorPlugin({
    languageWorkers: ['editorWorkerService', 'typescript', 'json', 'html']
  }),
]

页面使用

先把对应的几个 worker 引入下,不然控制台会有警告。这段代码可以单独放在一个组件里面引入到当前页面,因为它目前的作用就是解决控制台警告的,写在当前页面也是没问题的

javascript 复制代码
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker';
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker';


self.MonacoEnvironment = {
  getWorker(workerId, label) {
    if (label === 'json') {
      return new jsonWorker();
    }
    if (label === 'typescript' || label === 'javascript') {
      return new tsWorker();
    }
    if (label === 'html') {
      return new htmlWorker();
    }
    return new editorWorker();
  }
};

导入monaco模块准备初始化编辑器

javascript 复制代码
import * as monaco from 'monaco-editor';

const initEditor = () => {
  monacoEditor = monaco.editor.create(editRef.value, {
    theme: 'vs-dark', // 主题
    language: 'sql',
    value: '',
    renderLineHighlight: 'gutter',
    // folding: true, // 是否折叠
    // roundedSelection: false,
    // foldingHighlight: true, // 折叠等高线
    // foldingStrategy: 'indentation', // 折叠方式  auto | indentation
    // showFoldingControls: 'always', // 是否一直显示折叠 always | mouseover
    // disableLayerHinting: true, // 等宽优化
    // emptySelectionClipboard: false, // 空选择剪切板
    // selectionClipboard: false, // 选择剪切板
    automaticLayout: true, // 自动布局
    codeLens: true, // 代码镜头
    // scrollBeyondLastLine: false, // 滚动完最后一行后再滚动一屏幕
    colorDecorators: true // 颜色装饰器
    // accessibilitySupport: 'on', // 辅助功能支持  "auto" | "off" | "on"
    // lineNumbers: 'on', // 行号 取值: "on" | "off" | "relative" | "interval" | function
    // lineNumbersMinChars: 5, // 行号最小字符   number
    // enableSplitViewResizing: false,
    // readOnly: false //是否只读  取值 true | false
  });
};

// 执行初始化的方法
onMounted(() => {
  // 初始化编辑器
  initEditor();
});

如何添加SQL关键字提示?

SQL关键字其实插件内是有的,我们只需要把它拿过啦直接用就行了,如果你觉得不全,可以自己定义一个js文件,把你需要的关键字都加入到这个文件中,后续维护就只需要维护你这个js文件就行了

插件关键字的目录:/node_modules/monaco-editor/esm/vs/basic-languages/sql/sql.js

javascript 复制代码
import { language } from 'monaco-editor/esm/vs/basic-languages/sql/sql.js';

// 注册SQL关键字提示
monaco.languages.registerCompletionItemProvider('sql',{
  provideCompletionItems:(model, position) => {
    let suggestions = [];
    // language.keywords 是获取内置的SQL关键字
      language.keywords.map(item => {
      suggestions.push({
        label: item,
        kind: monaco.languages.CompletionItemKind['Keyword'],
        insertText: item + ' ',
        detail: '内置关键字',
      });
    });
     return {
        suggestions
      };
  }
})

如何添加表字段提示?

type类型文档

javascript 复制代码
// 这个是自定义的表字段数据
const fieldsArr = [
  {
    type: 'Field', // 这个类型是为了区分是关键字还是字段,具体可以看下文档
    value: 'name'
  },
  {
    type: 'Field',
    value: 'age'
  },
  {
    type: 'Field',
    value: 'sex'
  }
];



monaco.languages.registerCompletionItemProvider('sql',{
  provideCompletionItems:(model, position) => {
    let suggestions = [];
   // 再把内置的关键字数据处理下
    const temp = language.keywords.map(item => {
      return {
        type: 'Keyword',
        value: item
      };
    });
// 把关键字和表字段数据合到一起,这样就不用输入快捷键才会显示表字段了
const result = [...fieldsArr, ...temp];
result.map(item => {
  suggestions.push({
    label: item.value,
    kind: monaco.languages.CompletionItemKind[item.type],
    insertText: item.value + ' ',
    detail: item.type == 'Keyword' ? '内置关键字' : '表字段',
    range
  });
});
     return {
        suggestions
      };
  }
})

添加代码格式化右键菜单

SQL编辑器默认是没有右键格式化代码的,需要手动添加菜单并借助第三方的插件实现SQL代码的格式化

插件链接:https://www.npmjs.com/package/sql-formatter

# 安装格式化插件
npm install sql-formatter   /   yarn add sql-formatter
javascript 复制代码
import { format } from 'sql-formatter';

// 创建自定义菜单项
monacoEditor.addAction({
  id: 'format.sql',
  label: 'Formart SQL',
  precondition: null,
  contextMenuGroupId: 'navigation',
  contextMenuOrder: 1,
  run: function () {
    // sql代码格式化
    monacoEditor.setValue(format(monacoEditor.getValue()));
  }
});

自定义主题

javascript 复制代码
function defineTheme() {
  monaco.editor.defineTheme('naruto', {
    base: 'vs', // 以哪个默认主题为基础:"vs" | "vs-dark" | "hc-black" | "hc-light"
    inherit: true,
    rules: [
      // 高亮规则,即给代码里不同token类型的代码设置不同的显示样式
      { token: 'identifier', foreground: '#d06733' },
      { token: 'number', foreground: '#6bbeeb', fontStyle: 'italic' },
      { token: 'keyword', foreground: '#05a4d5' }
    ],
    colors: {
      'scrollbarSlider.background': '#edcaa6', // 滚动条背景
      'editor.foreground': '#0d0b09', // 基础字体颜色
      'editor.background': '#00090B', // 背景颜色
      'editorCursor.foreground': '#d4b886', // 焦点颜色
      'editor.lineHighlightBackground': '#6492a520', // 焦点所在的一行的背景颜色
      'editorLineNumber.foreground': '#008800' // 行号字体颜色
    }
  });
}
defineTheme();

monaco.editor.setTheme('naruto');

下面这个是已经实现的demo效果