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:
5
.changeset/popular-bags-relax.md
Normal file
5
.changeset/popular-bags-relax.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'slate': patch
|
||||
---
|
||||
|
||||
Optimize editor#above and allow passing a location that doesnt exist as long as its parent exists
|
@@ -1,6 +1,5 @@
|
||||
import { Editor, EditorInterface } from '../interfaces/editor'
|
||||
import { Text } from '../interfaces/text'
|
||||
import { Range } from '../interfaces/range'
|
||||
import { Range } from '../interfaces'
|
||||
import { Path } from '../interfaces/path'
|
||||
|
||||
export const above: EditorInterface['above'] = (editor, options = {}) => {
|
||||
@@ -15,27 +14,22 @@ export const above: EditorInterface['above'] = (editor, options = {}) => {
|
||||
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'
|
||||
|
||||
for (const [n, p] of Editor.levels(editor, {
|
||||
const [firstMatch] = Editor.levels(editor, {
|
||||
at: path,
|
||||
voids,
|
||||
match,
|
||||
reverse,
|
||||
})) {
|
||||
if (Text.isText(n)) continue
|
||||
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]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
return firstMatch // if nothing matches this returns undefined
|
||||
}
|
||||
|
@@ -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],
|
||||
]
|
Reference in New Issue
Block a user