1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-24 16:02:55 +02:00

Standardize node matching APIs (#3327)

* add lowest mode and universal flag to `Editor.nodes`

* add `mode` handling to all transforms

* add extra `Editor.is*` helpers

* change `Editor.previous` to make all optional

* change `Editor.next` to make all optional

* change `Editor.match` to make all optional

* add `Editor.void` helper

* remove non-function match arguments

* remove NodeMatch interface

* change to lowest match by default everywhere

* rename `Editor.match` to `Editor.above`

* use new helpers

* cleanup

* make NodeEntry generic, cleanup

* fix NodeEntry generics

* ensure only ancestors are returned from Editor.above

* add type-narrowing to `Editor.nodes`, remove extras

* remove other Node entry types

* cleanup

* remove `Editor.block` and `Editor.inline` helpers
This commit is contained in:
Ian Storm Taylor
2019-12-15 19:36:05 -05:00
committed by GitHub
parent b927fa3a11
commit 7d832b5e12
136 changed files with 894 additions and 1034 deletions

View File

@@ -81,9 +81,6 @@ The `Editor` interface, like all Slate interfaces, exposes helper functions that
// Get the start point of a specific node at path.
const point = Editor.start(editor, [0, 0])
// Check whether an element matches a set of properties.
const isMatch = Editor.isMatch(editor, element, { type: 'quote' })
// Get the fragment (a slice of the document) at a range.
const fragment = Editor.fragment(editor, range)
```
@@ -91,8 +88,8 @@ const fragment = Editor.fragment(editor, range)
There are also many iterator-based helpers, for example:
```js
// Iterate over every element in a range.
for (const [element, path] of Editor.elements(editor, { at: range })) {
// Iterate over every node in a range.
for (const [node, path] of Editor.nodes(editor, { at: range })) {
// ...
}

View File

@@ -147,7 +147,11 @@ const App = () => {
// Prevent the "`" from being inserted by default.
event.preventDefault()
// Otherwise, set the currently selected blocks type to "code".
Editor.setNodes(editor, { type: 'code' }, { match: 'block' })
Editor.setNodes(
editor,
{ type: 'code' },
{ match: n => Editor.isBlock(editor, n) }
)
}
}}
/>
@@ -200,12 +204,14 @@ const App = () => {
if (event.key === '`' && event.ctrlKey) {
event.preventDefault()
// Determine whether any of the currently selected blocks are code blocks.
const [match] = Editor.nodes(editor, { match: { type: 'code' } })
const [match] = Editor.nodes(editor, {
match: n => n.type === 'code',
})
// Toggle the block type depending on whether there's already a match.
Editor.setNodes(
editor,
{ type: match ? 'paragraph' : 'code' },
{ match: 'block' }
{ match: n => Editor.isBlock(editor, n) }
)
}
}}

View File

@@ -33,11 +33,13 @@ const App = () => {
if (event.key === '`' && event.ctrlKey) {
event.preventDefault()
const { selection } = editor
const [match] = Editor.nodes(editor, { match: { type: 'code' } })
const [match] = Editor.nodes(editor, {
match: n => n.type === 'code',
})
Editor.setNodes(
editor,
{ type: match ? 'paragraph' : 'code' },
{ match: 'block' }
{ match: n => Editor.isBlock(editor, n) }
)
}
}}
@@ -81,11 +83,13 @@ const App = () => {
// When "`" is pressed, keep our existing code block logic.
case '`': {
event.preventDefault()
const [match] = Editor.nodes(editor, { match: { type: 'code' } })
const [match] = Editor.nodes(editor, {
match: n => n.type === 'code',
})
Editor.setNodes(
editor,
{ type: match ? 'paragraph' : 'code' },
{ match: 'block' }
{ match: n => Editor.isBlock(editor, n) }
)
break
}
@@ -98,7 +102,7 @@ const App = () => {
{ bold: true },
// Apply it to text nodes, and split the text node up if the
// selection is overlapping only part of it.
{ match: 'text', split: true }
{ match: n => Text.isText(n), split: true }
)
break
}
@@ -170,11 +174,13 @@ const App = () => {
switch (event.key) {
case '`': {
event.preventDefault()
const [match] = Editor.nodes(editor, { match: { type: 'code' } })
const [match] = Editor.nodes(editor, {
match: n => n.type === 'code',
})
Editor.setNodes(
editor,
{ type: match ? null : 'code' },
{ match: 'block' }
{ match: n => Editor.isBlock(editor, n) }
)
break
}
@@ -184,7 +190,7 @@ const App = () => {
Editor.setNodes(
editor,
{ bold: true },
{ match: 'text', split: true }
{ match: n => Text.isText(n), split: true }
)
break
}

View File

@@ -46,11 +46,13 @@ const App = () => {
switch (event.key) {
case '`': {
event.preventDefault()
const [match] = Editor.nodes(editor, { match: { type: 'code' } })
const [match] = Editor.nodes(editor, {
match: n => n.type === 'code',
})
Editor.setNodes(
editor,
{ type: match ? null : 'code' },
{ match: 'block' }
{ match: n => Editor.isBlock(editor, n) }
)
break
}
@@ -60,7 +62,7 @@ const App = () => {
Editor.setNodes(
editor,
{ bold: true },
{ match: 'text', split: true }
{ match: n => Text.isText(n), split: true }
)
break
}
@@ -118,12 +120,14 @@ const App = () => {
switch (event.key) {
case '`': {
event.preventDefault()
const [node] = Editor.nodes(editor, { match: { type: 'code' } })
const isCodeActive = !!node
const [match] = Editor.nodes(editor, {
match: n => n.type === 'code',
})
const isCodeActive = !!match
Editor.setNodes(
editor,
{ type: isCodeActive ? null : 'code' },
{ match: 'block' }
{ match: n => Editor.isBlock(editor, n) }
)
break
}
@@ -133,7 +137,7 @@ const App = () => {
Editor.setNodes(
editor,
{ bold: true },
{ match: 'text', split: true }
{ match: n => Text.isText(n), split: true }
)
break
}
@@ -160,7 +164,7 @@ const withCustom = editor => {
Editor.setNodes(
editor,
{ bold: isActive ? null : true },
{ match: 'text', split: true }
{ match: n => Text.isText(n), split: true }
)
}
@@ -170,7 +174,7 @@ const withCustom = editor => {
Editor.setNodes(
editor,
{ type: isActive ? null : 'code' },
{ match: 'block' }
{ match: n => Editor.isBlock(editor, n) }
)
}
@@ -187,8 +191,8 @@ const withCustom = editor => {
const CustomEditor = {
isBoldMarkActive(editor) {
const [match] = Editor.nodes(editor, {
match: { bold: true },
mode: 'universal',
match: n => n.bold === true,
universal: true,
})
return !!match
@@ -196,8 +200,7 @@ const CustomEditor = {
isCodeBlockActive(editor) {
const [match] = Editor.nodes(editor, {
match: { type: 'code' },
mode: 'highest',
match: n => n.type === 'code',
})
return !!match

View File

@@ -512,7 +512,7 @@ export const Editable = (props: EditableProps) => {
const path = ReactEditor.findPath(editor, node)
const start = Editor.start(editor, path)
if (Editor.match(editor, start, 'void')) {
if (Editor.void(editor, { at: start })) {
const range = Editor.range(editor, start)
Editor.select(editor, range)
}
@@ -591,7 +591,7 @@ export const Editable = (props: EditableProps) => {
// default, and calling `preventDefault` hides the cursor.
const node = ReactEditor.toSlateNode(editor, event.target)
if (Element.isElement(node) && editor.isVoid(node)) {
if (Editor.isVoid(editor, node)) {
event.preventDefault()
}
}
@@ -606,7 +606,7 @@ export const Editable = (props: EditableProps) => {
) {
const node = ReactEditor.toSlateNode(editor, event.target)
const path = ReactEditor.findPath(editor, node)
const voidMatch = Editor.match(editor, path, 'void')
const voidMatch = Editor.void(editor, { at: path })
// If starting a drag on a void node, make sure it is selected
// so that it shows up in the selection's fragment.
@@ -989,8 +989,8 @@ const setFragmentData = (dataTransfer: DataTransfer, editor: Editor): void => {
}
const [start, end] = Range.edges(selection)
const startVoid = Editor.match(editor, start.path, 'void')
const endVoid = Editor.match(editor, end.path, 'void')
const startVoid = Editor.void(editor, { at: start.path })
const endVoid = Editor.void(editor, { at: end.path })
if (Range.isCollapsed(selection) && !startVoid) {
return

View File

@@ -83,7 +83,7 @@ const Element = (props: {
}
// If it's a void node, wrap the children in extra void-specific elements.
if (editor.isVoid(element)) {
if (Editor.isVoid(editor, element)) {
attributes['data-slate-void'] = true
if (!readOnly && isInline) {

View File

@@ -199,8 +199,7 @@ export const ReactEditor = {
// If we're inside a void node, force the offset to 0, otherwise the zero
// width spacing character will result in an incorrect offset of 1
const [match] = Editor.nodes(editor, { at: point, match: 'void' })
if (match) {
if (Editor.void(editor, { at: point })) {
point = { path: point.path, offset: 0 }
}
@@ -301,7 +300,7 @@ export const ReactEditor = {
// If the drop target is inside a void node, move it into either the
// next or previous node, depending on which side the `x` and `y`
// coordinates are closest to.
if (Element.isElement(node) && editor.isVoid(node)) {
if (Editor.isVoid(editor, node)) {
const rect = target.getBoundingClientRect()
const isPrev = editor.isInline(node)
? x - rect.left < rect.left + rect.width - x

View File

@@ -125,20 +125,19 @@ export const createEditor = (): Editor => {
if (Range.isExpanded(selection)) {
const [match] = Editor.nodes(editor, {
at: selection,
match: n => Text.isText(n) && Text.matches(n, properties),
// TODO: should be `mode: 'universal'`
universal: true,
})
if (match) {
const keys = Object.keys(properties)
Editor.unsetNodes(editor, keys, {
match: 'text',
match: Text.isText,
split: true,
})
} else {
Editor.setNodes(editor, properties, {
match: 'text',
match: Text.isText,
split: true,
})
}
@@ -186,17 +185,18 @@ export const createEditor = (): Editor => {
case 'insert_text': {
if (selection) {
const { anchor } = selection
// If the cursor is at the end of an inline, move it outside of
// the inline before inserting
if (Range.isCollapsed(selection)) {
const inline = Editor.match(editor, anchor, 'inline')
const inline = Editor.above(editor, {
match: n => Editor.isInline(editor, n),
mode: 'highest',
})
if (inline) {
const [, inlinePath] = inline
if (Editor.isEnd(editor, anchor, inlinePath)) {
if (Editor.isEnd(editor, selection.anchor, inlinePath)) {
const point = Editor.after(editor, inlinePath)!
Editor.setSelection(editor, { anchor: point, focus: point })
}

View File

@@ -5,7 +5,6 @@ import { GeneralTransforms } from './transforms/general'
import { GeneralQueries } from './queries/general'
import { LocationQueries } from './queries/location'
import { NodeTransforms } from './transforms/node'
import { NodeQueries } from './queries/node'
import { RangeQueries } from './queries/range'
import { SelectionTransforms } from './transforms/selection'
import { TextTransforms } from './transforms/text'
@@ -34,7 +33,6 @@ export const Editor = {
...GeneralQueries,
...GeneralTransforms,
...LocationQueries,
...NodeQueries,
...NodeTransforms,
...RangeQueries,
...SelectionTransforms,

View File

@@ -7,11 +7,12 @@ import {
Text,
PathRef,
PointRef,
Element,
NodeEntry,
Range,
RangeRef,
Node,
} from '../../..'
import { TextEntry } from '../../text'
export const NORMALIZING: WeakMap<Editor, boolean> = new WeakMap()
export const PATH_REFS: WeakMap<Editor, Set<PathRef>> = new WeakMap()
@@ -19,6 +20,14 @@ export const POINT_REFS: WeakMap<Editor, Set<PointRef>> = new WeakMap()
export const RANGE_REFS: WeakMap<Editor, Set<RangeRef>> = new WeakMap()
export const GeneralQueries = {
/**
* Check if a value is a block `Element` object.
*/
isBlock(editor: Editor, value: any): value is Element {
return Element.isElement(value) && !editor.isInline(value)
},
/**
* Check if a value is an `Editor` object.
*/
@@ -39,6 +48,14 @@ export const GeneralQueries = {
)
},
/**
* Check if a value is an inline `Element` object.
*/
isInline(editor: Editor, value: any): value is Element {
return Element.isElement(value) && editor.isInline(value)
},
/**
* Check if the editor is currently normalizing after each operation.
*/
@@ -48,6 +65,14 @@ export const GeneralQueries = {
return isNormalizing === undefined ? true : isNormalizing
},
/**
* Check if a value is a void `Element` object.
*/
isVoid(editor: Editor, value: any): value is Element {
return Element.isElement(value) && editor.isVoid(value)
},
/**
* Get the marks that would be added to text at the current selection.
*/
@@ -64,13 +89,10 @@ export const GeneralQueries = {
}
if (Range.isExpanded(selection)) {
const [match] = Editor.nodes(editor, {
match: 'text',
mode: 'all',
})
const [match] = Editor.nodes(editor, { match: Text.isText })
if (match) {
const [node] = match as TextEntry
const [node] = match as NodeEntry<Text>
const { text, ...rest } = node
return rest
} else {
@@ -83,8 +105,10 @@ export const GeneralQueries = {
let [node] = Editor.leaf(editor, path)
if (anchor.offset === 0) {
const prev = Editor.previous(editor, path, 'text')
const block = Editor.match(editor, path, 'block')
const prev = Editor.previous(editor, { at: path, match: Text.isText })
const block = Editor.above(editor, {
match: n => Editor.isBlock(editor, n),
})
if (prev && block) {
const [prevNode, prevPath] = prev

View File

@@ -1,26 +1,55 @@
import warning from 'tiny-warning'
import { reverse as reverseText } from 'esrever'
import {
Ancestor,
AncestorEntry,
Descendant,
Editor,
Element,
ElementEntry,
Location,
Node,
NodeEntry,
NodeMatch,
Path,
Point,
Range,
Span,
Text,
TextEntry,
} from '../../..'
export const LocationQueries = {
/**
* Get the ancestor above a location in the document.
*/
above<T extends Ancestor>(
editor: Editor,
options: {
at?: Location
match?: NodeMatch<T>
mode?: 'highest' | 'lowest'
voids?: boolean
} = {}
): NodeEntry<T> | undefined {
const { voids = false, mode = 'lowest', at = editor.selection } = options
let { match } = options
if (!match) {
match = () => true
}
if (!at) {
return
}
const path = Editor.path(editor, at)
const reverse = mode === 'lowest'
for (const [n, p] of Editor.levels(editor, { at: path, voids, reverse })) {
if (!Text.isText(n) && !Path.equals(path, p) && match(n)) {
return [n, p]
}
}
},
/**
* Get the point after a location.
*/
@@ -101,27 +130,6 @@ export const LocationQueries = {
return [Editor.start(editor, at), Editor.end(editor, at)]
},
/**
* Iterate through all of the elements in the Editor.
*/
*elements(
editor: Editor,
options: {
at?: Location
match?: NodeMatch
mode?: 'all' | 'highest'
reverse?: boolean
voids?: boolean
} = {}
): Iterable<ElementEntry> {
for (const [node, path] of Editor.nodes(editor, options)) {
if (Element.isElement(node)) {
yield [node, path]
}
}
},
/**
* Get the end point of a location.
*/
@@ -200,7 +208,7 @@ export const LocationQueries = {
depth?: number
edge?: 'start' | 'end'
} = {}
): TextEntry {
): NodeEntry<Text> {
const path = Editor.path(editor, at, options)
const node = Node.leaf(editor, path)
return [node, path]
@@ -230,7 +238,7 @@ export const LocationQueries = {
for (const [n, p] of Node.levels(editor, path)) {
levels.push([n, p])
if (!voids && Element.isElement(n) && editor.isVoid(n)) {
if (!voids && Editor.isVoid(editor, n)) {
break
}
}
@@ -243,88 +251,25 @@ export const LocationQueries = {
},
/**
* Get the first matching node in a single branch of the document.
* Get the matching node in the branch of the document after a location.
*/
match(
editor: Editor,
at: Location,
match: NodeMatch,
options: {
voids?: boolean
} = {}
): NodeEntry | undefined {
const { voids = false } = options
const path = Editor.path(editor, at)
for (const entry of Editor.levels(editor, { at: path, voids })) {
if (Editor.isMatch(editor, entry[0], match)) {
return entry
}
}
},
/**
* Iterate through all of the nodes that match.
*/
*matches(
next<T extends Node>(
editor: Editor,
options: {
at?: Location
match?: NodeMatch
reverse?: boolean
}
): Iterable<NodeEntry> {
warning(
false,
'The `Editor.matches` helper is deprecated, use `Editor.nodes` instead.'
)
const { at = editor.selection, reverse = false } = options
let { match } = options
match?: NodeMatch<T>
mode?: 'all' | 'highest' | 'lowest'
voids?: boolean
} = {}
): NodeEntry<T> | undefined {
const { mode = 'lowest', voids = false } = options
let { match, at = editor.selection } = options
if (!at) {
return
}
if (match == null) {
if (Path.isPath(at)) {
const [node] = Editor.node(editor, at)
match = n => n === node
} else {
match = () => true
}
}
let prevPath: Path | undefined
for (const [n, p] of Editor.nodes(editor, { at, reverse })) {
if (prevPath && Path.compare(p, prevPath) === 0) {
continue
}
if (Editor.isMatch(editor, n, match)) {
prevPath = p
yield [n, p]
}
}
},
/**
* Get the matching node in the branch of the document after a location.
*/
next(
editor: Editor,
at: Location,
match?: NodeMatch,
options: {
mode?: 'all' | 'highest'
voids?: boolean
} = {}
): NodeEntry | undefined {
const { mode = 'highest', voids = false } = options
const [, from] = Editor.last(editor, at)
const [, to] = Editor.last(editor, [])
const span: Span = [from, to]
@@ -367,23 +312,29 @@ export const LocationQueries = {
* Iterate through all of the nodes in the Editor.
*/
*nodes(
*nodes<T extends Node>(
editor: Editor,
options: {
at?: Location | Span
match?: NodeMatch
mode?: 'all' | 'highest'
match?: NodeMatch<T>
mode?: 'all' | 'highest' | 'lowest'
universal?: boolean
reverse?: boolean
voids?: boolean
} = {}
): Iterable<NodeEntry> {
): Iterable<NodeEntry<T>> {
const {
at = editor.selection,
match,
mode = 'all',
universal = false,
reverse = false,
voids = false,
} = options
let { match } = options
if (!match) {
match = () => true
}
if (!at) {
return
@@ -406,29 +357,65 @@ export const LocationQueries = {
reverse,
from,
to,
pass: ([n]) => (voids ? false : Element.isElement(n) && editor.isVoid(n)),
pass: ([n]) => (voids ? false : Editor.isVoid(editor, n)),
})
let prev: NodeEntry | undefined
const matches: NodeEntry<T>[] = []
let hit: NodeEntry<T> | undefined
for (const entry of iterable) {
if (match) {
if (
mode === 'highest' &&
prev &&
Path.compare(entry[1], prev[1]) === 0
) {
for (const [node, path] of iterable) {
const isLower = hit && Path.compare(path, hit[1]) === 0
// In highest mode any node lower than the last hit is not a match.
if (mode === 'highest' && isLower) {
continue
}
if (!Editor.isMatch(editor, entry[0], match)) {
if (!match(node)) {
// If we've arrived at a leaf text node that is not lower than the last
// hit, then we've found a branch that doesn't include a match, which
// means the match is not universal.
if (universal && !isLower && Text.isText(node)) {
return
} else {
continue
}
}
// If there's a match and it's lower than the last, update the hit.
if (mode === 'lowest' && isLower) {
hit = [node, path]
continue
}
prev = entry
// In lowest mode we emit the last hit, once it's guaranteed lowest.
const emit: NodeEntry<T> | undefined =
mode === 'lowest' ? hit : [node, path]
if (emit) {
if (universal) {
matches.push(emit)
} else {
yield emit
}
}
yield entry
hit = [node, path]
}
// Since lowest is always emitting one behind, catch up at the end.
if (mode === 'lowest' && hit) {
if (universal) {
matches.push(hit)
} else {
yield hit
}
}
// Universal defers to ensure that the match occurs in every branch, so we
// yield all of the matches after iterating.
if (universal) {
yield* matches
}
},
@@ -443,11 +430,11 @@ export const LocationQueries = {
depth?: number
edge?: 'start' | 'end'
} = {}
): AncestorEntry {
): NodeEntry<Ancestor> {
const path = Editor.path(editor, at, options)
const parentPath = Path.parent(path)
const entry = Editor.node(editor, parentPath)
return entry as AncestorEntry
return entry as NodeEntry<Ancestor>
},
/**
@@ -664,16 +651,22 @@ export const LocationQueries = {
* Get the matching node in the branch of the document before a location.
*/
previous(
previous<T extends Node>(
editor: Editor,
at: Location,
match?: NodeMatch,
options: {
mode?: 'all' | 'highest'
at?: Location
match?: NodeMatch<T>
mode?: 'all' | 'highest' | 'lowest'
voids?: boolean
} = {}
): NodeEntry | undefined {
const { mode = 'highest', voids = false } = options
): NodeEntry<T> | undefined {
const { mode = 'lowest', voids = false } = options
let { match, at = editor.selection } = options
if (!at) {
return
}
const [, from] = Editor.first(editor, at)
const [, to] = Editor.first(editor, [])
const span: Span = [from, to]
@@ -736,7 +729,10 @@ export const LocationQueries = {
const [start, end] = Range.edges(range)
let text = ''
for (const [node, path] of Editor.texts(editor, { at: range })) {
for (const [node, path] of Editor.nodes(editor, {
at: range,
match: Text.isText,
})) {
let t = node.text
if (Path.equals(path, end.path)) {
@@ -754,24 +750,21 @@ export const LocationQueries = {
},
/**
* Iterate through all of the text nodes in the Editor.
* Match a void node in the current branch of the editor.
*/
*texts(
void(
editor: Editor,
options: {
at?: Location
match?: NodeMatch
mode?: 'all' | 'highest'
reverse?: boolean
mode?: 'highest' | 'lowest'
voids?: boolean
} = {}
): Iterable<TextEntry> {
for (const [node, path] of Editor.nodes(editor, options)) {
if (Text.isText(node)) {
yield [node, path]
}
}
): NodeEntry<Element> | undefined {
return Editor.above(editor, {
...options,
match: n => Editor.isVoid(editor, n),
})
},
}
@@ -854,3 +847,11 @@ const getWordDistance = (text: string): number => {
return length
}
/**
* A helper type for narrowing matched nodes with a predicate.
*/
type NodeMatch<T extends Node> =
| ((node: Node) => node is T)
| ((node: Node) => boolean)

View File

@@ -1,38 +0,0 @@
import { Editor, Element, Node, NodeMatch, Text } from '../../..'
export const NodeQueries = {
/**
* Check if a node entry is a match.
*/
isMatch(editor: Editor, node: Node, match: NodeMatch): boolean {
if (Array.isArray(match)) {
return match.some(m => Editor.isMatch(editor, node, m))
}
switch (match) {
case 'text':
return Text.isText(node)
case 'editor':
return Editor.isEditor(node)
case 'element':
return Element.isElement(node)
case 'inline':
return Element.isElement(node) && editor.isInline(node)
case 'block':
return (
Element.isElement(node) &&
!editor.isInline(node) &&
Editor.hasInlines(editor, node)
)
case 'void':
return Element.isElement(node) && editor.isVoid(node)
}
if (typeof match === 'function') {
return match(node, editor)
} else {
return Node.matches(node, match)
}
},
}

View File

@@ -1,4 +1,4 @@
import { Editor, Path, Range } from '../../..'
import { Editor, Text, Path, Range } from '../../..'
export const RangeQueries = {
/**
@@ -20,14 +20,18 @@ export const RangeQueries = {
return range
}
const closestBlock = Editor.match(editor, end.path, 'block')
const blockPath = closestBlock ? closestBlock[1] : []
const endBlock = Editor.above(editor, {
at: end,
match: n => Editor.isBlock(editor, n),
})
const blockPath = endBlock ? endBlock[1] : []
const first = Editor.start(editor, [])
const before = { anchor: first, focus: end }
let skip = true
for (const [node, path] of Editor.texts(editor, {
for (const [node, path] of Editor.nodes(editor, {
at: before,
match: Text.isText,
reverse: true,
voids,
})) {

View File

@@ -8,9 +8,9 @@ import {
Element,
Operation,
Descendant,
NodeEntry,
Path,
} from '../../..'
import { TextEntry } from '../../text'
export const DIRTY_PATHS: WeakMap<Editor, Path[]> = new WeakMap()
@@ -178,8 +178,8 @@ export const GeneralTransforms = {
if (selection != null && result != null) {
selection[key] = result
} else {
let prev: TextEntry | undefined
let next: TextEntry | undefined
let prev: NodeEntry<Text> | undefined
let next: NodeEntry<Text> | undefined
for (const [n, p] of Node.texts(editor)) {
if (Path.compare(p, path) === -1) {

View File

@@ -3,8 +3,6 @@ import {
Element,
Location,
Node,
NodeEntry,
NodeMatch,
Path,
Point,
Range,
@@ -21,14 +19,15 @@ export const NodeTransforms = {
nodes: Node | Node[],
options: {
at?: Location
match?: NodeMatch
match?: (node: Node) => boolean
mode?: 'highest' | 'lowest'
hanging?: boolean
select?: boolean
voids?: boolean
} = {}
) {
Editor.withoutNormalizing(editor, () => {
const { hanging = false, voids = false } = options
const { hanging = false, voids = false, mode = 'lowest' } = options
let { at, match, select } = options
if (Node.isNode(nodes)) {
@@ -78,21 +77,26 @@ export const NodeTransforms = {
if (Point.isPoint(at)) {
if (match == null) {
if (Text.isText(node)) {
match = 'text'
match = n => Text.isText(n)
} else if (editor.isInline(node)) {
match = ['inline', 'text']
match = n => Text.isText(n) || Editor.isInline(editor, n)
} else {
match = 'block'
match = n => Editor.isBlock(editor, n)
}
}
const atMatch = Editor.match(editor, at.path, match)
const [entry] = Editor.nodes(editor, {
at: at.path,
match,
mode,
voids,
})
if (atMatch) {
const [, matchPath] = atMatch
if (entry) {
const [, matchPath] = entry
const pathRef = Editor.pathRef(editor, matchPath)
const isAtEnd = Editor.isEnd(editor, at, matchPath)
Editor.splitNodes(editor, { at, match })
Editor.splitNodes(editor, { at, match, mode, voids })
const path = pathRef.unref()!
at = isAtEnd ? Path.next(path) : path
} else {
@@ -103,7 +107,7 @@ export const NodeTransforms = {
const parentPath = Path.parent(at)
let index = at[at.length - 1]
if (!voids && Editor.match(editor, parentPath, 'void')) {
if (!voids && Editor.void(editor, { at: parentPath })) {
return
}
@@ -132,17 +136,19 @@ export const NodeTransforms = {
editor: Editor,
options: {
at?: Location
match?: NodeMatch
mode?: 'all' | 'highest'
match?: (node: Node) => boolean
mode?: 'all' | 'highest' | 'lowest'
voids?: boolean
} = {}
) {
Editor.withoutNormalizing(editor, () => {
const { at = editor.selection, mode = 'highest', voids = false } = options
const { at = editor.selection, mode = 'lowest', voids = false } = options
let { match } = options
if (match == null) {
match = Path.isPath(at) ? matchPath(editor, at) : 'block'
match = Path.isPath(at)
? matchPath(editor, at)
: n => Editor.isBlock(editor, n)
}
if (!at) {
@@ -193,14 +199,15 @@ export const NodeTransforms = {
editor: Editor,
options: {
at?: Location
match?: NodeMatch
match?: (node: Node) => boolean
mode?: 'highest' | 'lowest'
hanging?: boolean
voids?: boolean
} = {}
) {
Editor.withoutNormalizing(editor, () => {
let { match, at = editor.selection } = options
const { hanging = false, voids = false } = options
const { hanging = false, voids = false, mode = 'lowest' } = options
if (!at) {
return
@@ -211,7 +218,7 @@ export const NodeTransforms = {
const [parent] = Editor.parent(editor, at)
match = n => parent.children.includes(n)
} else {
match = 'block'
match = n => Editor.isBlock(editor, n)
}
}
@@ -234,8 +241,8 @@ export const NodeTransforms = {
}
}
const current = Editor.match(editor, at, match, { voids })
const prev = Editor.previous(editor, at, match, { voids })
const [current] = Editor.nodes(editor, { at, match, voids, mode })
const prev = Editor.previous(editor, { at, match, voids, mode })
if (!current || !prev) {
return
@@ -257,12 +264,12 @@ export const NodeTransforms = {
// Determine if the merge will leave an ancestor of the path empty as a
// result, in which case we'll want to remove it after merging.
const emptyAncestor = Editor.match(
editor,
path,
n =>
levels.includes(n) && Element.isElement(n) && n.children.length === 1
)
const emptyAncestor = Editor.above(editor, {
at: path,
mode: 'highest',
match: n =>
levels.includes(n) && Element.isElement(n) && n.children.length === 1,
})
const emptyRef = emptyAncestor && Editor.pathRef(editor, emptyAncestor[1])
let properties
@@ -331,8 +338,8 @@ export const NodeTransforms = {
editor: Editor,
options: {
at?: Location
match?: NodeMatch
mode?: 'all' | 'highest'
match?: (node: Node) => boolean
mode?: 'all' | 'highest' | 'lowest'
to: Path
voids?: boolean
}
@@ -341,7 +348,7 @@ export const NodeTransforms = {
const {
to,
at = editor.selection,
mode = 'highest',
mode = 'lowest',
voids = false,
} = options
let { match } = options
@@ -351,7 +358,9 @@ export const NodeTransforms = {
}
if (match == null) {
match = Path.isPath(at) ? matchPath(editor, at) : 'block'
match = Path.isPath(at)
? matchPath(editor, at)
: n => Editor.isBlock(editor, n)
}
const toRef = Editor.pathRef(editor, to)
@@ -379,26 +388,24 @@ export const NodeTransforms = {
editor: Editor,
options: {
at?: Location
match?: NodeMatch
mode?: 'all' | 'highest'
match?: (node: Node) => boolean
mode?: 'highest' | 'lowest'
hanging?: boolean
voids?: boolean
} = {}
) {
Editor.withoutNormalizing(editor, () => {
const { hanging = false, voids = false } = options
let { at = editor.selection, mode, match } = options
const { hanging = false, voids = false, mode = 'lowest' } = options
let { at = editor.selection, match } = options
if (!at) {
return
}
if (match == null) {
match = Path.isPath(at) ? matchPath(editor, at) : 'block'
}
if (mode == null || mode === 'all') {
mode = 'highest'
match = Path.isPath(at)
? matchPath(editor, at)
: n => Editor.isBlock(editor, n)
}
if (!hanging && Range.isRange(at)) {
@@ -428,8 +435,8 @@ export const NodeTransforms = {
props: Partial<Node>,
options: {
at?: Location
match?: NodeMatch
mode?: 'all' | 'highest'
match?: (node: Node) => boolean
mode?: 'all' | 'highest' | 'lowest'
hanging?: boolean
split?: boolean
voids?: boolean
@@ -439,7 +446,7 @@ export const NodeTransforms = {
let { match, at = editor.selection } = options
const {
hanging = false,
mode = 'highest',
mode = 'lowest',
split = false,
voids = false,
} = options
@@ -449,7 +456,9 @@ export const NodeTransforms = {
}
if (match == null) {
match = Path.isPath(at) ? matchPath(editor, at) : 'block'
match = Path.isPath(at)
? matchPath(editor, at)
: n => Editor.isBlock(editor, n)
}
if (!hanging && Range.isRange(at)) {
@@ -459,8 +468,9 @@ export const NodeTransforms = {
if (split && Range.isRange(at)) {
const rangeRef = Editor.rangeRef(editor, at, { affinity: 'inward' })
const [start, end] = Range.edges(at)
Editor.splitNodes(editor, { at: end, match, voids })
Editor.splitNodes(editor, { at: start, match, voids })
const splitMode = mode === 'lowest' ? 'lowest' : 'highest'
Editor.splitNodes(editor, { at: end, match, mode: splitMode, voids })
Editor.splitNodes(editor, { at: start, match, mode: splitMode, voids })
at = rangeRef.unref()!
if (options.at == null) {
@@ -513,23 +523,19 @@ export const NodeTransforms = {
editor: Editor,
options: {
at?: Location
match?: NodeMatch
match?: (node: Node) => boolean
mode?: 'highest' | 'lowest'
always?: boolean
height?: number
voids?: boolean
} = {}
) {
Editor.withoutNormalizing(editor, () => {
let {
match,
at = editor.selection,
height = 0,
always = false,
voids = false,
} = options
const { mode = 'lowest', voids = false } = options
let { match, at = editor.selection, height = 0, always = false } = options
if (match == null) {
match = 'block'
match = n => Editor.isBlock(editor, n)
}
if (Range.isRange(at)) {
@@ -555,13 +561,13 @@ export const NodeTransforms = {
const beforeRef = Editor.pointRef(editor, at, {
affinity: 'backward',
})
const highest = Editor.match(editor, at, match, { voids })
const [highest] = Editor.nodes(editor, { at, match, mode, voids })
if (!highest) {
return
}
const voidMatch = Editor.match(editor, at, 'void')
const voidMatch = Editor.void(editor, { at, mode: 'highest' })
const nudge = 0
if (!voids && voidMatch) {
@@ -603,7 +609,7 @@ export const NodeTransforms = {
if (
path.length < highestPath.length ||
path.length === 0 ||
(!voids && Element.isElement(node) && editor.isVoid(node))
(!voids && Editor.isVoid(editor, node))
) {
break
}
@@ -646,8 +652,8 @@ export const NodeTransforms = {
props: string | string[],
options: {
at?: Location
match?: NodeMatch
mode?: 'all' | 'highest'
match?: (node: Node) => boolean
mode?: 'all' | 'highest' | 'lowest'
split?: boolean
voids?: boolean
} = {}
@@ -674,14 +680,14 @@ export const NodeTransforms = {
editor: Editor,
options: {
at?: Location
match?: NodeMatch
mode?: 'all' | 'highest'
match?: (node: Node) => boolean
mode?: 'all' | 'highest' | 'lowest'
split?: boolean
voids?: boolean
}
) {
Editor.withoutNormalizing(editor, () => {
const { mode = 'highest', split = false, voids = false } = options
const { mode = 'lowest', split = false, voids = false } = options
let { at = editor.selection, match } = options
if (!at) {
@@ -689,7 +695,9 @@ export const NodeTransforms = {
}
if (match == null) {
match = Path.isPath(at) ? matchPath(editor, at) : 'block'
match = Path.isPath(at)
? matchPath(editor, at)
: n => Editor.isBlock(editor, n)
}
if (Path.isPath(at)) {
@@ -732,14 +740,14 @@ export const NodeTransforms = {
element: Element,
options: {
at?: Location
match?: NodeMatch
mode?: 'all' | 'highest'
match?: (node: Node) => boolean
mode?: 'all' | 'highest' | 'lowest'
split?: boolean
voids?: boolean
} = {}
) {
Editor.withoutNormalizing(editor, () => {
const { mode = 'highest', split = false, voids = false } = options
const { mode = 'lowest', split = false, voids = false } = options
let { match, at = editor.selection } = options
if (!at) {
@@ -750,9 +758,9 @@ export const NodeTransforms = {
if (Path.isPath(at)) {
match = matchPath(editor, at)
} else if (editor.isInline(element)) {
match = ['inline', 'text']
match = n => Editor.isInline(editor, n) || Text.isText(n)
} else {
match = 'block'
match = n => Editor.isBlock(editor, n)
}
}
@@ -773,7 +781,9 @@ export const NodeTransforms = {
const roots = Array.from(
Editor.nodes(editor, {
at,
match: editor.isInline(element) ? 'block' : 'editor',
match: editor.isInline(element)
? n => Editor.isBlock(editor, n)
: n => Editor.isEditor(n),
mode: 'highest',
voids,
})

View File

@@ -5,6 +5,7 @@ import {
Node,
NodeEntry,
Path,
Text,
Point,
Range,
} from '../../..'
@@ -43,7 +44,7 @@ export const TextTransforms = {
}
if (Point.isPoint(at)) {
const furthestVoid = Editor.match(editor, at.path, 'void')
const furthestVoid = Editor.void(editor, { at, mode: 'highest' })
if (!voids && furthestVoid) {
const [, voidPath] = furthestVoid
@@ -72,13 +73,25 @@ export const TextTransforms = {
}
let [start, end] = Range.edges(at)
const startBlock = Editor.match(editor, start.path, 'block', { voids })
const endBlock = Editor.match(editor, end.path, 'block', { voids })
const startBlock = Editor.above(editor, {
match: n => Editor.isBlock(editor, n),
at: start,
voids,
})
const endBlock = Editor.above(editor, {
match: n => Editor.isBlock(editor, n),
at: end,
voids,
})
const isAcrossBlocks =
startBlock && endBlock && !Path.equals(startBlock[1], endBlock[1])
const isSingleText = Path.equals(start.path, end.path)
const startVoid = voids ? null : Editor.match(editor, start.path, 'void')
const endVoid = voids ? null : Editor.match(editor, end.path, 'void')
const startVoid = voids
? null
: Editor.void(editor, { at: start, mode: 'highest' })
const endVoid = voids
? null
: Editor.void(editor, { at: end, mode: 'highest' })
// If the start or end points are inside an inline void, nudge them out.
if (startVoid) {
@@ -106,10 +119,7 @@ export const TextTransforms = {
const matches: NodeEntry[] = []
let lastPath: Path | undefined
for (const entry of Editor.nodes(editor, {
at,
voids,
})) {
for (const entry of Editor.nodes(editor, { at, voids })) {
const [node, path] = entry
if (lastPath && Path.compare(path, lastPath) === 0) {
@@ -117,7 +127,7 @@ export const TextTransforms = {
}
if (
(!voids && Element.isElement(node) && editor.isVoid(node)) ||
(!voids && Editor.isVoid(editor, node)) ||
(!Path.isCommon(path, start.path) && !Path.isCommon(path, end.path))
) {
matches.push(entry)
@@ -206,7 +216,7 @@ export const TextTransforms = {
} else {
const [, end] = Range.edges(at)
if (!voids && Editor.match(editor, end, 'void')) {
if (!voids && Editor.void(editor, { at: end })) {
return
}
@@ -218,13 +228,18 @@ export const TextTransforms = {
at = Editor.start(editor, at)
}
if (!voids && Editor.match(editor, at.path, 'void')) {
if (!voids && Editor.void(editor, { at })) {
return
}
// If the insert point is at the edge of an inline node, move it outside
// instead since it will need to be split otherwise.
const inlineElementMatch = Editor.match(editor, at, 'inline', { voids })
const inlineElementMatch = Editor.above(editor, {
at,
match: n => Editor.isInline(editor, n),
mode: 'highest',
voids,
})
if (inlineElementMatch) {
const [, inlinePath] = inlineElementMatch
@@ -238,7 +253,11 @@ export const TextTransforms = {
}
}
const blockMatch = Editor.match(editor, at, 'block', { voids })!
const blockMatch = Editor.above(editor, {
match: n => Editor.isBlock(editor, n),
at,
voids,
})!
const [, blockPath] = blockMatch
const isBlockStart = Editor.isStart(editor, at, blockPath)
const isBlockEnd = Editor.isEnd(editor, at, blockPath)
@@ -299,9 +318,13 @@ export const TextTransforms = {
}
}
const inlineMatch = Editor.match(editor, at, ['inline', 'text'], {
const [inlineMatch] = Editor.nodes(editor, {
at,
match: n => Text.isText(n) || Editor.isInline(editor, n),
mode: 'highest',
voids,
})!
const [, inlinePath] = inlineMatch
const isInlineStart = Editor.isStart(editor, at, inlinePath)
const isInlineEnd = Editor.isEnd(editor, at, inlinePath)
@@ -318,7 +341,11 @@ export const TextTransforms = {
Editor.splitNodes(editor, {
at,
match: hasBlocks ? 'block' : ['inline', 'text'],
match: n =>
hasBlocks
? Editor.isBlock(editor, n)
: Text.isText(n) || Editor.isInline(editor, n),
mode: hasBlocks ? 'lowest' : 'highest',
voids,
})
@@ -331,19 +358,22 @@ export const TextTransforms = {
Editor.insertNodes(editor, starts, {
at: startRef.current!,
match: ['inline', 'text'],
match: n => Text.isText(n) || Editor.isInline(editor, n),
mode: 'highest',
voids,
})
Editor.insertNodes(editor, middles, {
at: middleRef.current!,
match: 'block',
match: n => Editor.isBlock(editor, n),
mode: 'lowest',
voids,
})
Editor.insertNodes(editor, ends, {
at: endRef.current!,
match: ['inline', 'text'],
match: n => Text.isText(n) || Editor.isInline(editor, n),
mode: 'highest',
voids,
})
@@ -398,7 +428,7 @@ export const TextTransforms = {
} else {
const end = Range.end(at)
if (!voids && Editor.match(editor, end, 'void')) {
if (!voids && Editor.void(editor, { at: end })) {
return
}
@@ -409,7 +439,7 @@ export const TextTransforms = {
}
}
if (!voids && Editor.match(editor, at.path, 'void')) {
if (!voids && Editor.void(editor, { at })) {
return
}

View File

@@ -1,5 +1,5 @@
import { produce } from 'immer'
import { Editor, Element, ElementEntry, Path, Range, Text, TextEntry } from '..'
import { Editor, Element, ElementEntry, Path, Range, Text } from '..'
/**
* The `Node` union type represents all of the different types of nodes that
@@ -38,10 +38,10 @@ export const Node = {
options: {
reverse?: boolean
} = {}
): Iterable<AncestorEntry> {
): Iterable<NodeEntry<Ancestor>> {
for (const p of Path.ancestors(path, options)) {
const n = Node.ancestor(root, p)
const entry: AncestorEntry = [n, p]
const entry: NodeEntry<Ancestor> = [n, p]
yield entry
}
},
@@ -80,7 +80,7 @@ export const Node = {
options: {
reverse?: boolean
} = {}
): Iterable<DescendantEntry> {
): Iterable<NodeEntry<Descendant>> {
const { reverse = false } = options
const ancestor = Node.ancestor(root, path)
const { children } = ancestor
@@ -132,12 +132,12 @@ export const Node = {
reverse?: boolean
pass?: (node: NodeEntry) => boolean
} = {}
): Iterable<DescendantEntry> {
): Iterable<NodeEntry<Descendant>> {
for (const [node, path] of Node.nodes(root, options)) {
if (path.length !== 0) {
// NOTE: we have to coerce here because checking the path's length does
// guarantee that `node` is not a `Editor`, but TypeScript doesn't know.
yield [node, path] as DescendantEntry
yield [node, path] as NodeEntry<Descendant>
}
}
},
@@ -484,7 +484,7 @@ export const Node = {
reverse?: boolean
pass?: (node: NodeEntry) => boolean
} = {}
): Iterable<TextEntry> {
): Iterable<NodeEntry<Text>> {
for (const [node, path] of Node.nodes(root, options)) {
if (Text.isText(node)) {
yield [node, path]
@@ -515,34 +515,4 @@ export type Ancestor = Editor | Element
* node in the document.
*/
export type NodeEntry = [Node, Path]
/**
* `DescendantEntry` objects are returned when iterating over the descendants in
* a Slate document tree.
*/
export type DescendantEntry = [Descendant, Path]
/**
* `AncestorEntry` objects are returned when iterating over the ancestors in a
* Slate document tree.
*/
export type AncestorEntry = [Ancestor, Path]
/**
* `NodeMatch` values are used as shorthands for matching a node by either its
* kind, its location, its behavior or its properties.
*/
export type NodeMatch =
| 'block'
| 'element'
| 'inline'
| 'text'
| 'editor'
| 'void'
| Partial<Node>
| ((node: Node, editor: Editor) => boolean)
| NodeMatch[]
export type NodeEntry<T extends Node = Node> = [T, Path]

View File

@@ -84,10 +84,3 @@ export const Text = {
return true
},
}
/**
* `TextEntry` objects refer to an `Text` and the `Path` where it can be
* found inside a root node.
*/
export type TextEntry = [Text, Path]

View File

@@ -8,17 +8,20 @@ export const input = (
<block>
<block>one</block>
</block>
<block>
<block>two</block>
</block>
</editor>
)
export const run = editor => {
return Array.from(Editor.texts(editor, { at: [] }))
return Editor.above(editor, {
at: [0, 0, 0],
match: n => Editor.isBlock(editor, n),
mode: 'highest',
})
}
export const output = [
[<text>one</text>, [0, 0, 0]],
[<text>two</text>, [1, 0, 0]],
<block>
<block>one</block>
</block>,
[0],
]

View File

@@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
import { jsx } from '../..'
export const input = (
<editor>
@@ -12,7 +12,11 @@ export const input = (
)
export const run = editor => {
return Editor.match(editor, [0, 0, 0], 'block')
return Editor.above(editor, {
at: [0, 0, 0],
match: n => Editor.isBlock(editor, n),
mode: 'lowest',
})
}
export const output = [<block>one</block>, [0, 0]]

View File

@@ -12,11 +12,10 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.texts(editor, { at: [] }))
return Editor.above(editor, {
at: [0, 1, 0],
match: n => Editor.isInline(editor, n),
})
}
export const output = [
[<text>one</text>, [0, 0]],
[<text>two</text>, [0, 1, 0]],
[<text>three</text>, [0, 2]],
]
export const output = [<inline>two</inline>, [0, 1]]

View File

@@ -10,7 +10,8 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.texts(editor, { at: [] }))
const block = editor.children[0]
return Editor.isBlock(editor, block)
}
export const output = [[<text>one</text>, [0, 0]]]
export const output = true

View File

@@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
import { jsx } from '../..'
export const input = (
<editor>
@@ -12,12 +12,8 @@ export const input = (
)
export const run = editor => {
return Editor.match(editor, [0, 1, 0], 'block')
const inline = editor.children[0].children[1]
return Editor.isBlock(editor, inline)
}
export const output = [
<block>
one<inline>two</inline>three
</block>,
[0],
]
export const output = false

View File

@@ -6,15 +6,12 @@ import { jsx } from '../..'
export const input = (
<editor>
<block>one</block>
<block>two</block>
</editor>
)
export const run = editor => {
return Array.from(Editor.texts(editor, { at: [] }))
const block = editor.children[0]
return Editor.isInline(editor, block)
}
export const output = [
[<text>one</text>, [0, 0]],
[<text>two</text>, [1, 0]],
]
export const output = false

View File

@@ -0,0 +1,19 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
export const input = (
<editor>
<block>
one<inline>two</inline>three
</block>
</editor>
)
export const run = editor => {
const inline = editor.children[0].children[1]
return Editor.isInline(editor, inline)
}
export const output = true

View File

@@ -10,7 +10,8 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.texts(editor, { at: [] }))
const block = editor.children[0]
return Editor.isVoid(editor, block)
}
export const output = []
export const output = true

View File

@@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
import { jsx } from '../..'
export const input = (
<editor>
@@ -10,7 +10,8 @@ export const input = (
)
export const run = editor => {
return Editor.match(editor, [0, 0], 'block')
const block = editor.children[0]
return Editor.isVoid(editor, block)
}
export const output = [<block>one</block>, [0]]
export const output = false

View File

@@ -12,10 +12,8 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.texts(editor, { at: [] }))
const inline = editor.children[0].children[1]
return Editor.isVoid(editor, inline)
}
export const output = [
[<text>one</text>, [0, 0]],
[<text>three</text>, [0, 2]],
]
export const output = true

View File

@@ -0,0 +1,19 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
export const input = (
<editor>
<block>
one<inline>two</inline>three
</block>
</editor>
)
export const run = editor => {
const inline = editor.children[0].children[1]
return Editor.isVoid(editor, inline)
}
export const output = false

View File

@@ -1,23 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block a>
<block a>one</block>
</block>
</editor>
)
export const run = editor => {
return Editor.match(editor, [0, 0, 0], { a: true })
}
export const output = [
<block a>
<block a>one</block>
</block>,
[0],
]

View File

@@ -1,23 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block a b c>
one
</block>
</editor>
)
export const run = editor => {
return Editor.match(editor, [0, 0], { a: true })
}
export const output = [
<block a b c>
one
</block>,
[0],
]

View File

@@ -1,16 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block a>one</block>
</editor>
)
export const run = editor => {
return Editor.match(editor, [0, 0], { a: true })
}
export const output = [<block a>one</block>, [0]]

View File

@@ -1,23 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block a>
one<inline>two</inline>three
</block>
</editor>
)
export const run = editor => {
return Editor.match(editor, [0, 1, 0], { a: true })
}
export const output = [
<block a>
one<inline>two</inline>three
</block>,
[0],
]

View File

@@ -1,23 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block a b c>
one
</block>
</editor>
)
export const run = editor => {
return Editor.match(editor, [0, 0], { a: true, b: true })
}
export const output = [
<block a b c>
one
</block>,
[0],
]

View File

@@ -11,7 +11,7 @@ export const input = (
)
export const run = editor => {
return Editor.next(editor, [0], 'block')
return Editor.next(editor, { at: [0], match: n => Editor.isBlock(editor, n) })
}
export const output = [<block>two</block>, [1]]

View File

@@ -11,7 +11,7 @@ export const input = (
)
export const run = editor => {
return Editor.next(editor, [0])
return Editor.next(editor, { at: [0] })
}
export const output = [<block>two</block>, [1]]

View File

@@ -1,6 +1,6 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { Editor, Text } from 'slate'
import { jsx } from '../..'
export const input = (
@@ -11,7 +11,7 @@ export const input = (
)
export const run = editor => {
return Editor.next(editor, [0], 'text')
return Editor.next(editor, { at: [0], match: Text.isText })
}
export const output = [<text>two</text>, [1, 0]]

View File

@@ -1,24 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block>one</block>
<block>two</block>
<block>three</block>
</editor>
)
export const run = editor => {
return Array.from(
Editor.nodes(editor, { at: [], match: 'block', mode: 'highest' })
)
}
export const output = [
[<block>one</block>, [0]],
[<block>two</block>, [1]],
[<block>three</block>, [2]],
]

View File

@@ -1,27 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block>
one<inline>two</inline>three
</block>
</editor>
)
export const run = editor => {
return Array.from(
Editor.nodes(editor, { at: [], match: 'block', mode: 'highest' })
)
}
export const output = [
[
<block>
one<inline>two</inline>three
</block>,
[0],
],
]

View File

@@ -11,7 +11,10 @@ export const input = (
export const run = editor => {
return Array.from(
Editor.nodes(editor, { at: [], match: 'block', mode: 'highest' })
Editor.nodes(editor, {
at: [],
match: n => Editor.isBlock(editor, n),
})
)
}

View File

@@ -13,7 +13,10 @@ export const input = (
export const run = editor => {
return Array.from(
Editor.nodes(editor, { at: [], match: 'inline', mode: 'highest' })
Editor.nodes(editor, {
at: [],
match: n => Editor.isInline(editor, n),
})
)
}

View File

@@ -1,23 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block>
one<inline>two</inline>three<inline>four</inline>five
</block>
</editor>
)
export const run = editor => {
return Array.from(
Editor.nodes(editor, { at: [], match: 'inline', mode: 'highest' })
)
}
export const output = [
[<inline>two</inline>, [0, 1]],
[<inline>four</inline>, [0, 3]],
]

View File

@@ -1,31 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block>
one
<inline>
two<inline>three</inline>four
</inline>
five
</block>
</editor>
)
export const run = editor => {
return Array.from(
Editor.nodes(editor, { at: [], match: 'inline', mode: 'highest' })
)
}
export const output = [
[
<inline>
two<inline>three</inline>four
</inline>,
[0, 1],
],
]

View File

@@ -1,20 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block>
one<inline void>two</inline>three
</block>
</editor>
)
export const run = editor => {
return Array.from(
Editor.nodes(editor, { at: [], match: 'inline', mode: 'highest' })
)
}
export const output = [[<inline void>two</inline>, [0, 1]]]

View File

@@ -1,26 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block>
one<inline>two</inline>three<inline>four</inline>five
</block>
</editor>
)
export const run = editor => {
return Array.from(
Editor.nodes(editor, { at: [], match: ['inline', 'text'], mode: 'highest' })
)
}
export const output = [
[<text>one</text>, [0, 0]],
[<inline>two</inline>, [0, 1]],
[<text>three</text>, [0, 2]],
[<inline>four</inline>, [0, 3]],
[<text>five</text>, [0, 4]],
]

View File

@@ -1,33 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block>
one
<inline>
two<inline>three</inline>four
</inline>
five
</block>
</editor>
)
export const run = editor => {
return Array.from(
Editor.nodes(editor, { at: [], match: ['inline', 'text'], mode: 'highest' })
)
}
export const output = [
[<text>one</text>, [0, 0]],
[
<inline>
two<inline>three</inline>four
</inline>,
[0, 1],
],
[<text>five</text>, [0, 2]],
]

View File

@@ -1,24 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block>
one<inline>two</inline>three
</block>
</editor>
)
export const run = editor => {
return Array.from(
Editor.nodes(editor, { at: [], match: ['inline', 'text'], mode: 'highest' })
)
}
export const output = [
[<text>one</text>, [0, 0]],
[<inline>two</inline>, [0, 1]],
[<text>three</text>, [0, 2]],
]

View File

@@ -0,0 +1,36 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block a>
<block a>one</block>
</block>
<block a>
<block a>two</block>
</block>
</editor>
)
export const run = editor => {
return Array.from(
Editor.nodes(editor, { at: [], match: n => n.a, mode: 'highest' })
)
}
export const output = [
[
<block a>
<block a>one</block>
</block>,
[0],
],
[
<block a>
<block a>two</block>
</block>,
[1],
],
]

View File

@@ -0,0 +1,38 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block a>
<block a>one</block>
</block>
<block a>
<block a>two</block>
</block>
</editor>
)
export const run = editor => {
return Array.from(
Editor.nodes(editor, { at: [], match: n => n.a, mode: 'all' })
)
}
export const output = [
[
<block a>
<block a>one</block>
</block>,
[0],
],
[<block a>one</block>, [0, 0]],
[
<block a>
<block a>two</block>
</block>,
[1],
],
[<block a>two</block>, [1, 0]],
]

View File

@@ -5,22 +5,22 @@ import { jsx } from '../../..'
export const input = (
<editor>
<block>
<block>one</block>
<block a>
<block a>one</block>
</block>
<block>
<block>two</block>
<block a>
<block a>two</block>
</block>
</editor>
)
export const run = editor => {
return Array.from(
Editor.nodes(editor, { at: [], match: 'block', mode: 'highest' })
Editor.nodes(editor, { at: [], match: n => n.a, mode: 'lowest' })
)
}
export const output = [
[<block>one</block>, [0, 0]],
[<block>two</block>, [1, 0]],
[<block a>one</block>, [0, 0]],
[<block a>two</block>, [1, 0]],
]

View File

@@ -5,9 +5,12 @@ import { jsx } from '../../..'
export const input = (
<editor>
<block>one</block>
<block>two</block>
<block>three</block>
<block a>
<block a>one</block>
</block>
<block a>
<block a>two</block>
</block>
</editor>
)
@@ -15,15 +18,14 @@ export const run = editor => {
return Array.from(
Editor.nodes(editor, {
at: [],
match: 'block',
mode: 'highest',
reverse: true,
match: n => n.a === true,
mode: 'lowest',
universal: true,
})
)
}
export const output = [
[<block>three</block>, [2]],
[<block>two</block>, [1]],
[<block>one</block>, [0]],
[<block a>one</block>, [0, 0]],
[<block a>two</block>, [1, 0]],
]

View File

@@ -5,9 +5,8 @@ import { jsx } from '../../..'
export const input = (
<editor>
<block>
one<inline>two</inline>three<inline>four</inline>five
</block>
<block a>one</block>
<block a>two</block>
</editor>
)
@@ -15,14 +14,14 @@ export const run = editor => {
return Array.from(
Editor.nodes(editor, {
at: [],
match: 'inline',
mode: 'highest',
reverse: true,
match: n => n.a === true,
mode: 'lowest',
universal: true,
})
)
}
export const output = [
[<inline>four</inline>, [0, 3]],
[<inline>two</inline>, [0, 1]],
[<block a>one</block>, [0]],
[<block a>two</block>, [1]],
]

View File

@@ -0,0 +1,36 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block a>
<block b>one</block>
</block>
<block b>
<block a>two</block>
</block>
</editor>
)
export const run = editor => {
return Array.from(
Editor.nodes(editor, {
at: [],
match: n => n.a === true,
mode: 'lowest',
universal: true,
})
)
}
export const output = [
[
<block a>
<block b>one</block>
</block>,
[0],
],
[<block a>two</block>, [1, 0]],
]

View File

@@ -0,0 +1,28 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block a>
<block a>one</block>
</block>
<block a>
<block a>two</block>
</block>
</editor>
)
export const run = editor => {
return Array.from(
Editor.nodes(editor, {
at: [],
match: n => n.b === true,
mode: 'lowest',
universal: true,
})
)
}
export const output = []

View File

@@ -5,15 +5,19 @@ import { jsx } from '../../..'
export const input = (
<editor>
<block void>
<block>one</block>
</block>
<block a>one</block>
<block a>two</block>
</editor>
)
export const run = editor => {
return Array.from(
Editor.nodes(editor, { at: [], match: 'block', mode: 'highest' })
Editor.nodes(editor, {
at: [],
match: n => n.b === true,
mode: 'lowest',
universal: true,
})
)
}

View File

@@ -0,0 +1,28 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block a>
<block a>one</block>
</block>
<block b>
<block b>two</block>
</block>
</editor>
)
export const run = editor => {
return Array.from(
Editor.nodes(editor, {
at: [],
match: n => n.a,
mode: 'lowest',
universal: true,
})
)
}
export const output = []

View File

@@ -5,13 +5,19 @@ import { jsx } from '../../..'
export const input = (
<editor>
<block>one</block>
<block a>one</block>
<block b>two</block>
</editor>
)
export const run = editor => {
return Array.from(
Editor.nodes(editor, { at: [], match: 'inline', mode: 'highest' })
Editor.nodes(editor, {
at: [],
match: n => n.a,
mode: 'lowest',
universal: true,
})
)
}

View File

@@ -1,6 +1,6 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { Editor, Text } from 'slate'
import { jsx } from '../../..'
export const input = (
@@ -11,7 +11,7 @@ export const input = (
export const run = editor => {
return Array.from(
Editor.nodes(editor, { at: [], match: 'text', voids: true })
Editor.nodes(editor, { at: [], match: Text.isText, voids: true })
)
}

View File

@@ -1,6 +1,6 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { Editor, Text } from 'slate'
import { jsx } from '../../..'
export const input = (
@@ -13,7 +13,7 @@ export const input = (
export const run = editor => {
return Array.from(
Editor.nodes(editor, { at: [], match: 'text', voids: true })
Editor.nodes(editor, { at: [], match: Text.isText, voids: true })
)
}

View File

@@ -11,7 +11,10 @@ export const input = (
)
export const run = editor => {
return Editor.previous(editor, [1], 'block')
return Editor.previous(editor, {
at: [1],
match: n => Editor.isBlock(editor, n),
})
}
export const output = [<block>one</block>, [0]]

View File

@@ -11,7 +11,7 @@ export const input = (
)
export const run = editor => {
return Editor.previous(editor, [1])
return Editor.previous(editor, { at: [1] })
}
export const output = [<block>one</block>, [0]]

View File

@@ -1,6 +1,6 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { Editor, Text } from 'slate'
import { jsx } from '../..'
export const input = (
@@ -11,7 +11,7 @@ export const input = (
)
export const run = editor => {
return Editor.previous(editor, [1], 'text')
return Editor.previous(editor, { at: [1], match: Text.isText })
}
export const output = [<text>one</text>, [0, 0]]

View File

@@ -1,20 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
export const input = (
<editor>
<block>one</block>
<block>two</block>
</editor>
)
export const run = editor => {
return Array.from(Editor.texts(editor, { at: [], reverse: true }))
}
export const output = [
[<text>two</text>, [1, 0]],
[<text>one</text>, [0, 0]],
]

View File

@@ -1,24 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
export const input = (
<editor>
<block>
one<inline>two</inline>three<inline>four</inline>five
</block>
</editor>
)
export const run = editor => {
return Array.from(Editor.texts(editor, { at: [] }))
}
export const output = [
[<text>one</text>, [0, 0]],
[<text>two</text>, [0, 1, 0]],
[<text>three</text>, [0, 2]],
[<text>four</text>, [0, 3, 0]],
[<text>five</text>, [0, 4]],
]

View File

@@ -1,28 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
export const input = (
<editor>
<block>
one
<inline>
two<inline>three</inline>four
</inline>
five
</block>
</editor>
)
export const run = editor => {
return Array.from(Editor.texts(editor, { at: [] }))
}
export const output = [
[<text>one</text>, [0, 0]],
[<text>two</text>, [0, 1, 0]],
[<text>three</text>, [0, 1, 1, 0]],
[<text>four</text>, [0, 1, 2]],
[<text>five</text>, [0, 2]],
]

View File

@@ -1,24 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
export const input = (
<editor>
<block>
one<inline>two</inline>three<inline>four</inline>five
</block>
</editor>
)
export const run = editor => {
return Array.from(Editor.texts(editor, { at: [], reverse: true }))
}
export const output = [
[<text>five</text>, [0, 4]],
[<text>four</text>, [0, 3, 0]],
[<text>three</text>, [0, 2]],
[<text>two</text>, [0, 1, 0]],
[<text>one</text>, [0, 0]],
]

View File

@@ -30,13 +30,13 @@ export const output = (
<editor>
<block>
<text />
<inline>wo</inline>
<text />
<inline>
wo
<inline void>
<cursor />
</inline>
<text />
<inline>rd</inline>
rd
</inline>
<text />
</block>
</editor>

View File

@@ -29,12 +29,14 @@ export const output = (
<editor>
<block>
one
<inline>two</inline>
<text />
<inline>
two
<inline void>
four
<cursor />
</inline>
<text />
</inline>
three
</block>
</editor>

View File

@@ -4,7 +4,7 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.liftNodes(editor, { match: { c: true } })
Editor.liftNodes(editor, { match: n => n.c })
}
export const input = (

View File

@@ -14,7 +14,7 @@ export const input = (
)
export const run = editor => {
Editor.mergeNodes(editor, { match: 'block' })
Editor.mergeNodes(editor, { match: n => Editor.isBlock(editor, n) })
}
export const output = (

View File

@@ -1,6 +1,6 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { Editor, Text } from 'slate'
import { jsx } from '../../..'
export const input = (
@@ -11,7 +11,7 @@ export const input = (
)
export const run = editor => {
Editor.mergeNodes(editor, { at: [1, 0], match: 'text' })
Editor.mergeNodes(editor, { at: [1, 0], match: Text.isText })
}
export const output = (

View File

@@ -4,7 +4,7 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.moveNodes(editor, { match: 'block', to: [1] })
Editor.moveNodes(editor, { match: n => Editor.isBlock(editor, n), to: [1] })
}
export const input = (

View File

@@ -4,7 +4,10 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.moveNodes(editor, { match: 'block', to: [0] })
Editor.moveNodes(editor, {
match: n => Editor.isBlock(editor, n),
to: [0],
})
}
export const input = (

View File

@@ -14,7 +14,10 @@ export const input = (
)
export const run = editor => {
Editor.moveNodes(editor, { match: 'block', to: [1] })
Editor.moveNodes(editor, {
match: n => Editor.isBlock(editor, n),
to: [1],
})
}
export const output = (

View File

@@ -4,7 +4,11 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.setNodes(editor, { key: true }, { match: 'block' })
Editor.setNodes(
editor,
{ key: true },
{ match: n => Editor.isBlock(editor, n) }
)
}
export const input = (

View File

@@ -4,7 +4,11 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.setNodes(editor, { key: true }, { match: 'block' })
Editor.setNodes(
editor,
{ key: true },
{ match: n => Editor.isBlock(editor, n) }
)
}
export const input = (

View File

@@ -4,7 +4,11 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.setNodes(editor, { key: true }, { match: 'block' })
Editor.setNodes(
editor,
{ key: true },
{ match: n => Editor.isBlock(editor, n) }
)
}
export const input = (

View File

@@ -4,7 +4,11 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.setNodes(editor, { key: true }, { match: 'block' })
Editor.setNodes(
editor,
{ key: true },
{ match: n => Editor.isBlock(editor, n) }
)
}
export const input = (

View File

@@ -4,7 +4,11 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.setNodes(editor, { key: true }, { match: 'block' })
Editor.setNodes(
editor,
{ key: true },
{ match: n => Editor.isBlock(editor, n) }
)
}
export const input = (

View File

@@ -4,7 +4,11 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.setNodes(editor, { key: true }, { match: 'inline' })
Editor.setNodes(
editor,
{ key: true },
{ match: n => Editor.isInline(editor, n) }
)
}
export const input = (

View File

@@ -4,7 +4,11 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.setNodes(editor, { key: true }, { match: 'inline' })
Editor.setNodes(
editor,
{ key: true },
{ match: n => Editor.isInline(editor, n) }
)
}
export const input = (

View File

@@ -4,7 +4,11 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.setNodes(editor, { key: true }, { match: 'inline' })
Editor.setNodes(
editor,
{ key: true },
{ match: n => Editor.isInline(editor, n) }
)
}
export const input = (

View File

@@ -4,7 +4,11 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.setNodes(editor, { key: true }, { match: 'inline' })
Editor.setNodes(
editor,
{ key: true },
{ match: n => Editor.isInline(editor, n) }
)
}
export const input = (
@@ -27,10 +31,10 @@ export const input = (
export const output = (
<editor>
<block>
<text />
<inline key>
<text />
<inline>
<text />
<inline key>
<cursor />
word
</inline>

View File

@@ -4,7 +4,11 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.setNodes(editor, { key: true }, { match: 'inline' })
Editor.setNodes(
editor,
{ key: true },
{ match: n => Editor.isInline(editor, n) }
)
}
export const input = (

View File

@@ -4,7 +4,11 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.setNodes(editor, { key: true }, { match: 'inline' })
Editor.setNodes(
editor,
{ key: true },
{ match: n => Editor.isInline(editor, n) }
)
}
export const input = (

View File

@@ -1,10 +1,10 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { Editor, Text } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.setNodes(editor, { key: null }, { match: 'text', split: true })
Editor.setNodes(editor, { key: null }, { match: Text.isText, split: true })
}
export const input = (

View File

@@ -1,10 +1,10 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { Editor, Text } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.setNodes(editor, { key: true }, { match: 'text', split: true })
Editor.setNodes(editor, { key: true }, { match: Text.isText, split: true })
}
export const input = (

View File

@@ -1,10 +1,10 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { Editor, Text } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.setNodes(editor, { key: true }, { match: 'text' })
Editor.setNodes(editor, { key: true }, { match: Text.isText })
}
export const input = (

View File

@@ -1,10 +1,10 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { Editor, Text } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.setNodes(editor, { key: true }, { match: 'text' })
Editor.setNodes(editor, { key: true }, { match: Text.isText })
}
export const input = (

View File

@@ -4,7 +4,10 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.splitNodes(editor, { match: 'block', always: true })
Editor.splitNodes(editor, {
match: n => Editor.isBlock(editor, n),
always: true,
})
}
export const input = (

View File

@@ -4,7 +4,10 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.splitNodes(editor, { match: 'block', always: true })
Editor.splitNodes(editor, {
match: n => Editor.isBlock(editor, n),
always: true,
})
}
export const input = (

View File

@@ -4,7 +4,10 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.splitNodes(editor, { match: 'block', always: true })
Editor.splitNodes(editor, {
match: n => Editor.isBlock(editor, n),
always: true,
})
}
export const input = (

View File

@@ -4,7 +4,10 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.splitNodes(editor, { match: 'block', always: true })
Editor.splitNodes(editor, {
match: n => Editor.isBlock(editor, n),
always: true,
})
}
export const input = (

View File

@@ -4,7 +4,10 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.splitNodes(editor, { match: 'block', always: true })
Editor.splitNodes(editor, {
match: n => Editor.isBlock(editor, n),
always: true,
})
}
export const input = (

View File

@@ -1,37 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.splitNodes(editor, { match: 'inline' })
}
export const input = (
<editor>
<block>
<text />
<inline>
wo
<cursor />
rd
</inline>
<text />
</block>
</editor>
)
export const output = (
<editor>
<block>
<text />
<inline>wo</inline>
<text />
<inline>
<cursor />
rd
</inline>
<text />
</block>
</editor>
)

View File

@@ -4,7 +4,7 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.splitNodes(editor, { match: () => true })
Editor.splitNodes(editor, { match: () => true, mode: 'highest' })
}
export const input = (

View File

@@ -4,7 +4,7 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.splitNodes(editor, { match: 'block' })
Editor.splitNodes(editor, { match: n => Editor.isBlock(editor, n) })
}
export const input = (

View File

@@ -4,7 +4,7 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.splitNodes(editor, { match: 'block' })
Editor.splitNodes(editor, { match: n => Editor.isBlock(editor, n) })
}
export const input = (

View File

@@ -4,7 +4,7 @@ import { Editor } from 'slate'
import { jsx } from '../../..'
export const run = editor => {
Editor.splitNodes(editor, { match: 'block' })
Editor.splitNodes(editor, { match: n => Editor.isBlock(editor, n) })
}
export const input = (

Some files were not shown because too many files have changed in this diff Show More