--- /dev/null
+import {$getRoot, LexicalEditor} from "lexical";
+import {$generateHtmlFromNodes, $generateNodesFromDOM} from "@lexical/html";
+
+
+export function setEditorContentFromHtml(editor: LexicalEditor, html: string) {
+ const parser = new DOMParser();
+ const dom = parser.parseFromString(html, 'text/html');
+
+ editor.update(() => {
+ const nodes = $generateNodesFromDOM(editor, dom);
+ const root = $getRoot();
+ for (const child of root.getChildren()) {
+ child.remove(true);
+ }
+ root.append(...nodes);
+ });
+}
+
+export function getEditorContentAsHtml(editor: LexicalEditor): Promise<string> {
+ return new Promise((resolve, reject) => {
+ editor.getEditorState().read(() => {
+ const html = $generateHtmlFromNodes(editor);
+ resolve(html);
+ });
+ });
+}
\ No newline at end of file
-import {$getRoot, createEditor, CreateEditorArgs} from 'lexical';
+import {createEditor, CreateEditorArgs} from 'lexical';
import {createEmptyHistoryState, registerHistory} from '@lexical/history';
import {registerRichText} from '@lexical/rich-text';
import {mergeRegister} from '@lexical/utils';
-import {$generateNodesFromDOM} from '@lexical/html';
import {getNodesForPageEditor} from './nodes';
import {buildEditorUI} from "./ui";
+import {setEditorContentFromHtml} from "./actions";
export function createPageEditorInstance(editArea: HTMLElement) {
const config: CreateEditorArgs = {
};
const startingHtml = editArea.innerHTML;
- const parser = new DOMParser();
- const dom = parser.parseFromString(startingHtml, 'text/html');
const editor = createEditor(config);
editor.setRootElement(editArea);
registerHistory(editor, createEmptyHistoryState(), 300),
);
- editor.update(() => {
- const startingNodes = $generateNodesFromDOM(editor, dom);
- const root = $getRoot();
- root.append(...startingNodes);
- });
+ setEditorContentFromHtml(editor, startingHtml);
const debugView = document.getElementById('lexical-debug');
editor.registerUpdateListener(({editorState}) => {
import {$isImageNode, ImageNode} from "../../nodes/image";
import {$createDetailsNode, $isDetailsNode} from "../../nodes/details";
import {$insertNodeToNearestRoot} from "@lexical/utils";
+import {getEditorContentAsHtml} from "../../actions";
export const undo: EditorButtonDefinition = {
label: 'Undo',
}
}
+export const source: EditorButtonDefinition = {
+ label: 'Source code',
+ async action(context: EditorUiContext) {
+ const modal = context.manager.createModal('source');
+ const source = await getEditorContentAsHtml(context.editor);
+ modal.show({source});
+ },
+ isActive() {
+ return false;
+ }
+};
import {$createLinkNode} from "@lexical/link";
import {$createTextNode, $getSelection} from "lexical";
import {$createImageNode} from "../../nodes/image";
+import {setEditorContentFromHtml} from "../../actions";
export const link: EditorFormDefinition = {
type: 'text',
},
],
+};
+
+export const source: EditorFormDefinition = {
+ submitText: 'Save',
+ action(formData, context: EditorUiContext) {
+ setEditorContentFromHtml(context.editor, formData.get('source')?.toString() || '');
+ return true;
+ },
+ fields: [
+ {
+ label: 'Source',
+ name: 'source',
+ type: 'textarea',
+ },
+ ],
};
\ No newline at end of file
export interface EditorFormFieldDefinition {
label: string;
name: string;
- type: 'text' | 'select';
+ type: 'text' | 'select' | 'textarea';
}
export interface EditorSelectFormFieldDefinition extends EditorFormFieldDefinition {
}
setValue(value: string) {
- const input = this.getDOMElement().querySelector('input,select') as HTMLInputElement;
+ const input = this.getDOMElement().querySelector('input,select,textarea') as HTMLInputElement;
input.value = value;
}
const labels = Object.keys(options);
const optionElems = labels.map(label => el('option', {value: options[label]}, [label]));
input = el('select', {id, name: this.definition.name, class: 'editor-form-field-input'}, optionElems);
+ } else if (this.definition.type === 'textarea') {
+ input = el('textarea', {id, name: this.definition.name, class: 'editor-form-field-input'});
} else {
input = el('input', {id, name: this.definition.name, class: 'editor-form-field-input'});
}
} from "lexical";
import {getMainEditorFullToolbar} from "./toolbars";
import {EditorUIManager} from "./framework/manager";
-import {image as imageFormDefinition, link as linkFormDefinition} from "./defaults/form-definitions";
+import {image as imageFormDefinition, link as linkFormDefinition, source as sourceFormDefinition} from "./defaults/form-definitions";
import {DecoratorListener} from "lexical/LexicalEditor";
import type {NodeKey} from "lexical/LexicalNode";
import {EditorDecoratorAdapter} from "./framework/decorator";
manager.registerModal('image', {
title: 'Insert/Edit Image',
form: imageFormDefinition
- })
+ });
+ manager.registerModal('source', {
+ title: 'Source code',
+ form: sourceFormDefinition,
+ });
// Register decorator listener
// Maybe move to manager?
dangerCallout, details,
h2, h3, h4, h5, image,
infoCallout, italic, link, paragraph,
- redo, strikethrough, subscript,
+ redo, source, strikethrough, subscript,
successCallout, superscript, underline,
undo,
warningCallout
new EditorButton(link),
new EditorButton(image),
new EditorButton(details),
+
+ new EditorButton(source),
]);
}
\ No newline at end of file