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
|
import { Range } from 'monaco-editor';
import { waitForCSSLoaded } from '~/helpers/startup_css_helper';
import { ERROR_INSTANCE_REQUIRED_FOR_EXTENSION, EDITOR_TYPE_CODE } from '../constants';
const hashRegexp = new RegExp('#?L', 'g');
const createAnchor = (href) => {
const fragment = new DocumentFragment();
const el = document.createElement('a');
el.classList.add('link-anchor');
el.href = href;
fragment.appendChild(el);
el.addEventListener('contextmenu', (e) => {
e.stopPropagation();
});
return fragment;
};
export class EditorLiteExtension {
constructor({ instance, ...options } = {}) {
if (instance) {
Object.assign(instance, options);
EditorLiteExtension.highlightLines(instance);
if (instance.getEditorType && instance.getEditorType() === EDITOR_TYPE_CODE) {
EditorLiteExtension.setupLineLinking(instance);
}
EditorLiteExtension.deferRerender(instance);
} else if (Object.entries(options).length) {
throw new Error(ERROR_INSTANCE_REQUIRED_FOR_EXTENSION);
}
}
static deferRerender(instance) {
waitForCSSLoaded(() => {
instance.layout();
});
}
static highlightLines(instance) {
const { hash } = window.location;
if (!hash) {
return;
}
const [start, end] = hash.replace(hashRegexp, '').split('-');
let startLine = start ? parseInt(start, 10) : null;
let endLine = end ? parseInt(end, 10) : startLine;
if (endLine < startLine) {
[startLine, endLine] = [endLine, startLine];
}
if (startLine) {
window.requestAnimationFrame(() => {
instance.revealLineInCenter(startLine);
Object.assign(instance, {
lineDecorations: instance.deltaDecorations(
[],
[
{
range: new Range(startLine, 1, endLine, 1),
options: { isWholeLine: true, className: 'active-line-text' },
},
],
),
});
});
}
}
static onMouseMoveHandler(e) {
const target = e.target.element;
if (target.classList.contains('line-numbers')) {
const lineNum = e.target.position.lineNumber;
const hrefAttr = `#L${lineNum}`;
let el = target.querySelector('a');
if (!el) {
el = createAnchor(hrefAttr);
target.appendChild(el);
}
}
}
static setupLineLinking(instance) {
instance.onMouseMove(EditorLiteExtension.onMouseMoveHandler);
instance.onMouseDown((e) => {
const isCorrectAnchor = e.target.element.classList.contains('link-anchor');
if (!isCorrectAnchor) {
return;
}
if (instance.lineDecorations) {
instance.deltaDecorations(instance.lineDecorations, []);
}
});
}
}
|