mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-09 08:46:35 +02:00
add split inline with tests
This commit is contained in:
@@ -237,10 +237,7 @@ const Node = {
|
|||||||
getBlocksAtRange(range) {
|
getBlocksAtRange(range) {
|
||||||
range = range.normalize(this)
|
range = range.normalize(this)
|
||||||
const texts = this.getTextsAtRange(range)
|
const texts = this.getTextsAtRange(range)
|
||||||
const blocks = texts.map((text) => {
|
const blocks = texts.map(text => this.getClosestBlock(text))
|
||||||
return this.getClosest(text, p => p.kind == 'block')
|
|
||||||
})
|
|
||||||
|
|
||||||
return blocks
|
return blocks
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -266,23 +263,80 @@ const Node = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get closest parent of `node` that matches `iterator`.
|
* Get closest parent of node by `key` that matches `iterator`.
|
||||||
*
|
*
|
||||||
* @param {Node} node
|
* @param {String or Node} key
|
||||||
* @param {Function} iterator
|
* @param {Function} iterator
|
||||||
* @return {Node or Null} node
|
* @return {Node or Null} parent
|
||||||
*/
|
*/
|
||||||
|
|
||||||
getClosest(node, iterator) {
|
getClosest(key, iterator) {
|
||||||
while (node) {
|
key = normalizeKey(key)
|
||||||
|
this.assertHasDeep(key)
|
||||||
|
|
||||||
|
let node = this.getDeep(key)
|
||||||
|
|
||||||
|
while (node = this.getParent(node)) {
|
||||||
if (node == this) return null
|
if (node == this) return null
|
||||||
if (iterator(node)) return node
|
if (iterator(node)) return node
|
||||||
node = this.getParent(node)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the closest block parent of a `node`.
|
||||||
|
*
|
||||||
|
* @param {String or Node} key
|
||||||
|
* @return {Node or Null} parent
|
||||||
|
*/
|
||||||
|
|
||||||
|
getClosestBlock(key) {
|
||||||
|
key = normalizeKey(key)
|
||||||
|
this.assertHasDeep(key)
|
||||||
|
|
||||||
|
const match = this.getClosest(key, parent => parent.kind == 'block')
|
||||||
|
return match
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the closest inline parent of a `node`.
|
||||||
|
*
|
||||||
|
* @param {String or Node} key
|
||||||
|
* @return {Node or Null} parent
|
||||||
|
*/
|
||||||
|
|
||||||
|
getClosestInline(key) {
|
||||||
|
key = normalizeKey(key)
|
||||||
|
this.assertHasDeep(key)
|
||||||
|
|
||||||
|
const match = this.getClosest(key, parent => parent.kind == 'inline')
|
||||||
|
return match
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the furthest inline parent of a node by `key`.
|
||||||
|
*
|
||||||
|
* @param {String or Node} key
|
||||||
|
* @return {Node or Null} parent
|
||||||
|
*/
|
||||||
|
|
||||||
|
getFurthestInline(key) {
|
||||||
|
key = normalizeKey(key)
|
||||||
|
this.assertHasDeep(key)
|
||||||
|
|
||||||
|
let child = this.getDeep(key)
|
||||||
|
let furthest = null
|
||||||
|
let next
|
||||||
|
|
||||||
|
while (next = this.getClosestInline(child)) {
|
||||||
|
furthest = next
|
||||||
|
child = next
|
||||||
|
}
|
||||||
|
|
||||||
|
return furthest
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a child node by `key`.
|
* Get a child node by `key`.
|
||||||
*
|
*
|
||||||
@@ -306,6 +360,8 @@ const Node = {
|
|||||||
|
|
||||||
getDepth(key, startAt = 1) {
|
getDepth(key, startAt = 1) {
|
||||||
key = normalizeKey(key)
|
key = normalizeKey(key)
|
||||||
|
this.assertHasDeep(key)
|
||||||
|
|
||||||
if (this.nodes.has(key)) return startAt
|
if (this.nodes.has(key)) return startAt
|
||||||
|
|
||||||
const child = this.nodes.find(node => {
|
const child = this.nodes.find(node => {
|
||||||
@@ -407,6 +463,7 @@ const Node = {
|
|||||||
|
|
||||||
getNextSibling(key) {
|
getNextSibling(key) {
|
||||||
key = normalizeKey(key)
|
key = normalizeKey(key)
|
||||||
|
this.assertHasDeep(key)
|
||||||
|
|
||||||
if (this.nodes.has(key)) {
|
if (this.nodes.has(key)) {
|
||||||
return this.nodes
|
return this.nodes
|
||||||
@@ -430,6 +487,8 @@ const Node = {
|
|||||||
|
|
||||||
getNextText(key) {
|
getNextText(key) {
|
||||||
key = normalizeKey(key)
|
key = normalizeKey(key)
|
||||||
|
this.assertHasDeep(key)
|
||||||
|
|
||||||
return this.getTextNodes()
|
return this.getTextNodes()
|
||||||
.skipUntil(text => text.key == key)
|
.skipUntil(text => text.key == key)
|
||||||
.take(2)
|
.take(2)
|
||||||
@@ -444,7 +503,9 @@ const Node = {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
getOffset(key) {
|
getOffset(key) {
|
||||||
|
key = normalizeKey(key)
|
||||||
this.assertHasDeep(key)
|
this.assertHasDeep(key)
|
||||||
|
|
||||||
const match = this.getDeep(key)
|
const match = this.getDeep(key)
|
||||||
|
|
||||||
// Find the shallow matching child.
|
// Find the shallow matching child.
|
||||||
@@ -479,8 +540,9 @@ const Node = {
|
|||||||
|
|
||||||
getParent(key) {
|
getParent(key) {
|
||||||
key = normalizeKey(key)
|
key = normalizeKey(key)
|
||||||
|
// this.assertHasDeep(key)
|
||||||
|
|
||||||
if (this.nodes.get(key)) return this
|
if (this.nodes.has(key)) return this
|
||||||
|
|
||||||
let node = null
|
let node = null
|
||||||
this.nodes.forEach((child) => {
|
this.nodes.forEach((child) => {
|
||||||
@@ -501,6 +563,7 @@ const Node = {
|
|||||||
|
|
||||||
getPreviousSibling(key) {
|
getPreviousSibling(key) {
|
||||||
key = normalizeKey(key)
|
key = normalizeKey(key)
|
||||||
|
this.assertHasDeep(key)
|
||||||
|
|
||||||
if (this.nodes.has(key)) {
|
if (this.nodes.has(key)) {
|
||||||
return this.nodes
|
return this.nodes
|
||||||
@@ -523,6 +586,8 @@ const Node = {
|
|||||||
|
|
||||||
getPreviousText(key) {
|
getPreviousText(key) {
|
||||||
key = normalizeKey(key)
|
key = normalizeKey(key)
|
||||||
|
this.assertHasDeep(key)
|
||||||
|
|
||||||
return this.getTextNodes()
|
return this.getTextNodes()
|
||||||
.takeUntil(text => text.key == key)
|
.takeUntil(text => text.key == key)
|
||||||
.last()
|
.last()
|
||||||
@@ -596,6 +661,7 @@ const Node = {
|
|||||||
|
|
||||||
hasDeep(key) {
|
hasDeep(key) {
|
||||||
key = normalizeKey(key)
|
key = normalizeKey(key)
|
||||||
|
|
||||||
return !! this.nodes.find((node) => {
|
return !! this.nodes.find((node) => {
|
||||||
return node.kind == 'text'
|
return node.kind == 'text'
|
||||||
? node.key == key
|
? node.key == key
|
||||||
@@ -762,6 +828,7 @@ const Node = {
|
|||||||
|
|
||||||
removeDeep(key) {
|
removeDeep(key) {
|
||||||
key = normalizeKey(key)
|
key = normalizeKey(key)
|
||||||
|
this.assertHasDeep(key)
|
||||||
|
|
||||||
let nodes = this.nodes.remove(key)
|
let nodes = this.nodes.remove(key)
|
||||||
return this.merge({ nodes })
|
return this.merge({ nodes })
|
||||||
@@ -854,52 +921,134 @@ const Node = {
|
|||||||
range = range.moveToStart()
|
range = range.moveToStart()
|
||||||
}
|
}
|
||||||
|
|
||||||
const { startKey, startOffset } = range
|
// Split the inline nodes at the range.
|
||||||
const startNode = node.getDeep(startKey)
|
node = node.splitInlineAtRange(range)
|
||||||
|
|
||||||
// Split the text node's characters.
|
// Find the highest inline elements that were split.
|
||||||
const { characters, length } = startNode
|
const { startKey } = range
|
||||||
const firstCharacters = characters.take(startOffset)
|
const firstText = node.getDeep(startKey)
|
||||||
const secondCharacters = characters.takeLast(length - startOffset)
|
const firstChild = node.getFurthestInline(firstText) || firstText
|
||||||
|
const secondText = node.getNextText(startKey)
|
||||||
|
const secondChild = node.getFurthestInline(secondText) || secondText
|
||||||
|
|
||||||
// Create a new first element with only the first set of characters.
|
// Remove the second inline child from the first block.
|
||||||
const parent = node.getParent(startNode)
|
let firstBlock = node.getBlocksAtRange(range).first()
|
||||||
const firstText = startNode.set('characters', firstCharacters)
|
firstBlock = firstBlock.removeDeep(secondChild)
|
||||||
const firstElement = parent.updateDeep(firstText)
|
|
||||||
|
|
||||||
// Create a brand new second element with the second set of characters.
|
// Create a new block with the second inline child in it.
|
||||||
let secondText = Text.create({})
|
const secondBlock = Block.create({
|
||||||
let secondElement = Block.create({
|
type: firstBlock.type,
|
||||||
type: firstElement.type,
|
data: firstBlock.data,
|
||||||
data: firstElement.data
|
nodes: Block.createMap([secondChild])
|
||||||
})
|
})
|
||||||
|
|
||||||
secondText = secondText.set('characters', secondCharacters)
|
// Replace the block in the parent with the two new blocks.
|
||||||
secondElement = secondElement.merge({
|
let parent = node.getParent(firstBlock)
|
||||||
nodes: secondElement.nodes.set(secondText.key, secondText)
|
const nodes = parent.nodes.takeUntil(n => n.key == firstBlock.key)
|
||||||
});
|
.set(firstBlock.key, firstBlock)
|
||||||
|
.set(secondBlock.key, secondBlock)
|
||||||
|
.concat(parent.nodes.skipUntil(n => n.key == firstBlock.key).rest())
|
||||||
|
|
||||||
// Replace the old parent node in the grandparent with the two new ones.
|
// If the node is the parent, just merge, otherwise deep merge.
|
||||||
let grandparent = node.getParent(parent)
|
if (parent == node) {
|
||||||
const befores = grandparent.nodes.takeUntil(child => child.key == parent.key)
|
|
||||||
const afters = grandparent.nodes.skipUntil(child => child.key == parent.key).rest()
|
|
||||||
const nodes = befores
|
|
||||||
.set(firstElement.key, firstElement)
|
|
||||||
.set(secondElement.key, secondElement)
|
|
||||||
.concat(afters)
|
|
||||||
|
|
||||||
// If the node is the grandparent, just merge, otherwise deep merge.
|
|
||||||
if (grandparent == node) {
|
|
||||||
node = node.merge({ nodes })
|
node = node.merge({ nodes })
|
||||||
} else {
|
} else {
|
||||||
grandparent = grandparent.merge({ nodes })
|
parent = parent.merge({ nodes })
|
||||||
node = node.updateDeep(grandparent)
|
node = node.updateDeep(parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize the node.
|
// Normalize the node.
|
||||||
return node.normalize()
|
return node.normalize()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
splitInlineAtRange(range) {
|
||||||
|
debugger
|
||||||
|
range = range.normalize(this)
|
||||||
|
const Inline = require('./inline').default
|
||||||
|
let node = this
|
||||||
|
|
||||||
|
// If the range is expanded, remove it first.
|
||||||
|
if (range.isExpanded) {
|
||||||
|
node = node.deleteAtRange(range)
|
||||||
|
range = range.moveToStart()
|
||||||
|
}
|
||||||
|
|
||||||
|
// First split the text nodes.
|
||||||
|
node = node.splitTextAtRange(range)
|
||||||
|
let firstChild = node.getDeep(range.startKey)
|
||||||
|
let secondChild = node.getNextText(firstChild)
|
||||||
|
let parent
|
||||||
|
|
||||||
|
// While the parent is an inline parent, split the inline nodes.
|
||||||
|
while (parent = node.getClosestInline(firstChild)) {
|
||||||
|
debugger
|
||||||
|
const firstNodes = Inline.createMap([firstChild])
|
||||||
|
const secondNodes = Inline.createMap([secondChild])
|
||||||
|
firstChild = parent.merge({ nodes: firstNodes })
|
||||||
|
secondChild = Inline.create({
|
||||||
|
nodes: secondNodes,
|
||||||
|
type: parent.type,
|
||||||
|
data: parent.data
|
||||||
|
})
|
||||||
|
|
||||||
|
// Split the children.
|
||||||
|
const isGrandparent = node.nodes.has(parent.key)
|
||||||
|
const grandparent = isGrandparent ? node : node.getParent(parent)
|
||||||
|
const nodes = grandparent.nodes
|
||||||
|
.takeUntil(c => c.key == firstChild.key)
|
||||||
|
.set(firstChild.key, firstChild)
|
||||||
|
.set(secondChild.key, secondChild)
|
||||||
|
.concat(grandparent.nodes.skipUntil(n => n.key == firstChild.key).rest())
|
||||||
|
|
||||||
|
// Update the grandparent.
|
||||||
|
node = isGrandparent
|
||||||
|
? node.merge({ nodes })
|
||||||
|
: node.updateDeep(grandparent.merge({ nodes }))
|
||||||
|
}
|
||||||
|
|
||||||
|
return node
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Split the text nodes at a `range`.
|
||||||
|
*
|
||||||
|
* @param {Selection} range
|
||||||
|
* @return {Node} node
|
||||||
|
*/
|
||||||
|
|
||||||
|
splitTextAtRange(range) {
|
||||||
|
range = range.normalize(this)
|
||||||
|
let node = this
|
||||||
|
|
||||||
|
// If the range is expanded, remove it first.
|
||||||
|
if (range.isExpanded) {
|
||||||
|
node = node.deleteAtRange(range)
|
||||||
|
range = range.moveToStart()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split the text node's characters.
|
||||||
|
const { startKey, startOffset } = range
|
||||||
|
const text = node.getDeep(startKey)
|
||||||
|
const { characters } = text
|
||||||
|
const firstChars = characters.take(startOffset)
|
||||||
|
const secondChars = characters.skip(startOffset)
|
||||||
|
let firstChild = text.merge({ characters: firstChars })
|
||||||
|
let secondChild = Text.create({ characters: secondChars })
|
||||||
|
|
||||||
|
// Split the text nodes.
|
||||||
|
let parent = node.getParent(text)
|
||||||
|
const nodes = parent.nodes
|
||||||
|
.takeUntil(c => c.key == firstChild.key)
|
||||||
|
.set(firstChild.key, firstChild)
|
||||||
|
.set(secondChild.key, secondChild)
|
||||||
|
.concat(parent.nodes.skipUntil(n => n.key == firstChild.key).rest())
|
||||||
|
|
||||||
|
// Update the nodes.
|
||||||
|
parent = parent.merge({ nodes })
|
||||||
|
node = node.updateDeep(parent)
|
||||||
|
return node
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove an existing `mark` to the characters at `range`.
|
* Remove an existing `mark` to the characters at `range`.
|
||||||
*
|
*
|
||||||
@@ -957,6 +1106,8 @@ const Node = {
|
|||||||
key = normalizeKey(key)
|
key = normalizeKey(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this.assertHasDeep(key)
|
||||||
|
|
||||||
if (this.nodes.get(key)) {
|
if (this.nodes.get(key)) {
|
||||||
const nodes = this.nodes.set(key, node)
|
const nodes = this.nodes.set(key, node)
|
||||||
return this.set('nodes', nodes)
|
return this.set('nodes', nodes)
|
||||||
@@ -1091,105 +1242,6 @@ const Node = {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
getClosestInline(child) {
|
|
||||||
return this.getClosest(child, p => p.kind == 'inline')
|
|
||||||
},
|
|
||||||
|
|
||||||
getFurthestInline(child) {
|
|
||||||
let furthest = null
|
|
||||||
let next
|
|
||||||
|
|
||||||
while (next = this.getClosestInline(child)) {
|
|
||||||
furthest = next
|
|
||||||
child = next
|
|
||||||
}
|
|
||||||
|
|
||||||
return furthest
|
|
||||||
},
|
|
||||||
|
|
||||||
splitTextAtRange(range) {
|
|
||||||
range = range.normalize(this)
|
|
||||||
let node = this
|
|
||||||
|
|
||||||
// If the range is expanded, remove it first.
|
|
||||||
if (range.isExpanded) {
|
|
||||||
node = node.deleteAtRange(range)
|
|
||||||
range = range.moveToStart()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split the text node's characters.
|
|
||||||
const { startKey, startOffset } = range
|
|
||||||
const text = node.getDeep(startKey)
|
|
||||||
const { characters } = text
|
|
||||||
const firstChars = characters.take(startOffset)
|
|
||||||
const secondChars = characters.skip(startOffset)
|
|
||||||
let firstChild = text.merge({ characters: firstChars })
|
|
||||||
let secondChild = Text.create({ characters: secondChars })
|
|
||||||
|
|
||||||
// Split the text nodes.
|
|
||||||
let parent = node.getParent(text)
|
|
||||||
const nodes = parent.nodes
|
|
||||||
.takeUntil(c => c.key == firstChild.key)
|
|
||||||
.set(firstChild.key, firstChild)
|
|
||||||
.set(secondChild.key, secondChild)
|
|
||||||
.concat(parent.nodes.skipUntil(n => n.key == firstChild.key).rest())
|
|
||||||
|
|
||||||
// Update the nodes.
|
|
||||||
parent = parent.merge({ nodes })
|
|
||||||
node = node.updateDeep(parent)
|
|
||||||
return node
|
|
||||||
},
|
|
||||||
|
|
||||||
splitInlineAtRange(range) {
|
|
||||||
range = range.normalize(this)
|
|
||||||
const Inline = require('./inline').default
|
|
||||||
let node = this
|
|
||||||
|
|
||||||
// If the range is expanded, remove it first.
|
|
||||||
if (range.isExpanded) {
|
|
||||||
node = node.deleteAtRange(range)
|
|
||||||
range = range.moveToStart()
|
|
||||||
}
|
|
||||||
|
|
||||||
// First split the text nodes.
|
|
||||||
node = node.splitTextAtRange(range)
|
|
||||||
let firstChild = node.getDeep(range.startKey)
|
|
||||||
let secondChild = node.getNextText(firstChild)
|
|
||||||
let parent
|
|
||||||
|
|
||||||
// While the parent is an inline parent, split the inline nodes.
|
|
||||||
while (parent = node.getClosestInline(firstChild)) {
|
|
||||||
const firstNodes = Inline.createMap([firstChild])
|
|
||||||
const secondNodes = Inline.createMap([secondChild])
|
|
||||||
firstChild = parent.merge({ nodes: firstNodes })
|
|
||||||
secondChild = Inline.create({
|
|
||||||
nodes: secondNodes,
|
|
||||||
type: parent.type,
|
|
||||||
data: parent.data
|
|
||||||
})
|
|
||||||
|
|
||||||
// Split the children.
|
|
||||||
const isGrandparent = node.nodes.has(parent.key)
|
|
||||||
const grandparent = isGrandparent ? node : node.getParent(parent)
|
|
||||||
const nodes = grandparent.nodes
|
|
||||||
.takeUntil(c => c.key == firstChild.key)
|
|
||||||
.set(firstChild.key, firstChild)
|
|
||||||
.set(secondChild.key, secondChild)
|
|
||||||
.concat(parent.nodes.skipUntil(n => n.key == firstChild.key).rest())
|
|
||||||
|
|
||||||
// Update the parent.
|
|
||||||
node = isGrandparent
|
|
||||||
? node.merge({ nodes })
|
|
||||||
: node.updateDeep(parent.merge({ nodes }))
|
|
||||||
}
|
|
||||||
|
|
||||||
return node
|
|
||||||
},
|
|
||||||
|
|
||||||
wrapInlineAtRange(range, type, data = new Map()) {
|
wrapInlineAtRange(range, type, data = new Map()) {
|
||||||
range = range.normalize(this)
|
range = range.normalize(this)
|
||||||
|
|
||||||
|
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
export default function (state) {
|
||||||
|
const { document, selection } = state
|
||||||
|
const texts = document.getTextNodes()
|
||||||
|
const first = texts.first()
|
||||||
|
const range = selection.merge({
|
||||||
|
anchorKey: first.key,
|
||||||
|
anchorOffset: 2,
|
||||||
|
focusKey: first.key,
|
||||||
|
focusOffset: 2
|
||||||
|
})
|
||||||
|
|
||||||
|
return state
|
||||||
|
.transform()
|
||||||
|
.splitBlockAtRange(range)
|
||||||
|
.apply()
|
||||||
|
}
|
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: word
|
@@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: wo
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: rd
|
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
export default function (state) {
|
||||||
|
const { document, selection } = state
|
||||||
|
const texts = document.getTextNodes()
|
||||||
|
const first = texts.first()
|
||||||
|
const range = selection.merge({
|
||||||
|
anchorKey: first.key,
|
||||||
|
anchorOffset: first.length,
|
||||||
|
focusKey: first.key,
|
||||||
|
focusOffset: first.length
|
||||||
|
})
|
||||||
|
|
||||||
|
return state
|
||||||
|
.transform()
|
||||||
|
.splitInlineAtRange(range)
|
||||||
|
.apply()
|
||||||
|
}
|
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: word
|
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: word
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: ""
|
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
export default function (state) {
|
||||||
|
const { document, selection } = state
|
||||||
|
const texts = document.getTextNodes()
|
||||||
|
const first = texts.first()
|
||||||
|
const range = selection.merge({
|
||||||
|
anchorKey: first.key,
|
||||||
|
anchorOffset: 2,
|
||||||
|
focusKey: first.key,
|
||||||
|
focusOffset: 2
|
||||||
|
})
|
||||||
|
|
||||||
|
return state
|
||||||
|
.transform()
|
||||||
|
.splitInlineAtRange(range)
|
||||||
|
.apply()
|
||||||
|
}
|
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: word
|
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: wo
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: rd
|
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
export default function (state) {
|
||||||
|
const { document, selection } = state
|
||||||
|
const texts = document.getTextNodes()
|
||||||
|
const first = texts.first()
|
||||||
|
const range = selection.merge({
|
||||||
|
anchorKey: first.key,
|
||||||
|
anchorOffset: 0,
|
||||||
|
focusKey: first.key,
|
||||||
|
focusOffset: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
return state
|
||||||
|
.transform()
|
||||||
|
.splitInlineAtRange(range)
|
||||||
|
.apply()
|
||||||
|
}
|
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: word
|
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: ""
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: word
|
@@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
export default function (state) {
|
||||||
|
const { document, selection } = state
|
||||||
|
const texts = document.getTextNodes()
|
||||||
|
const first = texts.first()
|
||||||
|
const second = texts.last()
|
||||||
|
const range = selection.merge({
|
||||||
|
anchorKey: first.key,
|
||||||
|
anchorOffset: 2,
|
||||||
|
focusKey: second.key,
|
||||||
|
focusOffset: 2
|
||||||
|
})
|
||||||
|
|
||||||
|
return state
|
||||||
|
.transform()
|
||||||
|
.splitInlineAtRange(range)
|
||||||
|
.apply()
|
||||||
|
}
|
@@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: word
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: another
|
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: wo
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: other
|
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
export default function (state) {
|
||||||
|
const { document, selection } = state
|
||||||
|
const texts = document.getTextNodes()
|
||||||
|
const first = texts.first()
|
||||||
|
const range = selection.merge({
|
||||||
|
anchorKey: first.key,
|
||||||
|
anchorOffset: 1,
|
||||||
|
focusKey: first.key,
|
||||||
|
focusOffset: 3
|
||||||
|
})
|
||||||
|
|
||||||
|
return state
|
||||||
|
.transform()
|
||||||
|
.splitInlineAtRange(range)
|
||||||
|
.apply()
|
||||||
|
}
|
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: word
|
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: w
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: d
|
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
export default function (state) {
|
||||||
|
const { document, selection } = state
|
||||||
|
const texts = document.getTextNodes()
|
||||||
|
const first = texts.first()
|
||||||
|
const range = selection.merge({
|
||||||
|
anchorKey: first.key,
|
||||||
|
anchorOffset: 2,
|
||||||
|
focusKey: first.key,
|
||||||
|
focusOffset: 2
|
||||||
|
})
|
||||||
|
|
||||||
|
return state
|
||||||
|
.transform()
|
||||||
|
.splitInlineAtRange(range)
|
||||||
|
.apply()
|
||||||
|
}
|
@@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: word
|
||||||
|
marks:
|
||||||
|
- type: bold
|
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: wo
|
||||||
|
marks:
|
||||||
|
- type: bold
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
ranges:
|
||||||
|
- text: rd
|
||||||
|
marks:
|
||||||
|
- type: bold
|
Reference in New Issue
Block a user