mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-17 04:34:00 +02:00
Move selection to the offset of remove_text if it's in its bounds
If selection is inside a block of text that's removed, the part of the selection that's inside the bounds should clamp to the offset of the removed text. So if your cursor is at offset 5, and you're deleting from 2-10, your cursor should end up at offset 2.
This commit is contained in:
@@ -287,12 +287,20 @@ const APPLIERS = {
|
||||
const { anchorKey, focusKey, anchorOffset, focusOffset } = selection
|
||||
let node = document.assertPath(path)
|
||||
|
||||
if (anchorKey == node.key && anchorOffset >= rangeOffset) {
|
||||
selection = selection.moveAnchor(-length)
|
||||
if (anchorKey == node.key) {
|
||||
if (anchorOffset >= rangeOffset) {
|
||||
selection = selection.moveAnchor(-length)
|
||||
} else if (anchorOffset > offset) {
|
||||
selection = selection.moveAnchorTo(anchorKey, offset)
|
||||
}
|
||||
}
|
||||
|
||||
if (focusKey == node.key && focusOffset >= rangeOffset) {
|
||||
selection = selection.moveFocus(-length)
|
||||
if (focusKey == node.key) {
|
||||
if (focusOffset >= rangeOffset) {
|
||||
selection = selection.moveFocus(-length)
|
||||
} else if (focusOffset > offset) {
|
||||
selection = selection.moveFocusTo(focusKey, offset)
|
||||
}
|
||||
}
|
||||
|
||||
node = node.removeText(offset, length)
|
||||
|
@@ -20,6 +20,7 @@ describe('slate', () => {
|
||||
require('./schema')
|
||||
require('./changes')
|
||||
require('./history')
|
||||
require('./operations')
|
||||
})
|
||||
|
||||
/**
|
||||
|
@@ -0,0 +1,33 @@
|
||||
/** @jsx h */
|
||||
|
||||
import h from '../../../helpers/h'
|
||||
|
||||
export default function (change) {
|
||||
return change.applyOperation({
|
||||
type: 'remove_text',
|
||||
path: [0, 0],
|
||||
offset: 2,
|
||||
text: 'is is some text inside ',
|
||||
marks: []
|
||||
})
|
||||
}
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<paragraph>
|
||||
This <cursor />is some text inside a paragraph.
|
||||
</paragraph>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = (
|
||||
<value>
|
||||
<document>
|
||||
<paragraph>
|
||||
Th<cursor />a paragraph.
|
||||
</paragraph>
|
||||
</document>
|
||||
</value>
|
||||
)
|
42
packages/slate/test/operations/index.js
Normal file
42
packages/slate/test/operations/index.js
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
import assert from 'assert'
|
||||
import fs from 'fs-promise' // eslint-disable-line import/no-extraneous-dependencies
|
||||
import toCamel from 'to-camel-case' // eslint-disable-line import/no-extraneous-dependencies
|
||||
import { basename, extname, resolve } from 'path'
|
||||
|
||||
/**
|
||||
* Tests.
|
||||
*/
|
||||
|
||||
describe('operations', async () => {
|
||||
const dir = resolve(__dirname)
|
||||
const categories = fs.readdirSync(dir).filter(c => c[0] != '.' && c != 'index.js')
|
||||
|
||||
for (const category of categories) {
|
||||
describe(category, () => {
|
||||
const categoryDir = resolve(dir, category)
|
||||
const methods = fs.readdirSync(categoryDir).filter(c => c[0] != '.')
|
||||
|
||||
for (const method of methods) {
|
||||
describe(toCamel(method), () => {
|
||||
const testDir = resolve(categoryDir, method)
|
||||
const tests = fs.readdirSync(testDir).filter(t => t[0] != '.' && !!~t.indexOf('.js')).map(t => basename(t, extname(t)))
|
||||
|
||||
for (const test of tests) {
|
||||
it(test, async () => {
|
||||
const module = require(resolve(testDir, test))
|
||||
const { input, output } = module
|
||||
const fn = module.default
|
||||
const change = input.change()
|
||||
fn(change)
|
||||
const opts = { preserveSelection: true, preserveData: true }
|
||||
const actual = change.value.toJSON(opts)
|
||||
const expected = output.toJSON(opts)
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
Reference in New Issue
Block a user