1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-30 18:39:51 +02:00

Optimize editor#above and allow passing a location that doesnt exist as long as its parent exists (#5880)

* optimize editor#apply and allow potential paths as input

* fix Editor#above regression for cross-node ranges

* add test to prevent regressions

* add changeset

* improve comment

* factor out for-loop that will never actually loop

* aw crud I didnt lint. fixing
This commit is contained in:
nabbydude
2025-05-24 19:34:18 -04:00
committed by GitHub
parent 05263b544c
commit de260565c7
3 changed files with 51 additions and 19 deletions

View File

@@ -0,0 +1,5 @@
---
'slate': patch
---
Optimize editor#above and allow passing a location that doesnt exist as long as its parent exists

View File

@@ -1,6 +1,5 @@
import { Editor, EditorInterface } from '../interfaces/editor' import { Editor, EditorInterface } from '../interfaces/editor'
import { Text } from '../interfaces/text' import { Range } from '../interfaces'
import { Range } from '../interfaces/range'
import { Path } from '../interfaces/path' import { Path } from '../interfaces/path'
export const above: EditorInterface['above'] = (editor, options = {}) => { export const above: EditorInterface['above'] = (editor, options = {}) => {
@@ -15,27 +14,22 @@ export const above: EditorInterface['above'] = (editor, options = {}) => {
return return
} }
const path = Editor.path(editor, at) let path = Editor.path(editor, at)
// If `at` is a Range that spans mulitple nodes, `path` will be their common ancestor.
// Otherwise `path` will be a text node and/or the same as `at`, in which cases we want to start with its parent.
if (!Range.isRange(at) || Path.equals(at.focus.path, at.anchor.path)) {
if (path.length === 0) return
path = Path.parent(path)
}
const reverse = mode === 'lowest' const reverse = mode === 'lowest'
for (const [n, p] of Editor.levels(editor, { const [firstMatch] = Editor.levels(editor, {
at: path, at: path,
voids, voids,
match, match,
reverse, reverse,
})) { })
if (Text.isText(n)) continue return firstMatch // if nothing matches this returns undefined
if (Range.isRange(at)) {
if (
Path.isAncestor(p, at.anchor.path) &&
Path.isAncestor(p, at.focus.path)
) {
return [n, p]
}
} else {
if (!Path.equals(path, p)) {
return [n, p]
}
}
}
} }

View File

@@ -0,0 +1,33 @@
/** @jsx jsx */
import { Editor, Element } from 'slate'
import { jsx } from '../../..'
// `above` can never return the location passed into it, and shouldnt care if it exists, only if its parent exists.
export const input = (
<editor>
<block>
<block>
<block>one</block>
{/* path points here */}
</block>
<block>two</block>
</block>
</editor>
)
const path = [0, 0, 1]
export const test = editor => {
return Editor.above(editor, {
at: path,
match: n => Element.isElement(n) && Editor.isBlock(editor, n),
})
}
export const output = [
<block>
<block>one</block>
</block>,
[0, 0],
]