From 797b58e5c5ac3af9a88aa20c207142d2b282bebd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samy=20Pess=C3=A9?= Date: Fri, 2 Dec 2016 14:05:45 +0100 Subject: [PATCH] Implement "wrapInlineByKey" and use it in "wrapInlineAtRange" --- docs/reference/models/transform.md | 7 ++++++ src/transforms/at-range.js | 19 +++++++++++---- src/transforms/by-key.js | 24 +++++++++++++++++++ src/transforms/index.js | 2 ++ .../wrap-inline/inline-void/output.yaml | 4 ++++ .../wrap-inline-void/index.js | 22 +++++++++++++++++ .../wrap-inline-void/input.yaml | 9 +++++++ .../wrap-inline-void/output.yaml | 15 ++++++++++++ 8 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 test/transforms/fixtures/at-range/wrap-inline-at-range/wrap-inline-void/index.js create mode 100644 test/transforms/fixtures/at-range/wrap-inline-at-range/wrap-inline-void/input.yaml create mode 100644 test/transforms/fixtures/at-range/wrap-inline-at-range/wrap-inline-void/output.yaml diff --git a/docs/reference/models/transform.md b/docs/reference/models/transform.md index 235facfc5..19c5abd67 100644 --- a/docs/reference/models/transform.md +++ b/docs/reference/models/transform.md @@ -60,6 +60,7 @@ Transform methods can either operate on the [`Document`](./document.md), the [`S - [`unwrapInlineByKey`](#unwrapinlinebykey) - [`unwrapBlockByKey`](#unwrapblockbykey) - [`wrapBlockByKey`](#wrapblockbykey) + - [`wrapInlineByKey`](#wrapinlinebykey) - [Document Transforms](#document-transforms) - [`deleteAtRange`](#deleteatrange) - [`deleteBackwardAtRange`](#deletebackwardatrange) @@ -338,6 +339,12 @@ Unwrap all inner content of a [`Block`](./block.md) node that match `properties` Wrap the given node in a [`Block`](./block.md) node that match `properties`. For convenience, you can pass a `type` string or `properties` object. +### `wrapInlineByKey` +`wrapInlineByKey(key: String, properties: Object) => Transform`
+`wrapInlineByKey(key: String, type: String) => Transform` + +Wrap the given node in a [`Inline`](./inline.md) node that match `properties`. For convenience, you can pass a `type` string or `properties` object. + ## Document Transforms ### `deleteBackwardAtRange` diff --git a/src/transforms/at-range.js b/src/transforms/at-range.js index a8079a9fb..dc6773bba 100644 --- a/src/transforms/at-range.js +++ b/src/transforms/at-range.js @@ -987,15 +987,24 @@ export function wrapBlockAtRange(transform, range, block, options = {}) { */ export function wrapInlineAtRange(transform, range, inline, options = {}) { - if (range.isCollapsed) return + let { state } = transform + let { document } = state + const { normalize = true } = options + const { startKey, startOffset, endKey, endOffset } = range + + if (range.isCollapsed) { + // Wrapping an inline void + const inlineParent = document.getClosestInline(startKey) + if (!inlineParent.isVoid) { + return + } + + return transform.wrapInlineByKey(inlineParent.key, inline, options) + } inline = Normalize.inline(inline) inline = inline.merge({ nodes: inline.nodes.clear() }) - const { normalize = true } = options - const { startKey, startOffset, endKey, endOffset } = range - let { state } = transform - let { document } = state const blocks = document.getBlocksAtRange(range) let startBlock = document.getClosestBlock(startKey) let endBlock = document.getClosestBlock(endKey) diff --git a/src/transforms/by-key.js b/src/transforms/by-key.js index 3a128f803..2cd3eccc8 100644 --- a/src/transforms/by-key.js +++ b/src/transforms/by-key.js @@ -324,6 +324,30 @@ export function unwrapBlockByKey(transform, key, properties, options) { transform.unwrapBlockAtRange(range, properties, options) } + +/** + * Wrap a node in an inline with `properties`. + * + * @param {Transform} transform + * @param {String} key The node to wrap + * @param {Block|Object|String} inline The wrapping inline (its children are discarded) + * @param {Object} options + * @property {Boolean} normalize + */ + +export function wrapInlineByKey(transform, key, inline, options) { + inline = Normalize.inline(inline) + inline = inline.merge({ nodes: inline.nodes.clear() }) + + const { document } = transform.state + const node = document.assertDescendant(key) + const parent = document.getParent(node.key) + const index = parent.nodes.indexOf(node) + + transform.insertNodeByKey(parent.key, index, inline, { normalize: false }) + transform.moveNodeByKey(node.key, inline.key, 0, options) +} + /** * Wrap a node in a block with `properties`. * diff --git a/src/transforms/index.js b/src/transforms/index.js index 0f02063ea..fc16fb196 100644 --- a/src/transforms/index.js +++ b/src/transforms/index.js @@ -109,6 +109,7 @@ import { unwrapInlineByKey, unwrapBlockByKey, wrapBlockByKey, + wrapInlineByKey, } from './by-key' /** @@ -278,6 +279,7 @@ export default { unwrapInlineByKey, unwrapBlockByKey, wrapBlockByKey, + wrapInlineByKey, /** * On selection. diff --git a/test/transforms/fixtures/at-current-range/wrap-inline/inline-void/output.yaml b/test/transforms/fixtures/at-current-range/wrap-inline/inline-void/output.yaml index 3accc6952..8bf924c83 100644 --- a/test/transforms/fixtures/at-current-range/wrap-inline/inline-void/output.yaml +++ b/test/transforms/fixtures/at-current-range/wrap-inline/inline-void/output.yaml @@ -6,6 +6,10 @@ nodes: - kind: inline type: link nodes: + - kind: text + text: "" - kind: inline isVoid: true type: image + - kind: text + text: "" diff --git a/test/transforms/fixtures/at-range/wrap-inline-at-range/wrap-inline-void/index.js b/test/transforms/fixtures/at-range/wrap-inline-at-range/wrap-inline-void/index.js new file mode 100644 index 000000000..60352e380 --- /dev/null +++ b/test/transforms/fixtures/at-range/wrap-inline-at-range/wrap-inline-void/index.js @@ -0,0 +1,22 @@ + +export default function (state) { + const { document, selection } = state + const texts = document.getTexts() + // The first text is the one arround the inline void + const second = texts.get(1) + const range = selection.merge({ + anchorKey: second.key, + anchorOffset: 0, + focusKey: second.key, + focusOffset: 0 + }) + + const next = state + .transform() + .wrapInlineAtRange(range, { + type: 'link' + }) + .apply() + + return next +} diff --git a/test/transforms/fixtures/at-range/wrap-inline-at-range/wrap-inline-void/input.yaml b/test/transforms/fixtures/at-range/wrap-inline-at-range/wrap-inline-void/input.yaml new file mode 100644 index 000000000..1a259e41b --- /dev/null +++ b/test/transforms/fixtures/at-range/wrap-inline-at-range/wrap-inline-void/input.yaml @@ -0,0 +1,9 @@ + +nodes: + - kind: block + type: paragraph + nodes: + - kind: inline + key: image + isVoid: true + type: image diff --git a/test/transforms/fixtures/at-range/wrap-inline-at-range/wrap-inline-void/output.yaml b/test/transforms/fixtures/at-range/wrap-inline-at-range/wrap-inline-void/output.yaml new file mode 100644 index 000000000..8bf924c83 --- /dev/null +++ b/test/transforms/fixtures/at-range/wrap-inline-at-range/wrap-inline-void/output.yaml @@ -0,0 +1,15 @@ + +nodes: + - kind: block + type: paragraph + nodes: + - kind: inline + type: link + nodes: + - kind: text + text: "" + - kind: inline + isVoid: true + type: image + - kind: text + text: ""