mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-26 16:44:22 +02:00
handle lots of splitting cases
This commit is contained in:
@@ -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()
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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) {
|
||||
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
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ export default function (state) {
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
range.collapseToStartOf(updated).toJS()
|
||||
range.collapseToEndOf(updated).toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
|
@@ -8,8 +8,3 @@ nodes:
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word
|
||||
- kind: inline
|
||||
type: link
|
||||
nodes:
|
||||
- kind: text
|
||||
text: ""
|
||||
|
@@ -3,11 +3,6 @@ nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: inline
|
||||
type: link
|
||||
nodes:
|
||||
- kind: text
|
||||
text: ""
|
||||
- kind: inline
|
||||
type: link
|
||||
nodes:
|
||||
|
@@ -8,8 +8,3 @@ nodes:
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word
|
||||
- kind: inline
|
||||
type: link
|
||||
nodes:
|
||||
- kind: text
|
||||
text: ""
|
||||
|
@@ -3,11 +3,6 @@ nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: inline
|
||||
type: link
|
||||
nodes:
|
||||
- kind: text
|
||||
text: ""
|
||||
- kind: inline
|
||||
type: link
|
||||
nodes:
|
||||
|
Reference in New Issue
Block a user