1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-17 20:51:20 +02:00

refactor more transforms

This commit is contained in:
Ian Storm Taylor
2016-08-17 01:41:37 -07:00
parent 1d4c6db4d4
commit 3ad03538fd
3 changed files with 44 additions and 68 deletions

View File

@@ -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 {Transform} transform
* @param {Selection} range * @param {Selection} range
* @param {Number} depth (optional) * @param {Number} height (optional)
* @return {Transform} * @return {Transform}
*/ */
export function splitBlockAtRange(transform, range, depth = 1) { export function splitBlockAtRange(transform, range, height = 1) {
let { state } = transform
let { document } = state
// If the range is expanded, remove it first.
if (range.isExpanded) { if (range.isExpanded) {
transform = deleteAtRange(transform, range) transform.deleteAtRange(range)
state = transform.state
document = state.document
range = range.collapseToStart() range = range.collapseToStart()
} }
// Split the inline nodes at the range. const { startKey, startOffset } = range
transform = splitInlineAtRange(transform, range) const { state } = transform
state = transform.state const { document } = state
document = state.document let node = document.assertDescendant(startKey)
let parent = document.getClosestBlock(node)
let offset = startOffset
let h = 0
// Find the highest inline elements that were split. while (parent && parent.kind == 'block' && h < height) {
const { startKey } = range offset += parent.getOffset(node)
const firstText = document.getDescendant(startKey) node = parent
const secondText = document.getNextText(startKey) parent = document.getClosestBlock(parent)
let firstChild = document.getFurthestInline(firstText) || firstText h++
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)
} }
state = state.merge({ document }) transform.splitNodeByKey(node.key, offset)
transform.state = state transform.normalizeDocument()
return transform 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 {Transform} transform
* @param {Selection} range * @param {Selection} range
* @param {Number} depth (optiona) * @param {Number} height (optiona)
* @return {Transform} * @return {Transform}
*/ */
export function splitInlineAtRange(transform, range, depth = Infinity) { export function splitInlineAtRange(transform, range, height = Infinity) {
if (range.isExpanded) { if (range.isExpanded) {
transform.deleteAtRange(range) transform.deleteAtRange(range)
range = range.collapseToStart() range = range.collapseToStart()
@@ -704,19 +669,13 @@ export function splitInlineAtRange(transform, range, depth = Infinity) {
let node = document.assertDescendant(startKey) let node = document.assertDescendant(startKey)
let parent = document.getClosestInline(node) let parent = document.getClosestInline(node)
let offset = startOffset let offset = startOffset
let d = 0 let h = 0
debugger while (parent && parent.kind == 'inline' && h < height) {
offset += parent.getOffset(node)
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
node = parent node = parent
parent = document.getClosestInline(parent) parent = document.getClosestInline(parent)
d++ h++
} }
return transform.splitNodeByKey(node.key, offset) return transform.splitNodeByKey(node.key, offset)

View File

@@ -340,9 +340,10 @@ export function splitNodeByKey(transform, key, offset) {
while (child && child != parent) { while (child && child != parent) {
if (child.kind == 'text') { if (child.kind == 'text') {
const i = node.kind == 'text' ? offset : offset - node.getOffset(child)
const { characters } = child const { characters } = child
const oneChars = characters.take(offset) const oneChars = characters.take(i)
const twoChars = characters.skip(offset) const twoChars = characters.skip(i)
one = child.merge({ characters: oneChars }) one = child.merge({ characters: oneChars })
two = child.merge({ characters: twoChars, key: uid() }) two = child.merge({ characters: twoChars, key: uid() })
} }

View File

@@ -100,6 +100,15 @@ import {
moveToRangeOf, moveToRangeOf,
} from './on-selection' } from './on-selection'
/**
* Normalize.
*/
import {
normalizeDocument,
normalizeSelection,
} from './normalize'
/** /**
* Export. * Export.
* *
@@ -201,4 +210,11 @@ export default {
moveToOffsets, moveToOffsets,
moveToRangeOf, moveToRangeOf,
/**
* Normalize.
*/
normalizeDocument,
normalizeSelection,
} }