mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-16 12:14:14 +02:00
Merge PR #354
This commit is contained in:
@@ -53,6 +53,10 @@ class Block extends new Record(DEFAULTS) {
|
|||||||
properties.isVoid = !!properties.isVoid
|
properties.isVoid = !!properties.isVoid
|
||||||
properties.nodes = Block.createList(properties.nodes)
|
properties.nodes = Block.createList(properties.nodes)
|
||||||
|
|
||||||
|
if (properties.nodes.size == 0) {
|
||||||
|
properties.nodes = properties.nodes.push(Text.create())
|
||||||
|
}
|
||||||
|
|
||||||
return new Block(properties)
|
return new Block(properties)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -53,6 +53,10 @@ class Inline extends new Record(DEFAULTS) {
|
|||||||
properties.isVoid = !!properties.isVoid
|
properties.isVoid = !!properties.isVoid
|
||||||
properties.nodes = Inline.createList(properties.nodes)
|
properties.nodes = Inline.createList(properties.nodes)
|
||||||
|
|
||||||
|
if (properties.nodes.size == 0) {
|
||||||
|
properties.nodes = properties.nodes.push(Text.create())
|
||||||
|
}
|
||||||
|
|
||||||
return new Inline(properties)
|
return new Inline(properties)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -942,6 +942,24 @@ const Node = {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
insertNode(index, node) {
|
insertNode(index, node) {
|
||||||
|
let keys = new Set([ this.key ])
|
||||||
|
|
||||||
|
this.findDescendant((desc) => {
|
||||||
|
keys = keys.add(desc.key)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (keys.contains(node.key)) {
|
||||||
|
node = node.regenerateKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.kind != 'text') {
|
||||||
|
node = node.mapDescendants((desc) => {
|
||||||
|
return keys.contains(desc.key)
|
||||||
|
? desc.regenerateKey()
|
||||||
|
: desc
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const nodes = this.nodes.splice(index, 0, node)
|
const nodes = this.nodes.splice(index, 0, node)
|
||||||
return this.merge({ nodes })
|
return this.merge({ nodes })
|
||||||
},
|
},
|
||||||
@@ -1040,6 +1058,16 @@ const Node = {
|
|||||||
return this.merge({ nodes })
|
return this.merge({ nodes })
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regenerate the node's key.
|
||||||
|
*
|
||||||
|
* @return {Node} node
|
||||||
|
*/
|
||||||
|
|
||||||
|
regenerateKey() {
|
||||||
|
return this.merge({ key: uid() })
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a `node` from the children node map.
|
* Remove a `node` from the children node map.
|
||||||
*
|
*
|
||||||
|
@@ -34,7 +34,7 @@ class Text extends new Record(DEFAULTS) {
|
|||||||
* Create a new `Text` with `properties`.
|
* Create a new `Text` with `properties`.
|
||||||
*
|
*
|
||||||
* @param {Object} properties
|
* @param {Object} properties
|
||||||
* @return {Text} text
|
* @return {Text}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static create(properties = {}) {
|
static create(properties = {}) {
|
||||||
@@ -223,7 +223,7 @@ class Text extends new Record(DEFAULTS) {
|
|||||||
* @param {Numbder} index
|
* @param {Numbder} index
|
||||||
* @param {String} text
|
* @param {String} text
|
||||||
* @param {String} marks (optional)
|
* @param {String} marks (optional)
|
||||||
* @return {Text} text
|
* @return {Text}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
insertText(index, text, marks) {
|
insertText(index, text, marks) {
|
||||||
@@ -238,6 +238,16 @@ class Text extends new Record(DEFAULTS) {
|
|||||||
return this.merge({ characters })
|
return this.merge({ characters })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regenerate the node's key.
|
||||||
|
*
|
||||||
|
* @return {Text}
|
||||||
|
*/
|
||||||
|
|
||||||
|
regenerateKey() {
|
||||||
|
return this.merge({ key: uid() })
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a `mark` at `index` and `length`.
|
* Remove a `mark` at `index` and `length`.
|
||||||
*
|
*
|
||||||
@@ -265,7 +275,7 @@ class Text extends new Record(DEFAULTS) {
|
|||||||
*
|
*
|
||||||
* @param {Number} index
|
* @param {Number} index
|
||||||
* @param {Number} length
|
* @param {Number} length
|
||||||
* @return {Text} text
|
* @return {Text}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
removeText(index, length) {
|
removeText(index, length) {
|
||||||
|
@@ -90,8 +90,7 @@ function insertNode(state, operation) {
|
|||||||
let { document } = state
|
let { document } = state
|
||||||
let parent = document.assertPath(path)
|
let parent = document.assertPath(path)
|
||||||
const isParent = document == parent
|
const isParent = document == parent
|
||||||
const nodes = parent.nodes.splice(index, 0, node)
|
parent = parent.insertNode(index, node)
|
||||||
parent = parent.merge({ nodes })
|
|
||||||
document = isParent ? parent : document.updateDescendant(parent)
|
document = isParent ? parent : document.updateDescendant(parent)
|
||||||
state = state.merge({ document })
|
state = state.merge({ document })
|
||||||
return state
|
return state
|
||||||
@@ -212,7 +211,6 @@ function removeText(state, operation) {
|
|||||||
let node = document.assertPath(path)
|
let node = document.assertPath(path)
|
||||||
node = node.removeText(offset, length)
|
node = node.removeText(offset, length)
|
||||||
document = document.updateDescendant(node)
|
document = document.updateDescendant(node)
|
||||||
document = document.normalize()
|
|
||||||
state = state.merge({ document })
|
state = state.merge({ document })
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
@@ -249,7 +247,6 @@ function setNode(state, operation) {
|
|||||||
let node = document.assertPath(path)
|
let node = document.assertPath(path)
|
||||||
node = node.merge(properties)
|
node = node.merge(properties)
|
||||||
document = document.updateDescendant(node)
|
document = document.updateDescendant(node)
|
||||||
document = document.normalize()
|
|
||||||
state = state.merge({ document })
|
state = state.merge({ document })
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
@@ -436,18 +436,38 @@ export function splitBlock(transform, depth = 1) {
|
|||||||
export function splitInline(transform, depth = Infinity) {
|
export function splitInline(transform, depth = Infinity) {
|
||||||
let { state } = transform
|
let { state } = transform
|
||||||
let { document, selection } = state
|
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
|
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.unsetSelection()
|
||||||
transform.splitInlineAtRange(selection, depth)
|
transform.splitInlineAtRange(selection, depth)
|
||||||
state = transform.state
|
state = transform.state
|
||||||
document = state.document
|
document = state.document
|
||||||
|
const closestInline = document.getClosestInline(startKey)
|
||||||
|
|
||||||
const { startKey } = selection
|
if (closestInline) {
|
||||||
const inlineParent = document.getClosestInline(startKey)
|
startNode = document.getDescendant(startKey)
|
||||||
|
|
||||||
if (inlineParent) {
|
|
||||||
const startNode = document.getDescendant(startKey)
|
|
||||||
const nextNode = document.getNextText(startNode)
|
const nextNode = document.getNextText(startNode)
|
||||||
after = selection.collapseToStartOf(nextNode)
|
after = selection.collapseToStartOf(nextNode)
|
||||||
}
|
}
|
||||||
|
@@ -95,6 +95,7 @@ export function deleteAtRange(transform, range) {
|
|||||||
const lonely = document.getFurthest(endBlock, p => p.nodes.size == 1) || endBlock
|
const lonely = document.getFurthest(endBlock, p => p.nodes.size == 1) || endBlock
|
||||||
transform.removeNodeByKey(lonely.key)
|
transform.removeNodeByKey(lonely.key)
|
||||||
transform.normalize()
|
transform.normalize()
|
||||||
|
|
||||||
return transform
|
return transform
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,6 +271,7 @@ export function insertBlockAtRange(transform, range, block) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
transform.normalize()
|
transform.normalize()
|
||||||
|
|
||||||
return transform
|
return transform
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,7 +322,9 @@ export function insertFragmentAtRange(transform, range, fragment) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (startOffset != 0) {
|
||||||
transform.splitNodeByKey(startChild.key, offset)
|
transform.splitNodeByKey(startChild.key, offset)
|
||||||
|
}
|
||||||
|
|
||||||
state = transform.state
|
state = transform.state
|
||||||
document = state.document
|
document = state.document
|
||||||
@@ -347,12 +351,14 @@ export function insertFragmentAtRange(transform, range, fragment) {
|
|||||||
const inlineIndex = startBlock.nodes.indexOf(inlineChild)
|
const inlineIndex = startBlock.nodes.indexOf(inlineChild)
|
||||||
|
|
||||||
firstBlock.nodes.forEach((inline, i) => {
|
firstBlock.nodes.forEach((inline, i) => {
|
||||||
const newIndex = inlineIndex + i + 1
|
const o = startOffset == 0 ? 0 : 1
|
||||||
|
const newIndex = inlineIndex + i + o
|
||||||
transform.insertNodeByKey(startBlock.key, newIndex, inline)
|
transform.insertNodeByKey(startBlock.key, newIndex, inline)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
transform.normalize()
|
transform.normalize()
|
||||||
|
|
||||||
return transform
|
return transform
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,6 +393,7 @@ export function insertInlineAtRange(transform, range, inline) {
|
|||||||
transform.splitNodeByKey(startKey, startOffset)
|
transform.splitNodeByKey(startKey, startOffset)
|
||||||
transform.insertNodeByKey(parent.key, index + 1, inline)
|
transform.insertNodeByKey(parent.key, index + 1, inline)
|
||||||
transform.normalize()
|
transform.normalize()
|
||||||
|
|
||||||
return transform
|
return transform
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -524,6 +531,7 @@ export function splitBlockAtRange(transform, range, height = 1) {
|
|||||||
|
|
||||||
transform.splitNodeByKey(node.key, offset)
|
transform.splitNodeByKey(node.key, offset)
|
||||||
transform.normalize()
|
transform.normalize()
|
||||||
|
|
||||||
return transform
|
return transform
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,6 +681,7 @@ export function unwrapBlockAtRange(transform, range, properties) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
transform.normalize()
|
transform.normalize()
|
||||||
|
|
||||||
return transform
|
return transform
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -715,6 +724,7 @@ export function unwrapInlineAtRange(transform, range, properties) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
transform.normalize()
|
transform.normalize()
|
||||||
|
|
||||||
return transform
|
return transform
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -729,6 +739,7 @@ export function unwrapInlineAtRange(transform, range, properties) {
|
|||||||
|
|
||||||
export function wrapBlockAtRange(transform, range, block) {
|
export function wrapBlockAtRange(transform, range, block) {
|
||||||
block = Normalize.block(block)
|
block = Normalize.block(block)
|
||||||
|
block = block.merge({ nodes: block.nodes.clear() })
|
||||||
|
|
||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { document } = state
|
const { document } = state
|
||||||
@@ -799,6 +810,7 @@ export function wrapInlineAtRange(transform, range, inline) {
|
|||||||
if (range.isCollapsed) return transform
|
if (range.isCollapsed) return transform
|
||||||
|
|
||||||
inline = Normalize.inline(inline)
|
inline = Normalize.inline(inline)
|
||||||
|
inline = inline.merge({ nodes: inline.nodes.clear() })
|
||||||
|
|
||||||
const { startKey, startOffset, endKey, endOffset } = range
|
const { startKey, startOffset, endKey, endOffset } = range
|
||||||
let { state } = transform
|
let { state } = transform
|
||||||
@@ -820,15 +832,25 @@ export function wrapInlineAtRange(transform, range, inline) {
|
|||||||
: endChild.getOffset(endKey) + endOffset
|
: endChild.getOffset(endKey) + endOffset
|
||||||
|
|
||||||
if (startBlock == endBlock) {
|
if (startBlock == endBlock) {
|
||||||
|
if (endOff != endChild.length) {
|
||||||
transform.splitNodeByKey(endChild.key, endOff)
|
transform.splitNodeByKey(endChild.key, endOff)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startOff != 0) {
|
||||||
transform.splitNodeByKey(startChild.key, startOff)
|
transform.splitNodeByKey(startChild.key, startOff)
|
||||||
|
}
|
||||||
|
|
||||||
state = transform.state
|
state = transform.state
|
||||||
document = state.document
|
document = state.document
|
||||||
startBlock = document.getClosestBlock(startKey)
|
startBlock = document.getClosestBlock(startKey)
|
||||||
startChild = startBlock.getHighestChild(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 startInnerIndex = startBlock.nodes.indexOf(startInner)
|
||||||
|
|
||||||
const endInner = startKey == endKey ? startInner : startBlock.getHighestChild(endKey)
|
const endInner = startKey == endKey ? startInner : startBlock.getHighestChild(endKey)
|
||||||
const inlines = startBlock.nodes
|
const inlines = startBlock.nodes
|
||||||
.skipUntil(n => n == startInner)
|
.skipUntil(n => n == startInner)
|
||||||
@@ -880,6 +902,7 @@ export function wrapInlineAtRange(transform, range, inline) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
transform.normalize()
|
transform.normalize()
|
||||||
|
|
||||||
return transform
|
return transform
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -37,7 +37,42 @@ export function insertNodeByKey(transform, key, index, node) {
|
|||||||
const { document } = state
|
const { document } = state
|
||||||
const path = document.getPath(key)
|
const path = document.getPath(key)
|
||||||
const newPath = path.slice().push(index)
|
const newPath = path.slice().push(index)
|
||||||
return transform.insertNodeOperation(path, index, node)
|
|
||||||
|
transform.insertNodeOperation(path, index, node)
|
||||||
|
|
||||||
|
// If the node is an inline void, the parent is a block, and the node will be
|
||||||
|
// inserted at the block's edge, we need to add surrounding text nodes.
|
||||||
|
if (node.kind == 'inline' && node.isVoid) {
|
||||||
|
const parent = document.assertDescendant(key)
|
||||||
|
|
||||||
|
if (index == 0) {
|
||||||
|
const text = Text.create()
|
||||||
|
transform.insertNodeByKey(key, index, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == parent.nodes.size) {
|
||||||
|
const text = Text.create()
|
||||||
|
transform.insertNodeByKey(key, index + 1, text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the node is a text node, and it is insert next to a text node, it should
|
||||||
|
// be joined with it.
|
||||||
|
if (node.kind == 'text') {
|
||||||
|
const parent = document.assertDescendant(key)
|
||||||
|
const previous = index == 0 ? null : parent.nodes.get(index - 1)
|
||||||
|
const next = parent.nodes.get(index)
|
||||||
|
|
||||||
|
if (next && next.kind == 'text') {
|
||||||
|
transform.joinNodeByKey(next.key, node.key)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous && previous.kind == 'text') {
|
||||||
|
transform.joinNodeByKey(node.key, previous.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return transform
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,6 +93,23 @@ export function insertTextByKey(transform, key, offset, text, marks) {
|
|||||||
return transform.insertTextOperation(path, offset, text, marks)
|
return transform.insertTextOperation(path, offset, text, marks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join a node by `key` with a node `withKey`.
|
||||||
|
*
|
||||||
|
* @param {Transform} transform
|
||||||
|
* @param {String} key
|
||||||
|
* @param {String} withKey
|
||||||
|
* @return {Transform}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function joinNodeByKey(transform, key, withKey) {
|
||||||
|
const { state } = transform
|
||||||
|
const { document } = state
|
||||||
|
const path = document.getPath(key)
|
||||||
|
const withPath = document.getPath(withKey)
|
||||||
|
return transform.joinNodeOperation(path, withPath)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move a node by `key` to a new parent by `key` and `index`.
|
* Move a node by `key` to a new parent by `key` and `index`.
|
||||||
*
|
*
|
||||||
@@ -71,9 +123,39 @@ export function insertTextByKey(transform, key, offset, text, marks) {
|
|||||||
export function moveNodeByKey(transform, key, newKey, newIndex) {
|
export function moveNodeByKey(transform, key, newKey, newIndex) {
|
||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { document } = state
|
const { document } = state
|
||||||
|
const node = document.assertDescendant(key)
|
||||||
|
const prevParent = document.getParent(key)
|
||||||
const path = document.getPath(key)
|
const path = document.getPath(key)
|
||||||
const newPath = document.getPath(newKey)
|
const newPath = document.getPath(newKey)
|
||||||
return transform.moveNodeOperation(path, newPath, newIndex)
|
const parent = document.key == newKey ? document : document.assertDescendant(newKey)
|
||||||
|
const previous = newIndex == 0 ? null : parent.nodes.get(newIndex - 1)
|
||||||
|
const next = parent.nodes.get(newIndex)
|
||||||
|
transform.moveNodeOperation(path, newPath, newIndex)
|
||||||
|
|
||||||
|
// If the node to move is a text node, and it will be moved adjacent to
|
||||||
|
// another text node, join them together.
|
||||||
|
if (node.kind == 'text') {
|
||||||
|
if (next && next.kind == 'text') {
|
||||||
|
transform.joinNodeByKey(next.key, node.key)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous && previous.kind == 'text') {
|
||||||
|
transform.joinNodeByKey(node.key, previous.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the node to be moved is the last child of its parent, then create a new
|
||||||
|
// empty text node in its place.
|
||||||
|
if (prevParent.nodes.size == 1) {
|
||||||
|
if (prevParent.kind == 'block') {
|
||||||
|
const text = Text.create()
|
||||||
|
transform.insertNodeByKey(prevParent.key, 0, text)
|
||||||
|
} else {
|
||||||
|
transform.removeNodeByKey(prevParent.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return transform
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,21 +187,29 @@ export function removeMarkByKey(transform, key, offset, length, mark) {
|
|||||||
|
|
||||||
export function removeNodeByKey(transform, key) {
|
export function removeNodeByKey(transform, key) {
|
||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { document } = state
|
let { document } = state
|
||||||
const node = document.assertDescendant(key)
|
const node = document.assertDescendant(key)
|
||||||
const parent = document.getParent(key)
|
|
||||||
const index = parent.nodes.indexOf(node)
|
|
||||||
const path = document.getPath(key)
|
const path = document.getPath(key)
|
||||||
|
const parent = document.getParent(key)
|
||||||
|
const previous = document.getPreviousSibling(key)
|
||||||
|
const next = document.getNextSibling(key)
|
||||||
transform.removeNodeOperation(path)
|
transform.removeNodeOperation(path)
|
||||||
|
|
||||||
// If the node isn't a text node, or it isn't the last node in its parent,
|
// If there are no more remaining nodes in the parent, re-add an empty text
|
||||||
// then we have nothing else to do.
|
// node so that we guarantee to always have text nodes as the tree's leaves.
|
||||||
if (node.kind != 'text' || parent.nodes.size > 1) return transform
|
if (parent.nodes.size == 1) {
|
||||||
|
|
||||||
// Otherwise, re-add an empty text node into the parent so that we guarantee
|
|
||||||
// to always have text nodes as the leaves of the node tree.
|
|
||||||
const text = Text.create()
|
const text = Text.create()
|
||||||
transform.insertNodeByKey(parent.key, index, text)
|
transform.insertNodeByKey(parent.key, 0, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the previous and next siblings are both text nodes, join them.
|
||||||
|
if (
|
||||||
|
(previous && previous.kind == 'text') &&
|
||||||
|
(next && next.kind == 'text')
|
||||||
|
) {
|
||||||
|
transform.joinNodeByKey(next.key, previous.key)
|
||||||
|
}
|
||||||
|
|
||||||
return transform
|
return transform
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,9 +225,41 @@ export function removeNodeByKey(transform, key) {
|
|||||||
|
|
||||||
export function removeTextByKey(transform, key, offset, length) {
|
export function removeTextByKey(transform, key, offset, length) {
|
||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { document } = state
|
let { document } = state
|
||||||
const path = document.getPath(key)
|
const path = document.getPath(key)
|
||||||
return transform.removeTextOperation(path, offset, length)
|
transform.removeTextOperation(path, offset, length)
|
||||||
|
|
||||||
|
// If the text node is now empty, we might need to remove more nodes.
|
||||||
|
document = transform.state.document
|
||||||
|
const node = document.getDescendant(key)
|
||||||
|
const parent = document.getParent(key)
|
||||||
|
const previous = document.getPreviousSibling(key)
|
||||||
|
const next = document.getNextSibling(key)
|
||||||
|
|
||||||
|
// If the text node isn't empty, don't do anything more.
|
||||||
|
if (node.text != '') {
|
||||||
|
return transform
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the empty text node is the only node remaining in a non-void inline,
|
||||||
|
// remove the inline completely.
|
||||||
|
if (
|
||||||
|
parent.kind == 'inline' &&
|
||||||
|
parent.isVoid == false &&
|
||||||
|
parent.nodes.size == 1
|
||||||
|
) {
|
||||||
|
transform.removeNodeByKey(parent.key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, if the text node is not needed in the tree any more, remove it.
|
||||||
|
else if (
|
||||||
|
(previous && previous.isVoid == false) ||
|
||||||
|
(next && next.isVoid == false)
|
||||||
|
) {
|
||||||
|
transform.removeNodeByKey(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return transform
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -174,8 +296,58 @@ export function setNodeByKey(transform, key, properties) {
|
|||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { document } = state
|
const { document } = state
|
||||||
const node = document.assertDescendant(key)
|
const node = document.assertDescendant(key)
|
||||||
|
const parent = document.getParent(key)
|
||||||
|
const index = parent.nodes.indexOf(node)
|
||||||
const path = document.getPath(key)
|
const path = document.getPath(key)
|
||||||
return transform.setNodeOperation(path, properties)
|
const previous = document.getPreviousSibling(key)
|
||||||
|
const next = document.getNextSibling(key)
|
||||||
|
transform.setNodeOperation(path, properties)
|
||||||
|
|
||||||
|
// If the `isVoid` property is being changed to true, remove all of the node's
|
||||||
|
// children, and add additional text nodes around it if necessary.
|
||||||
|
if (properties.isVoid == true && node.isVoid == false) {
|
||||||
|
node.nodes.forEach((child) => {
|
||||||
|
transform.removeNodeByKey(child.key)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (node.kind == 'inline') {
|
||||||
|
if (!next) {
|
||||||
|
const text = Text.create()
|
||||||
|
transform.insertNodeByKey(parent.key, index + 1, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!previous) {
|
||||||
|
const text = Text.create()
|
||||||
|
transform.insertNodeByKey(parent.key, index, text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the `isVoid` property is being changed to `false` and the node is an
|
||||||
|
// inline node, remove any additional unnecessary text around it.
|
||||||
|
if (
|
||||||
|
properties.isVoid == false &&
|
||||||
|
node.isVoid == true &&
|
||||||
|
node.kind == 'inline'
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
previous &&
|
||||||
|
previous.kind == 'text' &&
|
||||||
|
previous.text == ''
|
||||||
|
) {
|
||||||
|
transform.removeNodeByKey(previous.key)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
next &&
|
||||||
|
next.kind == 'text' &&
|
||||||
|
next.text == ''
|
||||||
|
) {
|
||||||
|
transform.removeNodeByKey(next.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return transform
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -188,10 +360,92 @@ export function setNodeByKey(transform, key, properties) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export function splitNodeByKey(transform, key, offset) {
|
export function splitNodeByKey(transform, key, offset) {
|
||||||
const { state } = transform
|
let { state } = transform
|
||||||
const { document } = state
|
let { document } = state
|
||||||
const path = document.getPath(key)
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -15,6 +15,7 @@ import {
|
|||||||
addMarkOperation,
|
addMarkOperation,
|
||||||
insertNodeOperation,
|
insertNodeOperation,
|
||||||
insertTextOperation,
|
insertTextOperation,
|
||||||
|
joinNodeOperation,
|
||||||
moveNodeOperation,
|
moveNodeOperation,
|
||||||
removeMarkOperation,
|
removeMarkOperation,
|
||||||
removeNodeOperation,
|
removeNodeOperation,
|
||||||
@@ -85,6 +86,7 @@ import {
|
|||||||
addMarkByKey,
|
addMarkByKey,
|
||||||
insertNodeByKey,
|
insertNodeByKey,
|
||||||
insertTextByKey,
|
insertTextByKey,
|
||||||
|
joinNodeByKey,
|
||||||
moveNodeByKey,
|
moveNodeByKey,
|
||||||
removeMarkByKey,
|
removeMarkByKey,
|
||||||
removeNodeByKey,
|
removeNodeByKey,
|
||||||
@@ -169,6 +171,7 @@ export default {
|
|||||||
addMarkOperation,
|
addMarkOperation,
|
||||||
insertNodeOperation,
|
insertNodeOperation,
|
||||||
insertTextOperation,
|
insertTextOperation,
|
||||||
|
joinNodeOperation,
|
||||||
moveNodeOperation,
|
moveNodeOperation,
|
||||||
removeMarkOperation,
|
removeMarkOperation,
|
||||||
removeNodeOperation,
|
removeNodeOperation,
|
||||||
@@ -233,6 +236,7 @@ export default {
|
|||||||
addMarkByKey,
|
addMarkByKey,
|
||||||
insertNodeByKey,
|
insertNodeByKey,
|
||||||
insertTextByKey,
|
insertTextByKey,
|
||||||
|
joinNodeByKey,
|
||||||
moveNodeByKey,
|
moveNodeByKey,
|
||||||
removeMarkByKey,
|
removeMarkByKey,
|
||||||
removeNodeByKey,
|
removeNodeByKey,
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import Schema from '../models/schema'
|
import Schema from '../models/schema'
|
||||||
import { default as defaultSchema } from '../plugins/schema'
|
import { default as defaultSchema } from '../plugins/schema'
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@ export default function (state) {
|
|||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
next.selection.toJS(),
|
next.selection.toJS(),
|
||||||
range.collapseToStartOf(updated).toJS()
|
range.collapseToEndOf(updated).toJS()
|
||||||
)
|
)
|
||||||
|
|
||||||
return next
|
return next
|
||||||
|
@@ -8,8 +8,3 @@ nodes:
|
|||||||
nodes:
|
nodes:
|
||||||
- kind: text
|
- kind: text
|
||||||
text: word
|
text: word
|
||||||
- kind: inline
|
|
||||||
type: link
|
|
||||||
nodes:
|
|
||||||
- kind: text
|
|
||||||
text: ""
|
|
||||||
|
@@ -3,11 +3,6 @@ nodes:
|
|||||||
- kind: block
|
- kind: block
|
||||||
type: paragraph
|
type: paragraph
|
||||||
nodes:
|
nodes:
|
||||||
- kind: inline
|
|
||||||
type: link
|
|
||||||
nodes:
|
|
||||||
- kind: text
|
|
||||||
text: ""
|
|
||||||
- kind: inline
|
- kind: inline
|
||||||
type: link
|
type: link
|
||||||
nodes:
|
nodes:
|
||||||
|
@@ -8,8 +8,3 @@ nodes:
|
|||||||
nodes:
|
nodes:
|
||||||
- kind: text
|
- kind: text
|
||||||
text: word
|
text: word
|
||||||
- kind: inline
|
|
||||||
type: link
|
|
||||||
nodes:
|
|
||||||
- kind: text
|
|
||||||
text: ""
|
|
||||||
|
@@ -3,11 +3,6 @@ nodes:
|
|||||||
- kind: block
|
- kind: block
|
||||||
type: paragraph
|
type: paragraph
|
||||||
nodes:
|
nodes:
|
||||||
- kind: inline
|
|
||||||
type: link
|
|
||||||
nodes:
|
|
||||||
- kind: text
|
|
||||||
text: ""
|
|
||||||
- kind: inline
|
- kind: inline
|
||||||
type: link
|
type: link
|
||||||
nodes:
|
nodes:
|
||||||
|
@@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
import assert from 'assert'
|
||||||
|
import { Block } from '../../../../../..'
|
||||||
|
|
||||||
|
export default function (state) {
|
||||||
|
const { document, selection } = state
|
||||||
|
const first = document.getBlocks().first()
|
||||||
|
|
||||||
|
debugger
|
||||||
|
const next = state
|
||||||
|
.transform()
|
||||||
|
.insertNodeByKey(document.key, 0, first)
|
||||||
|
.apply()
|
||||||
|
|
||||||
|
const one = next.document.getBlocks().first()
|
||||||
|
const two = next.document.getBlocks().last()
|
||||||
|
|
||||||
|
assert.equal(one.type, two.type)
|
||||||
|
assert.notEqual(one.key, two.key)
|
||||||
|
|
||||||
|
return next
|
||||||
|
}
|
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: one
|
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: one
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: one
|
@@ -5,6 +5,6 @@ export default function (state) {
|
|||||||
|
|
||||||
return state
|
return state
|
||||||
.transform()
|
.transform()
|
||||||
.removeNodeByKey(first.key)
|
.moveNodeByKey(first.key, document.key, 1)
|
||||||
.apply()
|
.apply()
|
||||||
}
|
}
|
@@ -4,9 +4,9 @@ nodes:
|
|||||||
type: paragraph
|
type: paragraph
|
||||||
nodes:
|
nodes:
|
||||||
- kind: text
|
- kind: text
|
||||||
text: word
|
text: one
|
||||||
- kind: block
|
- kind: block
|
||||||
type: paragraph
|
type: paragraph
|
||||||
nodes:
|
nodes:
|
||||||
- kind: text
|
- kind: text
|
||||||
text: another
|
text: two
|
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: two
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: one
|
@@ -1,10 +1,11 @@
|
|||||||
|
|
||||||
export default function (state) {
|
export default function (state) {
|
||||||
const { document, selection } = state
|
const { document, selection } = state
|
||||||
|
const block = document.getBlocks().first()
|
||||||
const first = document.getInlines().first()
|
const first = document.getInlines().first()
|
||||||
|
|
||||||
return state
|
return state
|
||||||
.transform()
|
.transform()
|
||||||
.removeNodeByKey(first.key)
|
.moveNodeByKey(first.key, block.key, 1)
|
||||||
.apply()
|
.apply()
|
||||||
}
|
}
|
@@ -7,9 +7,9 @@ nodes:
|
|||||||
type: link
|
type: link
|
||||||
nodes:
|
nodes:
|
||||||
- kind: text
|
- kind: text
|
||||||
text: word
|
text: one
|
||||||
- kind: inline
|
- kind: inline
|
||||||
type: link
|
type: link
|
||||||
nodes:
|
nodes:
|
||||||
- kind: text
|
- kind: text
|
||||||
text: another
|
text: two
|
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: two
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: one
|
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
export default function (state) {
|
||||||
|
const { document, selection } = state
|
||||||
|
const text = document.getTexts().last()
|
||||||
|
const block = document.getBlocks().first()
|
||||||
|
|
||||||
|
return state
|
||||||
|
.transform()
|
||||||
|
.moveNodeByKey(text.key, block.key, 1)
|
||||||
|
.apply()
|
||||||
|
}
|
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: one
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: two
|
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: onetwo
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: ""
|
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
export default function (state) {
|
||||||
|
const { document, selection } = state
|
||||||
|
const second = document.getTexts().get(1)
|
||||||
|
|
||||||
|
return state
|
||||||
|
.transform()
|
||||||
|
.removeTextByKey(second.key, 0, 1)
|
||||||
|
.apply()
|
||||||
|
}
|
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: one
|
||||||
|
- kind: text
|
||||||
|
text: a
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: two
|
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: one
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: two
|
@@ -5,6 +5,6 @@ export default function (state) {
|
|||||||
|
|
||||||
return state
|
return state
|
||||||
.transform()
|
.transform()
|
||||||
.removeNodeByKey(first.key)
|
.removeTextByKey(first.key, 0, 1)
|
||||||
.apply()
|
.apply()
|
||||||
}
|
}
|
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: a
|
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
export default function (state) {
|
||||||
|
const { document, selection } = state
|
||||||
|
const last = document.getTexts().last()
|
||||||
|
|
||||||
|
return state
|
||||||
|
.transform()
|
||||||
|
.removeTextByKey(last.key, 0, 4)
|
||||||
|
.apply()
|
||||||
|
}
|
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: ""
|
||||||
|
- kind: inline
|
||||||
|
type: image
|
||||||
|
isVoid: true
|
||||||
|
- kind: text
|
||||||
|
text: word
|
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: ""
|
||||||
|
- kind: inline
|
||||||
|
type: image
|
||||||
|
isVoid: true
|
||||||
|
- kind: text
|
||||||
|
text: ""
|
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
export default function (state) {
|
||||||
|
const { document, selection } = state
|
||||||
|
const first = document.getTexts().first()
|
||||||
|
|
||||||
|
return state
|
||||||
|
.transform()
|
||||||
|
.removeTextByKey(first.key, 3, 1)
|
||||||
|
.apply()
|
||||||
|
}
|
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: word
|
@@ -7,4 +7,4 @@ nodes:
|
|||||||
type: link
|
type: link
|
||||||
nodes:
|
nodes:
|
||||||
- kind: text
|
- kind: text
|
||||||
text: another
|
text: wor
|
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
export default function (state) {
|
||||||
|
const { document, selection } = state
|
||||||
|
const second = document.getTexts().get(1)
|
||||||
|
|
||||||
|
return state
|
||||||
|
.transform()
|
||||||
|
.removeTextByKey(second.key, 0, 1)
|
||||||
|
.apply()
|
||||||
|
}
|
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: one
|
||||||
|
- kind: text
|
||||||
|
text: a
|
||||||
|
- kind: inline
|
||||||
|
type: image
|
||||||
|
isVoid: true
|
||||||
|
- kind: text
|
||||||
|
text: ""
|
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: one
|
||||||
|
- kind: inline
|
||||||
|
type: image
|
||||||
|
isVoid: true
|
||||||
|
- kind: text
|
||||||
|
text: ""
|
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
export default function (state) {
|
||||||
|
const { document, selection } = state
|
||||||
|
const third = document.getTexts().get(2)
|
||||||
|
|
||||||
|
return state
|
||||||
|
.transform()
|
||||||
|
.removeTextByKey(third.key, 0, 1)
|
||||||
|
.apply()
|
||||||
|
}
|
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: ""
|
||||||
|
- kind: inline
|
||||||
|
type: image
|
||||||
|
isVoid: true
|
||||||
|
- kind: text
|
||||||
|
text: a
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: two
|
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: ""
|
||||||
|
- kind: inline
|
||||||
|
type: image
|
||||||
|
isVoid: true
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: two
|
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
export default function (state) {
|
||||||
|
const { document, selection } = state
|
||||||
|
const first = document.getTexts().first()
|
||||||
|
|
||||||
|
return state
|
||||||
|
.transform()
|
||||||
|
.removeTextByKey(first.key, 3, 1)
|
||||||
|
.apply()
|
||||||
|
}
|
@@ -4,4 +4,4 @@ nodes:
|
|||||||
type: paragraph
|
type: paragraph
|
||||||
nodes:
|
nodes:
|
||||||
- kind: text
|
- kind: text
|
||||||
text: another
|
text: wor
|
@@ -18,7 +18,6 @@ describe('transforms', () => {
|
|||||||
|
|
||||||
for (const transform of transforms) {
|
for (const transform of transforms) {
|
||||||
if (transform[0] == '.') continue
|
if (transform[0] == '.') continue
|
||||||
if (transform == 'insert-node-by-key') continue
|
|
||||||
|
|
||||||
describe(`${toCamel(transform)}()`, () => {
|
describe(`${toCamel(transform)}()`, () => {
|
||||||
const transformDir = resolve(__dirname, './fixtures/by-key', transform)
|
const transformDir = resolve(__dirname, './fixtures/by-key', transform)
|
||||||
|
Reference in New Issue
Block a user