Skip to content

Commit

Permalink
Monaco Editor for Vue
Browse files Browse the repository at this point in the history
  • Loading branch information
FE-Mars committed Dec 28, 2018
0 parents commit 3e79920
Show file tree
Hide file tree
Showing 3 changed files with 254 additions and 0 deletions.
108 changes: 108 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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
<template>
<div id="app">
<MonacoEditor
width="800"
height="500"
theme="vs-dark"
language="javascript"
options={options}
@change="onChange"
></MonacoEditor>
</div>
</template>

<script>
import MonacoEditor from 'monaco-editor-vue';
export default {
name: "App",
components: {
MonacoEditor
},
data() {
return {
options: {
//Monaco Editor Options
}
}
},
methods: {
onChange(value) {
console.log(value);
}
}
};
</script>
```

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
<template>
<div id="app">
<MonacoEditor
:diffEditor="true"
original="..."
//...
></MonacoEditor>
</div>
</template>
```
21 changes: 21 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -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"
}
125 changes: 125 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -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 (
<div class="monaco_editor_container" style={this.style}></div>
);
},

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);
}
}
}

0 comments on commit 3e79920

Please sign in to comment.