]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/ui/decorators/code-block.ts
80dcef3bdeaa18aa6ae7f755338a9819089bcb3a
[bookstack] / resources / js / wysiwyg / ui / decorators / code-block.ts
1 import {EditorDecorator} from "../framework/decorator";
2 import {EditorUiContext} from "../framework/core";
3 import {$openCodeEditorForNode, CodeBlockNode} from "../../nodes/code-block";
4 import {ImageNode} from "../../nodes/image";
5
6
7 export class CodeBlockDecorator extends EditorDecorator {
8
9     protected completedSetup: boolean = false;
10     protected latestCode: string = '';
11     protected latestLanguage: string = '';
12
13     // @ts-ignore
14     protected editor: any = null;
15
16     setup(context: EditorUiContext, element: HTMLElement) {
17         const codeNode = this.getNode() as CodeBlockNode;
18         const preEl = element.querySelector('pre');
19         if (!preEl) {
20             return;
21         }
22
23         if (preEl) {
24             preEl.hidden = true;
25         }
26
27         this.latestCode = codeNode.__code;
28         this.latestLanguage = codeNode.__language;
29         const lines = this.latestCode.split('\n').length;
30         const height = (lines * 19.2) + 18 + 24;
31         element.style.height = `${height}px`;
32
33         const startTime = Date.now();
34
35         element.addEventListener('dblclick', event => {
36             context.editor.getEditorState().read(() => {
37                 $openCodeEditorForNode(context.editor, (this.getNode() as CodeBlockNode));
38             });
39         });
40
41         // @ts-ignore
42         const renderEditor = (Code) => {
43             this.editor = Code.wysiwygView(element, document, this.latestCode, this.latestLanguage);
44             setTimeout(() => {
45                 element.style.height = '';
46             }, 12);
47         };
48
49         // @ts-ignore
50         window.importVersioned('code').then((Code) => {
51             const timeout = (Date.now() - startTime < 20) ? 20 : 0;
52             setTimeout(() => renderEditor(Code), timeout);
53         });
54
55         this.completedSetup = true;
56     }
57
58     update() {
59         const codeNode = this.getNode() as CodeBlockNode;
60         const code = codeNode.getCode();
61         const language = codeNode.getLanguage();
62
63         if (this.latestCode === code && this.latestLanguage === language) {
64             return;
65         }
66         this.latestLanguage = language;
67         this.latestCode = code;
68
69         if (this.editor) {
70             this.editor.setContent(code);
71             this.editor.setMode(language, code);
72         }
73     }
74
75     render(context: EditorUiContext, element: HTMLElement): void {
76         if (this.completedSetup) {
77             this.update();
78         } else {
79             this.setup(context, element);
80         }
81     }
82 }