]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/index.ts
e53b9b057dd416f1995ac326037b7151c71a3b1c
[bookstack] / resources / js / wysiwyg / index.ts
1 import {createEditor, CreateEditorArgs, LexicalEditor} from 'lexical';
2 import {createEmptyHistoryState, registerHistory} from '@lexical/history';
3 import {registerRichText} from '@lexical/rich-text';
4 import {mergeRegister} from '@lexical/utils';
5 import {getNodesForPageEditor, registerCommonNodeMutationListeners} from './nodes';
6 import {buildEditorUI} from "./ui";
7 import {getEditorContentAsHtml, setEditorContentFromHtml} from "./actions";
8 import {registerTableResizer} from "./ui/framework/helpers/table-resizer";
9 import {el} from "./helpers";
10 import {EditorUiContext} from "./ui/framework/core";
11 import {listen as listenToCommonEvents} from "./common-events";
12
13 export function createPageEditorInstance(container: HTMLElement, htmlContent: string, options: Record<string, any> = {}): SimpleWysiwygEditorInterface {
14     const config: CreateEditorArgs = {
15         namespace: 'BookStackPageEditor',
16         nodes: getNodesForPageEditor(),
17         onError: console.error,
18         theme: {
19             text: {
20                 bold: 'editor-theme-bold',
21                 code: 'editor-theme-code',
22                 italic: 'editor-theme-italic',
23                 strikethrough: 'editor-theme-strikethrough',
24                 subscript: 'editor-theme-subscript',
25                 superscript: 'editor-theme-superscript',
26                 underline: 'editor-theme-underline',
27                 underlineStrikethrough: 'editor-theme-underline-strikethrough',
28             }
29         }
30     };
31
32     const editArea = el('div', {
33         contenteditable: 'true',
34         class: 'editor-content-area page-content',
35     });
36     const editWrap = el('div', {
37         class: 'editor-content-wrap',
38     }, [editArea]);
39     container.append(editWrap);
40     container.classList.add('editor-container');
41
42     const editor = createEditor(config);
43     editor.setRootElement(editArea);
44
45     mergeRegister(
46         registerRichText(editor),
47         registerHistory(editor, createEmptyHistoryState(), 300),
48         registerTableResizer(editor, editWrap),
49     );
50
51     listenToCommonEvents(editor);
52
53     setEditorContentFromHtml(editor, htmlContent);
54
55     const debugView = document.getElementById('lexical-debug');
56     if (debugView) {
57         debugView.hidden = true;
58     }
59     editor.registerUpdateListener(({editorState}) => {
60         console.log('editorState', editorState.toJSON());
61         if (debugView) {
62             debugView.textContent = JSON.stringify(editorState.toJSON(), null, 2);
63         }
64     });
65
66     const context: EditorUiContext = buildEditorUI(container, editArea, editWrap, editor, options);
67     registerCommonNodeMutationListeners(context);
68
69     return new SimpleWysiwygEditorInterface(editor);
70 }
71
72 export class SimpleWysiwygEditorInterface {
73     protected editor: LexicalEditor;
74
75     constructor(editor: LexicalEditor) {
76         this.editor = editor;
77     }
78
79     async getContentAsHtml(): Promise<string> {
80         return await getEditorContentAsHtml(this.editor);
81     }
82 }