From 6bfaf0872c4ca86da3fefbc36b8105d02daa223d Mon Sep 17 00:00:00 2001 From: Soreine Date: Wed, 9 Nov 2016 12:55:56 +0100 Subject: [PATCH] Add `deep` option to `joinNode` to allow correctly undoing `splitNode` --- src/models/node.js | 10 +++++++++- src/transforms/apply-operation.js | 30 +++++++++++++++++++----------- src/transforms/operations.js | 6 ++++-- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/models/node.js b/src/models/node.js index e528b196e..1585ce957 100644 --- a/src/models/node.js +++ b/src/models/node.js @@ -1137,10 +1137,13 @@ const Node = { * * @param {Node} first * @param {Node} second + * @param {Boolean} options.deep (optional) Join recursively the + * respective last node and first node of the nodes' children. Like a zipper :) * @return {Node} */ - joinNode(first, second) { + joinNode(first, second, options) { + const { deep = false } = options let node = this let parent = node.getParent(second.key) const isParent = node == parent @@ -1157,6 +1160,11 @@ const Node = { second.nodes.forEach((child, i) => { first = first.insertNode(size + i, child) }) + + if (deep) { + // Join recursively + first = first.joinNode(first.nodes.get(size - 1), first.nodes.get(size), { deep }) + } } parent = parent.removeNode(index) diff --git a/src/transforms/apply-operation.js b/src/transforms/apply-operation.js index f288dc8bc..76bb76e7c 100644 --- a/src/transforms/apply-operation.js +++ b/src/transforms/apply-operation.js @@ -132,33 +132,41 @@ function insertText(state, operation) { * * @param {State} state * @param {Object} operation + * @param {Boolean} operation.deep (optional) Join recursively the + * respective last node and first node of the nodes' children. Like a zipper :) * @return {State} */ function joinNode(state, operation) { - const { path, withPath } = operation + const { path, withPath, deep = false } = operation let { document, selection } = state const first = document.assertPath(withPath) const second = document.assertPath(path) // Update doc - document = document.joinNode(first, second) + document = document.joinNode(first, second, { deep }) + + // Update selection if we merged two texts together + if (deep || second.kind == 'text') { + const firstText = deep + ? first.getLastText() + : first + const secondText = deep + ? second.getFirstText() + : second - // Update selection - // When merging two texts together - if (second.kind == 'text') { const { anchorKey, anchorOffset, focusKey, focusOffset } = selection // The final key is the `first` key - if (anchorKey == second.key) { + if (anchorKey == secondText.key) { selection = selection.merge({ - anchorKey: first.key, - anchorOffset: anchorOffset + first.characters.size + anchorKey: firstText.key, + anchorOffset: anchorOffset + firstText.characters.size }) } - if (focusKey == second.key) { + if (focusKey == secondText.key) { selection = selection.merge({ - focusKey: first.key, - focusOffset: focusOffset + first.characters.size + focusKey: firstText.key, + focusOffset: focusOffset + firstText.characters.size }) } } diff --git a/src/transforms/operations.js b/src/transforms/operations.js index 52aa83a17..3fc6c7ec3 100644 --- a/src/transforms/operations.js +++ b/src/transforms/operations.js @@ -445,12 +445,14 @@ export function setSelectionOperation(transform, properties) { */ export function splitNodeOperation(transform, path, offset) { - const inverseIndex = path[path.length - 1] + 1 - const inversePath = path.slice(0, -1).concat([inverseIndex]) + const inversePath = path.slice() + inversePath[path.length - 1] += 1 + const inverse = [{ type: 'join_node', path: inversePath, withPath: path, + deep: true // we need to join nodes recursively }] const operation = {