Skip to content
This repository has been archived by the owner on Feb 6, 2023. It is now read-only.

Commit

Permalink
Unnest the first non-leaf child
Browse files Browse the repository at this point in the history
Summary:
We don't want to leave behind doubly nested children if their preceding block is untabbed. Here we iterate to make sure that the next block is never left with a non-leaf first child.

Diagram of this operation, also implemented in the test below:
https://pxl.cl/hs20

Reviewed By: vdurmont

Differential Revision: D9826012

fbshipit-source-id: 1c14c5091ce89ddee3e80b2a7e9eef9d4759c320
  • Loading branch information
niveditc authored and facebook-github-bot committed Sep 14, 2018
1 parent 77e6844 commit 0cb3804
Show file tree
Hide file tree
Showing 3 changed files with 203 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/model/modifier/exploration/NestedRichTextEditorUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,27 @@ const NestedRichTextEditorUtil: RichTextUtils = {
);
blockMap = DraftTreeOperations.moveChildUp(blockMap, key);
}

// on untab, we also want to unnest any sibling blocks that become two levels deep
// ensure that block's old parent does not have a non-leaf as its first child.
if (parentKey != null) {
let parent = blockMap.get(parentKey);
while (parent != null) {
const children = parent.getChildKeys();
const firstChildKey = children.first();
invariant(
firstChildKey != null,
'parent must have at least one child',
);
const firstChild = blockMap.get(firstChildKey);
if (firstChild.getChildKeys().count() === 0) {
break;
} else {
blockMap = DraftTreeOperations.moveChildUp(blockMap, firstChildKey);
parent = blockMap.get(parentKey);
}
}
}
}
content = editorState.getCurrentContent().merge({
blockMap: blockMap,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,66 @@ test('onTab (untab) on a middle child splits the block at that child', () => {
);
});

const contentBlockNodes4 = [
new ContentBlockNode({
key: 'A',
parent: null,
text: 'alpha',
children: Immutable.List([]),
prevSibling: null,
nextSibling: 'X',
type: 'ordered-list-item',
}),
new ContentBlockNode({
key: 'X',
parent: null,
text: '',
children: Immutable.List(['B', 'Y']),
prevSibling: 'A',
nextSibling: null,
type: 'ordered-list-item',
}),
new ContentBlockNode({
key: 'B',
parent: 'X',
text: 'beta',
children: Immutable.List([]),
prevSibling: null,
nextSibling: 'Y',
type: 'ordered-list-item',
}),
new ContentBlockNode({
key: 'Y',
parent: 'X',
text: '',
children: Immutable.List(['C']),
prevSibling: 'B',
nextSibling: null,
type: 'ordered-list-item',
}),
new ContentBlockNode({
key: 'C',
parent: 'Y',
text: 'charlie',
children: Immutable.List([]),
prevSibling: null,
nextSibling: null,
type: 'ordered-list-item',
}),
];

test('onTab (untab) unnests non-leaf next sibling', () => {
assertNestedUtilOperation(
editorState =>
onTab({preventDefault: () => {}, shiftKey: true}, editorState, 2),
{
anchorKey: 'B',
focusKey: 'B',
},
contentBlockNodes4,
);
});

// TODO (T32099101)
test('onSplitParent must split a nested block retaining parent', () => {
expect(true).toBe(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1903,6 +1903,128 @@ Object {
}
`;

exports[`onTab (untab) unnests non-leaf next sibling 1`] = `
Object {
"A": Object {
"characterList": Array [
Object {
"entity": null,
"style": Array [],
},
Object {
"entity": null,
"style": Array [],
},
Object {
"entity": null,
"style": Array [],
},
Object {
"entity": null,
"style": Array [],
},
Object {
"entity": null,
"style": Array [],
},
],
"children": Array [],
"data": Object {},
"depth": 0,
"key": "A",
"nextSibling": "B",
"parent": null,
"prevSibling": null,
"text": "alpha",
"type": "ordered-list-item",
},
"B": Object {
"characterList": Array [
Object {
"entity": null,
"style": Array [],
},
Object {
"entity": null,
"style": Array [],
},
Object {
"entity": null,
"style": Array [],
},
Object {
"entity": null,
"style": Array [],
},
],
"children": Array [],
"data": Object {},
"depth": 0,
"key": "B",
"nextSibling": "Y",
"parent": null,
"prevSibling": "A",
"text": "beta",
"type": "ordered-list-item",
},
"C": Object {
"characterList": Array [
Object {
"entity": null,
"style": Array [],
},
Object {
"entity": null,
"style": Array [],
},
Object {
"entity": null,
"style": Array [],
},
Object {
"entity": null,
"style": Array [],
},
Object {
"entity": null,
"style": Array [],
},
Object {
"entity": null,
"style": Array [],
},
Object {
"entity": null,
"style": Array [],
},
],
"children": Array [],
"data": Object {},
"depth": 0,
"key": "C",
"nextSibling": null,
"parent": "Y",
"prevSibling": null,
"text": "charlie",
"type": "ordered-list-item",
},
"Y": Object {
"characterList": Array [],
"children": Array [
"C",
],
"data": Object {},
"depth": 0,
"key": "Y",
"nextSibling": null,
"parent": null,
"prevSibling": "B",
"text": "",
"type": "ordered-list-item",
},
}
`;

exports[`onTab when siblings are at the same depth creates a new parent 1`] = `
Object {
"A": Object {
Expand Down

0 comments on commit 0cb3804

Please sign in to comment.