diff --git a/lib/transforms/at-range.js b/lib/transforms/at-range.js index 62ee84011..229ff0feb 100644 --- a/lib/transforms/at-range.js +++ b/lib/transforms/at-range.js @@ -614,85 +614,50 @@ export function setInlineAtRange(transform, range, properties) { } /** - * Split the block nodes at a `range`, to optional `depth`. + * Split the block nodes at a `range`, to optional `height`. * * @param {Transform} transform * @param {Selection} range - * @param {Number} depth (optional) + * @param {Number} height (optional) * @return {Transform} */ -export function splitBlockAtRange(transform, range, depth = 1) { - let { state } = transform - let { document } = state - - // If the range is expanded, remove it first. +export function splitBlockAtRange(transform, range, height = 1) { if (range.isExpanded) { - transform = deleteAtRange(transform, range) - state = transform.state - document = state.document + transform.deleteAtRange(range) range = range.collapseToStart() } - // Split the inline nodes at the range. - transform = splitInlineAtRange(transform, range) - state = transform.state - document = state.document + const { startKey, startOffset } = range + const { state } = transform + const { document } = state + let node = document.assertDescendant(startKey) + let parent = document.getClosestBlock(node) + let offset = startOffset + let h = 0 - // Find the highest inline elements that were split. - const { startKey } = range - const firstText = document.getDescendant(startKey) - const secondText = document.getNextText(startKey) - let firstChild = document.getFurthestInline(firstText) || firstText - let secondChild = document.getFurthestInline(secondText) || secondText - let parent = document.getClosestBlock(firstChild) - let firstChildren - let secondChildren - let d = 0 - - // While the parent is a block, split the block nodes. - while (parent && d < depth) { - firstChildren = parent.nodes.takeUntil(n => n == firstChild).push(firstChild) - secondChildren = parent.nodes.skipUntil(n => n == secondChild) - firstChild = parent.merge({ nodes: firstChildren }) - secondChild = Block.create({ - nodes: secondChildren, - type: parent.type, - data: parent.data - }) - - // Add the new children. - const grandparent = document.getParent(parent) - const nodes = grandparent.nodes - .takeUntil(n => n.key == firstChild.key) - .push(firstChild) - .push(secondChild) - .concat(grandparent.nodes.skipUntil(n => n.key == firstChild.key).rest()) - - // Update the grandparent. - document = grandparent == document - ? document.merge({ nodes }) - : document.updateDescendant(grandparent.merge({ nodes })) - - d++ - parent = document.getClosestBlock(firstChild) + while (parent && parent.kind == 'block' && h < height) { + offset += parent.getOffset(node) + node = parent + parent = document.getClosestBlock(parent) + h++ } - state = state.merge({ document }) - transform.state = state + transform.splitNodeByKey(node.key, offset) + transform.normalizeDocument() return transform } /** - * Split the inline nodes at a `range`, to optional `depth`. + * Split the inline nodes at a `range`, to optional `height`. * * @param {Transform} transform * @param {Selection} range - * @param {Number} depth (optiona) + * @param {Number} height (optiona) * @return {Transform} */ -export function splitInlineAtRange(transform, range, depth = Infinity) { +export function splitInlineAtRange(transform, range, height = Infinity) { if (range.isExpanded) { transform.deleteAtRange(range) range = range.collapseToStart() @@ -704,19 +669,13 @@ export function splitInlineAtRange(transform, range, depth = Infinity) { let node = document.assertDescendant(startKey) let parent = document.getClosestInline(node) let offset = startOffset - let d = 0 + let h = 0 - debugger - - while (parent && parent.kind == 'inline' && d < depth) { - const index = parent.nodes.indexOf(node) - const befores = parent.nodes.take(index) - const length = befores.reduce((l, n) => n.length, 0) - - offset += length + while (parent && parent.kind == 'inline' && h < height) { + offset += parent.getOffset(node) node = parent parent = document.getClosestInline(parent) - d++ + h++ } return transform.splitNodeByKey(node.key, offset) diff --git a/lib/transforms/by-key.js b/lib/transforms/by-key.js index 436418918..a8eb689e3 100644 --- a/lib/transforms/by-key.js +++ b/lib/transforms/by-key.js @@ -340,9 +340,10 @@ export function splitNodeByKey(transform, key, offset) { while (child && child != parent) { if (child.kind == 'text') { + const i = node.kind == 'text' ? offset : offset - node.getOffset(child) const { characters } = child - const oneChars = characters.take(offset) - const twoChars = characters.skip(offset) + const oneChars = characters.take(i) + const twoChars = characters.skip(i) one = child.merge({ characters: oneChars }) two = child.merge({ characters: twoChars, key: uid() }) } diff --git a/lib/transforms/index.js b/lib/transforms/index.js index c9781bd87..e8243238d 100644 --- a/lib/transforms/index.js +++ b/lib/transforms/index.js @@ -100,6 +100,15 @@ import { moveToRangeOf, } from './on-selection' +/** + * Normalize. + */ + +import { + normalizeDocument, + normalizeSelection, +} from './normalize' + /** * Export. * @@ -201,4 +210,11 @@ export default { moveToOffsets, moveToRangeOf, + /** + * Normalize. + */ + + normalizeDocument, + normalizeSelection, + }