mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-22 15:02:51 +02:00
fix mark operation range creation
This commit is contained in:
@@ -28,15 +28,41 @@ Changes.addMarkByKey = (change, key, offset, length, mark, options = {}) => {
|
||||
const { state } = change
|
||||
const { document } = state
|
||||
const path = document.getPath(key)
|
||||
const node = document.getNode(key)
|
||||
const ranges = node.getRanges()
|
||||
|
||||
change.applyOperation({
|
||||
type: 'add_mark',
|
||||
path,
|
||||
offset,
|
||||
length,
|
||||
mark,
|
||||
const operations = []
|
||||
const bx = offset
|
||||
const by = offset + length
|
||||
let o = 0
|
||||
|
||||
ranges.forEach((range) => {
|
||||
const ax = o
|
||||
const ay = ax + range.text.length
|
||||
|
||||
o += range.text.length
|
||||
|
||||
// If the range doesn't overlap with the operation, continue on.
|
||||
if (ay < bx || by < ax) return
|
||||
|
||||
// If the range already has the mark, continue on.
|
||||
if (range.marks.has(mark)) return
|
||||
|
||||
// Otherwise, determine which offset and characters overlap.
|
||||
const start = Math.max(ax, bx)
|
||||
const end = Math.min(ay, by)
|
||||
|
||||
operations.push({
|
||||
type: 'add_mark',
|
||||
path,
|
||||
offset: start,
|
||||
length: end - start,
|
||||
mark,
|
||||
})
|
||||
})
|
||||
|
||||
change.applyOperations(operations)
|
||||
|
||||
if (normalize) {
|
||||
const parent = document.getParent(key)
|
||||
change.normalizeNodeByKey(parent.key, SCHEMA)
|
||||
@@ -211,15 +237,41 @@ Changes.removeMarkByKey = (change, key, offset, length, mark, options = {}) => {
|
||||
const { state } = change
|
||||
const { document } = state
|
||||
const path = document.getPath(key)
|
||||
const node = document.getNode(key)
|
||||
const ranges = node.getRanges()
|
||||
|
||||
change.applyOperation({
|
||||
type: 'remove_mark',
|
||||
path,
|
||||
offset,
|
||||
length,
|
||||
mark,
|
||||
const operations = []
|
||||
const bx = offset
|
||||
const by = offset + length
|
||||
let o = 0
|
||||
|
||||
ranges.forEach((range) => {
|
||||
const ax = o
|
||||
const ay = ax + range.text.length
|
||||
|
||||
o += range.text.length
|
||||
|
||||
// If the range doesn't overlap with the operation, continue on.
|
||||
if (ay < bx || by < ax) return
|
||||
|
||||
// If the range already has the mark, continue on.
|
||||
if (!range.marks.has(mark)) return
|
||||
|
||||
// Otherwise, determine which offset and characters overlap.
|
||||
const start = Math.max(ax, bx)
|
||||
const end = Math.min(ay, by)
|
||||
|
||||
operations.push({
|
||||
type: 'remove_mark',
|
||||
path,
|
||||
offset: start,
|
||||
length: end - start,
|
||||
mark,
|
||||
})
|
||||
})
|
||||
|
||||
change.applyOperations(operations)
|
||||
|
||||
if (normalize) {
|
||||
const parent = document.getParent(key)
|
||||
change.normalizeNodeByKey(parent.key, SCHEMA)
|
||||
@@ -280,7 +332,6 @@ Changes.removeTextByKey = (change, key, offset, length, options = {}) => {
|
||||
let o = 0
|
||||
|
||||
ranges.forEach((range) => {
|
||||
const { marks } = range
|
||||
const ax = o
|
||||
const ay = ax + range.text.length
|
||||
|
||||
@@ -299,15 +350,12 @@ Changes.removeTextByKey = (change, key, offset, length, options = {}) => {
|
||||
path,
|
||||
offset: start,
|
||||
text: string,
|
||||
marks,
|
||||
marks: range.marks,
|
||||
})
|
||||
})
|
||||
|
||||
// Apply the removals in reverse order, so that subsequent removals aren't
|
||||
// impacted by previous ones.
|
||||
removals.reverse().forEach((op) => {
|
||||
change.applyOperation(op)
|
||||
})
|
||||
// Apply in reverse order, so subsequent removals don't impact previous ones.
|
||||
change.applyOperations(removals.reverse())
|
||||
|
||||
if (normalize) {
|
||||
const block = document.getClosestBlock(key)
|
||||
|
@@ -13,11 +13,11 @@ export default function (state) {
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.change()
|
||||
.select(range)
|
||||
.toggleMark('bold')
|
||||
.insertText('a')
|
||||
.apply()
|
||||
.state
|
||||
|
||||
assert.deepEqual(next.selection.toJS(), range.move(1).toJS())
|
||||
|
@@ -13,10 +13,10 @@ export default function (state) {
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.change()
|
||||
.select(range)
|
||||
.toggleMark('bold')
|
||||
.apply()
|
||||
.state
|
||||
|
||||
assert.deepEqual(next.selection.toJS(), range.toJS())
|
||||
|
@@ -12,10 +12,10 @@ export default function (state) {
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.change()
|
||||
.select(range)
|
||||
.toggleMark('bold')
|
||||
.apply()
|
||||
.state
|
||||
|
||||
assert.deepEqual(next.selection.toJS(), range.toJS())
|
||||
|
@@ -13,12 +13,12 @@ export default function (state) {
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.change()
|
||||
.select(range)
|
||||
.toggleMark('bold')
|
||||
.toggleMark('bold')
|
||||
.insertText('a')
|
||||
.apply()
|
||||
.state
|
||||
|
||||
assert.deepEqual(next.selection.toJS(), range.move(1).toJS())
|
||||
|
@@ -0,0 +1,18 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { selection } = state
|
||||
|
||||
const next = state
|
||||
.change()
|
||||
.removeMarkByKey('a', 0, 4, 'bold')
|
||||
.state
|
||||
|
||||
.change()
|
||||
.undo()
|
||||
.state
|
||||
|
||||
assert.deepEqual(next.selection.toJS(), selection.toJS())
|
||||
return next
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
key: a
|
||||
text: text
|
@@ -0,0 +1,8 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
key: a
|
||||
text: text
|
@@ -6,7 +6,7 @@ export default function (state) {
|
||||
|
||||
const next = state
|
||||
.change()
|
||||
.addMarkByKey('key1', 0, 8, 'marktype')
|
||||
.addMarkByKey('a', 0, 8, 'marktype')
|
||||
.state
|
||||
|
||||
.change()
|
||||
|
@@ -4,5 +4,10 @@ nodes:
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
key: 'key1'
|
||||
text: The text
|
||||
key: a
|
||||
ranges:
|
||||
- text: te
|
||||
marks: []
|
||||
- text: xt
|
||||
marks:
|
||||
- type: bold
|
||||
|
@@ -4,5 +4,9 @@ nodes:
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
key: 'key1'
|
||||
text: The text
|
||||
key: a
|
||||
ranges:
|
||||
- text: te
|
||||
- text: xt
|
||||
marks:
|
||||
- type: bold
|
||||
|
@@ -0,0 +1,18 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { selection } = state
|
||||
|
||||
const next = state
|
||||
.change()
|
||||
.addMarkByKey('a', 0, 4, 'bold')
|
||||
.state
|
||||
|
||||
.change()
|
||||
.undo()
|
||||
.state
|
||||
|
||||
assert.deepEqual(next.selection.toJS(), selection.toJS())
|
||||
return next
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
key: a
|
||||
text: text
|
@@ -0,0 +1,8 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
key: a
|
||||
text: text
|
Reference in New Issue
Block a user