diff --git a/resources/js/wysiwyg/lexical/core/LexicalEvents.ts b/resources/js/wysiwyg/lexical/core/LexicalEvents.ts index 5fd671a76..c70a906a0 100644 --- a/resources/js/wysiwyg/lexical/core/LexicalEvents.ts +++ b/resources/js/wysiwyg/lexical/core/LexicalEvents.ts @@ -355,7 +355,6 @@ function onSelectionChange( lastNode instanceof ParagraphNode && lastNode.getChildrenSize() === 0 ) { - selection.format = lastNode.getTextFormat(); selection.style = lastNode.getTextStyle(); } else { selection.format = 0; @@ -578,7 +577,6 @@ function onBeforeInput(event: InputEvent, editor: LexicalEditor): void { if ($isRangeSelection(selection)) { const anchorNode = selection.anchor.getNode(); anchorNode.markDirty(); - selection.format = anchorNode.getFormat(); invariant( $isTextNode(anchorNode), 'Anchor node must be a TextNode', @@ -912,7 +910,6 @@ function onCompositionStart( // need to invoke the empty space heuristic below. anchor.type === 'element' || !selection.isCollapsed() || - node.getFormat() !== selection.format || ($isTextNode(node) && node.getStyle() !== selection.style) ) { // We insert a zero width character, ready for the composition diff --git a/resources/js/wysiwyg/lexical/core/LexicalMutations.ts b/resources/js/wysiwyg/lexical/core/LexicalMutations.ts index 56f364501..c24dc9ebb 100644 --- a/resources/js/wysiwyg/lexical/core/LexicalMutations.ts +++ b/resources/js/wysiwyg/lexical/core/LexicalMutations.ts @@ -96,15 +96,6 @@ function shouldUpdateTextNodeFromMutation( targetDOM: Node, targetNode: TextNode, ): boolean { - if ($isRangeSelection(selection)) { - const anchorNode = selection.anchor.getNode(); - if ( - anchorNode.is(targetNode) && - selection.format !== anchorNode.getFormat() - ) { - return false; - } - } return targetDOM.nodeType === DOM_TEXT_TYPE && targetNode.isAttached(); } diff --git a/resources/js/wysiwyg/lexical/core/LexicalReconciler.ts b/resources/js/wysiwyg/lexical/core/LexicalReconciler.ts index 09d01bffd..7843027d7 100644 --- a/resources/js/wysiwyg/lexical/core/LexicalReconciler.ts +++ b/resources/js/wysiwyg/lexical/core/LexicalReconciler.ts @@ -17,7 +17,6 @@ import type {NodeKey, NodeMap} from './LexicalNode'; import type {ElementNode} from './nodes/LexicalElementNode'; import invariant from 'lexical/shared/invariant'; -import normalizeClassNames from 'lexical/shared/normalizeClassNames'; import { $isDecoratorNode, @@ -117,51 +116,6 @@ function setTextAlign(domStyle: CSSStyleDeclaration, value: string): void { domStyle.setProperty('text-align', value); } -const DEFAULT_INDENT_VALUE = '40px'; - -function setElementIndent(dom: HTMLElement, indent: number): void { - const indentClassName = activeEditorConfig.theme.indent; - - if (typeof indentClassName === 'string') { - const elementHasClassName = dom.classList.contains(indentClassName); - - if (indent > 0 && !elementHasClassName) { - dom.classList.add(indentClassName); - } else if (indent < 1 && elementHasClassName) { - dom.classList.remove(indentClassName); - } - } - - const indentationBaseValue = - getComputedStyle(dom).getPropertyValue('--lexical-indent-base-value') || - DEFAULT_INDENT_VALUE; - - dom.style.setProperty( - 'padding-inline-start', - indent === 0 ? '' : `calc(${indent} * ${indentationBaseValue})`, - ); -} - -function setElementFormat(dom: HTMLElement, format: number): void { - const domStyle = dom.style; - - if (format === 0) { - setTextAlign(domStyle, ''); - } else if (format === IS_ALIGN_LEFT) { - setTextAlign(domStyle, 'left'); - } else if (format === IS_ALIGN_CENTER) { - setTextAlign(domStyle, 'center'); - } else if (format === IS_ALIGN_RIGHT) { - setTextAlign(domStyle, 'right'); - } else if (format === IS_ALIGN_JUSTIFY) { - setTextAlign(domStyle, 'justify'); - } else if (format === IS_ALIGN_START) { - setTextAlign(domStyle, 'start'); - } else if (format === IS_ALIGN_END) { - setTextAlign(domStyle, 'end'); - } -} - function $createNode( key: NodeKey, parentDOM: null | HTMLElement, @@ -185,22 +139,14 @@ function $createNode( } if ($isElementNode(node)) { - const indent = node.__indent; const childrenSize = node.__size; - if (indent !== 0) { - setElementIndent(dom, indent); - } if (childrenSize !== 0) { const endIndex = childrenSize - 1; const children = createChildrenArray(node, activeNextNodeMap); $createChildren(children, node, 0, endIndex, dom, null); } - const format = node.__format; - if (format !== 0) { - setElementFormat(dom, format); - } if (!node.isInline()) { reconcileElementTerminatingLineBreak(null, node, dom); } @@ -349,10 +295,8 @@ function reconcileParagraphFormat(element: ElementNode): void { if ( $isParagraphNode(element) && subTreeTextFormat != null && - subTreeTextFormat !== element.__textFormat && !activeEditorStateReadOnly ) { - element.setTextFormat(subTreeTextFormat); element.setTextStyle(subTreeTextStyle); } } @@ -563,17 +507,6 @@ function $reconcileNode( if ($isElementNode(prevNode) && $isElementNode(nextNode)) { // Reconcile element children - const nextIndent = nextNode.__indent; - - if (nextIndent !== prevNode.__indent) { - setElementIndent(dom, nextIndent); - } - - const nextFormat = nextNode.__format; - - if (nextFormat !== prevNode.__format) { - setElementFormat(dom, nextFormat); - } if (isDirty) { $reconcileChildrenWithDirection(prevNode, nextNode, dom); if (!$isRootNode(nextNode) && !nextNode.isInline()) { diff --git a/resources/js/wysiwyg/lexical/core/__tests__/utils/index.ts b/resources/js/wysiwyg/lexical/core/__tests__/utils/index.ts index f7230595a..a4d74210e 100644 --- a/resources/js/wysiwyg/lexical/core/__tests__/utils/index.ts +++ b/resources/js/wysiwyg/lexical/core/__tests__/utils/index.ts @@ -129,8 +129,6 @@ export class TestElementNode extends ElementNode { serializedNode: SerializedTestElementNode, ): TestInlineElementNode { const node = $createTestInlineElementNode(); - node.setFormat(serializedNode.format); - node.setIndent(serializedNode.indent); node.setDirection(serializedNode.direction); return node; } @@ -195,8 +193,6 @@ export class TestInlineElementNode extends ElementNode { serializedNode: SerializedTestInlineElementNode, ): TestInlineElementNode { const node = $createTestInlineElementNode(); - node.setFormat(serializedNode.format); - node.setIndent(serializedNode.indent); node.setDirection(serializedNode.direction); return node; } @@ -241,8 +237,6 @@ export class TestShadowRootNode extends ElementNode { serializedNode: SerializedTestShadowRootNode, ): TestShadowRootNode { const node = $createTestShadowRootNode(); - node.setFormat(serializedNode.format); - node.setIndent(serializedNode.indent); node.setDirection(serializedNode.direction); return node; } @@ -322,8 +316,6 @@ export class TestExcludeFromCopyElementNode extends ElementNode { serializedNode: SerializedTestExcludeFromCopyElementNode, ): TestExcludeFromCopyElementNode { const node = $createTestExcludeFromCopyElementNode(); - node.setFormat(serializedNode.format); - node.setIndent(serializedNode.indent); node.setDirection(serializedNode.direction); return node; } diff --git a/resources/js/wysiwyg/lexical/core/nodes/CommonBlockNode.ts b/resources/js/wysiwyg/lexical/core/nodes/CommonBlockNode.ts new file mode 100644 index 000000000..37ca1cdef --- /dev/null +++ b/resources/js/wysiwyg/lexical/core/nodes/CommonBlockNode.ts @@ -0,0 +1,54 @@ +import {ElementNode} from "./LexicalElementNode"; +import {CommonBlockAlignment, SerializedCommonBlockNode} from "../../../nodes/_common"; + + +export class CommonBlockNode extends ElementNode { + __id: string = ''; + __alignment: CommonBlockAlignment = ''; + __inset: number = 0; + + setId(id: string) { + const self = this.getWritable(); + self.__id = id; + } + + getId(): string { + const self = this.getLatest(); + return self.__id; + } + + setAlignment(alignment: CommonBlockAlignment) { + const self = this.getWritable(); + self.__alignment = alignment; + } + + getAlignment(): CommonBlockAlignment { + const self = this.getLatest(); + return self.__alignment; + } + + setInset(size: number) { + const self = this.getWritable(); + self.__inset = size; + } + + getInset(): number { + const self = this.getLatest(); + return self.__inset; + } + + exportJSON(): SerializedCommonBlockNode { + return { + ...super.exportJSON(), + id: this.__id, + alignment: this.__alignment, + inset: this.__inset, + }; + } +} + +export function copyCommonBlockProperties(from: CommonBlockNode, to: CommonBlockNode): void { + to.__id = from.__id; + to.__alignment = from.__alignment; + to.__inset = from.__inset; +} \ No newline at end of file diff --git a/resources/js/wysiwyg/lexical/core/nodes/LexicalElementNode.ts b/resources/js/wysiwyg/lexical/core/nodes/LexicalElementNode.ts index 88c6d5678..002d825d6 100644 --- a/resources/js/wysiwyg/lexical/core/nodes/LexicalElementNode.ts +++ b/resources/js/wysiwyg/lexical/core/nodes/LexicalElementNode.ts @@ -42,8 +42,6 @@ export type SerializedElementNode< { children: Array; direction: 'ltr' | 'rtl' | null; - format: ElementFormatType; - indent: number; }, SerializedLexicalNode >; @@ -74,12 +72,8 @@ export class ElementNode extends LexicalNode { /** @internal */ __size: number; /** @internal */ - __format: number; - /** @internal */ __style: string; /** @internal */ - __indent: number; - /** @internal */ __dir: 'ltr' | 'rtl' | null; constructor(key?: NodeKey) { @@ -87,9 +81,7 @@ export class ElementNode extends LexicalNode { this.__first = null; this.__last = null; this.__size = 0; - this.__format = 0; this.__style = ''; - this.__indent = 0; this.__dir = null; } @@ -98,28 +90,14 @@ export class ElementNode extends LexicalNode { this.__first = prevNode.__first; this.__last = prevNode.__last; this.__size = prevNode.__size; - this.__indent = prevNode.__indent; - this.__format = prevNode.__format; this.__style = prevNode.__style; this.__dir = prevNode.__dir; } - getFormat(): number { - const self = this.getLatest(); - return self.__format; - } - getFormatType(): ElementFormatType { - const format = this.getFormat(); - return ELEMENT_FORMAT_TO_TYPE[format] || ''; - } getStyle(): string { const self = this.getLatest(); return self.__style; } - getIndent(): number { - const self = this.getLatest(); - return self.__indent; - } getChildren(): Array { const children: Array = []; let child: T | null = this.getFirstChild(); @@ -301,13 +279,6 @@ export class ElementNode extends LexicalNode { const self = this.getLatest(); return self.__dir; } - hasFormat(type: ElementFormatType): boolean { - if (type !== '') { - const formatFlag = ELEMENT_TYPE_TO_FORMAT[type]; - return (this.getFormat() & formatFlag) !== 0; - } - return false; - } // Mutators @@ -378,21 +349,11 @@ export class ElementNode extends LexicalNode { self.__dir = direction; return self; } - setFormat(type: ElementFormatType): this { - const self = this.getWritable(); - self.__format = type !== '' ? ELEMENT_TYPE_TO_FORMAT[type] : 0; - return this; - } setStyle(style: string): this { const self = this.getWritable(); self.__style = style || ''; return this; } - setIndent(indentLevel: number): this { - const self = this.getWritable(); - self.__indent = indentLevel; - return this; - } splice( start: number, deleteCount: number, @@ -528,8 +489,6 @@ export class ElementNode extends LexicalNode { return { children: [], direction: this.getDirection(), - format: this.getFormatType(), - indent: this.getIndent(), type: 'element', version: 1, }; diff --git a/resources/js/wysiwyg/lexical/core/nodes/LexicalParagraphNode.ts b/resources/js/wysiwyg/lexical/core/nodes/LexicalParagraphNode.ts index 4e69dc21c..6517d939e 100644 --- a/resources/js/wysiwyg/lexical/core/nodes/LexicalParagraphNode.ts +++ b/resources/js/wysiwyg/lexical/core/nodes/LexicalParagraphNode.ts @@ -19,39 +19,36 @@ import type { LexicalNode, NodeKey, } from '../LexicalNode'; -import type { - ElementFormatType, - SerializedElementNode, -} from './LexicalElementNode'; import type {RangeSelection} from 'lexical'; -import {TEXT_TYPE_TO_FORMAT} from '../LexicalConstants'; import { $applyNodeReplacement, getCachedClassNameArray, isHTMLElement, } from '../LexicalUtils'; -import {ElementNode} from './LexicalElementNode'; -import {$isTextNode, TextFormatType} from './LexicalTextNode'; +import {$isTextNode} from './LexicalTextNode'; +import { + commonPropertiesDifferent, deserializeCommonBlockNode, + SerializedCommonBlockNode, setCommonBlockPropsFromElement, + updateElementWithCommonBlockProps +} from "../../../nodes/_common"; +import {CommonBlockNode, copyCommonBlockProperties} from "lexical/nodes/CommonBlockNode"; export type SerializedParagraphNode = Spread< { - textFormat: number; textStyle: string; }, - SerializedElementNode + SerializedCommonBlockNode >; /** @noInheritDoc */ -export class ParagraphNode extends ElementNode { +export class ParagraphNode extends CommonBlockNode { ['constructor']!: KlassConstructor; /** @internal */ - __textFormat: number; __textStyle: string; constructor(key?: NodeKey) { super(key); - this.__textFormat = 0; this.__textStyle = ''; } @@ -59,22 +56,6 @@ export class ParagraphNode extends ElementNode { return 'paragraph'; } - getTextFormat(): number { - const self = this.getLatest(); - return self.__textFormat; - } - - setTextFormat(type: number): this { - const self = this.getWritable(); - self.__textFormat = type; - return self; - } - - hasTextFormat(type: TextFormatType): boolean { - const formatFlag = TEXT_TYPE_TO_FORMAT[type]; - return (this.getTextFormat() & formatFlag) !== 0; - } - getTextStyle(): string { const self = this.getLatest(); return self.__textStyle; @@ -92,8 +73,8 @@ export class ParagraphNode extends ElementNode { afterCloneFrom(prevNode: this) { super.afterCloneFrom(prevNode); - this.__textFormat = prevNode.__textFormat; this.__textStyle = prevNode.__textStyle; + copyCommonBlockProperties(prevNode, this); } // View @@ -105,6 +86,9 @@ export class ParagraphNode extends ElementNode { const domClassList = dom.classList; domClassList.add(...classNames); } + + updateElementWithCommonBlockProps(dom, this); + return dom; } updateDOM( @@ -112,7 +96,7 @@ export class ParagraphNode extends ElementNode { dom: HTMLElement, config: EditorConfig, ): boolean { - return false; + return commonPropertiesDifferent(prevNode, this); } static importDOM(): DOMConversionMap | null { @@ -131,16 +115,6 @@ export class ParagraphNode extends ElementNode { if (this.isEmpty()) { element.append(document.createElement('br')); } - - const formatType = this.getFormatType(); - element.style.textAlign = formatType; - - const indent = this.getIndent(); - if (indent > 0) { - // padding-inline-start is not widely supported in email HTML, but - // Lexical Reconciler uses padding-inline-start. Using text-indent instead. - element.style.textIndent = `${indent * 20}px`; - } } return { @@ -150,16 +124,13 @@ export class ParagraphNode extends ElementNode { static importJSON(serializedNode: SerializedParagraphNode): ParagraphNode { const node = $createParagraphNode(); - node.setFormat(serializedNode.format); - node.setIndent(serializedNode.indent); - node.setTextFormat(serializedNode.textFormat); + deserializeCommonBlockNode(serializedNode, node); return node; } exportJSON(): SerializedParagraphNode { return { ...super.exportJSON(), - textFormat: this.getTextFormat(), textStyle: this.getTextStyle(), type: 'paragraph', version: 1, @@ -173,11 +144,9 @@ export class ParagraphNode extends ElementNode { restoreSelection: boolean, ): ParagraphNode { const newElement = $createParagraphNode(); - newElement.setTextFormat(rangeSelection.format); newElement.setTextStyle(rangeSelection.style); const direction = this.getDirection(); newElement.setDirection(direction); - newElement.setFormat(this.getFormatType()); newElement.setStyle(this.getTextStyle()); this.insertAfter(newElement, restoreSelection); return newElement; @@ -210,13 +179,7 @@ export class ParagraphNode extends ElementNode { function $convertParagraphElement(element: HTMLElement): DOMConversionOutput { const node = $createParagraphNode(); - if (element.style) { - node.setFormat(element.style.textAlign as ElementFormatType); - const indent = parseInt(element.style.textIndent, 10) / 20; - if (indent > 0) { - node.setIndent(indent); - } - } + setCommonBlockPropsFromElement(element, node); return {node}; } diff --git a/resources/js/wysiwyg/lexical/core/nodes/LexicalRootNode.ts b/resources/js/wysiwyg/lexical/core/nodes/LexicalRootNode.ts index 74c8d5a7f..a1c8813c3 100644 --- a/resources/js/wysiwyg/lexical/core/nodes/LexicalRootNode.ts +++ b/resources/js/wysiwyg/lexical/core/nodes/LexicalRootNode.ts @@ -99,8 +99,6 @@ export class RootNode extends ElementNode { static importJSON(serializedNode: SerializedRootNode): RootNode { // We don't create a root, and instead use the existing root. const node = $getRoot(); - node.setFormat(serializedNode.format); - node.setIndent(serializedNode.indent); node.setDirection(serializedNode.direction); return node; } @@ -109,8 +107,6 @@ export class RootNode extends ElementNode { return { children: [], direction: this.getDirection(), - format: this.getFormatType(), - indent: this.getIndent(), type: 'root', version: 1, }; diff --git a/resources/js/wysiwyg/lexical/html/index.ts b/resources/js/wysiwyg/lexical/html/index.ts index 2975315cc..3e962ec72 100644 --- a/resources/js/wysiwyg/lexical/html/index.ts +++ b/resources/js/wysiwyg/lexical/html/index.ts @@ -327,9 +327,6 @@ function wrapContinuousInlines( for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; if ($isBlockElementNode(node)) { - if (textAlign && !node.getFormat()) { - node.setFormat(textAlign); - } out.push(node); } else { continuousInlines.push(node); @@ -338,7 +335,6 @@ function wrapContinuousInlines( (i < nodes.length - 1 && $isBlockElementNode(nodes[i + 1])) ) { const wrapper = createWrapperFn(); - wrapper.setFormat(textAlign); wrapper.append(...continuousInlines); out.push(wrapper); continuousInlines = []; diff --git a/resources/js/wysiwyg/lexical/link/index.ts b/resources/js/wysiwyg/lexical/link/index.ts index fe2b97570..884fe9153 100644 --- a/resources/js/wysiwyg/lexical/link/index.ts +++ b/resources/js/wysiwyg/lexical/link/index.ts @@ -162,8 +162,6 @@ export class LinkNode extends ElementNode { target: serializedNode.target, title: serializedNode.title, }); - node.setFormat(serializedNode.format); - node.setIndent(serializedNode.indent); node.setDirection(serializedNode.direction); return node; } @@ -402,8 +400,6 @@ export class AutoLinkNode extends LinkNode { target: serializedNode.target, title: serializedNode.title, }); - node.setFormat(serializedNode.format); - node.setIndent(serializedNode.indent); node.setDirection(serializedNode.direction); return node; } diff --git a/resources/js/wysiwyg/lexical/list/LexicalListItemNode.ts b/resources/js/wysiwyg/lexical/list/LexicalListItemNode.ts index 5026a0129..c20329e4b 100644 --- a/resources/js/wysiwyg/lexical/list/LexicalListItemNode.ts +++ b/resources/js/wysiwyg/lexical/list/LexicalListItemNode.ts @@ -126,14 +126,12 @@ export class ListItemNode extends ElementNode { const node = $createListItemNode(); node.setChecked(serializedNode.checked); node.setValue(serializedNode.value); - node.setFormat(serializedNode.format); node.setDirection(serializedNode.direction); return node; } exportDOM(editor: LexicalEditor): DOMExportOutput { const element = this.createDOM(editor._config); - element.style.textAlign = this.getFormatType(); return { element, }; @@ -172,7 +170,6 @@ export class ListItemNode extends ElementNode { if ($isListItemNode(replaceWithNode)) { return super.replace(replaceWithNode); } - this.setIndent(0); const list = this.getParentOrThrow(); if (!$isListNode(list)) { return replaceWithNode; @@ -351,41 +348,6 @@ export class ListItemNode extends ElementNode { this.setChecked(!this.__checked); } - getIndent(): number { - // If we don't have a parent, we are likely serializing - const parent = this.getParent(); - if (parent === null) { - return this.getLatest().__indent; - } - // ListItemNode should always have a ListNode for a parent. - let listNodeParent = parent.getParentOrThrow(); - let indentLevel = 0; - while ($isListItemNode(listNodeParent)) { - listNodeParent = listNodeParent.getParentOrThrow().getParentOrThrow(); - indentLevel++; - } - - return indentLevel; - } - - setIndent(indent: number): this { - invariant(typeof indent === 'number', 'Invalid indent value.'); - indent = Math.floor(indent); - invariant(indent >= 0, 'Indent value must be non-negative.'); - let currentIndent = this.getIndent(); - while (currentIndent !== indent) { - if (currentIndent < indent) { - $handleIndent(this); - currentIndent++; - } else { - $handleOutdent(this); - currentIndent--; - } - } - - return this; - } - /** @deprecated @internal */ canInsertAfter(node: LexicalNode): boolean { return $isListItemNode(node); diff --git a/resources/js/wysiwyg/lexical/list/formatList.ts b/resources/js/wysiwyg/lexical/list/formatList.ts index b9ca01169..aa0d5d611 100644 --- a/resources/js/wysiwyg/lexical/list/formatList.ts +++ b/resources/js/wysiwyg/lexical/list/formatList.ts @@ -84,10 +84,6 @@ export function insertList(editor: LexicalEditor, listType: ListType): void { if ($isRootOrShadowRoot(anchorNodeParent)) { anchorNode.replace(list); const listItem = $createListItemNode(); - if ($isElementNode(anchorNode)) { - listItem.setFormat(anchorNode.getFormatType()); - listItem.setIndent(anchorNode.getIndent()); - } list.append(listItem); } else if ($isListItemNode(anchorNode)) { const parent = anchorNode.getParentOrThrow(); @@ -157,8 +153,6 @@ function $createListOrMerge(node: ElementNode, listType: ListType): ListNode { const previousSibling = node.getPreviousSibling(); const nextSibling = node.getNextSibling(); const listItem = $createListItemNode(); - listItem.setFormat(node.getFormatType()); - listItem.setIndent(node.getIndent()); append(listItem, node.getChildren()); if ( diff --git a/resources/js/wysiwyg/lexical/rich-text/index.ts b/resources/js/wysiwyg/lexical/rich-text/index.ts index d937060c6..bc5c3f1d2 100644 --- a/resources/js/wysiwyg/lexical/rich-text/index.ts +++ b/resources/js/wysiwyg/lexical/rich-text/index.ts @@ -155,9 +155,6 @@ export class QuoteNode extends ElementNode { if (this.isEmpty()) { element.append(document.createElement('br')); } - - const formatType = this.getFormatType(); - element.style.textAlign = formatType; } return { @@ -167,8 +164,6 @@ export class QuoteNode extends ElementNode { static importJSON(serializedNode: SerializedQuoteNode): QuoteNode { const node = $createQuoteNode(); - node.setFormat(serializedNode.format); - node.setIndent(serializedNode.indent); return node; } @@ -315,9 +310,6 @@ export class HeadingNode extends ElementNode { if (this.isEmpty()) { element.append(document.createElement('br')); } - - const formatType = this.getFormatType(); - element.style.textAlign = formatType; } return { @@ -326,10 +318,7 @@ export class HeadingNode extends ElementNode { } static importJSON(serializedNode: SerializedHeadingNode): HeadingNode { - const node = $createHeadingNode(serializedNode.tag); - node.setFormat(serializedNode.format); - node.setIndent(serializedNode.indent); - return node; + return $createHeadingNode(serializedNode.tag); } exportJSON(): SerializedHeadingNode { @@ -402,18 +391,12 @@ function $convertHeadingElement(element: HTMLElement): DOMConversionOutput { nodeName === 'h6' ) { node = $createHeadingNode(nodeName); - if (element.style !== null) { - node.setFormat(element.style.textAlign as ElementFormatType); - } } return {node}; } function $convertBlockquoteElement(element: HTMLElement): DOMConversionOutput { const node = $createQuoteNode(); - if (element.style !== null) { - node.setFormat(element.style.textAlign as ElementFormatType); - } return {node}; } @@ -651,9 +634,6 @@ export function registerRichText(editor: LexicalEditor): () => void { (parentNode): parentNode is ElementNode => $isElementNode(parentNode) && !parentNode.isInline(), ); - if (element !== null) { - element.setFormat(format); - } } return true; }, @@ -691,28 +671,6 @@ export function registerRichText(editor: LexicalEditor): () => void { }, COMMAND_PRIORITY_EDITOR, ), - editor.registerCommand( - INDENT_CONTENT_COMMAND, - () => { - return $handleIndentAndOutdent((block) => { - const indent = block.getIndent(); - block.setIndent(indent + 1); - }); - }, - COMMAND_PRIORITY_EDITOR, - ), - editor.registerCommand( - OUTDENT_CONTENT_COMMAND, - () => { - return $handleIndentAndOutdent((block) => { - const indent = block.getIndent(); - if (indent > 0) { - block.setIndent(indent - 1); - } - }); - }, - COMMAND_PRIORITY_EDITOR, - ), editor.registerCommand( KEY_ARROW_UP_COMMAND, (event) => { @@ -846,19 +804,7 @@ export function registerRichText(editor: LexicalEditor): () => void { return false; } event.preventDefault(); - const {anchor} = selection; - const anchorNode = anchor.getNode(); - if ( - selection.isCollapsed() && - anchor.offset === 0 && - !$isRootNode(anchorNode) - ) { - const element = $getNearestBlockElementAncestorOrThrow(anchorNode); - if (element.getIndent() > 0) { - return editor.dispatchCommand(OUTDENT_CONTENT_COMMAND, undefined); - } - } return editor.dispatchCommand(DELETE_CHARACTER_COMMAND, true); }, COMMAND_PRIORITY_EDITOR, diff --git a/resources/js/wysiwyg/lexical/selection/range-selection.ts b/resources/js/wysiwyg/lexical/selection/range-selection.ts index dbadaf346..542eae4db 100644 --- a/resources/js/wysiwyg/lexical/selection/range-selection.ts +++ b/resources/js/wysiwyg/lexical/selection/range-selection.ts @@ -81,8 +81,6 @@ export function $setBlocksType( invariant($isElementNode(node), 'Expected block node to be an ElementNode'); const targetElement = createElement(); - targetElement.setFormat(node.getFormatType()); - targetElement.setIndent(node.getIndent()); node.replace(targetElement, true); } } @@ -136,8 +134,6 @@ export function $wrapNodes( : anchor.getNode(); const children = target.getChildren(); let element = createElement(); - element.setFormat(target.getFormatType()); - element.setIndent(target.getIndent()); children.forEach((child) => element.append(child)); if (wrappingElement) { @@ -277,8 +273,6 @@ export function $wrapNodesImpl( if (elementMapping.get(parentKey) === undefined) { const targetElement = createElement(); - targetElement.setFormat(parent.getFormatType()); - targetElement.setIndent(parent.getIndent()); elements.push(targetElement); elementMapping.set(parentKey, targetElement); // Move node and its siblings to the new @@ -299,8 +293,6 @@ export function $wrapNodesImpl( 'Expected node in emptyElements to be an ElementNode', ); const targetElement = createElement(); - targetElement.setFormat(node.getFormatType()); - targetElement.setIndent(node.getIndent()); elements.push(targetElement); node.remove(true); } diff --git a/resources/js/wysiwyg/nodes/custom-paragraph.ts b/resources/js/wysiwyg/nodes/custom-paragraph.ts deleted file mode 100644 index 3adc10d0e..000000000 --- a/resources/js/wysiwyg/nodes/custom-paragraph.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { - DOMConversion, - DOMConversionMap, - DOMConversionOutput, - LexicalNode, - ParagraphNode, SerializedParagraphNode, Spread, -} from "lexical"; -import {EditorConfig} from "lexical/LexicalEditor"; -import { - CommonBlockAlignment, commonPropertiesDifferent, deserializeCommonBlockNode, - SerializedCommonBlockNode, - setCommonBlockPropsFromElement, - updateElementWithCommonBlockProps -} from "./_common"; - -export type SerializedCustomParagraphNode = Spread - -export class CustomParagraphNode extends ParagraphNode { - __id: string = ''; - __alignment: CommonBlockAlignment = ''; - __inset: number = 0; - - static getType() { - return 'custom-paragraph'; - } - - setId(id: string) { - const self = this.getWritable(); - self.__id = id; - } - - getId(): string { - const self = this.getLatest(); - return self.__id; - } - - setAlignment(alignment: CommonBlockAlignment) { - const self = this.getWritable(); - self.__alignment = alignment; - } - - getAlignment(): CommonBlockAlignment { - const self = this.getLatest(); - return self.__alignment; - } - - setInset(size: number) { - const self = this.getWritable(); - self.__inset = size; - } - - getInset(): number { - const self = this.getLatest(); - return self.__inset; - } - - static clone(node: CustomParagraphNode): CustomParagraphNode { - const newNode = new CustomParagraphNode(node.__key); - newNode.__id = node.__id; - newNode.__alignment = node.__alignment; - newNode.__inset = node.__inset; - return newNode; - } - - createDOM(config: EditorConfig): HTMLElement { - const dom = super.createDOM(config); - updateElementWithCommonBlockProps(dom, this); - return dom; - } - - updateDOM(prevNode: CustomParagraphNode, dom: HTMLElement, config: EditorConfig): boolean { - return super.updateDOM(prevNode, dom, config) - || commonPropertiesDifferent(prevNode, this); - } - - exportJSON(): SerializedCustomParagraphNode { - return { - ...super.exportJSON(), - type: 'custom-paragraph', - version: 1, - id: this.__id, - alignment: this.__alignment, - inset: this.__inset, - }; - } - - static importJSON(serializedNode: SerializedCustomParagraphNode): CustomParagraphNode { - const node = $createCustomParagraphNode(); - deserializeCommonBlockNode(serializedNode, node); - return node; - } - - static importDOM(): DOMConversionMap|null { - return { - p(node: HTMLElement): DOMConversion|null { - return { - conversion: (element: HTMLElement): DOMConversionOutput|null => { - const node = $createCustomParagraphNode(); - if (element.style.textIndent) { - const indent = parseInt(element.style.textIndent, 10) / 20; - if (indent > 0) { - node.setIndent(indent); - } - } - - setCommonBlockPropsFromElement(element, node); - - return {node}; - }, - priority: 1, - }; - }, - }; - } -} - -export function $createCustomParagraphNode(): CustomParagraphNode { - return new CustomParagraphNode(); -} - -export function $isCustomParagraphNode(node: LexicalNode | null | undefined): node is CustomParagraphNode { - return node instanceof CustomParagraphNode; -} \ No newline at end of file diff --git a/resources/js/wysiwyg/nodes/index.ts b/resources/js/wysiwyg/nodes/index.ts index b5483c500..062394a98 100644 --- a/resources/js/wysiwyg/nodes/index.ts +++ b/resources/js/wysiwyg/nodes/index.ts @@ -7,7 +7,6 @@ import { LexicalNodeReplacement, NodeMutation, ParagraphNode } from "lexical"; -import {CustomParagraphNode} from "./custom-paragraph"; import {LinkNode} from "@lexical/link"; import {ImageNode} from "./image"; import {DetailsNode, SummaryNode} from "./details"; @@ -45,14 +44,8 @@ export function getNodesForPageEditor(): (KlassConstructor | CodeBlockNode, DiagramNode, MediaNode, // TODO - Alignment - CustomParagraphNode, + ParagraphNode, LinkNode, - { - replace: ParagraphNode, - with: (node: ParagraphNode) => { - return new CustomParagraphNode(); - } - }, { replace: HeadingNode, with: (node: HeadingNode) => { diff --git a/resources/js/wysiwyg/services/drop-paste-handling.ts b/resources/js/wysiwyg/services/drop-paste-handling.ts index 07e35d443..e049d5e7c 100644 --- a/resources/js/wysiwyg/services/drop-paste-handling.ts +++ b/resources/js/wysiwyg/services/drop-paste-handling.ts @@ -1,4 +1,5 @@ import { + $createParagraphNode, $insertNodes, $isDecoratorNode, COMMAND_PRIORITY_HIGH, DROP_COMMAND, LexicalEditor, @@ -8,7 +9,6 @@ import {$insertNewBlockNodesAtSelection, $selectSingleNode} from "../utils/selec import {$getNearestBlockNodeForCoords, $htmlToBlockNodes} from "../utils/nodes"; import {Clipboard} from "../../services/clipboard"; import {$createImageNode} from "../nodes/image"; -import {$createCustomParagraphNode} from "../nodes/custom-paragraph"; import {$createLinkNode} from "@lexical/link"; import {EditorImageData, uploadImageFile} from "../utils/images"; import {EditorUiContext} from "../ui/framework/core"; @@ -67,7 +67,7 @@ function handleMediaInsert(data: DataTransfer, context: EditorUiContext): boolea for (const imageFile of images) { const loadingImage = window.baseUrl('/loading.gif'); const loadingNode = $createImageNode(loadingImage); - const imageWrap = $createCustomParagraphNode(); + const imageWrap = $createParagraphNode(); imageWrap.append(loadingNode); $insertNodes([imageWrap]); diff --git a/resources/js/wysiwyg/services/keyboard-handling.ts b/resources/js/wysiwyg/services/keyboard-handling.ts index 2c7bfdbba..3f0b0c495 100644 --- a/resources/js/wysiwyg/services/keyboard-handling.ts +++ b/resources/js/wysiwyg/services/keyboard-handling.ts @@ -1,5 +1,6 @@ import {EditorUiContext} from "../ui/framework/core"; import { + $createParagraphNode, $getSelection, $isDecoratorNode, COMMAND_PRIORITY_LOW, @@ -13,7 +14,6 @@ import {$isImageNode} from "../nodes/image"; import {$isMediaNode} from "../nodes/media"; import {getLastSelection} from "../utils/selection"; import {$getNearestNodeBlockParent} from "../utils/nodes"; -import {$createCustomParagraphNode} from "../nodes/custom-paragraph"; import {$isCustomListItemNode} from "../nodes/custom-list-item"; import {$setInsetForSelection} from "../utils/lists"; @@ -45,7 +45,7 @@ function insertAfterSingleSelectedNode(editor: LexicalEditor, event: KeyboardEve if (nearestBlock) { requestAnimationFrame(() => { editor.update(() => { - const newParagraph = $createCustomParagraphNode(); + const newParagraph = $createParagraphNode(); nearestBlock.insertAfter(newParagraph); newParagraph.select(); }); diff --git a/resources/js/wysiwyg/todo.md b/resources/js/wysiwyg/todo.md index a49cccd26..817a235a7 100644 --- a/resources/js/wysiwyg/todo.md +++ b/resources/js/wysiwyg/todo.md @@ -2,7 +2,11 @@ ## In progress -// +Reorg + - Merge custom nodes into original nodes + - Reduce down to use CommonBlockNode where possible + - Remove existing formatType/ElementFormatType references (replaced with alignment). + - Remove existing indent references (replaced with inset). ## Main Todo diff --git a/resources/js/wysiwyg/utils/formats.ts b/resources/js/wysiwyg/utils/formats.ts index 0ec9220dd..3cfc96442 100644 --- a/resources/js/wysiwyg/utils/formats.ts +++ b/resources/js/wysiwyg/utils/formats.ts @@ -1,5 +1,13 @@ import {$isQuoteNode, HeadingNode, HeadingTagType} from "@lexical/rich-text"; -import {$createTextNode, $getSelection, $insertNodes, LexicalEditor, LexicalNode} from "lexical"; +import { + $createParagraphNode, + $createTextNode, + $getSelection, + $insertNodes, + $isParagraphNode, + LexicalEditor, + LexicalNode +} from "lexical"; import { $getBlockElementNodesInSelection, $getNodeFromSelection, @@ -8,7 +16,6 @@ import { getLastSelection } from "./selection"; import {$createCustomHeadingNode, $isCustomHeadingNode} from "../nodes/custom-heading"; -import {$createCustomParagraphNode, $isCustomParagraphNode} from "../nodes/custom-paragraph"; import {$createCustomQuoteNode} from "../nodes/custom-quote"; import {$createCodeBlockNode, $isCodeBlockNode, $openCodeEditorForNode, CodeBlockNode} from "../nodes/code-block"; import {$createCalloutNode, $isCalloutNode, CalloutCategory} from "../nodes/callout"; @@ -31,7 +38,7 @@ export function toggleSelectionAsHeading(editor: LexicalEditor, tag: HeadingTagT export function toggleSelectionAsParagraph(editor: LexicalEditor) { editor.update(() => { - $toggleSelectionBlockNodeType($isCustomParagraphNode, $createCustomParagraphNode); + $toggleSelectionBlockNodeType($isParagraphNode, $createParagraphNode); }); } diff --git a/resources/js/wysiwyg/utils/nodes.ts b/resources/js/wysiwyg/utils/nodes.ts index 2dd99d369..97634f96b 100644 --- a/resources/js/wysiwyg/utils/nodes.ts +++ b/resources/js/wysiwyg/utils/nodes.ts @@ -1,4 +1,5 @@ import { + $createParagraphNode, $getRoot, $isDecoratorNode, $isElementNode, $isRootNode, @@ -8,7 +9,6 @@ import { LexicalNode } from "lexical"; import {LexicalNodeMatcher} from "../nodes"; -import {$createCustomParagraphNode} from "../nodes/custom-paragraph"; import {$generateNodesFromDOM} from "@lexical/html"; import {htmlToDom} from "./dom"; import {NodeHasAlignment, NodeHasInset} from "../nodes/_common"; @@ -17,7 +17,7 @@ import {$findMatchingParent} from "@lexical/utils"; function wrapTextNodes(nodes: LexicalNode[]): LexicalNode[] { return nodes.map(node => { if ($isTextNode(node)) { - const paragraph = $createCustomParagraphNode(); + const paragraph = $createParagraphNode(); paragraph.append(node); return paragraph; } diff --git a/resources/js/wysiwyg/utils/selection.ts b/resources/js/wysiwyg/utils/selection.ts index 67c2d91b2..02838eba0 100644 --- a/resources/js/wysiwyg/utils/selection.ts +++ b/resources/js/wysiwyg/utils/selection.ts @@ -7,17 +7,15 @@ import { $isTextNode, $setSelection, BaseSelection, DecoratorNode, - ElementFormatType, ElementNode, LexicalEditor, LexicalNode, TextFormatType, TextNode } from "lexical"; -import {$findMatchingParent, $getNearestBlockElementAncestorOrThrow} from "@lexical/utils"; +import {$getNearestBlockElementAncestorOrThrow} from "@lexical/utils"; import {LexicalElementNodeCreator, LexicalNodeMatcher} from "../nodes"; import {$setBlocksType} from "@lexical/selection"; import {$getNearestNodeBlockParent, $getParentOfType, nodeHasAlignment} from "./nodes"; -import {$createCustomParagraphNode} from "../nodes/custom-paragraph"; import {CommonBlockAlignment} from "../nodes/_common"; const lastSelectionByEditor = new WeakMap; @@ -71,7 +69,7 @@ export function $toggleSelectionBlockNodeType(matcher: LexicalNodeMatcher, creat const selection = $getSelection(); const blockElement = selection ? $getNearestBlockElementAncestorOrThrow(selection.getNodes()[0]) : null; if (selection && matcher(blockElement)) { - $setBlocksType(selection, $createCustomParagraphNode); + $setBlocksType(selection, $createParagraphNode); } else { $setBlocksType(selection, creator); }