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:
@@ -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 })) {
|
||||
// ...
|
||||
}
|
||||
|
||||
|
@@ -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) }
|
||||
)
|
||||
}
|
||||
}}
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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) {
|
||||
|
@@ -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
|
||||
|
@@ -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 })
|
||||
}
|
||||
|
@@ -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,
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
}
|
||||
},
|
||||
}
|
@@ -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,
|
||||
})) {
|
||||
|
@@ -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) {
|
||||
|
@@ -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,
|
||||
})
|
||||
|
@@ -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
|
||||
}
|
||||
|
||||
|
@@ -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]
|
||||
|
@@ -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]
|
||||
|
@@ -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],
|
||||
]
|
@@ -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]]
|
@@ -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]]
|
@@ -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
|
@@ -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
|
@@ -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
|
19
packages/slate/test/queries/isInline/inline.js
Normal file
19
packages/slate/test/queries/isInline/inline.js
Normal 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
|
@@ -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
|
@@ -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
|
@@ -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
|
19
packages/slate/test/queries/isVoid/inline.js
Normal file
19
packages/slate/test/queries/isVoid/inline.js
Normal 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
|
@@ -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],
|
||||
]
|
@@ -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],
|
||||
]
|
@@ -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]]
|
@@ -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],
|
||||
]
|
@@ -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],
|
||||
]
|
@@ -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]]
|
||||
|
@@ -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]]
|
||||
|
@@ -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]]
|
||||
|
@@ -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]],
|
||||
]
|
@@ -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],
|
||||
],
|
||||
]
|
@@ -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),
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@@ -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),
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@@ -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]],
|
||||
]
|
@@ -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],
|
||||
],
|
||||
]
|
@@ -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]]]
|
@@ -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]],
|
||||
]
|
@@ -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]],
|
||||
]
|
@@ -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]],
|
||||
]
|
36
packages/slate/test/queries/nodes/mode-all/block.js
Normal file
36
packages/slate/test/queries/nodes/mode-all/block.js
Normal 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],
|
||||
],
|
||||
]
|
38
packages/slate/test/queries/nodes/mode-highest/block.js
Normal file
38
packages/slate/test/queries/nodes/mode-highest/block.js
Normal 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]],
|
||||
]
|
@@ -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]],
|
||||
]
|
@@ -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]],
|
||||
]
|
@@ -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]],
|
||||
]
|
@@ -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]],
|
||||
]
|
@@ -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 = []
|
@@ -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,
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@@ -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 = []
|
@@ -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,
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@@ -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 })
|
||||
)
|
||||
}
|
||||
|
||||
|
@@ -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 })
|
||||
)
|
||||
}
|
||||
|
||||
|
@@ -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]]
|
||||
|
@@ -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]]
|
||||
|
@@ -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]]
|
||||
|
@@ -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]],
|
||||
]
|
@@ -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]],
|
||||
]
|
@@ -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]],
|
||||
]
|
@@ -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]],
|
||||
]
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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>
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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>
|
||||
)
|
@@ -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 = (
|
@@ -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 = (
|
@@ -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 = (
|
@@ -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
Reference in New Issue
Block a user