mirror of
https://github.com/facebook/lexical.git
synced 2025-08-26 02:39:24 +08:00
A basic $dfs (#1351)
This commit is contained in:
@ -11,13 +11,17 @@ import type {LexicalNode} from 'lexical';
|
|||||||
|
|
||||||
import {$getRoot, $isElementNode, $isLineBreakNode, $isTextNode} from 'lexical';
|
import {$getRoot, $isElementNode, $isLineBreakNode, $isTextNode} from 'lexical';
|
||||||
|
|
||||||
export function $dfs__DEPRECATED(
|
export function $dfs(
|
||||||
startingNode: LexicalNode,
|
startingNode?: LexicalNode,
|
||||||
nextNode: (LexicalNode) => null | LexicalNode,
|
endingNode?: LexicalNode,
|
||||||
): void {
|
): Array<LexicalNode> {
|
||||||
let node = startingNode;
|
const nodes = [];
|
||||||
nextNode(node);
|
const start = (startingNode || $getRoot()).getLatest();
|
||||||
while (node !== null) {
|
const end =
|
||||||
|
endingNode || ($isElementNode(start) ? start.getLastDescendant() : start);
|
||||||
|
let node = start;
|
||||||
|
while (node !== null && !node.is(end)) {
|
||||||
|
nodes.push(node);
|
||||||
if ($isElementNode(node) && node.getChildrenSize() > 0) {
|
if ($isElementNode(node) && node.getChildrenSize() > 0) {
|
||||||
node = node.getFirstChild();
|
node = node.getFirstChild();
|
||||||
} else {
|
} else {
|
||||||
@ -32,10 +36,11 @@ export function $dfs__DEPRECATED(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (node !== null) {
|
|
||||||
node = nextNode(node);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (node !== null && node.is(end)) {
|
||||||
|
nodes.push(node);
|
||||||
|
}
|
||||||
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function $getNearestNodeOfType<T: LexicalNode>(
|
export function $getNearestNodeOfType<T: LexicalNode>(
|
||||||
|
@ -7,25 +7,26 @@
|
|||||||
* @flow strict
|
* @flow strict
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type {LexicalEditor, LexicalNode, NodeKey, State} from 'lexical';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
$areSiblingsNullOrSpace,
|
$areSiblingsNullOrSpace,
|
||||||
$dfs__DEPRECATED,
|
|
||||||
$getNearestNodeOfType,
|
$getNearestNodeOfType,
|
||||||
} from '@lexical/helpers/nodes';
|
} from '@lexical/helpers/nodes';
|
||||||
import {$createListItemNode, $createListNode, ListNode} from '@lexical/list';
|
import {$createListItemNode, $createListNode, ListNode} from '@lexical/list';
|
||||||
import {
|
import {
|
||||||
$createParagraphNode,
|
$createParagraphNode,
|
||||||
$createTextNode,
|
$createTextNode,
|
||||||
|
$getNodeByKey,
|
||||||
$getRoot,
|
$getRoot,
|
||||||
$isParagraphNode,
|
LexicalEditor,
|
||||||
|
NodeKey,
|
||||||
|
State,
|
||||||
} from 'lexical';
|
} from 'lexical';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
$createTestElementNode,
|
$createTestElementNode,
|
||||||
initializeUnitTest,
|
initializeUnitTest,
|
||||||
} from '../../../../lexical/src/__tests__/utils';
|
} from '../../../../lexical/src/__tests__/utils';
|
||||||
|
import {$dfs} from '../../LexicalNodeHelpers';
|
||||||
|
|
||||||
describe('LexicalNodeHelpers tests', () => {
|
describe('LexicalNodeHelpers tests', () => {
|
||||||
initializeUnitTest((testEnv) => {
|
initializeUnitTest((testEnv) => {
|
||||||
@ -78,47 +79,57 @@ describe('LexicalNodeHelpers tests', () => {
|
|||||||
text6.getKey(),
|
text6.getKey(),
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
editor.getEditorState().read(() => {
|
||||||
const dfsKeys = [];
|
const expectedNodes = expectedKeys.map((nodeKey) =>
|
||||||
await editor.update((state: State) => {
|
$getNodeByKey(nodeKey).getLatest(),
|
||||||
const root = $getRoot();
|
);
|
||||||
$dfs__DEPRECATED(root, (node: LexicalNode) => {
|
const first = expectedNodes[0];
|
||||||
dfsKeys.push(node.getKey());
|
const second = expectedNodes[1];
|
||||||
return node;
|
const last = expectedNodes[expectedNodes.length - 1];
|
||||||
});
|
const secondToLast = expectedNodes[expectedNodes.length - 2];
|
||||||
|
expect($dfs(first, last)).toEqual(expectedNodes);
|
||||||
|
expect($dfs(second, secondToLast)).toEqual(
|
||||||
|
expectedNodes.slice(1, expectedKeys.length - 1),
|
||||||
|
);
|
||||||
|
expect($dfs()).toEqual(expectedNodes);
|
||||||
|
expect($dfs($getRoot())).toEqual(expectedNodes);
|
||||||
});
|
});
|
||||||
expect(dfsKeys).toEqual(expectedKeys);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Skip some DFS nodes', async () => {
|
test('DFS triggers getLatest()', async () => {
|
||||||
const editor: LexicalEditor = testEnv.editor;
|
const editor: LexicalEditor = testEnv.editor;
|
||||||
let expectedKeys: Array<NodeKey> = [];
|
let rootKey;
|
||||||
await editor.update((state: State) => {
|
let paragraphKey;
|
||||||
|
let block1Key;
|
||||||
|
let block2Key;
|
||||||
|
await editor.update(() => {
|
||||||
const root = $getRoot();
|
const root = $getRoot();
|
||||||
const paragraph1 = $createParagraphNode();
|
const paragraph = $createParagraphNode();
|
||||||
const block1 = $createTestElementNode();
|
const block1 = $createTestElementNode();
|
||||||
const block2 = $createTestElementNode();
|
const block2 = $createTestElementNode();
|
||||||
|
rootKey = root.getKey();
|
||||||
|
paragraphKey = paragraph.getKey();
|
||||||
|
block1Key = block1.getKey();
|
||||||
|
block2Key = block2.getKey();
|
||||||
|
root.append(paragraph);
|
||||||
|
paragraph.append(block1, block2);
|
||||||
|
});
|
||||||
|
await editor.update(() => {
|
||||||
|
const root = $getNodeByKey(rootKey);
|
||||||
|
const paragraph = $getNodeByKey(paragraphKey);
|
||||||
|
const block1 = $getNodeByKey(block1Key);
|
||||||
|
const block2 = $getNodeByKey(block2Key);
|
||||||
const block3 = $createTestElementNode();
|
const block3 = $createTestElementNode();
|
||||||
root.append(paragraph1);
|
block1.append(block3);
|
||||||
paragraph1.append(block1, block2, block3);
|
|
||||||
|
|
||||||
expectedKeys = [root.getKey(), paragraph1.getKey(), block3.getKey()];
|
expect($dfs(root)).toEqual([
|
||||||
|
root.getLatest(),
|
||||||
|
paragraph.getLatest(),
|
||||||
|
block1.getLatest(),
|
||||||
|
block3.getLatest(),
|
||||||
|
block2.getLatest(),
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
const dfsKeys = [];
|
|
||||||
await editor.update((state: State) => {
|
|
||||||
const root = $getRoot();
|
|
||||||
$dfs__DEPRECATED(root, (node: LexicalNode) => {
|
|
||||||
dfsKeys.push(node.getKey());
|
|
||||||
if ($isParagraphNode(node)) {
|
|
||||||
return (
|
|
||||||
node.getLastChild() && node.getLastChild().getPreviousSibling()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
expect(dfsKeys).toEqual(expectedKeys);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('getNearestNodeOfType should return the top node if it is of the given type.', async () => {
|
test('getNearestNodeOfType should return the top node if it is of the given type.', async () => {
|
||||||
|
@ -9,11 +9,10 @@
|
|||||||
|
|
||||||
import type {LexicalEditor, LexicalNode} from 'lexical';
|
import type {LexicalEditor, LexicalNode} from 'lexical';
|
||||||
|
|
||||||
import {$dfs__DEPRECATED} from '@lexical/helpers/nodes';
|
import {$dfs} from '@lexical/helpers/nodes';
|
||||||
import {$textContentCurry} from '@lexical/helpers/root';
|
import {$textContentCurry} from '@lexical/helpers/root';
|
||||||
import withSubscriptions from '@lexical/react/withSubscriptions';
|
import withSubscriptions from '@lexical/react/withSubscriptions';
|
||||||
import {
|
import {
|
||||||
$getRoot,
|
|
||||||
$getSelection,
|
$getSelection,
|
||||||
$isLeafNode,
|
$isLeafNode,
|
||||||
$isRangeSelection,
|
$isRangeSelection,
|
||||||
@ -127,15 +126,10 @@ function findOffset(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function $wrapOverflowedNodes(offset: number): void {
|
function $wrapOverflowedNodes(offset: number): void {
|
||||||
const root = $getRoot();
|
const dfsNodes = $dfs();
|
||||||
|
const dfsNodesLength = dfsNodes.length;
|
||||||
let accumulatedLength = 0;
|
let accumulatedLength = 0;
|
||||||
|
for (let i = 0; i < dfsNodesLength; i += 1) {
|
||||||
const dfsNodes = [];
|
|
||||||
$dfs__DEPRECATED(root, (node: LexicalNode) => {
|
|
||||||
dfsNodes.push(node);
|
|
||||||
return node;
|
|
||||||
});
|
|
||||||
for (let i = 0; i < dfsNodes.length; i += 1) {
|
|
||||||
const node = dfsNodes[i];
|
const node = dfsNodes[i];
|
||||||
if ($isOverflowNode(node)) {
|
if ($isOverflowNode(node)) {
|
||||||
const previousLength = accumulatedLength;
|
const previousLength = accumulatedLength;
|
||||||
|
Reference in New Issue
Block a user