Skip to content

Monaco Editor 功能扩展

1358字约5分钟

vueMonaco Editor

2024-10-02

Monaco Editor 功能扩展

基本使用

插件安装。

npm install monaco-editor@0.29.1
npm install monaco-editor-webpack-plugin@5.0.0

配置 vue.config.js

 
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin')
 
module.exports = {
  configureWebpack: {
    plugins: [
      new MonacoWebpackPlugin({
        language: ['sql']
      })
    ]
  }
}

封装组件

<template>
    <div class="codeBox">
        <div style="text-align: center;">SQL编辑器</div>
        <div class="sqlEditor" id="sqlEditor"></div>
    </div>
</template>

<script>
import * as monaco from 'monaco-editor/esm/vs/editor/edcore.main'
import 'monaco-editor/esm/vs/basic-languages/sql/sql.contribution'

export default {
    data() {
        return {}
    },
    mounted() {
        this.initEditor()
    },
    methods: {
        initEditor() {
            this.editor = monaco.editor.create(document.getElementById('sqlEditor'), {
                value: '',
                theme: 'vs',
                language: 'sql',
                automaticLayout: true
            });
        }
    }
}
</script>

<style scoped>
.codeBox {
    text-align: center;
}

.sqlEditor {
    height: 300px;
    width: 100%;
    text-align: left;
}
</style>

实现效果

image-20240929174406630

自动补全

要在 Monaco Editor 中实现 SQL 的自动补全功能,需要添加额外的配置,步骤如下:

  1. 注册建议提供器:在初始化 SQL 编辑器时,使用 monaco.languages.registerCompletionItemProvider 注册一个建议提供器。
  2. 定义建议项:在建议提供器中定义可供自动补全的 SQL 关键字和结构。
initEditor() {
            this.editor = monaco.editor.create(document.getElementById('sqlEditor'), {
                value: '',
                theme: 'vs-dark',
                language: 'sql',
                automaticLayout: true
            });
			// 注册建议提供器
            monaco.languages.registerCompletionItemProvider('sql', {
                provideCompletionItems: () => {
                    return {
                        suggestions: [
                            // 定义建议项
                            {
                                label: 'SELECT',
                                kind: monaco.languages.CompletionItemKind.Keyword,
                                insertText: 'SELECT ',
                                documentation: 'Select data from a database.'
                            },
                            {
                                label: 'FROM',
                                kind: monaco.languages.CompletionItemKind.Keyword,
                                insertText: 'FROM ',
                                documentation: 'Specify the table to select from.'
                            },
                            {
                                label: 'WHERE',
                                kind: monaco.languages.CompletionItemKind.Keyword,
                                insertText: 'WHERE ',
                                documentation: 'Filter records.'
                            },
                            // 添加更多 SQL 关键字和建议项
                        ]
                    };
                }
            });
        }

实现效果如下

SQL自动补全

上面能够实现 SQL 的关键字提示,但还是有一些问题,比如 SQL 的关键字较多,写在一个组件中会导致组件过于臃肿,这里单独写一个 sqlKeywords.js 的关键字提示文件,内容如下所示:

// sqlKeywords.js
export default [
    'ACCESSIBLE',
    'ACCOUNT',
    'ACTION',
    'ADD',
    'AFTER',
    'AGAINST',
    'AGGREGATE',
    'ALGORITHM',
    'ALL',
    'ALTER',
    'ALWAYS',
    'ANALYSE',
    'ANALYZE',
    'AND',
    'ANY',
    'AS',
    'ASC',
    'ASCII',
    'ASENSITIVE',
    'AT',
    'AUTOEXTEND_SIZE',
    'AUTO_INCREMENT',
    'AVG',
    'AVG_ROW_LENGTH',
    'BACKUP',
    'BEFORE',
    'BEGIN',
    'BETWEEN',
    'BIGINT',
    'BINARY',
    'BINLOG',
    'BIT',
    'BLOB',
    'BLOCK',
    'BOOL',
    'BOOLEAN',
    'BOTH',
    'BTREE',
    'BY',
    'BYTE',
    'CACHE',
    'CALL',
    'CASCADE',
    'CASCADED',
    'CASE',
    'CATALOG_NAME',
    'CHAIN',
    'CHANGE',
    'CHANGED',
    'CHANNEL',
    'CHAR',
    'CHARACTER',
    'CHARSET',
    'CHECK',
    'CHECKSUM',
    'CIPHER',
    'CLASS_ORIGIN',
    'CLIENT',
    'CLOSE',
    'COALESCE',
    'CODE',
    'COLLATE',
    'COLLATION',
    'COLUMN',
    'COLUMNS',
    'COLUMN_FORMAT',
    'COLUMN_NAME',
    'COMMENT',
    'COMMIT',
    'COMMITTED',
    'COMPACT',
    'COMPLETION',
    'COMPRESSED',
    'COMPRESSION',
    'CONCURRENT',
    'CONDITION',
    'CONNECTION',
    'CONSISTENT',
    'CONSTRAINT',
    'CONSTRAINT_CATALOG',
    'CONSTRAINT_NAME',
    'CONSTRAINT_SCHEMA',
    'CONTAINS',
    'CONTEXT',
    'CONTINUE',
    'CONVERT',
    'CPU',
    'CREATE',
    'CROSS',
    'CUBE',
    'CURRENT',
    'CURRENT_DATE',
    'CURRENT_TIME',
    'CURRENT_TIMESTAMP',
    'CURRENT_USER',
    'CURSOR',
    'CURSOR_NAME',
    'DATA',
    'DATABASE',
    'DATABASES',
    'DATAFILE',
    'DATE',
    'DATETIME',
    'DAY',
    'DAY_HOUR',
    'DAY_MICROSECOND',
    'DAY_MINUTE',
    'DAY_SECOND',
    'DEALLOCATE',
    'DEC',
    'DECIMAL',
    'DECLARE',
    'DEFAULT',
    'DEFAULT_AUTH',
    'DEFINER',
    'DELAYED',
    'DELAY_KEY_WRITE',
    'DELETE',
    'DESC',
    'DESCRIBE',
    'DES_KEY_FILE',
    'DETERMINISTIC',
    'DIAGNOSTICS',
    'DIRECTORY',
    'DISABLE',
    'DISCARD',
    'DISK',
    'DISTINCT',
    'DISTINCTROW',
    'DIV',
    'DO',
    'DOUBLE',
    'DROP',
    'DUAL',
    'DUMPFILE',
    'DUPLICATE',
    'DYNAMIC',
    'EACH',
    'ELSE',
    'ELSEIF',
    'ENABLE',
    'ENCLOSED',
    'ENCRYPTION',
    'END',
    'ENDS',
    'ENGINE',
    'ENGINES',
    'ENUM',
    'ERROR',
    'ERRORS',
    'ESCAPE',
    'ESCAPED',
    'EVENT',
    'EVENTS',
    'EVERY',
    'EXCHANGE',
    'EXECUTE',
    'EXISTS',
    'EXIT',
    'EXPANSION',
    'EXPIRE',
    'EXPLAIN',
    'EXPORT',
    'EXTENDED',
    'EXTENT_SIZE',
    'FALSE',
    'FAST',
    'FAULTS',
    'FETCH',
    'FIELDS',
    'FILE',
    'FILE_BLOCK_SIZE',
    'FILTER',
    'FIRST',
    'FIXED',
    'FLOAT',
    'FLOAT4',
    'FLOAT8',
    'FLUSH',
    'FOLLOWS',
    'FOR',
    'FORCE',
    'FOREIGN',
    'FORMAT',
    'FOUND',
    'FROM',
    'FULL',
    'FULLTEXT',
    'FUNCTION',
    'GENERAL',
    'GENERATED',
    'GEOMETRY',
    'GEOMETRYCOLLECTION',
    'GET',
    'GET_FORMAT',
    'GLOBAL',
    'GRANT',
    'GRANTS',
    'GROUP',
    'GROUP_REPLICATION',
    'HANDLER',
    'HASH',
    'HAVING',
    'HELP',
    'HIGH_PRIORITY',
    'HOST',
    'HOSTS',
    'HOUR',
    'HOUR_MICROSECOND',
    'HOUR_MINUTE',
    'HOUR_SECOND',
    'IDENTIFIED',
    'IF',
    'IGNORE',
    'IGNORE_SERVER_IDS',
    'IMPORT',
    'IN',
    'INDEX',
    'INDEXES',
    'INFILE',
    'INITIAL_SIZE',
    'INNER',
    'INOUT',
    'INSENSITIVE',
    'INSERT',
    'INSERT_METHOD',
    'INSTALL',
    'INSTANCE',
    'INT',
    'INT1',
    'INT2',
    'INT3',
    'INT4',
    'INT8',
    'INTEGER',
    'INTERVAL',
    'INTO',
    'INVOKER',
    'IO',
    'IO_AFTER_GTIDS',
    'IO_BEFORE_GTIDS',
    'IO_THREAD',
    'IPC',
    'IS',
    'ISOLATION',
    'ISSUER',
    'ITERATE',
    'JOIN',
    'JSON',
    'KEY',
    'KEYS',
    'KEY_BLOCK_SIZE',
    'KILL',
    'LANGUAGE',
    'LAST',
    'LEADING',
    'LEAVE',
    'LEAVES',
    'LEFT',
    'LESS',
    'LEVEL',
    'LIKE',
    'LIMIT',
    'LINEAR',
    'LINES',
    'LINESTRING',
    'LIST',
    'LOAD',
    'LOCAL',
    'LOCALTIME',
    'LOCALTIMESTAMP',
    'LOCK',
    'LOCKS',
    'LOGFILE',
    'LOGS',
    'LONG',
    'LONGBLOB',
    'LONGTEXT',
    'LOOP',
    'LOW_PRIORITY',
    'MASTER',
    'MASTER_AUTO_POSITION',
    'MASTER_BIND',
    'MASTER_CONNECT_RETRY',
    'MASTER_DELAY',
    'MASTER_HEARTBEAT_PERIOD',
    'MASTER_HOST',
    'MASTER_LOG_FILE',
    'MASTER_LOG_POS',
    'MASTER_PASSWORD',
    'MASTER_PORT',
    'MASTER_RETRY_COUNT',
    'MASTER_SERVER_ID',
    'MASTER_SSL',
    'MASTER_SSL_CA',
    'MASTER_SSL_CAPATH',
    'MASTER_SSL_CERT',
    'MASTER_SSL_CIPHER',
    'MASTER_SSL_CRL',
    'MASTER_SSL_CRLPATH',
    'MASTER_SSL_KEY',
    'MASTER_SSL_VERIFY_SERVER_CERT',
    'MASTER_TLS_VERSION',
    'MASTER_USER',
    'MATCH',
    'MAXVALUE',
    'MAX_CONNECTIONS_PER_HOUR',
    'MAX_QUERIES_PER_HOUR',
    'MAX_ROWS',
    'MAX_SIZE',
    'MAX_STATEMENT_TIME',
    'MAX_UPDATES_PER_HOUR',
    'MAX_USER_CONNECTIONS',
    'MEDIUM',
    'MEDIUMBLOB',
    'MEDIUMINT',
    'MEDIUMTEXT',
    'MEMORY',
    'MERGE',
    'MESSAGE_TEXT',
    'MICROSECOND',
    'MIDDLEINT',
    'MIGRATE',
    'MINUTE',
    'MINUTE_MICROSECOND',
    'MINUTE_SECOND',
    'MIN_ROWS',
    'MOD',
    'MODE',
    'MODIFIES',
    'MODIFY',
    'MONTH',
    'MULTILINESTRING',
    'MULTIPOINT',
    'MULTIPOLYGON',
    'MUTEX',
    'MYSQL_ERRNO',
    'NAME',
    'NAMES',
    'NATIONAL',
    'NATURAL',
    'NCHAR',
    'NDB',
    'NDBCLUSTER',
    'NEVER',
    'NEW',
    'NEXT',
    'NO',
    'NODEGROUP',
    'NONBLOCKING',
    'NONE',
    'NOT',
    'NO_WAIT',
    'NO_WRITE_TO_BINLOG',
    'NULL',
    'NUMBER',
    'NUMERIC',
    'NVARCHAR',
    'OFFSET',
    'OLD_PASSWORD',
    'ON',
    'ONE',
    'ONLY',
    'OPEN',
    'OPTIMIZE',
    'OPTIMIZER_COSTS',
    'OPTION',
    'OPTIONALLY',
    'OPTIONS',
    'OR',
    'ORDER',
    'OUT',
    'OUTER',
    'OUTFILE',
    'OWNER',
    'PACK_KEYS',
    'PAGE',
    'PARSER',
    'PARSE_GCOL_EXPR',
    'PARTIAL',
    'PARTITION',
    'PARTITIONING',
    'PARTITIONS',
    'PASSWORD',
    'PHASE',
    'PLUGIN',
    'PLUGINS',
    'PLUGIN_DIR',
    'POINT',
    'POLYGON',
    'PORT',
    'PRECEDES',
    'PRECISION',
    'PREPARE',
    'PRESERVE',
    'PREV',
    'PRIMARY',
    'PRIVILEGES',
    'PROCEDURE',
    'PROCESSLIST',
    'PROFILE',
    'PROFILES',
    'PROXY',
    'PURGE',
    'QUARTER',
    'QUERY',
    'QUICK',
    'RANGE',
    'READ',
    'READS',
    'READ_ONLY',
    'READ_WRITE',
    'REAL',
    'REBUILD',
    'RECOVER',
    'REDOFILE',
    'REDO_BUFFER_SIZE',
    'REDUNDANT',
    'REFERENCES',
    'REGEXP',
    'RELAY',
    'RELAYLOG',
    'RELAY_LOG_FILE',
    'RELAY_LOG_POS',
    'RELAY_THREAD',
    'RELEASE',
    'RELOAD',
    'REMOVE',
    'RENAME',
    'REORGANIZE',
    'REPAIR',
    'REPEAT',
    'REPEATABLE',
    'REPLACE',
    'REPLICATE_DO_DB',
    'REPLICATE_DO_TABLE',
    'REPLICATE_IGNORE_DB',
    'REPLICATE_IGNORE_TABLE',
    'REPLICATE_REWRITE_DB',
    'REPLICATE_WILD_DO_TABLE',
    'REPLICATE_WILD_IGNORE_TABLE',
    'REPLICATION',
    'REQUIRE',
    'RESET',
    'RESIGNAL',
    'RESTORE',
    'RESTRICT',
    'RESUME',
    'RETURN',
    'RETURNED_SQLSTATE',
    'RETURNS',
    'REVERSE',
    'REVOKE',
    'RIGHT',
    'RLIKE',
    'ROLLBACK',
    'ROLLUP',
    'ROTATE',
    'ROUTINE',
    'ROW',
    'ROWS',
    'ROW_COUNT',
    'ROW_FORMAT',
    'RTREE',
    'SAVEPOINT',
    'SCHEDULE',
    'SCHEMA',
    'SCHEMAS',
    'SCHEMA_NAME',
    'SECOND',
    'SECOND_MICROSECOND',
    'SECURITY',
    'SELECT',
    'SENSITIVE',
    'SEPARATOR',
    'SERIAL',
    'SERIALIZABLE',
    'SERVER',
    'SESSION',
    'SET',
    'SHARE',
    'SHOW',
    'SHUTDOWN',
    'SIGNAL',
    'SIGNED',
    'SIMPLE',
    'SLAVE',
    'SLOW',
    'SMALLINT',
    'SNAPSHOT',
    'SOCKET',
    'SOME',
    'SONAME',
    'SOUNDS',
    'SOURCE',
    'SPATIAL',
    'SPECIFIC',
    'SQL',
    'SQLEXCEPTION',
    'SQLSTATE',
    'SQLWARNING',
    'SQL_AFTER_GTIDS',
    'SQL_AFTER_MTS_GAPS',
    'SQL_BEFORE_GTIDS',
    'SQL_BIG_RESULT',
    'SQL_BUFFER_RESULT',
    'SQL_CACHE',
    'SQL_CALC_FOUND_ROWS',
    'SQL_NO_CACHE',
    'SQL_SMALL_RESULT',
    'SQL_THREAD',
    'SQL_TSI_DAY',
    'SQL_TSI_HOUR',
    'SQL_TSI_MINUTE',
    'SQL_TSI_MONTH',
    'SQL_TSI_QUARTER',
    'SQL_TSI_SECOND',
    'SQL_TSI_WEEK',
    'SQL_TSI_YEAR',
    'SSL',
    'STACKED',
    'START',
    'STARTING',
    'STARTS',
    'STATS_AUTO_RECALC',
    'STATS_PERSISTENT',
    'STATS_SAMPLE_PAGES',
    'STATUS',
    'STOP',
    'STORAGE',
    'STORED',
    'STRAIGHT_JOIN',
    'STRING',
    'SUBCLASS_ORIGIN',
    'SUBJECT',
    'SUBPARTITION',
    'SUBPARTITIONS',
    'SUPER',
    'SUSPEND',
    'SWAPS',
    'SWITCHES',
    'TABLE',
    'TABLES',
    'TABLESPACE',
    'TABLE_CHECKSUM',
    'TABLE_NAME',
    'TEMPORARY',
    'TEMPTABLE',
    'TERMINATED',
    'TEXT',
    'THAN',
    'THEN',
    'TIME',
    'TIMESTAMP',
    'TIMESTAMPADD',
    'TIMESTAMPDIFF',
    'TINYBLOB',
    'TINYINT',
    'TINYTEXT',
    'TO',
    'TRAILING',
    'TRANSACTION',
    'TRIGGER',
    'TRIGGERS',
    'TRUE',
    'TRUNCATE',
    'TYPE',
    'TYPES',
    'UNCOMMITTED',
    'UNDEFINED',
    'UNDO',
    'UNDOFILE',
    'UNDO_BUFFER_SIZE',
    'UNICODE',
    'UNINSTALL',
    'UNION',
    'UNIQUE',
    'UNKNOWN',
    'UNLOCK',
    'UNSIGNED',
    'UNTIL',
    'UPDATE',
    'UPGRADE',
    'USAGE',
    'USE',
    'USER',
    'USER_RESOURCES',
    'USE_FRM',
    'USING',
    'UTC_DATE',
    'UTC_TIME',
    'UTC_TIMESTAMP',
    'VALIDATION',
    'VALUE',
    'VALUES',
    'VARBINARY',
    'VARCHAR',
    'VARCHARACTER',
    'VARIABLES',
    'VARYING',
    'VIEW',
    'VIRTUAL',
    'WAIT',
    'WARNINGS',
    'WEEK',
    'WEIGHT_STRING',
    'WHEN',
    'WHERE',
    'WHILE',
    'WITH',
    'WITHOUT',
    'WORK',
    'WRAPPER',
    'WRITE',
    'X509',
    'XA',
    'XID',
    'XML',
    'XOR',
    'YEAR',
    'YEAR_MONTH',
    'ZEROFILL'
  ]

在原来的 vue 组件中导入 sqlKeywords.js,并使用 map 函数进行建议提供器的注册,如下所示:

import sqlKeywords from './sqlKeywords.js'

// 构造建议提供器
getSQLSuggest() {
            return sqlKeywords.map((key) => ({
                label: key,
                kind: monaco.languages.CompletionItemKind.Keyword,
                insertText: key,
                documentation: key
            }))
        }

// 建议提示器修改
initEditor() {
            this.editor = monaco.editor.create(document.getElementById('sqlEditor'), {
                value: '',
                theme: 'vs',
                language: 'sql',
                automaticLayout: true
            });

            monaco.languages.registerCompletionItemProvider('sql', {
                provideCompletionItems: () => {
                    return {
                        // 这里的建议直接从js文件经map函数构造而来
                        suggestions: [...this.getSQLSuggest()]
                    };
                }
            });
        },

优化后的效果如下所示

SQL自动补全优化

SQL 格式化

要在Monaco Editor 中实现 SQL 格式化,需要使用其提供的格式化 API,步骤如下:

  1. 添加鼠标右键菜单,提供 SQL 格式化的入口调用。
  2. 创建格式化函数:修改 SQL 编辑器中编写的 sql 格式。

initEditor() {
            this.editor = monaco.editor.create(document.getElementById('sqlEditor'), {
                value: '',
                theme: 'vs',
                language: 'sql',
                automaticLayout: true
            });

            // 注册鼠标右键菜单
            this.registerContextMenu();

            monaco.languages.registerCompletionItemProvider('sql', {
                provideCompletionItems: () => {
                    return {
                        suggestions: [...this.getSQLSuggest()]
                    };
                }
            });
        },

// 新增加Format SQL的入口
registerContextMenu() {
            this.editor.addAction({
                id: 'format-sql',
                label: 'Format SQL',
                contextMenuGroupId: 'navigation',
                contextMenuOrder: 1,
                run: () => {
                    this.formatSQL();
                }
            });
        }

// formatSQL 函数,这里可以调用后端配合实现SQL的格式化
formatSQL() {
            // 获取SQL内容
            // const model = this.editor.getModel();
            // const value = model.getValue();
            // 返回格式化后的SQL
            const formatted = "SELECT e.ename,\n       d.dname,\n       l.loc_name\nFROM employee e\nJOIN department d ON d.deptno = e.deptno\nJOIN LOCATION l ON d.loc = l.loc;"
            this.editor.setValue(formatted);
        },

实现效果

SQL格式化