diff --git a/.changeset/heavy-pants-cover.md b/.changeset/heavy-pants-cover.md new file mode 100644 index 000000000..4a425bc58 --- /dev/null +++ b/.changeset/heavy-pants-cover.md @@ -0,0 +1,5 @@ +--- +'slate': patch +--- + +Fix: The `split: true` option on `Transforms.wrapNodes` does not work correctly when one or more points is at the start or end of a text node. diff --git a/packages/slate/src/transforms-node/wrap-nodes.ts b/packages/slate/src/transforms-node/wrap-nodes.ts index af2e15760..cae00d9d3 100644 --- a/packages/slate/src/transforms-node/wrap-nodes.ts +++ b/packages/slate/src/transforms-node/wrap-nodes.ts @@ -6,6 +6,7 @@ import { Element } from '../interfaces/element' import { Text } from '../interfaces/text' import { Range } from '../interfaces/range' import { Transforms } from '../interfaces/transforms' +import { Point } from '../interfaces' export const wrapNodes: NodeTransforms['wrapNodes'] = ( editor, @@ -33,11 +34,35 @@ export const wrapNodes: NodeTransforms['wrapNodes'] = ( if (split && Range.isRange(at)) { const [start, end] = Range.edges(at) + const rangeRef = Editor.rangeRef(editor, at, { affinity: 'inward', }) - Transforms.splitNodes(editor, { at: end, match, voids }) - Transforms.splitNodes(editor, { at: start, match, voids }) + + // Always split if we're in the middle of a block, to ensure that text + // node boundaries are handled correctly. + const isAtBlockEdge = (point: Point) => { + const blockAbove = Editor.above(editor, { + at: point, + match: n => Element.isElement(n) && Editor.isBlock(editor, n), + }) + return blockAbove && Editor.isEdge(editor, point, blockAbove[1]) + } + + Transforms.splitNodes(editor, { + at: end, + match, + voids, + always: !isAtBlockEdge(end), + }) + + Transforms.splitNodes(editor, { + at: start, + match, + voids, + always: !isAtBlockEdge(start), + }) + at = rangeRef.unref()! if (options.at == null) { diff --git a/packages/slate/test/transforms/wrapNodes/split-block/block-mark.tsx b/packages/slate/test/transforms/wrapNodes/split-block/block-mark.tsx new file mode 100644 index 000000000..9b746ee29 --- /dev/null +++ b/packages/slate/test/transforms/wrapNodes/split-block/block-mark.tsx @@ -0,0 +1,39 @@ +/** @jsx jsx */ +import { Transforms } from 'slate' +import { jsx } from '../../..' + +export const input = ( + + + + one + + + two + + + three + + + +) +export const run = editor => { + Transforms.wrapNodes(editor, , { split: true }) +} +export const output = ( + + one + + + + + two + + + + + + three + + +) diff --git a/packages/slate/test/transforms/wrapNodes/split-inline/inline-mark.tsx b/packages/slate/test/transforms/wrapNodes/split-inline/inline-mark.tsx new file mode 100644 index 000000000..9d1ddad1c --- /dev/null +++ b/packages/slate/test/transforms/wrapNodes/split-inline/inline-mark.tsx @@ -0,0 +1,37 @@ +/** @jsx jsx */ +import { Transforms } from 'slate' +import { jsx } from '../../..' + +export const input = ( + + + + one + + + two + + + three + + + +) +export const run = editor => { + Transforms.wrapNodes(editor, , { split: true }) +} +export const output = ( + + + one + + + + two + + + + three + + +)