import {HttpError} from "./http";
export class EventManager {
- protected listeners: Record<string, ((data: {}) => void)[]> = {};
+ protected listeners: Record<string, ((data: any) => void)[]> = {};
protected stack: {name: string, data: {}}[] = [];
/**
/**
* Listen to a custom event and run the given callback when that event occurs.
*/
- listen(eventName: string, callback: (data: {}) => void): void {
+ listen<T>(eventName: string, callback: (data: T) => void): void {
if (typeof this.listeners[eventName] === 'undefined') this.listeners[eventName] = [];
this.listeners[eventName].push(callback);
}
-import {$createParagraphNode, $getRoot, $isTextNode, LexicalEditor} from "lexical";
+import {$getRoot, $getSelection, $isTextNode, LexicalEditor, LexicalNode, RootNode} from "lexical";
import {$generateHtmlFromNodes, $generateNodesFromDOM} from "@lexical/html";
import {$createCustomParagraphNode} from "./nodes/custom-paragraph";
+function htmlToDom(html: string): Document {
+ const parser = new DOMParser();
+ return parser.parseFromString(html, 'text/html');
+}
+
+function wrapTextNodes(nodes: LexicalNode[]): LexicalNode[] {
+ return nodes.map(node => {
+ if ($isTextNode(node)) {
+ const paragraph = $createCustomParagraphNode();
+ paragraph.append(node);
+ return paragraph;
+ }
+ return node;
+ });
+}
+
+function appendNodesToRoot(root: RootNode, nodes: LexicalNode[]) {
+ root.append(...wrapTextNodes(nodes));
+}
export function setEditorContentFromHtml(editor: LexicalEditor, html: string) {
- const parser = new DOMParser();
- const dom = parser.parseFromString(html, 'text/html');
+ const dom = htmlToDom(html);
- console.log(html);
editor.update(() => {
// Empty existing
const root = $getRoot();
}
const nodes = $generateNodesFromDOM(editor, dom);
+ root.append(...wrapTextNodes(nodes));
+ });
+}
+
+export function appendHtmlToEditor(editor: LexicalEditor, html: string) {
+ const dom = htmlToDom(html);
- // Wrap top-level text nodes
- for (let i = 0; i < nodes.length; i++) {
- const node = nodes[i];
- if ($isTextNode(node)) {
- const paragraph = $createCustomParagraphNode();
- paragraph.append(node);
- nodes[i] = paragraph;
+ editor.update(() => {
+ const root = $getRoot();
+ const nodes = $generateNodesFromDOM(editor, dom);
+ root.append(...wrapTextNodes(nodes));
+ });
+}
+
+export function prependHtmlToEditor(editor: LexicalEditor, html: string) {
+ const dom = htmlToDom(html);
+
+ editor.update(() => {
+ const root = $getRoot();
+ const nodes = wrapTextNodes($generateNodesFromDOM(editor, dom));
+ let reference = root.getChildren()[0];
+ for (let i = nodes.length - 1; i >= 0; i--) {
+ if (reference) {
+ reference.insertBefore(nodes[i]);
+ } else {
+ root.append(nodes[i])
}
+ reference = nodes[i];
}
+ });
+}
+
+export function insertHtmlIntoEditor(editor: LexicalEditor, html: string) {
+ const dom = htmlToDom(html);
+ editor.update(() => {
+ const selection = $getSelection();
+ const nodes = wrapTextNodes($generateNodesFromDOM(editor, dom));
- root.append(...nodes);
+ const reference = selection?.getNodes()[0];
+ const referencesParents = reference?.getParents() || [];
+ const topLevel = referencesParents[referencesParents.length - 1];
+ if (topLevel && reference) {
+ for (let i = nodes.length - 1; i >= 0; i--) {
+ reference.insertAfter(nodes[i]);
+ }
+ }
});
}
resolve(html);
});
});
+}
+
+export function focusEditor(editor: LexicalEditor) {
+ editor.focus(() => {}, {defaultSelection: "rootStart"});
}
\ No newline at end of file
--- /dev/null
+import {LexicalEditor} from "lexical";
+import {
+ appendHtmlToEditor,
+ focusEditor,
+ insertHtmlIntoEditor,
+ prependHtmlToEditor,
+ setEditorContentFromHtml
+} from "./actions";
+
+type EditorEventContent = {
+ html: string;
+ markdown: string;
+};
+
+function getContentToInsert(eventContent: EditorEventContent): string {
+ return eventContent.html || '';
+}
+
+export function listen(editor: LexicalEditor): void {
+ window.$events.listen<EditorEventContent>('editor::replace', eventContent => {
+ const html = getContentToInsert(eventContent);
+ setEditorContentFromHtml(editor, html);
+ });
+
+ window.$events.listen<EditorEventContent>('editor::append', eventContent => {
+ const html = getContentToInsert(eventContent);
+ appendHtmlToEditor(editor, html);
+ });
+
+ window.$events.listen<EditorEventContent>('editor::prepend', eventContent => {
+ const html = getContentToInsert(eventContent);
+ prependHtmlToEditor(editor, html);
+ });
+
+ window.$events.listen<EditorEventContent>('editor::insert', eventContent => {
+ const html = getContentToInsert(eventContent);
+ insertHtmlIntoEditor(editor, html);
+ });
+
+ window.$events.listen<EditorEventContent>('editor::focus', () => {
+ focusEditor(editor);
+ });
+}
import {registerTableResizer} from "./ui/framework/helpers/table-resizer";
import {el} from "./helpers";
import {EditorUiContext} from "./ui/framework/core";
+import {listen as listenToCommonEvents} from "./common-events";
export function createPageEditorInstance(container: HTMLElement, htmlContent: string, options: Record<string, any> = {}): SimpleWysiwygEditorInterface {
const config: CreateEditorArgs = {
registerTableResizer(editor, editWrap),
);
+ listenToCommonEvents(editor);
+
setEditorContentFromHtml(editor, htmlContent);
const debugView = document.getElementById('lexical-debug');