diff --git a/lib/components/void.js b/lib/components/void.js
index 2dc05bfbd..bf684d39f 100644
--- a/lib/components/void.js
+++ b/lib/components/void.js
@@ -121,7 +121,6 @@ class Void extends React.Component {
visibility: 'hidden'
}
: {
- pointerEvents: 'none',
position: 'absolute',
top: '0px',
left: '-9999px',
@@ -129,7 +128,7 @@ class Void extends React.Component {
}
return (
- {this.renderLeaf()}
+ {this.renderLeaf()}
)
}
diff --git a/lib/models/state.js b/lib/models/state.js
index 632490280..fc5661470 100644
--- a/lib/models/state.js
+++ b/lib/models/state.js
@@ -558,13 +558,36 @@ class State extends new Record(DEFAULTS) {
delete() {
let state = this
let { document, selection } = state
+ let after
// When collapsed, there's nothing to do.
if (selection.isCollapsed) return state
- // Otherwise, delete and update the selection.
+ // Determine what the selection will be after deleting.
+ const { startText } = this
+ const { startKey, startOffset, endKey, endOffset } = selection
+ const previous = document.getPreviousSibling(startText)
+
+ if (
+ previous &&
+ startOffset == 0 &&
+ (endKey != startKey || endOffset == startText.length)
+ ) {
+ if (previous.kind == 'text') {
+ after = selection.collapseToEndOf(previous)
+ } else {
+ const last = previous.getTexts().last()
+ after = selection.collapseToEndOf(last)
+ }
+ }
+
+ else {
+ after = selection.collapseToStart()
+ }
+
+ // Delete and update the selection.
document = document.deleteAtRange(selection)
- selection = selection.collapseToStart()
+ selection = after
state = state.merge({ document, selection })
return state
}
@@ -607,6 +630,19 @@ class State extends new Record(DEFAULTS) {
}
}
+ else if (selection.isAtEndOf(startNode) && startNode.length == 1) {
+ const previous = document.getPreviousSibling(startNode)
+
+ if (previous && previous.kind == 'text') {
+ after = selection.collapseToEndOf(previous)
+ } else if (previous) {
+ const last = previous.getTexts().last()
+ after = selection.collapseToEndOf(last)
+ } else {
+ after = selection.moveBackward(n)
+ }
+ }
+
else {
after = selection.moveBackward(n)
}
@@ -628,12 +664,14 @@ class State extends new Record(DEFAULTS) {
deleteForward(n = 1) {
let state = this
let { document, selection } = state
- let { startKey } = selection
+ let { startKey, startOffset } = selection
let after = selection
// Determine what the selection should be after deleting.
const block = document.getClosestBlock(startKey)
const inline = document.getClosestInline(startKey)
+ const previous = document.getPreviousSibling(startKey)
+ const startText = document.getDescendant(startKey)
if (selection.isExpanded) {
after = selection.collapseToStart()
@@ -641,10 +679,19 @@ class State extends new Record(DEFAULTS) {
else if ((block && block.isVoid) || (inline && inline.isVoid)) {
const next = document.getNextText(startKey)
- const previous = document.getPreviousText(startKey)
+ const prev = document.getPreviousText(startKey)
after = next
? selection.collapseToStartOf(next)
- : selection.collapseToEndOf(previous)
+ : selection.collapseToEndOf(prev)
+ }
+
+ else if (previous && startOffset == 0 && startText.length == 1) {
+ if (previous.kind == 'text') {
+ after = selection.collapseToEndOf(previous)
+ } else {
+ const last = previous.getTexts().last()
+ after = selection.collapseToEndOf(last)
+ }
}
// Delete forward and then update the selection.
diff --git a/lib/models/transforms.js b/lib/models/transforms.js
index e95737719..8daa3458a 100644
--- a/lib/models/transforms.js
+++ b/lib/models/transforms.js
@@ -79,7 +79,7 @@ const Transforms = {
let text = node.getDescendant(startKey)
text = text.removeCharacters(startOffset, endOffset)
node = node.updateDescendant(text)
- return node
+ return node.normalize()
}
// Split the blocks and determine the edge boundaries.
diff --git a/test/transforms/fixtures/delete-at-range/before-inline-sibling/index.js b/test/transforms/fixtures/delete-at-range/before-inline-sibling/index.js
new file mode 100644
index 000000000..e7311ea44
--- /dev/null
+++ b/test/transforms/fixtures/delete-at-range/before-inline-sibling/index.js
@@ -0,0 +1,17 @@
+
+export default function (state) {
+ const { document, selection } = state
+ const texts = document.getTexts()
+ const last = texts.last()
+ const range = selection.merge({
+ anchorKey: last.key,
+ anchorOffset: last.length - 1,
+ focusKey: last.key,
+ focusOffset: last.length
+ })
+
+ return state
+ .transform()
+ .deleteAtRange(range)
+ .apply()
+}
diff --git a/test/transforms/fixtures/delete-at-range/before-inline-sibling/input.yaml b/test/transforms/fixtures/delete-at-range/before-inline-sibling/input.yaml
new file mode 100644
index 000000000..6286c3b87
--- /dev/null
+++ b/test/transforms/fixtures/delete-at-range/before-inline-sibling/input.yaml
@@ -0,0 +1,14 @@
+
+nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: one
+ - kind: inline
+ type: link
+ nodes:
+ - kind: text
+ text: two
+ - kind: text
+ text: a
diff --git a/test/transforms/fixtures/delete-at-range/before-inline-sibling/output.yaml b/test/transforms/fixtures/delete-at-range/before-inline-sibling/output.yaml
new file mode 100644
index 000000000..798f00a1b
--- /dev/null
+++ b/test/transforms/fixtures/delete-at-range/before-inline-sibling/output.yaml
@@ -0,0 +1,12 @@
+
+nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: one
+ - kind: inline
+ type: link
+ nodes:
+ - kind: text
+ text: two
diff --git a/test/transforms/fixtures/delete-backward-at-range/before-inline-sibling/index.js b/test/transforms/fixtures/delete-backward-at-range/before-inline-sibling/index.js
new file mode 100644
index 000000000..cce7cc965
--- /dev/null
+++ b/test/transforms/fixtures/delete-backward-at-range/before-inline-sibling/index.js
@@ -0,0 +1,17 @@
+
+export default function (state) {
+ const { document, selection } = state
+ const texts = document.getTexts()
+ const last = texts.last()
+ const range = selection.merge({
+ anchorKey: last.key,
+ anchorOffset: last.length,
+ focusKey: last.key,
+ focusOffset: last.length
+ })
+
+ return state
+ .transform()
+ .deleteBackwardAtRange(range)
+ .apply()
+}
diff --git a/test/transforms/fixtures/delete-backward-at-range/before-inline-sibling/input.yaml b/test/transforms/fixtures/delete-backward-at-range/before-inline-sibling/input.yaml
new file mode 100644
index 000000000..6286c3b87
--- /dev/null
+++ b/test/transforms/fixtures/delete-backward-at-range/before-inline-sibling/input.yaml
@@ -0,0 +1,14 @@
+
+nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: one
+ - kind: inline
+ type: link
+ nodes:
+ - kind: text
+ text: two
+ - kind: text
+ text: a
diff --git a/test/transforms/fixtures/delete-backward-at-range/before-inline-sibling/output.yaml b/test/transforms/fixtures/delete-backward-at-range/before-inline-sibling/output.yaml
new file mode 100644
index 000000000..798f00a1b
--- /dev/null
+++ b/test/transforms/fixtures/delete-backward-at-range/before-inline-sibling/output.yaml
@@ -0,0 +1,12 @@
+
+nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: one
+ - kind: inline
+ type: link
+ nodes:
+ - kind: text
+ text: two
diff --git a/test/transforms/fixtures/delete-backward/before-inline-sibling/index.js b/test/transforms/fixtures/delete-backward/before-inline-sibling/index.js
new file mode 100644
index 000000000..238bf01cf
--- /dev/null
+++ b/test/transforms/fixtures/delete-backward/before-inline-sibling/index.js
@@ -0,0 +1,29 @@
+
+import assert from 'assert'
+
+export default function (state) {
+ const { document, selection } = state
+ const texts = document.getTexts()
+ const last = texts.last()
+ const range = selection.merge({
+ anchorKey: last.key,
+ anchorOffset: last.length,
+ focusKey: last.key,
+ focusOffset: last.length
+ })
+
+ const next = state
+ .transform()
+ .moveTo(range)
+ .deleteBackward()
+ .apply()
+
+ const updated = next.document.getTexts().last()
+
+ assert.deepEqual(
+ next.selection.toJS(),
+ range.collapseToEndOf(updated).toJS()
+ )
+
+ return next
+}
diff --git a/test/transforms/fixtures/delete-backward/before-inline-sibling/input.yaml b/test/transforms/fixtures/delete-backward/before-inline-sibling/input.yaml
new file mode 100644
index 000000000..6286c3b87
--- /dev/null
+++ b/test/transforms/fixtures/delete-backward/before-inline-sibling/input.yaml
@@ -0,0 +1,14 @@
+
+nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: one
+ - kind: inline
+ type: link
+ nodes:
+ - kind: text
+ text: two
+ - kind: text
+ text: a
diff --git a/test/transforms/fixtures/delete-backward/before-inline-sibling/output.yaml b/test/transforms/fixtures/delete-backward/before-inline-sibling/output.yaml
new file mode 100644
index 000000000..798f00a1b
--- /dev/null
+++ b/test/transforms/fixtures/delete-backward/before-inline-sibling/output.yaml
@@ -0,0 +1,12 @@
+
+nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: one
+ - kind: inline
+ type: link
+ nodes:
+ - kind: text
+ text: two
diff --git a/test/transforms/fixtures/delete-forward-at-range/before-inline-sibling/index.js b/test/transforms/fixtures/delete-forward-at-range/before-inline-sibling/index.js
new file mode 100644
index 000000000..876bb95df
--- /dev/null
+++ b/test/transforms/fixtures/delete-forward-at-range/before-inline-sibling/index.js
@@ -0,0 +1,17 @@
+
+export default function (state) {
+ const { document, selection } = state
+ const texts = document.getTexts()
+ const last = texts.last()
+ const range = selection.merge({
+ anchorKey: last.key,
+ anchorOffset: 0,
+ focusKey: last.key,
+ focusOffset: 0
+ })
+
+ return state
+ .transform()
+ .deleteForwardAtRange(range)
+ .apply()
+}
diff --git a/test/transforms/fixtures/delete-forward-at-range/before-inline-sibling/input.yaml b/test/transforms/fixtures/delete-forward-at-range/before-inline-sibling/input.yaml
new file mode 100644
index 000000000..6286c3b87
--- /dev/null
+++ b/test/transforms/fixtures/delete-forward-at-range/before-inline-sibling/input.yaml
@@ -0,0 +1,14 @@
+
+nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: one
+ - kind: inline
+ type: link
+ nodes:
+ - kind: text
+ text: two
+ - kind: text
+ text: a
diff --git a/test/transforms/fixtures/delete-forward-at-range/before-inline-sibling/output.yaml b/test/transforms/fixtures/delete-forward-at-range/before-inline-sibling/output.yaml
new file mode 100644
index 000000000..798f00a1b
--- /dev/null
+++ b/test/transforms/fixtures/delete-forward-at-range/before-inline-sibling/output.yaml
@@ -0,0 +1,12 @@
+
+nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: one
+ - kind: inline
+ type: link
+ nodes:
+ - kind: text
+ text: two
diff --git a/test/transforms/fixtures/delete-forward/before-inline-sibling/index.js b/test/transforms/fixtures/delete-forward/before-inline-sibling/index.js
new file mode 100644
index 000000000..1bd341afc
--- /dev/null
+++ b/test/transforms/fixtures/delete-forward/before-inline-sibling/index.js
@@ -0,0 +1,29 @@
+
+import assert from 'assert'
+
+export default function (state) {
+ const { document, selection } = state
+ const texts = document.getTexts()
+ const last = texts.last()
+ const range = selection.merge({
+ anchorKey: last.key,
+ anchorOffset: 0,
+ focusKey: last.key,
+ focusOffset: 0
+ })
+
+ const next = state
+ .transform()
+ .moveTo(range)
+ .deleteForward()
+ .apply()
+
+ const updated = next.document.getTexts().last()
+
+ assert.deepEqual(
+ next.selection.toJS(),
+ range.collapseToEndOf(updated).toJS()
+ )
+
+ return next
+}
diff --git a/test/transforms/fixtures/delete-forward/before-inline-sibling/input.yaml b/test/transforms/fixtures/delete-forward/before-inline-sibling/input.yaml
new file mode 100644
index 000000000..6286c3b87
--- /dev/null
+++ b/test/transforms/fixtures/delete-forward/before-inline-sibling/input.yaml
@@ -0,0 +1,14 @@
+
+nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: one
+ - kind: inline
+ type: link
+ nodes:
+ - kind: text
+ text: two
+ - kind: text
+ text: a
diff --git a/test/transforms/fixtures/delete-forward/before-inline-sibling/output.yaml b/test/transforms/fixtures/delete-forward/before-inline-sibling/output.yaml
new file mode 100644
index 000000000..798f00a1b
--- /dev/null
+++ b/test/transforms/fixtures/delete-forward/before-inline-sibling/output.yaml
@@ -0,0 +1,12 @@
+
+nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: one
+ - kind: inline
+ type: link
+ nodes:
+ - kind: text
+ text: two
diff --git a/test/transforms/fixtures/delete/before-inline-sibling/index.js b/test/transforms/fixtures/delete/before-inline-sibling/index.js
new file mode 100644
index 000000000..0bdd2d9a3
--- /dev/null
+++ b/test/transforms/fixtures/delete/before-inline-sibling/index.js
@@ -0,0 +1,34 @@
+
+import assert from 'assert'
+
+export default function (state) {
+ const { document, selection } = state
+ const texts = document.getTexts()
+ const last = texts.last()
+ const range = selection.merge({
+ anchorKey: last.key,
+ anchorOffset: last.length - 1,
+ focusKey: last.key,
+ focusOffset: last.length
+ })
+
+ const next = state
+ .transform()
+ .moveTo(range)
+ .delete()
+ .apply()
+
+ const updated = next.document.getTexts().last()
+
+ assert.deepEqual(
+ next.selection.toJS(),
+ range.merge({
+ anchorKey: updated.key,
+ anchorOffset: updated.length,
+ focusKey: updated.key,
+ focusOffset: updated.length
+ }).toJS()
+ )
+
+ return next
+}
diff --git a/test/transforms/fixtures/delete/before-inline-sibling/input.yaml b/test/transforms/fixtures/delete/before-inline-sibling/input.yaml
new file mode 100644
index 000000000..6286c3b87
--- /dev/null
+++ b/test/transforms/fixtures/delete/before-inline-sibling/input.yaml
@@ -0,0 +1,14 @@
+
+nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: one
+ - kind: inline
+ type: link
+ nodes:
+ - kind: text
+ text: two
+ - kind: text
+ text: a
diff --git a/test/transforms/fixtures/delete/before-inline-sibling/output.yaml b/test/transforms/fixtures/delete/before-inline-sibling/output.yaml
new file mode 100644
index 000000000..798f00a1b
--- /dev/null
+++ b/test/transforms/fixtures/delete/before-inline-sibling/output.yaml
@@ -0,0 +1,12 @@
+
+nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: one
+ - kind: inline
+ type: link
+ nodes:
+ - kind: text
+ text: two