Monaco代码编辑器

微软官方编辑器:https://github.com/microsoft/monaco-editor

官方提供的整合教程:https://github.com/microsoft/monaco-editor/blob/main/docs/integrate-esm.md

参考博客:http://chart.zhenglinglu.cn/pages/2244bd/

https://segmentfault.com/a/1190000042292716 推荐

  1. 该开源代码编辑器是微软官方编辑器,操作方式和风格都很想vscode
  2. 可以扩展性强
  3. 相比较于md编辑器更适合写编程语言的编写,md更适合编程文章

安装

  • 安装编辑器monaco-editor

    • ```sh
      npm install monaco-editor —save
      1
      2
      3
      4
      5
      6

      + vue-cli 项目(webpack 项目)整合 monaco-editor。
      先安装 monaco-editor-webpack-plugin(https://github.com/microsoft/monaco-editor/blob/main/webpack-plugin/README.md):

      + ```sh
      npm install monaco-editor-webpack-plugin --save

配置

如何使用 Monaco Editor?查看示例教程:
https://microsoft.github.io/monaco-editor/playground.html?source=v0.40.0#example-creating-the-editor-hello-world

在 vue.config.js 中配置 webpack 插件:

全量加载:

1
2
3
4
5
6
7
8
9
const { defineConfig } = require("@vue/cli-service");
const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin");

module.exports = defineConfig({
transpileDependencies: true,
chainWebpack(config) {
config.plugin("monaco").use(new MonacoWebpackPlugin());
},
});

按需加载:

1
2
3
4
5
6
7
8
9
10
11
12
13
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin')
module.exports = {
chainWebpack: config => {
config.plugin('monaco-editor').use(MonacoWebpackPlugin, [
{
// Languages are loaded on demand at runtime
languages: ['json', 'go', 'css', 'html', 'java', 'javascript', 'less', 'markdown', 'mysql', 'php', 'python', 'scss', 'shell', 'redis', 'sql', 'typescript', 'xml'], // ['abap', 'apex', 'azcli', 'bat', 'cameligo', 'clojure', 'coffee', 'cpp', 'csharp', 'csp', 'css', 'dart', 'dockerfile', 'ecl', 'fsharp', 'go', 'graphql', 'handlebars', 'hcl', 'html', 'ini', 'java', 'javascript', 'json', 'julia', 'kotlin', 'less', 'lexon', 'lua', 'm3', 'markdown', 'mips', 'msdax', 'mysql', 'objective-c', 'pascal', 'pascaligo', 'perl', 'pgsql', 'php', 'postiats', 'powerquery', 'powershell', 'pug', 'python', 'r', 'razor', 'redis', 'redshift', 'restructuredtext', 'ruby', 'rust', 'sb', 'scala', 'scheme', 'scss', 'shell', 'solidity', 'sophia', 'sql', 'st', 'swift', 'systemverilog', 'tcl', 'twig', 'typescript', 'vb', 'xml', 'yaml'],

features: ['format', 'find', 'contextmenu', 'gotoError', 'gotoLine', 'gotoSymbol', 'hover' , 'documentSymbols'] //['accessibilityHelp', 'anchorSelect', 'bracketMatching', 'caretOperations', 'clipboard', 'codeAction', 'codelens', 'colorPicker', 'comment', 'contextmenu', 'coreCommands', 'cursorUndo', 'dnd', 'documentSymbols', 'find', 'folding', 'fontZoom', 'format', 'gotoError', 'gotoLine', 'gotoSymbol', 'hover', 'iPadShowKeyboard', 'inPlaceReplace', 'indentation', 'inlineHints', 'inspectTokens', 'linesOperations', 'linkedEditing', 'links', 'multicursor', 'parameterHints', 'quickCommand', 'quickHelp', 'quickOutline', 'referenceSearch', 'rename', 'smartSelect', 'snippets', 'suggest', 'toggleHighContrast', 'toggleTabFocusMode', 'transpose', 'unusualLineTerminators', 'viewportSemanticTokens', 'wordHighlighter', 'wordOperations', 'wordPartOperations']
}
])
}
}

创建Vue组件

注意,monaco editor 在读写值的时候,要使用 toRaw(编辑器实例)的语法来执行操作,否则会卡死。
示例整合代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<template>
<div id="code-editor" ref="codeEditorRef" style="min-height: 400px"></div>
</template>

<script setup lang="ts">
import * as monaco from "monaco-editor";
import { onMounted, ref, toRaw, withDefaults, defineProps } from "vue";
/**
* 定义组件属性类型
*/
interface Props {
value: string;
handleChange: (v: string) => void;
}

/**
* 给组件指定初始值
*/
const props = withDefaults(defineProps<Props>(), {
value: () => "",
handleChange: (v: string) => {
console.log(v);
},
});
// ref 可以获取到vue 的dom 节点 使用toRaw 可以转为 原生Dom 节点
const codeEditorRef = ref();
const codeEditor = ref();
// 在 页面dom节点加载完成时运行
onMounted(() => {
if (!codeEditorRef.value) {
return;
}
//code 编辑器配置创建和相应的初始化
codeEditor.value = monaco.editor.create(codeEditorRef.value, {
value: props.value, // 值
language: "java", // 语言
automaticLayout: true, // 自动布局
colorDecorators: true, // 颜色装饰器
minimap: {
enabled: true, //小地图是否开启
},
readOnly: false, //是否只读
theme: "vs-dark", //主题
lineNumbers: "off", //行号
// roundedSelection: false, //四舍五入
// scrollBeyondLastLine: false, //滚动完最后一行后再滚动一屏幕
});

// 编辑 监听内容变化
codeEditor.value.onDidChangeModelContent(() => {
props.handleChange(toRaw(codeEditor.value).getValue());
});
});
</script>

<style scoped>
#codeEditor {
}
</style>

实例化代码及具体配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//const beautify = require('js-beautify')
//import { setLocaleData } from 'monaco-editor-nls'
//import zh_CN from 'monaco-editor-nls/locale/zh-hans'
//setLocaleData(zh_CN)
//const monaco = require('monaco-editor')
//const beautify_js = beautify.js
//const beautify_css = beautify.css
//const beautify_html = beautify.html

import * as monaco from "monaco-editor";

this.editor = monaco.editor.create(this.$refs.editor, {
acceptSuggestionOnCommitCharacter: true, // 接受关于提交字符的建议
acceptSuggestionOnEnter: 'on', // 接受输入建议 "on" | "off" | "smart"
accessibilityPageSize: 10, // 辅助功能页面大小 Number 说明:控制编辑器中可由屏幕阅读器读出的行数。警告:这对大于默认值的数字具有性能含义。
accessibilitySupport: 'on', // 辅助功能支持 控制编辑器是否应在为屏幕阅读器优化的模式下运行。
autoClosingBrackets: 'always', // 是否自动添加结束括号(包括中括号) "always" | "languageDefined" | "beforeWhitespace" | "never"
autoClosingDelete: 'always', // 是否自动删除结束括号(包括中括号) "always" | "never" | "auto"
autoClosingOvertype: 'always', // 是否关闭改写 即使用insert模式时是覆盖后面的文字还是不覆盖后面的文字 "always" | "never" | "auto"
autoClosingQuotes: 'always', // 是否自动添加结束的单引号 双引号 "always" | "languageDefined" | "beforeWhitespace" | "never"
autoIndent: 'None', // 控制编辑器在用户键入、粘贴、移动或缩进行时是否应自动调整缩进
automaticLayout: true, // 自动布局
codeLens: false, // 是否显示codeLens 通过 CodeLens,你可以在专注于工作的同时了解代码所发生的情况 – 而无需离开编辑器。 可以查找代码引用、代码更改、关联的 Bug、工作项、代码评审和单元测试。
codeLensFontFamily: '', // codeLens的字体样式
codeLensFontSize: 14, // codeLens的字体大小
colorDecorators: false, // 呈现内联色彩装饰器和颜色选择器
comments: {
ignoreEmptyLines: true, // 插入行注释时忽略空行。默认为真。
insertSpace: true // 在行注释标记之后和块注释标记内插入一个空格。默认为真。
}, // 注释配置
contextmenu: true, // 启用上下文菜单
columnSelection: false, // 启用列编辑 按下shift键位然后按↑↓键位可以实现列选择 然后实现列编辑
autoSurround: 'never', // 是否应自动环绕选择
copyWithSyntaxHighlighting: true, // 是否应将语法突出显示复制到剪贴板中 即 当你复制到word中是否保持文字高亮颜色
cursorBlinking: 'Solid', // 光标动画样式
cursorSmoothCaretAnimation: true, // 是否启用光标平滑插入动画 当你在快速输入文字的时候 光标是直接平滑的移动还是直接"闪现"到当前文字所处位置
cursorStyle: 'UnderlineThin', // "Block"|"BlockOutline"|"Line"|"LineThin"|"Underline"|"UnderlineThin" 光标样式
cursorSurroundingLines: 0, // 光标环绕行数 当文字输入超过屏幕时 可以看见右侧滚动条中光标所处位置是在滚动条中间还是顶部还是底部 即光标环绕行数 环绕行数越大 光标在滚动条中位置越居中
cursorSurroundingLinesStyle: 'all', // "default" | "all" 光标环绕样式
cursorWidth: 2, // <=25 光标宽度
minimap: {
enabled: false // 是否启用预览图
}, // 预览图设置
folding: true, // 是否启用代码折叠
links: true, // 是否点击链接
overviewRulerBorder: false, // 是否应围绕概览标尺绘制边框
renderLineHighlight: 'gutter', // 当前行突出显示方式
roundedSelection: false, // 选区是否有圆角
scrollBeyondLastLine: false, // 设置编辑器是否可以滚动到最后一行之后
readOnly: false, // 是否为只读模式
theme: 'vs'// vs, hc-black, or vs-dark
})

本地化 i18n

本地化采用monaco-editor-esm-webpack-plugin方式实现,Github地址:https://github.com/wang12124468/monaco-editor-esm-webpack-plugin

1
2
3
4
5
6
7
8
9
10
# 汉化扩展(需要下载包的):

# 是对整个编辑器的汉化处理,如果需要进行汉化,那么需要安装此包。
npm install monaco-editor-nls -S
//或者使用npm install --save-dev monaco-editor-locales-plugin
# 针对汉化包所做的webpack插件,需要和汉化包配合使用。
npm install monaco-editor-esm-webpack-plugin --save-dev

# 是用来做代码美化的,主要是做一些格式化的工作。
npm install js-beautify -S
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const { defineConfig } = require("@vue/cli-service");

module.exports = defineConfig({
transpileDependencies: true,
});
// 引入 code 编辑器
const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin");
const MonacoLocalesPlugin = require("monaco-editor-locales-plugin");
module.exports = {
chainWebpack(config) {
config
.plugin("monaco")
.use(new MonacoWebpackPlugin())
.use(
new MonacoLocalesPlugin({
//设置支持的语言
languages: ["es", "zh-cn"],
//默认语言
defaultLanguage: "zh-cn",
//打印不匹配的文本
logUnmatched: false,
//自定义文本翻译
mapLanguages: {
"zh-cn": {
"Peek References": "查找引用",
"Go to Symbol...": "跳到变量位置",
"Command Palette": "命令面板",
"Go to References": "参考",
},
},
})
);
},
};