From 3e799202b00ce03e7c3c6fea82d481efbc6b0d16 Mon Sep 17 00:00:00 2001 From: jwong <18810157617@163.com> Date: Fri, 28 Dec 2018 17:42:30 +0800 Subject: [PATCH] Monaco Editor for Vue --- README.md | 108 ++++++++++++++++++++++++++++++++++++++++++++ package.json | 21 +++++++++ src/index.js | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 254 insertions(+) create mode 100644 README.md create mode 100644 package.json create mode 100644 src/index.js diff --git a/README.md b/README.md new file mode 100644 index 0000000..80d85c1 --- /dev/null +++ b/README.md @@ -0,0 +1,108 @@ +# vue-monaco-editor + +> [Monaco Editor](https://github.com/Microsoft/monaco-editor) for Vue. + +[![NPM version][npm-image]][npm-url] +[![Downloads][downloads-image]][npm-url] + +[![monaco-editor-vue](https://nodei.co/npm/monaco-editor-vue.png)](https://npmjs.org/package/monaco-editor-vue) + +[npm-url]: https://www.npmjs.com/package/monaco-editor-vue +[downloads-image]: http://img.shields.io/npm/dm/monaco-editor-vue.svg +[npm-image]: http://img.shields.io/npm/v/monaco-editor-vue.svg + +## Installation + +```bash +npm install monaco-editor-vue +``` + +## Using with Webpack + +```js + + + +``` + +Add the [Monaco Webpack plugin](https://github.com/Microsoft/monaco-editor-webpack-plugin) `monaco-editor-webpack-plugin` to your `webpack.config.js`: + +```js +const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); +module.exports = { + plugins: [ + new MonacoWebpackPlugin({ + // available options are documented at https://github.com/Microsoft/monaco-editor-webpack-plugin#options + languages: ['javascript'] + }) + ] +}; +``` + +## Properties + +If you specify `value` property, the component behaves in controlled mode. +Otherwise, it behaves in uncontrolled mode. + +- `width` width of editor. Defaults to `100%`. +- `height` height of editor. Defaults to `100%`. +- `value` value of the auto created model in the editor. +- `language` the initial language of the auto created model in the editor. Defaults to `javascript`. +- `theme` the theme of the editor. Defaults to `vs`. +- `options` refer to [Monaco interface IEditorConstructionOptions](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.ieditorconstructionoptions.html). +- `change(newValue, event)` an event emitted when the content of the current model has changed. +- `editorBeforeMount(monaco)` an event emitted before the editor mounted (similar to `beforeMount` of Vue). +- `editorMounted(editor, monaco)` an event emitted when the editor has been mounted (similar to `mounted` of Vue). + +## Events & Methods + +Refer to [Monaco interface IEditor](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.ieditor.html). + +### Use multiple themes + +[Monaco only supports one theme](https://github.com/Microsoft/monaco-editor/issues/338). + +### How to use the diff editor + +```js + +``` diff --git a/package.json b/package.json new file mode 100644 index 0000000..fc31db6 --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "monaco-editor-vue", + "version": "1.0.1", + "description": "Monaco Editor for Vue.", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "dependencies": { + "monaco-editor": "^0.15.6", + }, + "keywords": [ + "Vue", + "monaco", + "monaco-editor", + "vue-monaco-editor", + "monaco-editor-vue" + ], + "author": "jwong", + "license": "MIT" +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..d62bb81 --- /dev/null +++ b/src/index.js @@ -0,0 +1,125 @@ +import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; + +function noop() { } + +export default { + name: 'MonacoEditor', + props: { + diffEditor: { type: Boolean, default: false }, //是否使用diff模式 + width: {type: [String, Number], default: '100%'}, + height: {type: [String, Number], default: '100%'}, + original: String, //只有在diff模式下有效 + value: String, + language: {type: String, default: 'javascript'}, + theme: {type: String, default: 'vs'}, + options: {type: Object, default() {return {};}}, + editorMounted: {type: Function, default: noop}, + editorBeforeMount: {type: Function, default: noop} + }, + + watch: { + options: { + deep: true, + handler(options) { + this.editor && this.editor.updateOptions(options) + } + }, + + value() { + this.editor && this.value !== this.editor.getValue() && this.editor.setValue(this.value); + }, + + language() { + if(!this.editor) return; + if(this.diffEditor){ //diff模式下更新language + const { original, modified } = this.editor.getModel(); + monaco.editor.setModelLanguage(original, this.language); + monaco.editor.setModelLanguage(modified, this.language); + }else + monaco.editor.setModelLanguage(this.editor.getModel(), this.language); + }, + + theme() { + this.editor && monaco.editor.setTheme(this.theme); + }, + + style() { + this.editor && this.$nextTick(() => { + this.editor.layout(); + }); + } + }, + + computed: { + style() { + return { + width: !/^\d+$/.test(this.width) ? this.width : `${this.width}px`, + height: !/^\d+$/.test(this.height) ? this.height : `${this.height}px` + } + } + }, + + mounted () { + this.initMonaco(); + }, + + beforeDestroy() { + this.editor && this.editor.dispose(); + }, + + render (h) { + return ( +
+ ); + }, + + methods: { + initMonaco() { + const { value, language, theme, options } = this; + Object.assign(options, this._editorBeforeMount()); //编辑器初始化前 + this.editor = monaco.editor[this.diffEditor ? 'createDiffEditor' : 'create'](this.$el, { + value: this.value, + language: this.language, + theme: this.theme, + ...options + }); + this.diffEditor && this._setModel(this.value, this.original); + this._editorMounted(this.editor); //编辑器初始化后 + }, + + _setModel(value, original) { //diff模式下设置model + const { language } = this; + const originalModel = monaco.editor.createModel(original, language); + const modifiedModel = monaco.editor.createModel(value, language); + this.editor.setModel({ + original: originalModel, + modified: modifiedModel + }); + }, + + _editorBeforeMount() { + const options = this.editorBeforeMount(monaco); + return options || {}; + }, + + _editorMounted(editor) { + this.editorMounted(editor, monaco); + if(this.diffEditor){ + editor.onDidUpdateDiff(() => { + const value = editor.getModel().modified.getValue(); + this._emitChange(value, event); + }); + }else{ + editor.onDidChangeModelContent(event => { + const value = editor.getValue(); + this._emitChange(value, event); + }); + } + }, + + _emitChange(value, event) { + this.$emit('change', value, event); + this.$emit('input', value); + } + } +} \ No newline at end of file