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
|
import { editor as monacoEditor, languages as monacoLanguages, Position, Uri } from 'monaco-editor';
import { DEFAULT_THEME, themes } from '~/ide/lib/themes';
import languages from '~/ide/lib/languages';
import { defaultEditorOptions } from '~/ide/lib/editor_options';
import { registerLanguages } from '~/ide/utils';
import { joinPaths } from '~/lib/utils/url_utility';
import { clearDomElement } from './utils';
export default class Editor {
constructor(options = {}) {
this.editorEl = null;
this.blobContent = '';
this.blobPath = '';
this.instance = null;
this.model = null;
this.options = {
extraEditorClassName: 'gl-editor-lite',
...defaultEditorOptions,
...options,
};
Editor.setupMonacoTheme();
registerLanguages(...languages);
}
static setupMonacoTheme() {
const themeName = window.gon?.user_color_scheme || DEFAULT_THEME;
const theme = themes.find(t => t.name === themeName);
if (theme) monacoEditor.defineTheme(themeName, theme.data);
monacoEditor.setTheme(theme ? themeName : DEFAULT_THEME);
}
/**
* Creates a monaco instance with the given options.
*
* @param {Object} options Options used to initialize monaco.
* @param {Element} options.el The element which will be used to create the monacoEditor.
* @param {string} options.blobPath The path used as the URI of the model. Monaco uses the extension of this path to determine the language.
* @param {string} options.blobContent The content to initialize the monacoEditor.
* @param {string} options.blobGlobalId This is used to help globally identify monaco instances that are created with the same blobPath.
*/
createInstance({ el = undefined, blobPath = '', blobContent = '', blobGlobalId = '' } = {}) {
if (!el) return;
this.editorEl = el;
this.blobContent = blobContent;
this.blobPath = blobPath;
clearDomElement(this.editorEl);
const uriFilePath = joinPaths('gitlab', blobGlobalId, blobPath);
this.model = monacoEditor.createModel(this.blobContent, undefined, Uri.file(uriFilePath));
monacoEditor.onDidCreateEditor(this.renderEditor.bind(this));
this.instance = monacoEditor.create(this.editorEl, this.options);
this.instance.setModel(this.model);
}
dispose() {
if (this.model) {
this.model.dispose();
this.model = null;
}
return this.instance && this.instance.dispose();
}
renderEditor() {
delete this.editorEl.dataset.editorLoading;
}
onChangeContent(fn) {
return this.model.onDidChangeContent(fn);
}
updateModelLanguage(path) {
if (path === this.blobPath) return;
this.blobPath = path;
const ext = `.${path.split('.').pop()}`;
const language = monacoLanguages
.getLanguages()
.find(lang => lang.extensions.indexOf(ext) !== -1);
const id = language ? language.id : 'plaintext';
monacoEditor.setModelLanguage(this.model, id);
}
getValue() {
return this.instance.getValue();
}
setValue(val) {
this.instance.setValue(val);
}
focus() {
this.instance.focus();
}
navigateFileStart() {
this.instance.setPosition(new Position(1, 1));
}
updateOptions(options = {}) {
this.instance.updateOptions(options);
}
use(exts = []) {
const extensions = Array.isArray(exts) ? exts : [exts];
Object.assign(this, ...extensions);
}
}
|