diff --git a/docs/reference/models/transform.md b/docs/reference/models/transform.md
index 49d8b4576..c650fb8cd 100644
--- a/docs/reference/models/transform.md
+++ b/docs/reference/models/transform.md
@@ -57,6 +57,8 @@ Transform methods can either operate on the [`Document`](./document.md), the [`S
- [`setMarkByKey`](#setmarkbykey)
- [`setNodeByKey`](#setnodebykey)
- [`splitNodeByKey`](#splitnodebykey)
+ - [`unwrapInlineByKey`](#unwrapinlinebykey)
+ - [`unwrapBlockByKey`](#unwrapblockbykey)
- [Document Transforms](#document-transforms)
- [`deleteAtRange`](#deleteatrange)
- [`deleteBackwardAtRange`](#deletebackwardatrange)
@@ -317,6 +319,19 @@ Set a dictionary of `properties` on a [`Node`](./node.md) by its `key`. For conv
Split a node by its `key` at an `offset`.
+### `unwrapInlineByKey`
+`unwrapInlineByKey(key: String, properties: Object) => Transform`
+`unwrapInlineByKey(key: String, type: String) => Transform`
+
+Unwrap all inner content of an [`Inline`](./inline.md) node that match `properties`. For convenience, you can pass a `type` string or `properties` object.
+
+### `unwrapBlockByKey`
+`unwrapBlockByKey(key: String, properties: Object) => Transform`
+`unwrapBlockByKey(key: String, type: String) => Transform`
+
+Unwrap all inner content of a [`Block`](./block.md) node that match `properties`. For convenience, you can pass a `type` string or `properties` object.
+
+>>>>>>> slate/master
## Document Transforms
### `deleteBackwardAtRange`
diff --git a/src/transforms/at-range.js b/src/transforms/at-range.js
index 69ab12723..c09a792af 100644
--- a/src/transforms/at-range.js
+++ b/src/transforms/at-range.js
@@ -775,7 +775,7 @@ export function unwrapInlineAtRange(transform, range, properties, options = {})
const { normalize = true } = options
const { state } = transform
const { document } = state
- const texts = document.getTexts()
+ const texts = document.getTextsAtRange(range)
const inlines = texts
.map((text) => {
return document.getClosest(text, (parent) => {
diff --git a/src/transforms/by-key.js b/src/transforms/by-key.js
index dc27ca4da..0bfb45a01 100644
--- a/src/transforms/by-key.js
+++ b/src/transforms/by-key.js
@@ -323,3 +323,39 @@ export function splitNodeByKey(transform, key, offset, options = {}) {
return transform
}
+
+/**
+ * Unwrap content from an inline parent with `properties`.
+ *
+ * @param {Transform} transform
+ * @param {String} key
+ * @param {Object or String} properties
+ * @return {Transform}
+ */
+
+export function unwrapInlineByKey(transform, key, properties) {
+ const { state } = transform
+ const { document, selection } = state
+ const node = document.assertDescendant(key)
+ const texts = node.getTexts()
+ const range = selection.moveToRangeOf(texts.first(), texts.last())
+ return transform.unwrapInlineAtRange(range, properties)
+}
+
+/**
+ * Unwrap content from a block parent with `properties`.
+ *
+ * @param {Transform} transform
+ * @param {String} key
+ * @param {Object or String} properties
+ * @return {Transform}
+ */
+
+export function unwrapBlockByKey(transform, key, properties) {
+ const { state } = transform
+ const { document, selection } = state
+ const node = document.assertDescendant(key)
+ const texts = node.getTexts()
+ const range = selection.moveToRangeOf(texts.first(), texts.last())
+ return transform.unwrapBlockAtRange(range, properties)
+}
diff --git a/src/transforms/index.js b/src/transforms/index.js
index bc9ac26bc..5bb9d8b97 100644
--- a/src/transforms/index.js
+++ b/src/transforms/index.js
@@ -94,7 +94,8 @@ import {
setMarkByKey,
setNodeByKey,
splitNodeByKey,
- unwrapInlineByKey
+ unwrapInlineByKey,
+ unwrapBlockByKey,
} from './by-key'
/**
@@ -250,6 +251,10 @@ export default {
setNodeByKey,
splitNodeByKey,
unwrapInlineByKey,
+<<<<<<< HEAD
+=======
+ unwrapBlockByKey,
+>>>>>>> slate/master
/**
* On selection.
diff --git a/test/transforms/fixtures/at-current-range/unwrap-inline/nested-block/index.js b/test/transforms/fixtures/at-current-range/unwrap-inline/nested-block/index.js
index 0a24eb2b9..2a1231b72 100644
--- a/test/transforms/fixtures/at-current-range/unwrap-inline/nested-block/index.js
+++ b/test/transforms/fixtures/at-current-range/unwrap-inline/nested-block/index.js
@@ -5,11 +5,12 @@ export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
+ const last = texts.get(1)
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 1,
- focusKey: first.key,
- focusOffset: 3
+ focusKey: last.key,
+ focusOffset: 2
})
const next = state
diff --git a/test/transforms/fixtures/at-current-range/unwrap-inline/only-one/index.js b/test/transforms/fixtures/at-current-range/unwrap-inline/only-one/index.js
new file mode 100644
index 000000000..2dc5f582a
--- /dev/null
+++ b/test/transforms/fixtures/at-current-range/unwrap-inline/only-one/index.js
@@ -0,0 +1,28 @@
+
+import assert from 'assert'
+
+export default function (state) {
+ const { document, selection } = state
+ const texts = document.getTexts()
+ const first = texts.get(2)
+ const last = texts.get(3)
+ const range = selection.merge({
+ anchorKey: first.key,
+ anchorOffset: 2,
+ focusKey: last.key,
+ focusOffset: 2
+ })
+
+ const next = state
+ .transform()
+ .moveTo(range)
+ .unwrapInline('hashtag')
+ .apply()
+
+ assert.deepEqual(
+ next.selection.toJS(),
+ range.toJS()
+ )
+
+ return next
+}
diff --git a/test/transforms/fixtures/at-current-range/unwrap-inline/only-one/input.yaml b/test/transforms/fixtures/at-current-range/unwrap-inline/only-one/input.yaml
new file mode 100644
index 000000000..d93ed90ad
--- /dev/null
+++ b/test/transforms/fixtures/at-current-range/unwrap-inline/only-one/input.yaml
@@ -0,0 +1,21 @@
+
+nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: he
+ - kind: inline
+ type: hashtag
+ nodes:
+ - kind: text
+ text: ll
+ - kind: text
+ text: "o w"
+ - kind: inline
+ type: hashtag
+ nodes:
+ - kind: text
+ text: or
+ - kind: text
+ text: d
diff --git a/test/transforms/fixtures/at-current-range/unwrap-inline/only-one/output.yaml b/test/transforms/fixtures/at-current-range/unwrap-inline/only-one/output.yaml
new file mode 100644
index 000000000..80cea6855
--- /dev/null
+++ b/test/transforms/fixtures/at-current-range/unwrap-inline/only-one/output.yaml
@@ -0,0 +1,14 @@
+
+nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: he
+ - kind: inline
+ type: hashtag
+ nodes:
+ - kind: text
+ text: ll
+ - kind: text
+ text: "o word"
diff --git a/test/transforms/fixtures/at-current-range/unwrap-inline/single-block/index.js b/test/transforms/fixtures/at-current-range/unwrap-inline/single-block/index.js
index 0a24eb2b9..2a1231b72 100644
--- a/test/transforms/fixtures/at-current-range/unwrap-inline/single-block/index.js
+++ b/test/transforms/fixtures/at-current-range/unwrap-inline/single-block/index.js
@@ -5,11 +5,12 @@ export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
+ const last = texts.get(1)
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 1,
- focusKey: first.key,
- focusOffset: 3
+ focusKey: last.key,
+ focusOffset: 2
})
const next = state
diff --git a/test/transforms/fixtures/at-current-range/unwrap-inline/with-object/index.js b/test/transforms/fixtures/at-current-range/unwrap-inline/with-object/index.js
index ac861d6cb..971d03375 100644
--- a/test/transforms/fixtures/at-current-range/unwrap-inline/with-object/index.js
+++ b/test/transforms/fixtures/at-current-range/unwrap-inline/with-object/index.js
@@ -5,11 +5,12 @@ export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
+ const last = texts.get(1)
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 1,
- focusKey: first.key,
- focusOffset: 3
+ focusKey: last.key,
+ focusOffset: 2
})
const next = state
diff --git a/test/transforms/fixtures/at-range/unwrap-inline-at-range/nested-block/index.js b/test/transforms/fixtures/at-range/unwrap-inline-at-range/nested-block/index.js
index 8d03c6ce9..cdf642f9c 100644
--- a/test/transforms/fixtures/at-range/unwrap-inline-at-range/nested-block/index.js
+++ b/test/transforms/fixtures/at-range/unwrap-inline-at-range/nested-block/index.js
@@ -3,11 +3,12 @@ export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
+ const last = texts.get(1)
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 1,
- focusKey: first.key,
- focusOffset: 3
+ focusKey: last.key,
+ focusOffset: 2
})
return state
diff --git a/test/transforms/fixtures/at-range/unwrap-inline-at-range/single-block/index.js b/test/transforms/fixtures/at-range/unwrap-inline-at-range/single-block/index.js
index 8d03c6ce9..cdf642f9c 100644
--- a/test/transforms/fixtures/at-range/unwrap-inline-at-range/single-block/index.js
+++ b/test/transforms/fixtures/at-range/unwrap-inline-at-range/single-block/index.js
@@ -3,11 +3,12 @@ export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
+ const last = texts.get(1)
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 1,
- focusKey: first.key,
- focusOffset: 3
+ focusKey: last.key,
+ focusOffset: 2
})
return state
diff --git a/test/transforms/fixtures/at-range/unwrap-inline-at-range/with-object/index.js b/test/transforms/fixtures/at-range/unwrap-inline-at-range/with-object/index.js
index e18ed3821..4f3f594cc 100644
--- a/test/transforms/fixtures/at-range/unwrap-inline-at-range/with-object/index.js
+++ b/test/transforms/fixtures/at-range/unwrap-inline-at-range/with-object/index.js
@@ -3,11 +3,12 @@ export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
+ const last = texts.get(1)
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 1,
- focusKey: first.key,
- focusOffset: 3
+ focusKey: last.key,
+ focusOffset: 2
})
return state
diff --git a/test/transforms/fixtures/by-key/unwrap-block-by-key/single-block/index.js b/test/transforms/fixtures/by-key/unwrap-block-by-key/single-block/index.js
new file mode 100644
index 000000000..57e84a62e
--- /dev/null
+++ b/test/transforms/fixtures/by-key/unwrap-block-by-key/single-block/index.js
@@ -0,0 +1,10 @@
+
+export default function (state) {
+ const { document, selection } = state
+ const block = document.nodes.get(0)
+
+ return state
+ .transform()
+ .unwrapBlockByKey(block, 'quote')
+ .apply()
+}
diff --git a/test/transforms/fixtures/by-key/unwrap-block-by-key/single-block/input.yaml b/test/transforms/fixtures/by-key/unwrap-block-by-key/single-block/input.yaml
new file mode 100644
index 000000000..ab4efb609
--- /dev/null
+++ b/test/transforms/fixtures/by-key/unwrap-block-by-key/single-block/input.yaml
@@ -0,0 +1,18 @@
+
+nodes:
+ - kind: block
+ type: quote
+ nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: word
+ - kind: block
+ type: quote
+ nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: word
diff --git a/test/transforms/fixtures/by-key/unwrap-block-by-key/single-block/output.yaml b/test/transforms/fixtures/by-key/unwrap-block-by-key/single-block/output.yaml
new file mode 100644
index 000000000..c5a0f1a30
--- /dev/null
+++ b/test/transforms/fixtures/by-key/unwrap-block-by-key/single-block/output.yaml
@@ -0,0 +1,15 @@
+
+nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: word
+ - kind: block
+ type: quote
+ nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: word
diff --git a/test/transforms/fixtures/by-key/unwrap-inline-by-key/single-block/index.js b/test/transforms/fixtures/by-key/unwrap-inline-by-key/single-block/index.js
new file mode 100644
index 000000000..150a8fcf8
--- /dev/null
+++ b/test/transforms/fixtures/by-key/unwrap-inline-by-key/single-block/index.js
@@ -0,0 +1,14 @@
+
+import assert from 'assert'
+
+export default function (state) {
+ const { document, selection } = state
+ const inline = document.assertPath([0, 1])
+
+ const next = state
+ .transform()
+ .unwrapInlineByKey(inline.key, 'hashtag')
+ .apply()
+
+ return next
+}
diff --git a/test/transforms/fixtures/by-key/unwrap-inline-by-key/single-block/input.yaml b/test/transforms/fixtures/by-key/unwrap-inline-by-key/single-block/input.yaml
new file mode 100644
index 000000000..4a8715778
--- /dev/null
+++ b/test/transforms/fixtures/by-key/unwrap-inline-by-key/single-block/input.yaml
@@ -0,0 +1,19 @@
+
+nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: w
+ - kind: inline
+ type: hashtag
+ nodes:
+ - kind: text
+ text: or
+ - kind: text
+ text: d
+ - kind: inline
+ type: hashtag
+ nodes:
+ - kind: text
+ text: another
diff --git a/test/transforms/fixtures/by-key/unwrap-inline-by-key/single-block/output.yaml b/test/transforms/fixtures/by-key/unwrap-inline-by-key/single-block/output.yaml
new file mode 100644
index 000000000..f5dba7769
--- /dev/null
+++ b/test/transforms/fixtures/by-key/unwrap-inline-by-key/single-block/output.yaml
@@ -0,0 +1,12 @@
+
+nodes:
+ - kind: block
+ type: paragraph
+ nodes:
+ - kind: text
+ text: word
+ - kind: inline
+ type: hashtag
+ nodes:
+ - kind: text
+ text: another