diff --git a/packages/slate/src/operations/apply.js b/packages/slate/src/operations/apply.js
index 067d6d31a..9fe5a608e 100644
--- a/packages/slate/src/operations/apply.js
+++ b/packages/slate/src/operations/apply.js
@@ -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)
diff --git a/packages/slate/test/index.js b/packages/slate/test/index.js
index 6871abd08..bfc424731 100644
--- a/packages/slate/test/index.js
+++ b/packages/slate/test/index.js
@@ -20,6 +20,7 @@ describe('slate', () => {
require('./schema')
require('./changes')
require('./history')
+ require('./operations')
})
/**
diff --git a/packages/slate/test/operations/apply/remove_text/cursor-inside-removed-text.js b/packages/slate/test/operations/apply/remove_text/cursor-inside-removed-text.js
new file mode 100644
index 000000000..cfc446704
--- /dev/null
+++ b/packages/slate/test/operations/apply/remove_text/cursor-inside-removed-text.js
@@ -0,0 +1,31 @@
+/** @jsx h */
+
+import h from '../../../helpers/h'
+
+export default [{
+ type: 'remove_text',
+ path: [0, 0],
+ offset: 2,
+ text: 'is is some text inside ',
+ marks: []
+}]
+
+export const input = (
+
+
+
+ This is some text inside a paragraph.
+
+
+
+)
+
+export const output = (
+
+
+
+ Tha paragraph.
+
+
+
+)
diff --git a/packages/slate/test/operations/index.js b/packages/slate/test/operations/index.js
new file mode 100644
index 000000000..1615d21c6
--- /dev/null
+++ b/packages/slate/test/operations/index.js
@@ -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 operations = module.default
+ const change = input.change()
+ change.applyOperations(operations)
+ const opts = { preserveSelection: true, preserveData: true }
+ const actual = change.value.toJSON(opts)
+ const expected = output.toJSON(opts)
+ assert.deepEqual(actual, expected)
+ })
+ }
+ })
+ }
+ })
+ }
+})