/
index.ts
139 lines (136 loc) · 3.73 KB
/
index.ts
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import ace, { type Ace } from 'ace-builds';
import { capitalize, defineComponent, markRaw, h } from 'vue';
import ResizeObserver from 'resize-observer-polyfill';
import type { VAceEditorInstance } from './types';
const Events = [
'blur',
'input',
'change',
'changeSelectionStyle',
'changeSession',
'copy',
'focus',
'paste',
];
export const VAceEditor = defineComponent({
name: 'VAceEditor',
props: {
value: {
type: String,
required: true,
},
lang: {
type: String,
default: 'text',
},
theme: {
type: String,
default: 'chrome',
},
options: Object,
placeholder: String,
readonly: Boolean,
wrap: Boolean,
printMargin: {
type: [Boolean, Number],
default: true,
},
minLines: Number,
maxLines: Number,
},
emits: ['update:value', 'init', ...Events],
render(this: VAceEditorInstance) {
return h('div');
},
mounted(this: VAceEditorInstance) {
const editor = this._editor = markRaw(ace.edit(this.$el, {
placeholder: this.placeholder,
readOnly: this.readonly,
value: this.value,
mode: 'ace/mode/' + this.lang,
theme: 'ace/theme/' + this.theme,
wrap: this.wrap,
printMargin: this.printMargin,
useWorker: false,
minLines: this.minLines,
maxLines: this.maxLines,
...this.options,
}));
this._contentBackup = this.value;
this._isSettingContent = false;
editor.on('change', () => {
// ref: https://github.com/CarterLi/vue3-ace-editor/issues/11
if (this._isSettingContent) return;
const content = editor.getValue();
this._contentBackup = content;
this.$emit('update:value', content);
});
Events.forEach(x => {
const eventName = 'on' + capitalize(x);
if (typeof this.$.vnode.props![eventName] === 'function') {
editor.on(x as any, this.$emit.bind(this, x));
}
});
this._ro = new ResizeObserver(() => editor.resize());
this._ro.observe(this.$el);
this.$emit('init', editor);
},
beforeUnmount(this: VAceEditorInstance) {
this._ro?.disconnect();
this._editor?.destroy();
},
methods: {
focus(this: VAceEditorInstance) {
this._editor.focus();
},
blur(this: VAceEditorInstance) {
this._editor.blur();
},
selectAll(this: VAceEditorInstance) {
this._editor.selectAll();
},
getAceInstance(this: VAceEditorInstance) {
return this._editor;
},
},
watch: {
value(this: VAceEditorInstance, val: string) {
if (this._contentBackup !== val) {
try {
this._isSettingContent = true;
this._editor.setValue(val, 1);
} finally {
this._isSettingContent = false;
}
this._contentBackup = val;
}
},
theme(this: VAceEditorInstance, val: string) {
this._editor.setTheme('ace/theme/' + val);
},
options(this: VAceEditorInstance, val: Partial<Ace.EditorOptions>) {
this._editor.setOptions(val);
},
readonly(this: VAceEditorInstance, val: boolean) {
this._editor.setReadOnly(val);
},
placeholder(this: VAceEditorInstance, val: string) {
this._editor.setOption('placeholder', val);
},
wrap(this: VAceEditorInstance, val: boolean) {
this._editor.setWrapBehavioursEnabled(val);
},
printMargin(this: VAceEditorInstance, val: boolean | number) {
this._editor.setOption('printMargin', val);
},
lang(this: VAceEditorInstance, val: string) {
this._editor.setOption('mode', 'ace/mode/' + val);
},
minLines(this: VAceEditorInstance, val: number) {
this._editor.setOption('minLines', val);
},
maxLines(this: VAceEditorInstance, val: number) {
this._editor.setOption('maxLines', val);
},
}
});