diff --git a/docs/reference/models/transform.md b/docs/reference/models/transform.md index e99de6985..de57a41fd 100644 --- a/docs/reference/models/transform.md +++ b/docs/reference/models/transform.md @@ -56,6 +56,7 @@ Transform methods can either operate on the [`Document`](./document.md), the [`S - [Node Transforms](#node-transforms) - [`addMarkByKey`](#addmarkbykey) - [`insertNodeByKey`](#insertnodebykey) + - [`insertFragmentByKey`](#insertfragmentbykey) - [`insertTextByKey`](#inserttextbykey) - [`moveNodeByKey`](#movenodebykey) - [`removeMarkByKey`](#removemarkbykey) @@ -332,6 +333,11 @@ Add a `mark` to `length` characters starting at an `offset` in a [`Node`](./node Insert a `node` at `index` inside a parent [`Node`](./node.md) by its `key`. +### `insertFragmentByKey` +`insertFragmentByKey(key: String, index: Number, fragment: Fragment) => Transform` + +Insert a [`Fragment`](./fragment.md) at `index` inside a parent [`Node`](./node.md) by its `key`. + ### `insertTextByKey` `insertTextByKey(key: String, offset: Number, text: String, [marks: Set]) => Transform` diff --git a/src/transforms/by-key.js b/src/transforms/by-key.js index 67e5bd9d0..699c4b3d6 100644 --- a/src/transforms/by-key.js +++ b/src/transforms/by-key.js @@ -37,6 +37,27 @@ Transforms.addMarkByKey = (transform, key, offset, length, mark, options = {}) = } } +/** + * Insert a `fragment` at `index` in a node by `key`. + * + * @param {Transform} transform + * @param {String} key + * @param {Number} index + * @param {Fragment} fragment + * @param {Object} options + * @property {Boolean} normalize + */ + +Transforms.insertFragmentByKey = (transform, key, index, fragment, options = {}) => { + const { normalize = true } = options + + fragment.nodes.forEach((node, i) => transform.insertNodeByKey(key, index + i, node)) + + if (normalize) { + transform.normalizeNodeByKey(key, SCHEMA) + } +} + /** * Insert a `node` at `index` in a node by `key`. * diff --git a/test/transforms/fixtures/by-key/insert-fragment-by-key/end-of-target/fragment.yaml b/test/transforms/fixtures/by-key/insert-fragment-by-key/end-of-target/fragment.yaml new file mode 100644 index 000000000..bcead8e4c --- /dev/null +++ b/test/transforms/fixtures/by-key/insert-fragment-by-key/end-of-target/fragment.yaml @@ -0,0 +1,12 @@ + +nodes: + - kind: block + type: paragraph + nodes: + - kind: text + text: fragment + - kind: block + type: paragraph + nodes: + - kind: text + text: fragment2 diff --git a/test/transforms/fixtures/by-key/insert-fragment-by-key/end-of-target/index.js b/test/transforms/fixtures/by-key/insert-fragment-by-key/end-of-target/index.js new file mode 100644 index 000000000..fc2dc70a1 --- /dev/null +++ b/test/transforms/fixtures/by-key/insert-fragment-by-key/end-of-target/index.js @@ -0,0 +1,18 @@ + +import path from 'path' +import readMetadata from 'read-metadata' +import { Raw } from '../../../../../..' + +export default function (state) { + const file = path.resolve(__dirname, 'fragment.yaml') + const raw = readMetadata.sync(file) + const fragment = Raw.deserialize(raw, { terse: true }).document + + const { document } = state + const end = document.nodes.size + + return state + .transform() + .insertFragmentByKey(document.key, end, fragment) + .apply() +} diff --git a/test/transforms/fixtures/by-key/insert-fragment-by-key/end-of-target/input.yaml b/test/transforms/fixtures/by-key/insert-fragment-by-key/end-of-target/input.yaml new file mode 100644 index 000000000..27f668fe2 --- /dev/null +++ b/test/transforms/fixtures/by-key/insert-fragment-by-key/end-of-target/input.yaml @@ -0,0 +1,7 @@ + +nodes: + - kind: block + type: paragraph + nodes: + - kind: text + text: word diff --git a/test/transforms/fixtures/by-key/insert-fragment-by-key/end-of-target/output.yaml b/test/transforms/fixtures/by-key/insert-fragment-by-key/end-of-target/output.yaml new file mode 100644 index 000000000..f9792bf00 --- /dev/null +++ b/test/transforms/fixtures/by-key/insert-fragment-by-key/end-of-target/output.yaml @@ -0,0 +1,17 @@ + +nodes: + - kind: block + type: paragraph + nodes: + - kind: text + text: word + - kind: block + type: paragraph + nodes: + - kind: text + text: fragment + - kind: block + type: paragraph + nodes: + - kind: text + text: fragment2 diff --git a/test/transforms/fixtures/by-key/insert-fragment-by-key/middle-of-target/fragment.yaml b/test/transforms/fixtures/by-key/insert-fragment-by-key/middle-of-target/fragment.yaml new file mode 100644 index 000000000..bcead8e4c --- /dev/null +++ b/test/transforms/fixtures/by-key/insert-fragment-by-key/middle-of-target/fragment.yaml @@ -0,0 +1,12 @@ + +nodes: + - kind: block + type: paragraph + nodes: + - kind: text + text: fragment + - kind: block + type: paragraph + nodes: + - kind: text + text: fragment2 diff --git a/test/transforms/fixtures/by-key/insert-fragment-by-key/middle-of-target/index.js b/test/transforms/fixtures/by-key/insert-fragment-by-key/middle-of-target/index.js new file mode 100644 index 000000000..1102cb5ac --- /dev/null +++ b/test/transforms/fixtures/by-key/insert-fragment-by-key/middle-of-target/index.js @@ -0,0 +1,17 @@ + +import path from 'path' +import readMetadata from 'read-metadata' +import { Raw } from '../../../../../..' + +export default function (state) { + const file = path.resolve(__dirname, 'fragment.yaml') + const raw = readMetadata.sync(file) + const fragment = Raw.deserialize(raw, { terse: true }).document + + const { document } = state + + return state + .transform() + .insertFragmentByKey(document.key, 2, fragment) + .apply() +} diff --git a/test/transforms/fixtures/by-key/insert-fragment-by-key/middle-of-target/input.yaml b/test/transforms/fixtures/by-key/insert-fragment-by-key/middle-of-target/input.yaml new file mode 100644 index 000000000..cba6b71ab --- /dev/null +++ b/test/transforms/fixtures/by-key/insert-fragment-by-key/middle-of-target/input.yaml @@ -0,0 +1,17 @@ + +nodes: + - kind: block + type: paragraph + nodes: + - kind: text + text: word + - kind: block + type: paragraph + nodes: + - kind: text + text: word2 + - kind: block + type: paragraph + nodes: + - kind: text + text: word3 diff --git a/test/transforms/fixtures/by-key/insert-fragment-by-key/middle-of-target/output.yaml b/test/transforms/fixtures/by-key/insert-fragment-by-key/middle-of-target/output.yaml new file mode 100644 index 000000000..5f87a11e0 --- /dev/null +++ b/test/transforms/fixtures/by-key/insert-fragment-by-key/middle-of-target/output.yaml @@ -0,0 +1,27 @@ + +nodes: + - kind: block + type: paragraph + nodes: + - kind: text + text: word + - kind: block + type: paragraph + nodes: + - kind: text + text: word2 + - kind: block + type: paragraph + nodes: + - kind: text + text: fragment + - kind: block + type: paragraph + nodes: + - kind: text + text: fragment2 + - kind: block + type: paragraph + nodes: + - kind: text + text: word3 diff --git a/test/transforms/fixtures/by-key/insert-fragment-by-key/start-of-target/fragment.yaml b/test/transforms/fixtures/by-key/insert-fragment-by-key/start-of-target/fragment.yaml new file mode 100644 index 000000000..bcead8e4c --- /dev/null +++ b/test/transforms/fixtures/by-key/insert-fragment-by-key/start-of-target/fragment.yaml @@ -0,0 +1,12 @@ + +nodes: + - kind: block + type: paragraph + nodes: + - kind: text + text: fragment + - kind: block + type: paragraph + nodes: + - kind: text + text: fragment2 diff --git a/test/transforms/fixtures/by-key/insert-fragment-by-key/start-of-target/index.js b/test/transforms/fixtures/by-key/insert-fragment-by-key/start-of-target/index.js new file mode 100644 index 000000000..e393f377d --- /dev/null +++ b/test/transforms/fixtures/by-key/insert-fragment-by-key/start-of-target/index.js @@ -0,0 +1,17 @@ + +import path from 'path' +import readMetadata from 'read-metadata' +import { Raw } from '../../../../../..' + +export default function (state) { + const file = path.resolve(__dirname, 'fragment.yaml') + const raw = readMetadata.sync(file) + const fragment = Raw.deserialize(raw, { terse: true }).document + + const { document } = state + + return state + .transform() + .insertFragmentByKey(document.key, 0, fragment) + .apply() +} diff --git a/test/transforms/fixtures/by-key/insert-fragment-by-key/start-of-target/input.yaml b/test/transforms/fixtures/by-key/insert-fragment-by-key/start-of-target/input.yaml new file mode 100644 index 000000000..27f668fe2 --- /dev/null +++ b/test/transforms/fixtures/by-key/insert-fragment-by-key/start-of-target/input.yaml @@ -0,0 +1,7 @@ + +nodes: + - kind: block + type: paragraph + nodes: + - kind: text + text: word diff --git a/test/transforms/fixtures/by-key/insert-fragment-by-key/start-of-target/output.yaml b/test/transforms/fixtures/by-key/insert-fragment-by-key/start-of-target/output.yaml new file mode 100644 index 000000000..deb0947fc --- /dev/null +++ b/test/transforms/fixtures/by-key/insert-fragment-by-key/start-of-target/output.yaml @@ -0,0 +1,17 @@ + +nodes: + - kind: block + type: paragraph + nodes: + - kind: text + text: fragment + - kind: block + type: paragraph + nodes: + - kind: text + text: fragment2 + - kind: block + type: paragraph + nodes: + - kind: text + text: word