monaco-editor 實現SQL編輯器

奔跑的前端猿發表於2024-06-07

原文連結: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
import monacoEditorPlugin from 'vite-plugin-monaco-editor'

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

頁面使用

先把對應的幾個 worker 引入下,不然控制檯會有警告。這段程式碼可以單獨放在一個元件裡面引入到當前頁面,因為它目前的作用就是解決控制檯警告的,寫在當前頁面也是沒問題的

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模組準備初始化編輯器

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

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型別文件

// 這個是自定義的表欄位資料
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
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()));
  }
});

自定義主題

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效果

相關文章