1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-07-28 17:02:04 +03:00

Lexical: Started comment implementation

Refactors some UI and toolbar code for better abstract use across editor
versions.
This commit is contained in:
Dan Brown
2025-06-24 17:47:53 +01:00
parent dfeca246a0
commit c606970e38
5 changed files with 149 additions and 144 deletions

View File

@ -1,4 +1,4 @@
import {$getSelection, createEditor, CreateEditorArgs, LexicalEditor} from 'lexical';
import {createEditor, LexicalEditor} from 'lexical';
import {createEmptyHistoryState, registerHistory} from '@lexical/history';
import {registerRichText} from '@lexical/rich-text';
import {mergeRegister} from '@lexical/utils';
@ -11,65 +11,66 @@ import {listen as listenToCommonEvents} from "./services/common-events";
import {registerDropPasteHandling} from "./services/drop-paste-handling";
import {registerTaskListHandler} from "./ui/framework/helpers/task-list-handler";
import {registerTableSelectionHandler} from "./ui/framework/helpers/table-selection-handler";
import {el} from "./utils/dom";
import {registerShortcuts} from "./services/shortcuts";
import {registerNodeResizer} from "./ui/framework/helpers/node-resizer";
import {registerKeyboardHandling} from "./services/keyboard-handling";
import {registerAutoLinks} from "./services/auto-links";
import {contextToolbars, getMainEditorFullToolbar} from "./ui/defaults/toolbars";
import {modals} from "./ui/defaults/modals";
import {CodeBlockDecorator} from "./ui/decorators/code-block";
import {DiagramDecorator} from "./ui/decorators/diagram";
const theme = {
text: {
bold: 'editor-theme-bold',
code: 'editor-theme-code',
italic: 'editor-theme-italic',
strikethrough: 'editor-theme-strikethrough',
subscript: 'editor-theme-subscript',
superscript: 'editor-theme-superscript',
underline: 'editor-theme-underline',
underlineStrikethrough: 'editor-theme-underline-strikethrough',
}
};
export function createPageEditorInstance(container: HTMLElement, htmlContent: string, options: Record<string, any> = {}): SimpleWysiwygEditorInterface {
const config: CreateEditorArgs = {
const editor = createEditor({
namespace: 'BookStackPageEditor',
nodes: getNodesForPageEditor(),
onError: console.error,
theme: {
text: {
bold: 'editor-theme-bold',
code: 'editor-theme-code',
italic: 'editor-theme-italic',
strikethrough: 'editor-theme-strikethrough',
subscript: 'editor-theme-subscript',
superscript: 'editor-theme-superscript',
underline: 'editor-theme-underline',
underlineStrikethrough: 'editor-theme-underline-strikethrough',
}
}
};
const editArea = el('div', {
contenteditable: 'true',
class: 'editor-content-area page-content',
theme: theme,
});
const editWrap = el('div', {
class: 'editor-content-wrap',
}, [editArea]);
container.append(editWrap);
container.classList.add('editor-container');
container.setAttribute('dir', options.textDirection);
if (options.darkMode) {
container.classList.add('editor-dark');
}
const editor = createEditor(config);
editor.setRootElement(editArea);
const context: EditorUiContext = buildEditorUI(container, editArea, editWrap, editor, options);
const context: EditorUiContext = buildEditorUI(container, editor, {
...options,
editorClass: 'page-content',
});
editor.setRootElement(context.editorDOM);
mergeRegister(
registerRichText(editor),
registerHistory(editor, createEmptyHistoryState(), 300),
registerShortcuts(context),
registerKeyboardHandling(context),
registerTableResizer(editor, editWrap),
registerTableResizer(editor, context.scrollDOM),
registerTableSelectionHandler(editor),
registerTaskListHandler(editor, editArea),
registerTaskListHandler(editor, context.editorDOM),
registerDropPasteHandling(context),
registerNodeResizer(context),
registerAutoLinks(editor),
);
listenToCommonEvents(editor);
// Register toolbars, modals & decorators
context.manager.setToolbar(getMainEditorFullToolbar(context));
for (const key of Object.keys(contextToolbars)) {
context.manager.registerContextToolbar(key, contextToolbars[key]);
}
for (const key of Object.keys(modals)) {
context.manager.registerModal(key, modals[key]);
}
context.manager.registerDecoratorType('code', CodeBlockDecorator);
context.manager.registerDecoratorType('diagram', DiagramDecorator);
listenToCommonEvents(editor);
setEditorContentFromHtml(editor, htmlContent);
const debugView = document.getElementById('lexical-debug');
@ -92,6 +93,33 @@ export function createPageEditorInstance(container: HTMLElement, htmlContent: st
return new SimpleWysiwygEditorInterface(editor);
}
export function createCommentEditorInstance(container: HTMLElement, htmlContent: string, options: Record<string, any> = {}): SimpleWysiwygEditorInterface {
const editor = createEditor({
namespace: 'BookStackCommentEditor',
nodes: getNodesForPageEditor(),
onError: console.error,
theme: theme,
});
const context: EditorUiContext = buildEditorUI(container, editor, options);
editor.setRootElement(context.editorDOM);
mergeRegister(
registerRichText(editor),
registerHistory(editor, createEmptyHistoryState(), 300),
registerShortcuts(context),
registerAutoLinks(editor),
);
// Register toolbars, modals & decorators
context.manager.setToolbar(getMainEditorFullToolbar(context)); // TODO - Create comment toolbar
context.manager.registerContextToolbar('link', contextToolbars.link);
context.manager.registerModal('link', modals.link);
setEditorContentFromHtml(editor, htmlContent);
return new SimpleWysiwygEditorInterface(editor);
}
export class SimpleWysiwygEditorInterface {
protected editor: LexicalEditor;