Monaco Editorカスタム言語の実装
16526 ワード
余計なことは言わない
The Monaco Editor is the code editor that powers VS Code.
It is licensed under the MIT License and supports IE 9/10/11, Edge, Chrome, Firefox, Safari and Opera.
インストール
参照
私はVue+Webpackを書くことが多いです.これを例に挙げます.
第一の書き方:使用 monaco-editor-webpack-plugin
2つ目の書き方:
カスタム言語
本人が使っているのは2つ目の方法で、Editorを引用します.カスタム言語が必要なため、値はeditor.workerパッケージを参照します.
Webpack.base.conf.jsでの構成
.vueファイルに対応するscriptコードセグメント、monaco-editorを参照し、
custom-languageとcustom-completionの導入
スクリーンショット:
もっと情報が欲しいなら、公式サイトとstackoverflowを見てみましょう.
公式サイトの説明:
公式サイトアドレス:microsoft.github.io/monaco-edit...
カスタム言語のDEMO:microsoft.github.io/monaco-edit...
Webpackクラスのプロジェクトでの参照方法:github.com/Microsoft/m...
The Monaco Editor is the code editor that powers VS Code.
It is licensed under the MIT License and supports IE 9/10/11, Edge, Chrome, Firefox, Safari and Opera.
インストール
npm install monaco-editor
参照
私はVue+Webpackを書くことが多いです.これを例に挙げます.
第一の書き方:使用 monaco-editor-webpack-plugin
// .vue script
import * as monaco from 'monaco-editor';
monaco.editor.create(document.getElementById('container'), {
value: [
'function x() {',
'\tconsole.log("Hello world!");',
'}'
].join('
'),
language: 'javascript'
});
// webpack.base.conf.js
// monaco-editor-webpack-plugin
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
const path = require('path');
module.exports = {
...
plugins: [
new MonacoWebpackPlugin()
]
};
2つ目の書き方:
// .vue script
import * as monaco from 'monaco-editor';
// Since packaging is done by you, you need
// to instruct the editor how you named the
// bundles that contain the web workers.
self.MonacoEnvironment = {
getWorkerUrl: function (moduleId, label) {
if (label === 'json') {
return './json.worker.bundle.js';
}
if (label === 'css') {
return './css.worker.bundle.js';
}
if (label === 'html') {
return './html.worker.bundle.js';
}
if (label === 'typescript' || label === 'javascript') {
return './ts.worker.bundle.js';
}
return './editor.worker.bundle.js';
}
}
monaco.editor.create(document.getElementById('container'), {
value: [
'function x() {',
'\tconsole.log("Hello world!");',
'}'
].join('
'),
language: 'javascript'
});
// webpack.base.conf.js
// const path = require('path');
module.exports = {
entry: {
"app": './index.js',
// Package each language's worker and give these filenames in `getWorkerUrl`
"editor.worker": 'monaco-editor/esm/vs/editor/editor.worker.js',
"json.worker": 'monaco-editor/esm/vs/language/json/json.worker',
"css.worker": 'monaco-editor/esm/vs/language/css/css.worker',
"html.worker": 'monaco-editor/esm/vs/language/html/html.worker',
"ts.worker": 'monaco-editor/esm/vs/language/typescript/ts.worker',
},
...
};
カスタム言語
本人が使っているのは2つ目の方法で、Editorを引用します.カスタム言語が必要なため、値はeditor.workerパッケージを参照します.
Webpack.base.conf.jsでの構成
module.exports = {
entry: {
app: ['babel-polyfill', './src/main.js'], // './src/main.js'
"editor.worker": 'monaco-editor/esm/vs/editor/editor.worker.js', }
......
}
.vueファイルに対応するscriptコードセグメント、monaco-editorを参照し、
custom-languageとcustom-completionの導入
import * as monaco from 'monaco-editor'
import vLang from './custom-language'
import vCompletion from './custon-completion'
initEditor () {
// methods
this.MonacoEnvironment = {
getWorkerUrl: function (moduleId, label) {
return './editor.worker.bundle.js'
}
}
//
monaco.languages.register({ id: 'mySpecialLanguage' })
// Token
monaco.languages.setMonarchTokensProvider('mySpecialLanguage', vLang)
// --
monaco.languages.registerCompletionItemProvider('mySpecialLanguage', { provideCompletionItems: () => { return { suggestions: vCompletion } } })
//
this.vEditor.editor = monaco.editor.create(document.getElementById('editor'), {
value: this.vEditor.value,
theme: this.vEditor.theme,
language: 'mySpecialLanguage',
})
},
// custom-language.js
/* eslint-disable no-useless-escape */
export default {
// Set defaultToken to invalid to see what you do not tokenize yet
// defaultToken: 'invalid',
keywords: [ 'IF', 'THEN', 'END', 'WHILE', 'DO', 'ELSE' ],
typeKeywords: [],
operators: ['=', '>', ', '==', '<=', '>=', '!=', '<>', '+', '-', '*', '/'],
digits: /\d+(_+\d+)*/,
octaldigits: /[0-7]+(_+[0-7]+)*/, binarydigits: /[0-1]+(_+[0-1]+)*/,
hexdigits: /[[0-9a-fA-F]+(_+[0-9a-fA-F]+)*/,
// The main tokenizer for our languages
tokenizer: {
root: [
// identifiers and keywords
[/[a-z_$][\w$]*/, {
cases: {
'@typeKeywords': 'keyword',
'@keywords': 'keyword',
'@default': 'identifier'
}
}],
[/[A-Z][\w\$]*/, 'type.identifier'], // to show class names nicely
// whitespace
{ include: '@whitespace' },
// delimiters and operators
[/[{}()\[\]]/, '@brackets'],
// @ annotations.
// As an example, we emit a debugging log message on these tokens.
// Note: message are supressed during the first load -- change some lines to see them.
// eslint-disable-next-line no-useless-escape
[/@\s*[a-zA-Z_\$][\w\$]*/, { token: 'annotation', log: 'annotation token: $0' }],
// numbers
[/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'],
[/0[xX][0-9a-fA-F]+/, 'number.hex'],
[/\d+/, 'number'],
// delimiter: after number because of .\d floats
[/[;,.]/, 'delimiter'],
// strings
[/"([^"\\]|\\.)*$/, 'string.invalid'],
// non-teminated string
[/"/, { token: 'string.quote', bracket: '@open', next: '@string' }],
// characters
[/'[^\\']'/, 'string'],
[/'/, 'string.invalid'] ],
comment: [
[/[^\/*]+/, 'comment'],
[/\/\*/, 'comment', '@push'],
// nested comment
['\\*/', 'comment', '@pop'],
[/[\/*]/, 'comment']
],
string: [
[/[^\\"]+/, 'string'],
[/\\./, 'string.escape.invalid'],
[/"/, { token: 'string.quote', bracket: '@close', next: '@pop' }]
],
whitespace: [
[/[ \t\r
]+/, 'white'],
[/\/\*/, 'comment', '@comment'],
[/\/\/.*$/, 'comment'],
],
},}
// custom-completion.js
/* eslint-disable no-template-curly-in-string */
export default [
/** * */
{
label: 'getValue',
kind: monaco.languages.CompletionItemKind.Function,
insertText: 'getValue(${1:pattern})',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: ' pattern , '
}, {
label: 'getIniString',
kind: monaco.languages.CompletionItemKind.Function,
insertText: 'getIniString(${1:sec}, ${2: key})',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: ' ini , section key, key , '
}, {
label: 'getIniInt',
kind: monaco.languages.CompletionItemKind.Function,
insertText: 'getIniInt(${1:sec}, ${2: key})',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: ' ini , section key, key ,, '
}, {
label: 'getIniDouble',
kind: monaco.languages.CompletionItemKind.Function,
insertText: 'getIniDouble(${1:sec}, ${2: key})',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: ' ini , section key, key , '
}, {
label: 'isEmpty',
kind: monaco.languages.CompletionItemKind.Function,
insertText: 'isEmpty(${1:str})',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: ' str '
}, {
label: 'isEqual',
kind: monaco.languages.CompletionItemKind.Function,
insertText: 'isEqual(${1:str1}, ${2: str2})',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: ' str '
}, {
label: 'isContain',
kind: monaco.languages.CompletionItemKind.Function,
insertText: 'isContain(${1:str})',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: ' str'
}, {
label: 'getJsonInt',
kind: monaco.languages.CompletionItemKind.Function,
insertText: 'getJsonInt(${1:path})',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: ' path JSON '
}, {
label: 'getJsonDouble',
kind: monaco.languages.CompletionItemKind.Function,
insertText: 'getJsonDouble(${1:path})',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: ' path JSON '
}, {
label: 'getJsonSize',
kind: monaco.languages.CompletionItemKind.Function,
insertText: 'getJsonSize(${1:path})',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: ' path JSON '
},
/** * */
{
label: 'IF-ELSE',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'IF ${1:condition} THEN',
'\t$0',
'ELSE',
'\t$0',
'END'
].join('
'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: 'If-Else Statement'
}, {
label: 'WHILE-DO',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'WHILE ${1:condition} DO',
'\t$0',
'END'
].join('
'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: 'WHILE-DO Statement'
}]
スクリーンショット:
もっと情報が欲しいなら、公式サイトとstackoverflowを見てみましょう.
公式サイトの説明:
公式サイトアドレス:microsoft.github.io/monaco-edit...
カスタム言語のDEMO:microsoft.github.io/monaco-edit...
Webpackクラスのプロジェクトでの参照方法:github.com/Microsoft/m...