Skip to content

Commit

Permalink
feat: Support DiffEditor (#36)
Browse files Browse the repository at this point in the history
BREAKING CHANGE:

Removed a bunch of unnecessary component events, only two are left: `editorDidMount` and `change`
  • Loading branch information
egoist authored Jun 26, 2019
1 parent 00228bb commit ce400d3
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 78 deletions.
91 changes: 63 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,45 +133,80 @@ window.MonacoEnvironment = {
### Props

- `options`: The [second argument](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.ieditorconstructionoptions.html) of [`monaco.editor.create`](https://microsoft.github.io/monaco-editor/api/modules/monaco.editor.html#create).
- `code`: A shortcut to set `options.value`.
- `value`: A shortcut to set `options.value`.
- `theme`: A shortcut to set `options.theme`.
- `language`: A shortcut to set `options.language`.
- `amdRequire`: Load monaco-editor using given amd-style require function.

### Events

| Event | IStandaloneCodeEditor Event | Parameters |
| ------------------ | --------------------------- | ------------------------------------------- |
| `editorDidMount` | | IStandaloneCodeEditor |
| `contextMenu` | onContextMenu | IEditorMouseEvent |
| `blur` | onDidBlurEditorWidget | |
| `blurText` | onDidBlurEditorText | |
| `configuration` | onDidBlurEditorText | IConfigurationChangedEvent |
| `position` | onDidChangeCursorPosition | ICursorPositionChangedEvent |
| `selection` | onDidChangeCursorSelection | ICursorSelectionChangedEvent |
| `model` | onDidChangeModel | IModelChangedEvent |
| `change` | onDidChangeModelContent | value: string, e: IModelContentChangedEvent |
| `modelDecorations` | onDidChangeModelDecorations | IModelDecorationsChangedEvent |
| `modelLanguage` | onDidChangeModelLanguage | IModelLanguageChangedEvent |
| `modelOptions` | onDidChangeModelOptions | IModelOptionsChangedEvent |
| `afterDispose` | onDidDispose | |
| `focus` | onDidFocusEditorWidget | |
| `focusText` | onDidFocusEditorText | |
| `layout` | onDidLayoutChange | EditorLayoutInfo |
| `scroll` | onDidScrollChange | IScrollEvent |
| `keydown` | onKeyDown | IKeyboardEvent |
| `keyup` | onKeyUp | IKeyboardEvent |
| `mouseDown` | onMouseDown | IEditorMouseEvent |
| `mouseLeave` | onMouseLeave | IEditorMouseEvent |
| `mouseMove` | onMouseMove | IEditorMouseEvent |
| `mouseUp` | onMouseUp | IEditorMouseEvent |
### Component Events

#### `editorDidMount`

- Params:
- `editor`: [`IStandaloneCodeEditor`](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonecodeeditor.html) for normal editor, [`IStandaloneDiffEditor`](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonediffeditor.html) for diff editor.

Editor is created.

#### `change`

Editor value is updated.

- Params:
- `value`: New editor value.
- `event`: The `event` from [`onDidChangeModelContent`](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonecodeeditor.html#ondidchangemodelcontent).

#### Editor Events

You can listen to the editor events directly like this:

```vue
<template>
<MonacoEditor v-model="code" @editorDidMount="editorDidMount" />
</template>
<script>
export default {
methods: {
editorDidMount(editor) {
// Listen to `scroll` event
editor.onDidScrollChange(e => {
console.log(e)
})
}
},
data() {
return {
code: '...'
}
}
}
</script>
```

Refer to [this page](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonecodeeditor.html) for all editor events.

### Methods

- `getEditor(): IStandaloneCodeEditor`: Return the [editor instance](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonecodeeditor.html).

Use `ref` to interact with the `MonacoEditor` component in order to access methods: `<MonacoEditor ref="editor" />`, then `this.$refs.editor.getEditor()` will be available.

### Use the DiffEditor

Use `diffEditor` prop to indicate that this is a DiffEditor, use `original` prop to set the content for the original editor, use `value` prop to set the content for the modified editor.

```vue
<MonacoEditor
language="javascript"
:diffEditor="true"
:value="code"
:original="originalCode"
/>
```

In this case, the component's `getEditor()` returns the [`IStandaloneDiffEditor`](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonediffeditor.html) instance, while you can use `getModifiedEditor()` to get the modified editor which is an [`IStandaloneCodeEditor`](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonecodeeditor.html) instance.

## Contributing

1. Fork it!
Expand Down
14 changes: 11 additions & 3 deletions example/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,21 @@ new Vue({
<button onClick={this.updateCode}>update</button>
<MonacoEditor
class="editor"
style="height: 100%;"
value={this.code}
language={this.language}
theme={this.theme}
options={this.options}
onChange={newValue => this.code = newValue}
placeholder={<div>hello</div>}
onChange={newValue => (this.code = newValue)}
/>
<MonacoEditor
class="editor"
diffEditor={true}
original={`original value`}
value={this.code}
language={this.language}
theme={this.theme}
options={this.options}
onChange={newValue => (this.code = newValue)}
/>
</div>
)
Expand Down
8 changes: 4 additions & 4 deletions example/style.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
html, body, #app {
height: 100%;
}

body {
margin: 0;
}

.editor {
height: 100vh;
}
90 changes: 47 additions & 43 deletions src/MonacoEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ export default {
name: 'MonacoEditor',

props: {
value: String,
original: String,
value: {
type: String,
required: true
},
theme: {
type: String,
default: 'vs'
Expand All @@ -13,6 +17,10 @@ export default {
options: Object,
amdRequire: {
type: Function
},
diffEditor: {
type: Boolean,
default: false
}
},

Expand All @@ -25,41 +33,46 @@ export default {
deep: true,
handler(options) {
if (this.editor) {
this.editor.updateOptions(options)
const editor = this.getModifiedEditor()
editor.updateOptions(options)
}
}
},

value(newValue) {
if (this.editor) {
if (newValue !== this.editor.getValue()) {
this.editor.setValue(newValue)
const editor = this.getModifiedEditor()
if (newValue !== editor.getValue()) {
editor.setValue(newValue)
}
}
},

language(newVal) {
if (this.editor) {
window.monaco.editor.setModelLanguage(this.editor.getModel(), newVal)
const editor = this.getModifiedEditor()
this.monaco.editor.setModelLanguage(editor.getModel(), newVal)
}
},

theme(newVal) {
if (this.editor) {
window.monaco.editor.setTheme(newVal)
this.monaco.editor.setTheme(newVal)
}
}
},

mounted() {
if (this.amdRequire) {
this.amdRequire(['vs/editor/editor.main'], () => {
this.monaco = window.monaco
this.initMonaco(window.monaco)
})
} else {
// ESM format so it can't be resolved by commonjs `require` in eslint
// eslint-disable-next-line import/no-unresolved
const monaco = require('monaco-editor')
this.monaco = monaco
this.initMonaco(monaco)
}
},
Expand All @@ -79,47 +92,34 @@ export default {
this.options
)

this.editor = monaco.editor.create(this.$el, options)
this.$emit('editorDidMount', this.editor)
this.editor.onContextMenu(event => this.$emit('contextMenu', event))
this.editor.onDidBlurEditorWidget(() => this.$emit('blur'))
this.editor.onDidBlurEditorText(() => this.$emit('blurText'))
this.editor.onDidChangeConfiguration(event =>
this.$emit('configuration', event)
)
this.editor.onDidChangeCursorPosition(event =>
this.$emit('position', event)
)
this.editor.onDidChangeCursorSelection(event =>
this.$emit('selection', event)
)
this.editor.onDidChangeModel(event => this.$emit('model', event))
this.editor.onDidChangeModelContent(event => {
const value = this.editor.getValue()
if (this.diffEditor) {
this.editor = monaco.editor.createDiffEditor(this.$el, options)
const originalModel = monaco.editor.createModel(
this.original,
this.language
)
const modifiedModel = monaco.editor.createModel(
this.value,
this.language
)
this.editor.setModel({
original: originalModel,
modified: modifiedModel
})
} else {
this.editor = monaco.editor.create(this.$el, options)
}

// @event `change`
const editor = this.getModifiedEditor()
editor.onDidChangeModelContent(event => {
const value = editor.getValue()
if (this.value !== value) {
this.$emit('change', value, event)
}
})
this.editor.onDidChangeModelDecorations(event =>
this.$emit('modelDecorations', event)
)
this.editor.onDidChangeModelLanguage(event =>
this.$emit('modelLanguage', event)
)
this.editor.onDidChangeModelOptions(event =>
this.$emit('modelOptions', event)
)
this.editor.onDidDispose(event => this.$emit('afterDispose', event))
this.editor.onDidFocusEditorWidget(() => this.$emit('focus'))
this.editor.onDidFocusEditorText(() => this.$emit('focusText'))
this.editor.onDidLayoutChange(event => this.$emit('layout', event))
this.editor.onDidScrollChange(event => this.$emit('scroll', event))
this.editor.onKeyDown(event => this.$emit('keydown', event))
this.editor.onKeyUp(event => this.$emit('keyup', event))
this.editor.onMouseDown(event => this.$emit('mouseDown', event))
this.editor.onMouseLeave(event => this.$emit('mouseLeave', event))
this.editor.onMouseMove(event => this.$emit('mouseMove', event))
this.editor.onMouseUp(event => this.$emit('mouseUp', event))

this.$emit('editorDidMount', this.editor)
},

/** @deprecated */
Expand All @@ -131,6 +131,10 @@ export default {
return this.editor
},

getModifiedEditor() {
return this.diffEditor ? this.editor.getModifiedEditor() : this.editor
},

focus() {
this.editor.focus()
}
Expand Down

0 comments on commit ce400d3

Please sign in to comment.