]> BookStack Code Mirror - bookstack/blob - resources/js/code/views.js
Updated cm6 theme handling to allow extension via API
[bookstack] / resources / js / code / views.js
1 import {getLanguageExtension} from "./languages"
2 import {HighlightStyle, syntaxHighlighting} from "@codemirror/language";
3 import {Compartment} from "@codemirror/state"
4 import {EditorView} from "@codemirror/view"
5 import {oneDarkTheme, oneDarkHighlightStyle} from "@codemirror/theme-one-dark"
6 import {tags} from "@lezer/highlight"
7
8 const viewLangCompartments = new WeakMap();
9
10 /**
11  * Create a new editor view.
12  *
13  * @param {{parent: Element, doc: String, extensions: Array}} config
14  * @returns {EditorView}
15  */
16 export function createView(config) {
17     const langCompartment = new Compartment();
18     config.extensions.push(langCompartment.of([]));
19     config.extensions.push(getTheme(config.parent));
20
21     const ev = new EditorView(config);
22
23     viewLangCompartments.set(ev, langCompartment);
24
25     return ev;
26 }
27
28 /**
29  * Get the theme extension to use for editor view instance.
30  * @returns {Extension[]}
31  */
32 function getTheme(viewParentEl) {
33     const darkMode = document.documentElement.classList.contains('dark-mode');
34     let viewTheme = darkMode ? oneDarkTheme : [];
35     let highlightStyle = darkMode ? oneDarkHighlightStyle : null;
36
37     const eventData = {
38         darkModeActive: darkMode,
39         registerViewTheme(builder) {
40             const spec = builder();
41             if (spec) {
42                 viewTheme = EditorView.theme(spec);
43             }
44         },
45         registerHighlightStyle(builder) {
46             const tagStyles = builder(tags) || [];
47             console.log('called', tagStyles);
48             if (tagStyles.length) {
49                 highlightStyle = HighlightStyle.define(tagStyles);
50             }
51         }
52     };
53
54     window.$events.emitPublic(viewParentEl, 'library-cm6::configure-theme', eventData);
55
56     return [viewTheme, highlightStyle ? syntaxHighlighting(highlightStyle) : []];
57 }
58
59 /**
60  * Set the language mode of an EditorView.
61  *
62  * @param {EditorView} ev
63  * @param {string} modeSuggestion
64  * @param {string} content
65  */
66 export async function updateViewLanguage(ev, modeSuggestion, content) {
67     const compartment = viewLangCompartments.get(ev);
68     const language = await getLanguageExtension(modeSuggestion, content);
69
70     ev.dispatch({
71         effects: compartment.reconfigure(language ? language : [])
72     })
73 }