1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-23 07:22:55 +02:00

fix mark operation range creation

This commit is contained in:
Ian Storm Taylor
2017-09-05 18:24:21 -07:00
parent 6f3f8ee685
commit 367a22c39a
22 changed files with 157 additions and 32 deletions

View File

@@ -28,15 +28,41 @@ Changes.addMarkByKey = (change, key, offset, length, mark, options = {}) => {
const { state } = change const { state } = change
const { document } = state const { document } = state
const path = document.getPath(key) const path = document.getPath(key)
const node = document.getNode(key)
const ranges = node.getRanges()
change.applyOperation({ const operations = []
type: 'add_mark', const bx = offset
path, const by = offset + length
offset, let o = 0
length,
mark, 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) { if (normalize) {
const parent = document.getParent(key) const parent = document.getParent(key)
change.normalizeNodeByKey(parent.key, SCHEMA) change.normalizeNodeByKey(parent.key, SCHEMA)
@@ -211,15 +237,41 @@ Changes.removeMarkByKey = (change, key, offset, length, mark, options = {}) => {
const { state } = change const { state } = change
const { document } = state const { document } = state
const path = document.getPath(key) const path = document.getPath(key)
const node = document.getNode(key)
const ranges = node.getRanges()
change.applyOperation({ const operations = []
type: 'remove_mark', const bx = offset
path, const by = offset + length
offset, let o = 0
length,
mark, 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) { if (normalize) {
const parent = document.getParent(key) const parent = document.getParent(key)
change.normalizeNodeByKey(parent.key, SCHEMA) change.normalizeNodeByKey(parent.key, SCHEMA)
@@ -280,7 +332,6 @@ Changes.removeTextByKey = (change, key, offset, length, options = {}) => {
let o = 0 let o = 0
ranges.forEach((range) => { ranges.forEach((range) => {
const { marks } = range
const ax = o const ax = o
const ay = ax + range.text.length const ay = ax + range.text.length
@@ -299,15 +350,12 @@ Changes.removeTextByKey = (change, key, offset, length, options = {}) => {
path, path,
offset: start, offset: start,
text: string, text: string,
marks, marks: range.marks,
}) })
}) })
// Apply the removals in reverse order, so that subsequent removals aren't // Apply in reverse order, so subsequent removals don't impact previous ones.
// impacted by previous ones. change.applyOperations(removals.reverse())
removals.reverse().forEach((op) => {
change.applyOperation(op)
})
if (normalize) { if (normalize) {
const block = document.getClosestBlock(key) const block = document.getClosestBlock(key)

View File

@@ -13,11 +13,11 @@ export default function (state) {
}) })
const next = state const next = state
.transform() .change()
.select(range) .select(range)
.toggleMark('bold') .toggleMark('bold')
.insertText('a') .insertText('a')
.apply() .state
assert.deepEqual(next.selection.toJS(), range.move(1).toJS()) assert.deepEqual(next.selection.toJS(), range.move(1).toJS())

View File

@@ -13,10 +13,10 @@ export default function (state) {
}) })
const next = state const next = state
.transform() .change()
.select(range) .select(range)
.toggleMark('bold') .toggleMark('bold')
.apply() .state
assert.deepEqual(next.selection.toJS(), range.toJS()) assert.deepEqual(next.selection.toJS(), range.toJS())

View File

@@ -12,10 +12,10 @@ export default function (state) {
}) })
const next = state const next = state
.transform() .change()
.select(range) .select(range)
.toggleMark('bold') .toggleMark('bold')
.apply() .state
assert.deepEqual(next.selection.toJS(), range.toJS()) assert.deepEqual(next.selection.toJS(), range.toJS())

View File

@@ -13,12 +13,12 @@ export default function (state) {
}) })
const next = state const next = state
.transform() .change()
.select(range) .select(range)
.toggleMark('bold') .toggleMark('bold')
.toggleMark('bold') .toggleMark('bold')
.insertText('a') .insertText('a')
.apply() .state
assert.deepEqual(next.selection.toJS(), range.move(1).toJS()) assert.deepEqual(next.selection.toJS(), range.move(1).toJS())

View File

@@ -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
}

View File

@@ -0,0 +1,8 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
key: a
text: text

View File

@@ -0,0 +1,8 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
key: a
text: text

View File

@@ -6,7 +6,7 @@ export default function (state) {
const next = state const next = state
.change() .change()
.addMarkByKey('key1', 0, 8, 'marktype') .addMarkByKey('a', 0, 8, 'marktype')
.state .state
.change() .change()

View File

@@ -4,5 +4,10 @@ nodes:
type: paragraph type: paragraph
nodes: nodes:
- kind: text - kind: text
key: 'key1' key: a
text: The text ranges:
- text: te
marks: []
- text: xt
marks:
- type: bold

View File

@@ -4,5 +4,9 @@ nodes:
type: paragraph type: paragraph
nodes: nodes:
- kind: text - kind: text
key: 'key1' key: a
text: The text ranges:
- text: te
- text: xt
marks:
- type: bold

View File

@@ -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
}

View File

@@ -0,0 +1,8 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
key: a
text: text

View File

@@ -0,0 +1,8 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
key: a
text: text