UNPKG

lexical

Version:

Lexical is an extensible text editor framework that provides excellent reliability, accessible and performance.

141 lines (121 loc) 3.43 kB
/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ import type {KlassConstructor} from '../LexicalEditor'; import type { DOMConversionMap, DOMConversionOutput, NodeKey, SerializedLexicalNode, } from '../LexicalNode'; import {LexicalNode} from '../LexicalNode'; import { $applyNodeReplacement, isBlockDomNode, isDOMTextNode, } from '../LexicalUtils'; export type SerializedLineBreakNode = SerializedLexicalNode; /** @noInheritDoc */ export class LineBreakNode extends LexicalNode { /** @internal */ declare ['constructor']: KlassConstructor<typeof LineBreakNode>; static getType(): string { return 'linebreak'; } static clone(node: LineBreakNode): LineBreakNode { return new LineBreakNode(node.__key); } constructor(key?: NodeKey) { super(key); } getTextContent(): '\n' { return '\n'; } createDOM(): HTMLElement { return document.createElement('br'); } updateDOM(): false { return false; } isInline(): true { return true; } static importDOM(): DOMConversionMap | null { return { br: (node: Node) => { if (isOnlyChildInBlockNode(node) || isLastChildInBlockNode(node)) { return null; } return { conversion: $convertLineBreakElement, priority: 0, }; }, }; } static importJSON( serializedLineBreakNode: SerializedLineBreakNode, ): LineBreakNode { return $createLineBreakNode().updateFromJSON(serializedLineBreakNode); } } function $convertLineBreakElement(node: Node): DOMConversionOutput { return {node: $createLineBreakNode()}; } export function $createLineBreakNode(): LineBreakNode { return $applyNodeReplacement(new LineBreakNode()); } export function $isLineBreakNode( node: LexicalNode | null | undefined, ): node is LineBreakNode { return node instanceof LineBreakNode; } function isOnlyChildInBlockNode(node: Node): boolean { const parentElement = node.parentElement; if (parentElement !== null && isBlockDomNode(parentElement)) { const firstChild = parentElement.firstChild!; if ( firstChild === node || (firstChild.nextSibling === node && isWhitespaceDomTextNode(firstChild)) ) { const lastChild = parentElement.lastChild!; if ( lastChild === node || (lastChild.previousSibling === node && isWhitespaceDomTextNode(lastChild)) ) { return true; } } } return false; } function isLastChildInBlockNode(node: Node): boolean { const parentElement = node.parentElement; if (parentElement !== null && isBlockDomNode(parentElement)) { // check if node is first child, because only child dont count const firstChild = parentElement.firstChild!; if ( firstChild === node || (firstChild.nextSibling === node && isWhitespaceDomTextNode(firstChild)) ) { return false; } // check if its last child const lastChild = parentElement.lastChild!; if ( lastChild === node || (lastChild.previousSibling === node && isWhitespaceDomTextNode(lastChild)) ) { return true; } } return false; } function isWhitespaceDomTextNode(node: Node): boolean { return isDOMTextNode(node) && /^( |\t|\r?\n)+$/.test(node.textContent || ''); }