mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-22 23:12:52 +02:00
Add unwrapNodeByKey (#509)
* Add separate splitNodeOperation in two different op * Add transform unwrapNodeByKey * Add tests for unwrapNodeByKey * Add test for undo of unwrapNodeByKey * Support normalize option * Handle last/first sibling case * Document new unwrapNodeByKey transform
This commit is contained in:
committed by
Ian Storm Taylor
parent
36670d0d41
commit
ed0395999c
@@ -59,6 +59,7 @@ Transform methods can either operate on the [`Document`](./document.md), the [`S
|
||||
- [`splitNodeByKey`](#splitnodebykey)
|
||||
- [`unwrapInlineByKey`](#unwrapinlinebykey)
|
||||
- [`unwrapBlockByKey`](#unwrapblockbykey)
|
||||
- [`unwrapNodeByKey`](#unwrapnodebykey)
|
||||
- [`wrapBlockByKey`](#wrapblockbykey)
|
||||
- [`wrapInlineByKey`](#wrapinlinebykey)
|
||||
- [Document Transforms](#document-transforms)
|
||||
@@ -333,6 +334,11 @@ Unwrap all inner content of an [`Inline`](./inline.md) node that match `properti
|
||||
|
||||
Unwrap all inner content of a [`Block`](./block.md) node that match `properties`. For convenience, you can pass a `type` string or `properties` object.
|
||||
|
||||
### `unwrapNodeByKey`
|
||||
`unwrapNodeByKey(key: String) => Transform`
|
||||
|
||||
Unwrap a single node from its parent. If the node is surrounded with siblings, its parent will be split. If the node is the only child, the parent is removed, and simply replaced by the node itself. Cannot unwrap a root node.
|
||||
|
||||
### `wrapBlockByKey`
|
||||
`wrapBlockByKey(key: String, properties: Object) => Transform` <br/>
|
||||
`wrapBlockByKey(key: String, type: String) => Transform`
|
||||
|
@@ -276,7 +276,7 @@ export function splitNodeByKey(transform, key, offset, options = {}) {
|
||||
let { document } = state
|
||||
const path = document.getPath(key)
|
||||
|
||||
transform.splitNodeOperation(path, offset)
|
||||
transform.splitNodeAtOffsetOperation(path, offset)
|
||||
|
||||
if (normalize) {
|
||||
const parent = document.getParent(key)
|
||||
@@ -324,6 +324,63 @@ export function unwrapBlockByKey(transform, key, properties, options) {
|
||||
transform.unwrapBlockAtRange(range, properties, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwrap a single node from its parent.
|
||||
*
|
||||
* If the node is surrounded with siblings, its parent will be
|
||||
* split. If the node is the only child, the parent is removed, and
|
||||
* simply replaced by the node itself. Cannot unwrap a root node.
|
||||
*
|
||||
* @param {Transform} transform
|
||||
* @param {String} key
|
||||
* @param {Object} options
|
||||
* @property {Boolean} normalize
|
||||
*/
|
||||
|
||||
export function unwrapNodeByKey(transform, key, options = {}) {
|
||||
const { normalize = true } = options
|
||||
const { state } = transform
|
||||
const { document } = state
|
||||
const parent = document.getParent(key)
|
||||
const node = parent.getChild(key)
|
||||
|
||||
const index = parent.nodes.indexOf(node)
|
||||
const isFirst = index === 0
|
||||
const isLast = index === parent.nodes.size - 1
|
||||
|
||||
const parentParent = document.getParent(parent.key)
|
||||
const parentIndex = parentParent.nodes.indexOf(parent)
|
||||
|
||||
|
||||
if (parent.nodes.size === 1) {
|
||||
// Remove the parent
|
||||
transform.removeNodeByKey(parent.key, { normalize: false })
|
||||
// and replace it by the node itself
|
||||
transform.insertNodeByKey(parentParent.key, parentIndex, node, options)
|
||||
}
|
||||
|
||||
else if (isFirst) {
|
||||
// Just move the node before its parent
|
||||
transform.moveNodeByKey(key, parentParent.key, parentIndex, options)
|
||||
}
|
||||
|
||||
else if (isLast) {
|
||||
// Just move the node after its parent
|
||||
transform.moveNodeByKey(key, parentParent.key, parentIndex + 1, options)
|
||||
}
|
||||
|
||||
else {
|
||||
const parentPath = document.getPath(parent.key)
|
||||
// Split the parent
|
||||
transform.splitNodeOperation(parentPath, index)
|
||||
// Extract the node in between the splitted parent
|
||||
transform.moveNodeByKey(key, parentParent.key, parentIndex + 1, { normalize: false })
|
||||
|
||||
if (normalize) {
|
||||
transform.normalizeNodeByKey(parentParent.key, SCHEMA)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a node in an inline with `properties`.
|
||||
|
@@ -29,6 +29,7 @@ import {
|
||||
setMarkOperation,
|
||||
setNodeOperation,
|
||||
setSelectionOperation,
|
||||
splitNodeAtOffsetOperation,
|
||||
splitNodeOperation,
|
||||
} from './operations'
|
||||
|
||||
@@ -114,6 +115,7 @@ import {
|
||||
splitNodeByKey,
|
||||
unwrapInlineByKey,
|
||||
unwrapBlockByKey,
|
||||
unwrapNodeByKey,
|
||||
wrapBlockByKey,
|
||||
wrapInlineByKey,
|
||||
} from './by-key'
|
||||
@@ -211,6 +213,7 @@ export default {
|
||||
setMarkOperation,
|
||||
setNodeOperation,
|
||||
setSelectionOperation,
|
||||
splitNodeAtOffsetOperation,
|
||||
splitNodeOperation,
|
||||
|
||||
/**
|
||||
@@ -290,6 +293,7 @@ export default {
|
||||
splitNodeByKey,
|
||||
unwrapInlineByKey,
|
||||
unwrapBlockByKey,
|
||||
unwrapNodeByKey,
|
||||
wrapBlockByKey,
|
||||
wrapInlineByKey,
|
||||
|
||||
|
@@ -432,7 +432,7 @@ export function setSelectionOperation(transform, properties, options = {}) {
|
||||
* @param {Number} offset
|
||||
*/
|
||||
|
||||
export function splitNodeOperation(transform, path, offset) {
|
||||
export function splitNodeAtOffsetOperation(transform, path, offset) {
|
||||
const inversePath = path.slice()
|
||||
inversePath[path.length - 1] += 1
|
||||
|
||||
@@ -440,13 +440,45 @@ export function splitNodeOperation(transform, path, offset) {
|
||||
type: 'join_node',
|
||||
path: inversePath,
|
||||
withPath: path,
|
||||
deep: true // we need to join nodes recursively
|
||||
// we will split down to the text nodes, so we must join nodes recursively
|
||||
deep: true
|
||||
}]
|
||||
|
||||
const operation = {
|
||||
type: 'split_node',
|
||||
path,
|
||||
offset,
|
||||
count: null,
|
||||
inverse,
|
||||
}
|
||||
|
||||
transform.applyOperation(operation)
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a node by `path` after its 'count' child.
|
||||
*
|
||||
* @param {Transform} transform
|
||||
* @param {Array} path
|
||||
* @param {Number} count
|
||||
*/
|
||||
|
||||
export function splitNodeOperation(transform, path, count) {
|
||||
const inversePath = path.slice()
|
||||
inversePath[path.length - 1] += 1
|
||||
|
||||
const inverse = [{
|
||||
type: 'join_node',
|
||||
path: inversePath,
|
||||
withPath: path,
|
||||
deep: false
|
||||
}]
|
||||
|
||||
const operation = {
|
||||
type: 'split_node',
|
||||
path,
|
||||
offset: null,
|
||||
count,
|
||||
inverse,
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,7 @@
|
||||
|
||||
export default function (state) {
|
||||
return state
|
||||
.transform()
|
||||
.unwrapNodeByKey('to-unwrap')
|
||||
.apply()
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: quote
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
key: 'to-unwrap'
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word1
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word2
|
@@ -0,0 +1,15 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word1
|
||||
- kind: block
|
||||
type: quote
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word2
|
@@ -0,0 +1,7 @@
|
||||
|
||||
export default function (state) {
|
||||
return state
|
||||
.transform()
|
||||
.unwrapNodeByKey('to-unwrap')
|
||||
.apply()
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: quote
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word1
|
||||
- kind: block
|
||||
type: paragraph
|
||||
key: 'to-unwrap'
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word2
|
@@ -0,0 +1,15 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: quote
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word1
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word2
|
@@ -0,0 +1,7 @@
|
||||
|
||||
export default function (state) {
|
||||
return state
|
||||
.transform()
|
||||
.unwrapNodeByKey('to-unwrap')
|
||||
.apply()
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: quote
|
||||
nodes:
|
||||
- kind: block
|
||||
key: 'to-unwrap'
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word
|
||||
- kind: block
|
||||
type: quote
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word
|
@@ -0,0 +1,15 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word
|
||||
- kind: block
|
||||
type: quote
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word
|
@@ -0,0 +1,7 @@
|
||||
|
||||
export default function (state) {
|
||||
return state
|
||||
.transform()
|
||||
.unwrapNodeByKey('to-unwrap')
|
||||
.apply()
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: quote
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word1
|
||||
- kind: block
|
||||
type: paragraph
|
||||
key: 'to-unwrap'
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word2
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word3
|
@@ -0,0 +1,23 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: quote
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word1
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word2
|
||||
- kind: block
|
||||
type: quote
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word3
|
@@ -0,0 +1,11 @@
|
||||
|
||||
export default function (state) {
|
||||
return state
|
||||
.transform()
|
||||
.unwrapNodeByKey('to-unwrap')
|
||||
.apply()
|
||||
|
||||
.transform()
|
||||
.undo()
|
||||
.apply()
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: quote
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word1
|
||||
- kind: block
|
||||
type: paragraph
|
||||
key: 'to-unwrap'
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word2
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word3
|
@@ -0,0 +1,20 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: quote
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word1
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word2
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: word3
|
Reference in New Issue
Block a user