1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-04-20 05:11:53 +02:00

Fix overly-aggressive unhangRange (#5193)

`Editor.unhangRange()` could decide to proceed with an adjustment in cases where the range was not hanging.
Because the algorithm it uses *always* skips over the first node it encounters, this meant the selection was adjusted in non-hanging cases.
This change reduces the chances of an incorrect decision to adjust.
Transforms now pass the `voids` flag to `unhangRange()` as it seems logical that the adjusted range should reflect the intention of the operation.
This fixes a unit test I added for markable voids that had to be skipped because of the `unhangRange()` error, and fixes a couple other long-skipped tests.
This commit is contained in:
Brian Bucknam 2022-11-17 09:18:11 -08:00 committed by GitHub
parent c8c75e9e2d
commit 6909a8f7da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 183 additions and 12 deletions

View File

@ -0,0 +1,5 @@
---
'slate': patch
---
Stops Editor.unhangRange() from adjusting the range in some cases when it was not actually hanging

View File

@ -1632,13 +1632,19 @@ export const Editor: EditorInterface = {
let [start, end] = Range.edges(range)
// PERF: exit early if we can guarantee that the range isn't hanging.
if (start.offset !== 0 || end.offset !== 0 || Range.isCollapsed(range)) {
if (
start.offset !== 0 ||
end.offset !== 0 ||
Range.isCollapsed(range) ||
Path.hasPrevious(end.path)
) {
return range
}
const endBlock = Editor.above(editor, {
at: end,
match: n => Editor.isBlock(editor, n),
voids,
})
const blockPath = endBlock ? endBlock[1] : []
const first = Editor.start(editor, start)

View File

@ -180,7 +180,7 @@ export const NodeTransforms: NodeTransforms = {
if (Range.isRange(at)) {
if (!hanging) {
at = Editor.unhangRange(editor, at)
at = Editor.unhangRange(editor, at, { voids })
}
if (Range.isCollapsed(at)) {
@ -345,7 +345,7 @@ export const NodeTransforms: NodeTransforms = {
}
if (!hanging && Range.isRange(at)) {
at = Editor.unhangRange(editor, at)
at = Editor.unhangRange(editor, at, { voids })
}
if (Range.isRange(at)) {
@ -543,7 +543,7 @@ export const NodeTransforms: NodeTransforms = {
}
if (!hanging && Range.isRange(at)) {
at = Editor.unhangRange(editor, at)
at = Editor.unhangRange(editor, at, { voids })
}
const depths = Editor.nodes(editor, { at, match, mode, voids })
@ -598,7 +598,7 @@ export const NodeTransforms: NodeTransforms = {
}
if (!hanging && Range.isRange(at)) {
at = Editor.unhangRange(editor, at)
at = Editor.unhangRange(editor, at, { voids })
}
if (split && Range.isRange(at)) {

View File

@ -265,7 +265,7 @@ export const TextTransforms: TextTransforms = {
return
} else if (Range.isRange(at)) {
if (!hanging) {
at = Editor.unhangRange(editor, at)
at = Editor.unhangRange(editor, at, { voids })
}
if (Range.isCollapsed(at)) {

View File

@ -0,0 +1,29 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block>
<anchor />
This is a first paragraph
</block>
<block>This is the second paragraph</block>
<block void>
This is the third paragraph
{/* unhang should move focus to here */}
</block>
<block>
<focus />
</block>
</editor>
)
export const test = editor => {
return Editor.unhangRange(editor, editor.selection, { voids: true })
}
export const output = {
anchor: { path: [0, 0], offset: 0 },
focus: { path: [2, 0], offset: 27 },
}

View File

@ -8,8 +8,11 @@ export const input = (
<anchor />
This is a first paragraph
</block>
<block>This is the second paragraph</block>
<block void />
<block>
This is the second paragraph
{/* unhang should move focus to here because, without `voids` set, it should skip over void block below */}
</block>
<block void>This void paragraph gets skipped over</block>
<block>
<focus />
</block>

View File

@ -0,0 +1,30 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block>
<anchor />
This is a first paragraph
<inline void>
<text />
</inline>
<text />
{/* unhang should move focus to here */}
</block>
<block>
<focus />
This is the second paragraph
</block>
</editor>
)
export const test = editor => {
return Editor.unhangRange(editor, editor.selection, { voids: true })
}
export const output = {
anchor: { path: [0, 0], offset: 0 },
focus: { path: [0, 2], offset: 0 },
}

View File

@ -0,0 +1,37 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block>
<anchor />
This is the first paragraph
<inline void>
<text />
</inline>
<text />
</block>
<block>
This is the second paragraph
<inline void>
<text />
</inline>
<text />
{/* unhang should move focus to here */}
</block>
<block>
<focus />
This is the third paragraph
</block>
</editor>
)
export const test = editor => {
return Editor.unhangRange(editor, editor.selection, { voids: true })
}
export const output = {
anchor: { path: [0, 0], offset: 0 },
focus: { path: [1, 2], offset: 0 },
}

View File

@ -0,0 +1,29 @@
/** @jsx jsx */
/* The starting selection range is not hanging, so should not be adjusted */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block>
<anchor />
This is the first paragraph
<inline void>
<text />
</inline>
<text>
<focus />
</text>
</block>
<block>This is the second paragraph</block>
</editor>
)
export const test = editor => {
return Editor.unhangRange(editor, editor.selection, { voids: true })
}
export const output = {
anchor: { path: [0, 0], offset: 0 },
focus: { path: [0, 2], offset: 0 },
}

View File

@ -0,0 +1,36 @@
/** @jsx jsx */
/* The starting selection range is not hanging, so should not be adjusted */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block>
<anchor />
This is the first paragraph
<inline void>
<text />
</inline>
<text />
</block>
<block>
This is the second paragraph
<inline void>
<text />
</inline>
<text>
<focus />
</text>
</block>
<block>This is the third paragraph</block>
</editor>
)
export const test = editor => {
return Editor.unhangRange(editor, editor.selection, { voids: true })
}
export const output = {
anchor: { path: [0, 0], offset: 0 },
focus: { path: [1, 2], offset: 0 },
}

View File

@ -28,4 +28,3 @@ export const output = (
</block>
</editor>
)
export const skip = true

View File

@ -25,4 +25,3 @@ export const output = (
<block>two</block>
</editor>
)
export const skip = true

View File

@ -47,5 +47,3 @@ export const output = (
</block>
</editor>
)
// TODO this has to be skipped because the second void and the final empty text fail to be marked bold
export const skip = true