1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-26 08:34:28 +02:00

handle lots of splitting cases

This commit is contained in:
Ian Storm Taylor
2016-10-14 16:40:45 -07:00
parent dfe52446e7
commit fa5d59c063
9 changed files with 129 additions and 36 deletions

View File

@@ -53,6 +53,10 @@ class Inline extends new Record(DEFAULTS) {
properties.isVoid = !!properties.isVoid
properties.nodes = Inline.createList(properties.nodes)
if (properties.nodes.size == 0) {
properties.nodes = properties.nodes.push(Text.create())
}
return new Inline(properties).normalize()
}

View File

@@ -436,18 +436,38 @@ export function splitBlock(transform, depth = 1) {
export function splitInline(transform, depth = Infinity) {
let { state } = transform
let { document, selection } = state
// If the selection is expanded, remove it first.
if (selection.isExpanded) {
transform.delete()
state = transform.state
document = state.document
selection = state.selection
}
let after = selection
const { startKey, startOffset } = selection
let startNode = document.assertDescendant(startKey)
const furthestInline = document.getFurthestInline(startKey)
const offset = furthestInline.getOffset(startNode)
// If the selection is at the start of end of the furthest inline, there isn't
// anything to split, so abort.
if (
(offset + startOffset == 0) ||
(offset + startNode.length == startOffset)
) {
return transform
}
transform.unsetSelection()
transform.splitInlineAtRange(selection, depth)
state = transform.state
document = state.document
const closestInline = document.getClosestInline(startKey)
const { startKey } = selection
const inlineParent = document.getClosestInline(startKey)
if (inlineParent) {
const startNode = document.getDescendant(startKey)
if (closestInline) {
startNode = document.getDescendant(startKey)
const nextNode = document.getNextText(startNode)
after = selection.collapseToStartOf(nextNode)
}

View File

@@ -268,7 +268,6 @@ export function insertBlockAtRange(transform, range, block) {
transform.insertNodeByKey(parent.key, index + 1, block)
}
transform.normalizeDocument()
return transform
}
@@ -385,7 +384,6 @@ export function insertInlineAtRange(transform, range, inline) {
transform.splitNodeByKey(startKey, startOffset)
transform.insertNodeByKey(parent.key, index + 1, inline)
transform.normalizeDocument()
return transform
}
@@ -818,15 +816,25 @@ export function wrapInlineAtRange(transform, range, inline) {
: endChild.getOffset(endKey) + endOffset
if (startBlock == endBlock) {
transform.splitNodeByKey(endChild.key, endOff)
transform.splitNodeByKey(startChild.key, startOff)
if (endOff != endChild.length) {
transform.splitNodeByKey(endChild.key, endOff)
}
if (startOff != 0) {
transform.splitNodeByKey(startChild.key, startOff)
}
state = transform.state
document = state.document
startBlock = document.getClosestBlock(startKey)
startChild = startBlock.getHighestChild(startKey)
const startInner = document.getNextSibling(startChild)
const startInner = startOff == 0
? startChild
: document.getNextSibling(startChild)
const startInnerIndex = startBlock.nodes.indexOf(startInner)
const endInner = startKey == endKey ? startInner : startBlock.getHighestChild(endKey)
const inlines = startBlock.nodes
.skipUntil(n => n == startInner)
@@ -877,7 +885,6 @@ export function wrapInlineAtRange(transform, range, inline) {
})
}
transform.normalizeDocument()
return transform
}

View File

@@ -308,7 +308,7 @@ export function setNodeByKey(transform, key, properties) {
}
// If the `isVoid` property is being changed to `false` and the node is an
// inline node, remove any additional unnecessary text it.
// inline node, remove any additional unnecessary text around it.
if (
properties.isVoid == false &&
node.isVoid == true &&
@@ -344,8 +344,90 @@ export function setNodeByKey(transform, key, properties) {
*/
export function splitNodeByKey(transform, key, offset) {
const { state } = transform
const { document } = state
let { state } = transform
let { document } = state
const path = document.getPath(key)
return transform.splitNodeOperation(path, offset)
transform.splitNodeOperation(path, offset)
// Traverse the nodes on both sides of the split, ensuring that there are no
// empty inline nodes, or empty text nodes that should be removed.
state = transform.state
document = state.document
const parent = document.getParent(key)
// Define an iterator that will apply normalization transforms.
parent.filterDescendants((d) => {
// We don't need to do any normalization for block nodes.
if (d.kind == 'block') {
return
}
// If an inline void node has no text, add a space character.
if (
d.kind == 'inline' &&
d.text == '' &&
d.isVoid == true
) {
transform.insertTextByKey(d.key, 0, ' ')
}
// If an non-void inline node has no text now, remove it.
if (
d.kind == 'inline' &&
d.text == '' &&
d.isVoid == false
) {
transform.removeNodeByKey(d.key)
}
// Check to ensure that extra empty text nodes are preserved around inline
// void nodes.
if (
d.kind == 'inline' &&
d.isVoid == true
) {
const previous = document.getPreviousSibling(d)
const next = document.getNextSibling(d)
if (
(!previous) ||
(previous.kind == 'block' || previous.kind == 'inline' && previous.isVoid)
) {
const p = document.getParent(d)
const index = p.nodes.indexOf(d)
const text = Text.create()
transform.insertNodeByKey(p, index, text)
}
if (
(!next) ||
(next.kind == 'block' || next.kind == 'inline' && next.isVoid)
) {
const p = document.getParent(d)
const index = p.nodes.indexOf(d)
const text = Text.create()
transform.insertNodeByKey(p, index + 1, text)
}
}
// If an empty text node is adjacent to an non-void inline node, remove it.
if (
d.kind == 'text' &&
d.text == ''
) {
const previous = document.getPreviousSibling(d)
const next = document.getNextSibling(d)
if (
(previous && previous.kind == 'inline' && previous.isVoid == false) ||
(next && next.kind == 'inline' && next.isVoid == false)
) {
transform.removeNodeByKey(d.key)
}
}
})
// Return the transform.
return transform
}

View File

@@ -22,7 +22,7 @@ export default function (state) {
assert.deepEqual(
next.selection.toJS(),
range.collapseToStartOf(updated).toJS()
range.collapseToEndOf(updated).toJS()
)
return next

View File

@@ -8,8 +8,3 @@ nodes:
nodes:
- kind: text
text: word
- kind: inline
type: link
nodes:
- kind: text
text: ""

View File

@@ -3,11 +3,6 @@ nodes:
- kind: block
type: paragraph
nodes:
- kind: inline
type: link
nodes:
- kind: text
text: ""
- kind: inline
type: link
nodes:

View File

@@ -8,8 +8,3 @@ nodes:
nodes:
- kind: text
text: word
- kind: inline
type: link
nodes:
- kind: text
text: ""

View File

@@ -3,11 +3,6 @@ nodes:
- kind: block
type: paragraph
nodes:
- kind: inline
type: link
nodes:
- kind: text
text: ""
- kind: inline
type: link
nodes: