Lexical: Fixed formatting on reverse selection ranges in lists

Block formatting on range selection could break when made from bottom to
top, due to using the first selected for insertion position instead of
the first in the doc structure.
This commit is contained in:
Dan Brown
2026-09-05 18:15:57 +01:00
parent e573d2458b
commit 9b56295dfd
2 changed files with 10 additions and 6 deletions
+7 -3
View File
@@ -122,7 +122,12 @@ export function $getNearestNodeBlockParent(node: LexicalNode): LexicalNode|null
return $findMatchingParent(node, isBlockNode);
}
export function $sortNodes(nodes: LexicalNode[]): LexicalNode[] {
/**
* Sort the given node array by their position in the document.
* A search point can be provided to limit the search to a specific part of the document, which can
* avoid having to traverse the entire document.
*/
export function $sortNodes(nodes: LexicalNode[], searchPoint: ElementNode|null = null): LexicalNode[] {
const idChain: string[] = [];
const addIds = (n: ElementNode) => {
for (const child of n.getChildren()) {
@@ -133,8 +138,7 @@ export function $sortNodes(nodes: LexicalNode[]): LexicalNode[] {
}
};
const root = $getRoot();
addIds(root);
addIds(searchPoint || $getRoot());
const sorted = Array.from(nodes);
sorted.sort((a, b) => {
+3 -3
View File
@@ -15,7 +15,7 @@ import {$getNearestBlockElementAncestorOrThrow} from "@lexical/utils";
import {LexicalElementNodeCreator, LexicalNodeMatcher} from "../nodes";
import {$setBlocksType} from "@lexical/selection";
import {$getNearestNodeBlockParent, $getParentOfType, nodeHasAlignment} from "./nodes";
import {$getNearestNodeBlockParent, $getParentOfType, $sortNodes, nodeHasAlignment} from "./nodes";
import {CommonBlockAlignment} from "lexical/nodes/common";
import {$isListItemNode} from "@lexical/list";
import {$createCollapsedRangeSelectionForNode} from "lexical/LexicalSelection";
@@ -90,8 +90,8 @@ function createNewBlockIfSelectionIsSingleListItemText(selection: BaseSelection)
if (isSingleListItemTextSelection) {
const wrapper = $createParagraphNode();
const startNode = startEnd[0].getNode();
startNode.insertBefore(wrapper);
const firstNode = $sortNodes([startEnd[0].getNode(), startEnd[1].getNode()], startBlock)[0];
firstNode.insertBefore(wrapper);
wrapper.append(...selection.getNodes());
}
}