mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-29 18:09:49 +02:00
Merge remote-tracking branch 'origin/schema-normalize-selection-ops' into schema-normalize-selection-ops
This commit is contained in:
@@ -975,38 +975,37 @@ const Node = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Join a node by `key` with another `withKey`.
|
* Join a children node `first` with another children node `second`.
|
||||||
* It brings Node<key> after Node<WithKey>
|
* `first` and `second` will be concatenated in that order.
|
||||||
|
* `first` and `second` must be two Nodes or two Text.
|
||||||
*
|
*
|
||||||
* @param {String} key
|
* @param {Node} first
|
||||||
* @param {String} withKey
|
* @param {Node} second
|
||||||
* @return {Node}
|
* @return {Node}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
joinNode(key, withKey) {
|
joinNode(first, second) {
|
||||||
let node = this
|
let node = this
|
||||||
let target = node.assertPath(key)
|
let parent = node.getParent(second)
|
||||||
let withTarget = node.assertPath(withKey)
|
|
||||||
let parent = node.getParent(target)
|
|
||||||
const isParent = node == parent
|
const isParent = node == parent
|
||||||
const index = parent.nodes.indexOf(target)
|
const index = parent.nodes.indexOf(second)
|
||||||
|
|
||||||
if (target.kind == 'text') {
|
if (second.kind == 'text') {
|
||||||
let { characters } = withTarget
|
let { characters } = first
|
||||||
characters = characters.concat(target.characters)
|
characters = characters.concat(second.characters)
|
||||||
withTarget = withTarget.merge({ characters })
|
first = first.merge({ characters })
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
const size = withTarget.nodes.size
|
const size = first.nodes.size
|
||||||
target.nodes.forEach((child, i) => {
|
second.nodes.forEach((child, i) => {
|
||||||
withTarget = withTarget.insertNode(size + i, child)
|
first = first.insertNode(size + i, child)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
parent = parent.removeNode(index)
|
parent = parent.removeNode(index)
|
||||||
node = isParent ? parent : node.updateDescendant(parent)
|
node = isParent ? parent : node.updateDescendant(parent)
|
||||||
node = node.updateDescendant(withTarget)
|
node = node.updateDescendant(first)
|
||||||
return node
|
return node
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@@ -136,9 +136,32 @@ function insertText(state, operation) {
|
|||||||
|
|
||||||
function joinNode(state, operation) {
|
function joinNode(state, operation) {
|
||||||
const { path, withPath } = operation
|
const { path, withPath } = operation
|
||||||
let { document } = state
|
let { document, selection } = state
|
||||||
document = document.joinNode(path, withPath)
|
const first = document.assertPath(withPath)
|
||||||
state = state.merge({ document })
|
const second = document.assertPath(path)
|
||||||
|
|
||||||
|
// Update doc
|
||||||
|
document = document.joinNode(first, second)
|
||||||
|
|
||||||
|
// Update selection
|
||||||
|
// When merging two texts together
|
||||||
|
if (second.kind == 'text') {
|
||||||
|
// The final key is the `first` key
|
||||||
|
if (selection.anchorKey == second.key) {
|
||||||
|
selection = selection.merge({
|
||||||
|
anchorKey: first.key,
|
||||||
|
anchorOffset: selection.anchorOffset + first.characters.size
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (selection.focusKey == second.key) {
|
||||||
|
selection = selection.merge({
|
||||||
|
focusKey: first.key,
|
||||||
|
focusOffset: selection.focusOffset + first.characters.size
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state = state.merge({ document, selection })
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,14 +2,11 @@
|
|||||||
import assert from 'assert'
|
import assert from 'assert'
|
||||||
|
|
||||||
export default function (state) {
|
export default function (state) {
|
||||||
const { document, selection } = state
|
const { selection } = state
|
||||||
const texts = document.getTexts()
|
|
||||||
let first = texts.first()
|
|
||||||
const second = texts.last()
|
|
||||||
const range = selection.merge({
|
const range = selection.merge({
|
||||||
anchorKey: first.key,
|
anchorKey: 'anchor',
|
||||||
anchorOffset: 2,
|
anchorOffset: 1,
|
||||||
focusKey: second.key,
|
focusKey: 'focus',
|
||||||
focusOffset: 2
|
focusOffset: 2
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -19,15 +16,18 @@ export default function (state) {
|
|||||||
.unwrapInline('hashtag')
|
.unwrapInline('hashtag')
|
||||||
.apply()
|
.apply()
|
||||||
|
|
||||||
// Selection is reset, in theory it should me on the image
|
// Test selection
|
||||||
first = next.document.getTexts().first()
|
const { document } = next
|
||||||
|
const first = document.getTexts().first()
|
||||||
|
const last = document.getTexts().last()
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
next.selection.toJS(),
|
next.selection.toJS(),
|
||||||
range.merge({
|
range.merge({
|
||||||
anchorKey: first.key,
|
anchorKey: first.key,
|
||||||
anchorOffset: 0,
|
anchorOffset: 1,
|
||||||
focusKey: first.key,
|
focusKey: last.key,
|
||||||
focusOffset: 0
|
focusOffset: 4
|
||||||
}).toJS()
|
}).toJS()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -4,6 +4,7 @@ nodes:
|
|||||||
type: paragraph
|
type: paragraph
|
||||||
nodes:
|
nodes:
|
||||||
- kind: text
|
- kind: text
|
||||||
|
key: 'anchor' # w[o
|
||||||
text: wo
|
text: wo
|
||||||
- kind: inline
|
- kind: inline
|
||||||
type: hashtag
|
type: hashtag
|
||||||
@@ -19,4 +20,5 @@ nodes:
|
|||||||
- kind: text
|
- kind: text
|
||||||
text: an
|
text: an
|
||||||
- kind: text
|
- kind: text
|
||||||
|
key: 'focus' # ot]her
|
||||||
text: other
|
text: other
|
||||||
|
@@ -10,3 +10,5 @@ nodes:
|
|||||||
nodes:
|
nodes:
|
||||||
- kind: text
|
- kind: text
|
||||||
text: another
|
text: another
|
||||||
|
# Selection
|
||||||
|
# w[ordanot]her
|
@@ -2,14 +2,11 @@
|
|||||||
import assert from 'assert'
|
import assert from 'assert'
|
||||||
|
|
||||||
export default function (state) {
|
export default function (state) {
|
||||||
const { document, selection } = state
|
const { selection } = state
|
||||||
const texts = document.getTexts()
|
|
||||||
const first = texts.first()
|
|
||||||
const last = texts.get(1)
|
|
||||||
const range = selection.merge({
|
const range = selection.merge({
|
||||||
anchorKey: first.key,
|
anchorKey: 'anchor',
|
||||||
anchorOffset: 1,
|
anchorOffset: 1,
|
||||||
focusKey: last.key,
|
focusKey: 'focus',
|
||||||
focusOffset: 2
|
focusOffset: 2
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -21,7 +18,10 @@ export default function (state) {
|
|||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
next.selection.toJS(),
|
next.selection.toJS(),
|
||||||
range.collapseToStartOf(next.document).toJS()
|
range.merge({
|
||||||
|
focusKey: 'anchor',
|
||||||
|
focusOffset: 3
|
||||||
|
}).toJS()
|
||||||
)
|
)
|
||||||
|
|
||||||
return next
|
return next
|
||||||
|
@@ -7,11 +7,15 @@ nodes:
|
|||||||
type: paragraph
|
type: paragraph
|
||||||
nodes:
|
nodes:
|
||||||
- kind: text
|
- kind: text
|
||||||
|
key: 'anchor'
|
||||||
text: w
|
text: w
|
||||||
- kind: inline
|
- kind: inline
|
||||||
type: hashtag
|
type: hashtag
|
||||||
nodes:
|
nodes:
|
||||||
- kind: text
|
- kind: text
|
||||||
|
key: 'focus'
|
||||||
text: or
|
text: or
|
||||||
- kind: text
|
- kind: text
|
||||||
text: d
|
text: d
|
||||||
|
# Selection
|
||||||
|
# w[or]d
|
@@ -2,14 +2,11 @@
|
|||||||
import assert from 'assert'
|
import assert from 'assert'
|
||||||
|
|
||||||
export default function (state) {
|
export default function (state) {
|
||||||
const { document, selection } = state
|
const { selection } = state
|
||||||
const texts = document.getTexts()
|
|
||||||
const first = texts.get(2)
|
|
||||||
const last = texts.get(3)
|
|
||||||
const range = selection.merge({
|
const range = selection.merge({
|
||||||
anchorKey: first.key,
|
anchorKey: 'anchor',
|
||||||
anchorOffset: 2,
|
anchorOffset: 2,
|
||||||
focusKey: last.key,
|
focusKey: 'focus',
|
||||||
focusOffset: 2
|
focusOffset: 2
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -21,7 +18,10 @@ export default function (state) {
|
|||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
next.selection.toJS(),
|
next.selection.toJS(),
|
||||||
range.collapseToStartOf(next.document).toJS()
|
range.merge({
|
||||||
|
focusKey: 'anchor',
|
||||||
|
focusOffset: 5
|
||||||
|
}).toJS()
|
||||||
)
|
)
|
||||||
|
|
||||||
return next
|
return next
|
||||||
|
@@ -11,11 +11,16 @@ nodes:
|
|||||||
- kind: text
|
- kind: text
|
||||||
text: ll
|
text: ll
|
||||||
- kind: text
|
- kind: text
|
||||||
|
key: 'anchor'
|
||||||
text: "o w"
|
text: "o w"
|
||||||
- kind: inline
|
- kind: inline
|
||||||
type: hashtag
|
type: hashtag
|
||||||
nodes:
|
nodes:
|
||||||
- kind: text
|
- kind: text
|
||||||
|
key: 'focus'
|
||||||
text: or
|
text: or
|
||||||
- kind: text
|
- kind: text
|
||||||
text: d
|
text: d
|
||||||
|
|
||||||
|
# Selection
|
||||||
|
# hello [wor]d
|
@@ -12,3 +12,5 @@ nodes:
|
|||||||
text: ll
|
text: ll
|
||||||
- kind: text
|
- kind: text
|
||||||
text: "o word"
|
text: "o word"
|
||||||
|
# Selection
|
||||||
|
# hello [wor]d
|
@@ -2,14 +2,11 @@
|
|||||||
import assert from 'assert'
|
import assert from 'assert'
|
||||||
|
|
||||||
export default function (state) {
|
export default function (state) {
|
||||||
const { document, selection } = state
|
const { selection } = state
|
||||||
const texts = document.getTexts()
|
|
||||||
const first = texts.first()
|
|
||||||
const last = texts.get(1)
|
|
||||||
const range = selection.merge({
|
const range = selection.merge({
|
||||||
anchorKey: first.key,
|
anchorKey: 'anchor',
|
||||||
anchorOffset: 1,
|
anchorOffset: 1,
|
||||||
focusKey: last.key,
|
focusKey: 'focus',
|
||||||
focusOffset: 2
|
focusOffset: 2
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -21,7 +18,10 @@ export default function (state) {
|
|||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
next.selection.toJS(),
|
next.selection.toJS(),
|
||||||
range.collapseToStartOf(next.document).toJS()
|
range.merge({
|
||||||
|
focusKey: 'anchor',
|
||||||
|
focusOffset: 3
|
||||||
|
}).toJS()
|
||||||
)
|
)
|
||||||
|
|
||||||
return next
|
return next
|
||||||
|
@@ -4,11 +4,16 @@ nodes:
|
|||||||
type: paragraph
|
type: paragraph
|
||||||
nodes:
|
nodes:
|
||||||
- kind: text
|
- kind: text
|
||||||
|
key: 'anchor'
|
||||||
text: w
|
text: w
|
||||||
- kind: inline
|
- kind: inline
|
||||||
type: hashtag
|
type: hashtag
|
||||||
nodes:
|
nodes:
|
||||||
- kind: text
|
- kind: text
|
||||||
|
key: 'focus'
|
||||||
text: or
|
text: or
|
||||||
- kind: text
|
- kind: text
|
||||||
text: d
|
text: d
|
||||||
|
|
||||||
|
# selection:
|
||||||
|
# w[or]d
|
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
import assert from 'assert'
|
||||||
|
|
||||||
|
export default function (state) {
|
||||||
|
const { selection } = state
|
||||||
|
|
||||||
|
const range = selection.merge({
|
||||||
|
anchorKey: 'anchor',
|
||||||
|
anchorOffset: 1,
|
||||||
|
focusKey: 'focus',
|
||||||
|
focusOffset: 2
|
||||||
|
})
|
||||||
|
|
||||||
|
const next = state
|
||||||
|
.transform()
|
||||||
|
.moveTo(range)
|
||||||
|
.joinNodeByKey('key2', 'key1')
|
||||||
|
.apply()
|
||||||
|
|
||||||
|
assert.deepEqual(
|
||||||
|
next.selection.toJS(),
|
||||||
|
range.merge({
|
||||||
|
focusKey: 'anchor',
|
||||||
|
focusOffset: 5
|
||||||
|
}).toJS()
|
||||||
|
)
|
||||||
|
|
||||||
|
return next
|
||||||
|
}
|
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
key: 'key1'
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
key: 'anchor'
|
||||||
|
text: The
|
||||||
|
- kind: block
|
||||||
|
key: 'key2'
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
key: 'focus'
|
||||||
|
text: text
|
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
key: key1
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: Thetext
|
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
import assert from 'assert'
|
||||||
|
|
||||||
|
export default function (state) {
|
||||||
|
const { selection } = state
|
||||||
|
|
||||||
|
const range = selection.merge({
|
||||||
|
anchorKey: 'anchor',
|
||||||
|
anchorOffset: 1,
|
||||||
|
focusKey: 'focus',
|
||||||
|
focusOffset: 2
|
||||||
|
})
|
||||||
|
|
||||||
|
const next = state
|
||||||
|
.transform()
|
||||||
|
.moveTo(range)
|
||||||
|
.joinNodeByKey('focus', 'anchor')
|
||||||
|
.apply()
|
||||||
|
|
||||||
|
assert.deepEqual(
|
||||||
|
next.selection.toJS(),
|
||||||
|
range.merge({
|
||||||
|
focusKey: 'anchor',
|
||||||
|
focusOffset: 5
|
||||||
|
}).toJS()
|
||||||
|
)
|
||||||
|
|
||||||
|
return next
|
||||||
|
}
|
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
key: 'anchor'
|
||||||
|
text: one
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: two
|
||||||
|
- kind: text
|
||||||
|
key: 'focus'
|
||||||
|
text: three
|
@@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
nodes:
|
||||||
|
- kind: block
|
||||||
|
type: paragraph
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
key: 'anchor'
|
||||||
|
text: onethree
|
||||||
|
- kind: inline
|
||||||
|
type: link
|
||||||
|
nodes:
|
||||||
|
- kind: text
|
||||||
|
text: two
|
Reference in New Issue
Block a user