1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-04-19 21:01:57 +02:00

improve Editor.marks and Editor.nodes abstraction

This commit is contained in:
Ian Storm Taylor 2019-11-29 23:15:08 -05:00
parent 0da1dd128c
commit 68569f286e
51 changed files with 381 additions and 237 deletions

View File

@ -173,15 +173,13 @@ const App = () => {
if (event.key === '`' && event.ctrlKey) {
event.preventDefault()
// Determine whether any of the currently selected blocks are code blocks.
const { selection } = editor
const isCode = selection
? Editor.match(editor, selection, { type: 'code' })
: false
const [node] = Editor.nodes(editor, { match: { type: 'code' } })
const isCodeActive = !!node
// Toggle the block type depending on `isCode`.
Editor.setNodes(
editor,
{ type: isCode ? 'paragraph' : 'code' },
{ type: isCodeActive ? 'paragraph' : 'code' },
{ match: 'block' }
)
}

View File

@ -26,13 +26,11 @@ const App = () => {
if (event.key === '`' && event.ctrlKey) {
event.preventDefault()
const { selection } = editor
const isCode = selection
? Editor.match(editor, selection, { type: 'code' })
: false
const [node] = Editor.nodes(editor, { match: { type: 'code' } })
const isCodeActive = !!node
Editor.setNodes(
editor,
{ type: isCode ? 'paragraph' : 'code' },
{ type: isCodeActive ? 'paragraph' : 'code' },
{ match: 'block' }
)
}
@ -70,14 +68,11 @@ const App = () => {
// When "`" is pressed, keep our existing code block logic.
case '`': {
event.preventDefault()
const { selection } = editor
const isCode = selection
? Editor.match(editor, selection, { type: 'code' })
: false
const [node] = Editor.nodes(editor, { match: { type: 'code' } })
const isCodeActive = !!node
Editor.setNodes(
editor,
{ type: isCode ? null : 'code' },
{ type: isCodeActive ? null : 'code' },
{ match: 'block' }
)
break
@ -147,14 +142,11 @@ const App = () => {
switch (event.key) {
case '`': {
event.preventDefault()
const { selection } = editor
const isCode = selection
? Editor.match(editor, selection, { type: 'code' })
: false
const [node] = Editor.nodes(editor, { match: { type: 'code' } })
const isCodeActive = !!node
Editor.setNodes(
editor,
{ type: isCode ? null : 'code' },
{ type: isCodeActive ? null : 'code' },
{ match: 'block' }
)
break

View File

@ -43,14 +43,11 @@ const App = () => {
switch (event.key) {
case '`': {
event.preventDefault()
const { selection } = editor
const isCode = selection
? Editor.match(editor, selection, { type: 'code' })
: false
const [node] = Editor.nodes(editor, { match: { type: 'code' } })
const isCodeActive = !!node
Editor.setNodes(
editor,
{ type: isCode ? null : 'code' },
{ type: isCodeActive ? null : 'code' },
{ match: 'block' }
)
break
@ -112,14 +109,11 @@ const App = () => {
switch (event.key) {
case '`': {
event.preventDefault()
const { selection } = editor
const isCode = selection
? Editor.match(editor, selection, { type: 'code' })
: false
const [node] = Editor.nodes(editor, { match: { type: 'code' } })
const isCodeActive = !!node
Editor.setNodes(
editor,
{ type: isCode ? null : 'code' },
{ type: isCodeActive ? null : 'code' },
{ match: 'block' }
)
break
@ -182,17 +176,21 @@ const withCustom = editor => {
// Define our own custom set of helpers for common queries.
const CustomEditor = {
isBoldMarkActive(editor) {
const { selection } = editor
const activeMarks = Editor.activeMarks(editor)
return activeMarks.some(mark => mark.type === 'bold')
const [mark] = Editor.marks(editor, {
match: { type: 'bold' },
mode: 'universal',
})
return !!mark
},
isCodeBlockActive(editor) {
const { selection } = editor
const isCode = selection
? Editor.match(editor, selection, { type: 'code' })
: false
return isCode
const [node] = Editor.nodes(editor, {
match: { type: 'code' },
mode: 'highest',
})
return !!node
},
}

View File

@ -20,7 +20,7 @@
"serve": "cd ./site && next",
"start": "npm-run-all --parallel --print-label watch serve",
"test": "mocha --require ./config/babel/register.cjs ./packages/*/test/index.js",
"test:debug": "mocha debug --require ./config/babel/register ./packages/*/test/index.js",
"test:debug": "mocha debug --require ./config/babel/register.cjs ./packages/*/test/index.js",
"watch": "yarn build:rollup --watch"
},
"devDependencies": {

View File

@ -18,7 +18,8 @@
"@types/esrever": "^0.2.0",
"esrever": "^0.2.0",
"immer": "^5.0.0",
"is-plain-object": "^3.0.0"
"is-plain-object": "^3.0.0",
"tiny-warning": "^1.0.3"
},
"keywords": [
"canvas",

View File

@ -1,3 +1,4 @@
import warning from 'tiny-warning'
import { reverse as reverseText } from 'esrever'
import {
@ -20,6 +21,7 @@ import {
Text,
TextEntry,
} from '../../..'
import { MarkMatch } from '../../mark'
export const LocationQueries = {
/**
@ -44,69 +46,19 @@ export const LocationQueries = {
hanging?: boolean
} = {}
): Mark[] {
const { union = false, hanging = false } = options
let { at = editor.selection } = options
warning(
false,
'The `Editor.activeMarks` helper is deprecated, use `Editor.marks` instead.'
)
if (!at) {
return []
}
at = Editor.range(editor, at)
if (!hanging) {
at = Editor.unhangRange(editor, at)
}
// If the range is collapsed at the start of a text node, it should carry
// over the marks from the previous text node in the same block.
if (Range.isCollapsed(at) && at.anchor.offset === 0) {
const { anchor } = at
const prev = Editor.previous(editor, anchor, 'text')
if (prev && Path.isSibling(anchor.path, prev[1])) {
const [prevNode, prevPath] = prev
if (Text.isText(prevNode)) {
at = Editor.range(editor, prevPath)
}
}
}
const marks: Mark[] = []
let first = true
for (const [node] of Editor.texts(editor, { at })) {
if (first) {
marks.push(...node.marks)
first = false
continue
}
if (union) {
for (const mark of node.marks) {
if (!Mark.exists(mark, marks)) {
marks.push(mark)
}
}
} else {
// PERF: If we're doing an intersection and the result hits zero it can
// never increase again, so we can exit early.
if (marks.length === 0) {
break
}
// Iterate backwards so that removing marks doesn't impact indexing.
for (let i = marks.length - 1; i >= 0; i--) {
const existing = marks[i]
if (!Mark.exists(existing, node.marks)) {
marks.splice(i, 1)
}
}
}
}
return marks
return Array.from(
Editor.marks(editor, {
at: options.at,
mode: options.union ? 'distinct' : 'universal',
continuing: true,
}),
([m]) => m
)
},
/**
@ -368,23 +320,117 @@ export const LocationQueries = {
editor: Editor,
options: {
at?: Location | Span
match?: MarkMatch
mode?: 'all' | 'first' | 'distinct' | 'universal'
reverse?: boolean
continuing?: boolean
} = {}
): Iterable<MarkEntry> {
const { at = editor.selection } = options
const { match, mode = 'all', reverse = false, continuing = false } = options
let { at = editor.selection } = options
if (!at) {
return
}
const [from, to] = toSpan(editor, at, options)
// If the range is collapsed at the start of a text node, it should continue
// the marks from the previous text node in the same block.
if (
continuing &&
Range.isRange(at) &&
Range.isCollapsed(at) &&
at.anchor.offset === 0
) {
const { anchor } = at
const prev = Editor.previous(editor, anchor, 'text')
yield* Node.marks(editor, {
...options,
if (prev && Path.isSibling(anchor.path, prev[1])) {
const [, prevPath] = prev
at = Editor.range(editor, prevPath)
}
}
const [from, to] = toSpan(editor, at, options)
const iterable = Node.texts(editor, {
reverse,
from,
to,
pass: ([n]) => Element.isElement(n) && editor.isVoid(n),
})
let universalMarks: Mark[] = []
let distinctMarks: Mark[] = []
let universalEntries: MarkEntry[] = []
let first = true
for (const entry of iterable) {
const [node, path] = entry
const isMatch = (m: MarkMatch, entry: MarkEntry) => {
if (typeof m === 'function') {
return m(entry)
} else {
return Mark.matches(entry[0], m)
}
}
debugger
if (mode === 'universal') {
debugger
if (first) {
universalMarks.push(...node.marks)
universalEntries = node.marks.map((m, i) => [m, i, node, path])
first = false
continue
}
// PERF: If we're in universal mode and the eligible marks hits zero
// it can never increase again, so we can exit early.
if (universalMarks.length === 0) {
debugger
return
}
debugger
for (let i = universalMarks.length - 1; i >= 0; i--) {
const existing = universalMarks[i]
if (!Mark.exists(existing, node.marks)) {
universalMarks.splice(i, 1)
}
}
} else {
for (let index = 0; index < node.marks.length; index++) {
const mark = node.marks[index]
const markEntry: MarkEntry = [mark, index, node, path]
if (match != null && !isMatch(match, markEntry)) {
continue
}
if (mode === 'distinct') {
if (Mark.exists(mark, distinctMarks)) {
continue
} else {
distinctMarks.push(mark)
}
}
yield markEntry
// After matching a mark, if we're in first mode skip to the next text.
if (mode === 'first') {
break
}
}
}
}
// In universal mode, the marks are collected while iterating and we can
// only be certain of which are universal when we've finished.
if (mode === 'universal') {
debugger
yield* universalEntries
}
},
/**
@ -413,6 +459,11 @@ export const LocationQueries = {
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
@ -453,7 +504,11 @@ export const LocationQueries = {
const span: Span = [from, to]
let i = 0
for (const entry of Editor.matches(editor, { at: span, match })) {
for (const entry of Editor.nodes(editor, {
at: span,
match,
mode: 'highest',
})) {
if (i === 1) {
return entry
}
@ -487,10 +542,17 @@ export const LocationQueries = {
editor: Editor,
options: {
at?: Location | Span
match?: NodeMatch
mode?: 'all' | 'highest'
reverse?: boolean
} = {}
): Iterable<NodeEntry> {
const { at = editor.selection } = options
const {
at = editor.selection,
match,
mode = 'all',
reverse = false,
} = options
if (!at) {
return
@ -498,13 +560,32 @@ export const LocationQueries = {
const [from, to] = toSpan(editor, at, options)
const iterable = Node.nodes(editor, {
...options,
reverse,
from,
to,
pass: ([n]) => Element.isElement(n) && editor.isVoid(n),
})
let prev: NodeEntry | undefined
for (const entry of iterable) {
if (match != null) {
if (mode === 'highest' && prev) {
const [, prevPath] = prev
const [, path] = entry
if (Path.compare(path, prevPath) === 0) {
continue
}
}
if (!Editor.isMatch(editor, entry, match)) {
continue
}
prev = entry
}
yield entry
}
},
@ -751,10 +832,11 @@ export const LocationQueries = {
const span: Span = [from, to]
let i = 0
for (const entry of Editor.matches(editor, {
for (const entry of Editor.nodes(editor, {
match,
at: span,
reverse: true,
mode: 'highest',
})) {
if (i === 1) {
return entry

View File

@ -144,7 +144,7 @@ export const NodeTransforms = {
return
}
const matches = Editor.matches(editor, { at, match })
const matches = Editor.nodes(editor, { at, match, mode: 'highest' })
const pathRefs = Array.from(matches, ([, p]) => Editor.pathRef(editor, p))
for (const pathRef of pathRefs) {
@ -352,7 +352,7 @@ export const NodeTransforms = {
}
const toRef = Editor.pathRef(editor, to)
const targets = Editor.matches(editor, { at, match })
const targets = Editor.nodes(editor, { at, match, mode: 'highest' })
const pathRefs = Array.from(targets, ([, p]) => Editor.pathRef(editor, p))
for (const pathRef of pathRefs) {
@ -401,7 +401,7 @@ export const NodeTransforms = {
at = Editor.unhangRange(editor, at)
}
const depths = Editor.matches(editor, { at, match })
const depths = Editor.nodes(editor, { at, match, mode: 'highest' })
const pathRefs = Array.from(depths, ([, p]) => Editor.pathRef(editor, p))
for (const pathRef of pathRefs) {
@ -446,7 +446,11 @@ export const NodeTransforms = {
at = Editor.unhangRange(editor, at)
}
for (const [node, path] of Editor.matches(editor, { at, match })) {
for (const [node, path] of Editor.nodes(editor, {
at,
match,
mode: 'highest',
})) {
const properties: Partial<Node> = {}
const newProperties: Partial<Node> = {}
@ -631,7 +635,7 @@ export const NodeTransforms = {
return
}
const matches = Editor.matches(editor, { at, match })
const matches = Editor.nodes(editor, { at, match, mode: 'highest' })
const pathRefs = Array.from(matches, ([, p]) => Editor.pathRef(editor, p))
for (const pathRef of pathRefs) {
@ -699,7 +703,14 @@ export const NodeTransforms = {
}
const roots: NodeEntry[] = editor.isInline(element)
? Array.from(Editor.matches(editor, { ...options, at, match: 'block' }))
? Array.from(
Editor.nodes(editor, {
...options,
at,
match: 'block',
mode: 'highest',
})
)
: [[editor, []]]
for (const [, rootPath] of roots) {
@ -712,7 +723,7 @@ export const NodeTransforms = {
}
const matches = Array.from(
Editor.matches(editor, { ...options, at: a, match })
Editor.nodes(editor, { ...options, at: a, match, mode: 'highest' })
)
if (matches.length > 0) {

View File

@ -92,8 +92,9 @@ export const TextTransforms = {
// Get the highest nodes that are completely inside the range, as well as
// the start and end nodes.
const matches = Editor.matches(editor, {
const matches = Editor.nodes(editor, {
at,
mode: 'highest',
match: ([n, p]) =>
(Element.isElement(n) && editor.isVoid(n)) ||
(!Path.isCommon(p, start.path) && !Path.isCommon(p, end.path)),

View File

@ -1,24 +0,0 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
export const input = (
<editor>
<block>
<mark key="a">
<anchor />o
</mark>
n
<mark key="b">
e<focus />
</mark>
</block>
</editor>
)
export const run = editor => {
return Array.from(Editor.activeMarks(editor, { union: true }))
}
export const output = [{ key: 'a' }, { key: 'b' }]

View File

@ -1,21 +1,23 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
import { jsx } from '../../..'
export const input = (
<editor>
<block>
<mark key="a">one</mark>
<cursor />
two
<text>
<cursor />
two
</text>
</block>
<block />
</editor>
)
export const run = editor => {
return Array.from(Editor.activeMarks(editor))
return Array.from(Editor.marks(editor, { continuing: true }), ([m]) => m)
}
export const output = [{ key: 'a' }]

View File

@ -0,0 +1,28 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block>
<mark key="a">
<mark key="b">
<anchor />o
</mark>
</mark>
n
<mark key="a">
<mark key="b">
e<focus />
</mark>
</mark>
</block>
</editor>
)
export const run = editor => {
return Array.from(Editor.marks(editor), ([m]) => m)
}
export const output = [{ key: 'b' }, { key: 'a' }, { key: 'b' }, { key: 'a' }]

View File

@ -0,0 +1,28 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../../..'
export const input = (
<editor>
<block>
<mark key="a">
<mark key="b">
<anchor />o
</mark>
</mark>
n
<mark key="a">
<mark key="b">
e<focus />
</mark>
</mark>
</block>
</editor>
)
export const run = editor => {
return Array.from(Editor.marks(editor, { mode: 'distinct' }), ([m]) => m)
}
export const output = [{ key: 'b' }, { key: 'a' }]

View File

@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
import { jsx } from '../../..'
export const input = (
<editor>
@ -16,8 +16,8 @@ export const input = (
<block>
<mark key="a">
<mark key="b">
o<focus />
ne
t<focus />
wo
</mark>
</mark>
</block>
@ -25,7 +25,7 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.activeMarks(editor))
return Array.from(Editor.marks(editor, { mode: 'universal' }), ([m]) => m)
}
export const output = [{ key: 'b' }, { key: 'a' }]

View File

@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
import { jsx } from '../../..'
export const input = (
<editor>
@ -16,7 +16,7 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.activeMarks(editor))
return Array.from(Editor.marks(editor, { mode: 'universal' }), ([m]) => m)
}
export const output = []

View File

@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
import { jsx } from '../../..'
export const input = (
<editor>
@ -17,7 +17,7 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.activeMarks(editor))
return Array.from(Editor.marks(editor, { mode: 'universal' }), ([m]) => m)
}
export const output = []

View File

@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
import { jsx } from '../../..'
export const input = (
<editor>
@ -18,7 +18,7 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.activeMarks(editor))
return Array.from(Editor.marks(editor, { mode: 'universal' }), ([m]) => m)
}
export const output = []

View File

@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
import { jsx } from '../../..'
export const input = (
<editor>
@ -17,7 +17,7 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.activeMarks(editor))
return Array.from(Editor.marks(editor, { mode: 'universal' }), ([m]) => m)
}
export const output = [{ key: 'b' }, { key: 'a' }]

View File

@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
import { jsx } from '../../..'
export const input = (
<editor>
@ -13,7 +13,7 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.activeMarks(editor))
return Array.from(Editor.marks(editor, { mode: 'universal' }), ([m]) => m)
}
export const output = []

View File

@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
import { jsx } from '../../..'
export const input = (
<editor>
@ -15,7 +15,7 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.activeMarks(editor))
return Array.from(Editor.marks(editor, { mode: 'universal' }), ([m]) => m)
}
export const output = [{ key: 'a' }]

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,7 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.activeMarks(editor))
return Array.from(Editor.marks(editor, { mode: 'universal' }), ([m]) => m)
}
export const output = []

View File

@ -13,12 +13,12 @@ export const input = (
export const run = editor => {
return Array.from(
Editor.matches(editor, { at: [], match: 'block', reverse: true })
Editor.nodes(editor, { at: [], match: 'block', mode: 'highest' })
)
}
export const output = [
[<block>three</block>, [2]],
[<block>two</block>, [1]],
[<block>one</block>, [0]],
[<block>two</block>, [1]],
[<block>three</block>, [2]],
]

View File

@ -15,7 +15,9 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.matches(editor, { at: [], match: 'block' }))
return Array.from(
Editor.nodes(editor, { at: [], match: 'block', mode: 'highest' })
)
}
export const output = [

View File

@ -12,11 +12,18 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.matches(editor, { at: [], match: 'block' }))
return Array.from(
Editor.nodes(editor, {
at: [],
match: 'block',
mode: 'highest',
reverse: true,
})
)
}
export const output = [
[<block>one</block>, [0]],
[<block>two</block>, [1]],
[<block>three</block>, [2]],
[<block>two</block>, [1]],
[<block>one</block>, [0]],
]

View File

@ -12,7 +12,9 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.matches(editor, { at: [], match: 'block' }))
return Array.from(
Editor.nodes(editor, { at: [], match: 'block', mode: 'highest' })
)
}
export const output = []

View File

@ -10,7 +10,9 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.matches(editor, { at: [], match: 'block' }))
return Array.from(
Editor.nodes(editor, { at: [], match: 'block', mode: 'highest' })
)
}
export const output = [[<block>one</block>, [0]]]

View File

@ -12,7 +12,9 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.matches(editor, { at: [], match: 'block' }))
return Array.from(
Editor.nodes(editor, { at: [], match: 'block', mode: 'highest' })
)
}
export const output = [

View File

@ -13,7 +13,11 @@ export const input = (
export const run = editor => {
return Array.from(
Editor.matches(editor, { at: [], match: ([, p]) => p.length === 1 })
Editor.nodes(editor, {
at: [],
match: ([, p]) => p.length === 1,
mode: 'highest',
})
)
}

View File

@ -10,7 +10,9 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.matches(editor, { at: [], match: 'inline' }))
return Array.from(
Editor.nodes(editor, { at: [], match: 'inline', mode: 'highest' })
)
}
export const output = [[<text>one</text>, [0, 0]]]

View File

@ -13,14 +13,14 @@ export const input = (
export const run = editor => {
return Array.from(
Editor.matches(editor, { at: [], match: 'inline', reverse: true })
Editor.nodes(editor, { at: [], match: 'inline', mode: 'highest' })
)
}
export const output = [
[<text>five</text>, [0, 4]],
[<inline>four</inline>, [0, 3]],
[<text>three</text>, [0, 2]],
[<inline>two</inline>, [0, 1]],
[<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

@ -16,7 +16,9 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.matches(editor, { at: [], match: 'inline' }))
return Array.from(
Editor.nodes(editor, { at: [], match: 'inline', mode: 'highest' })
)
}
export const output = [

View File

@ -12,13 +12,20 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.matches(editor, { at: [], match: 'inline' }))
return Array.from(
Editor.nodes(editor, {
at: [],
match: 'inline',
mode: 'highest',
reverse: true,
})
)
}
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]],
[<inline>four</inline>, [0, 3]],
[<text>three</text>, [0, 2]],
[<inline>two</inline>, [0, 1]],
[<text>one</text>, [0, 0]],
]

View File

@ -12,7 +12,9 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.matches(editor, { at: [], match: 'inline' }))
return Array.from(
Editor.nodes(editor, { at: [], match: 'inline', mode: 'highest' })
)
}
export const output = [

View File

@ -12,7 +12,9 @@ export const input = (
)
export const run = editor => {
return Array.from(Editor.matches(editor, { at: [], match: 'inline' }))
return Array.from(
Editor.nodes(editor, { at: [], match: 'inline', mode: 'highest' })
)
}
export const output = [

View File

@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
import { jsx } from '../../..'
export const input = (
<editor>

View File

@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
import { jsx } from '../../..'
export const input = (
<editor>

View File

@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
import { jsx } from '../../..'
export const input = (
<editor>

View File

@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
import { jsx } from '../../..'
export const input = (
<editor>

View File

@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
import { jsx } from '../../..'
export const input = (
<editor>

View File

@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
import { jsx } from '../../..'
export const input = (
<editor>

View File

@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
import { jsx } from '../../..'
export const input = (
<editor>

View File

@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
import { jsx } from '../../..'
export const input = (
<editor>

View File

@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
import { jsx } from '../../..'
export const input = (
<editor>

View File

@ -1,7 +1,7 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { jsx } from '../..'
import { jsx } from '../../..'
export const input = (
<editor>

View File

@ -33,16 +33,15 @@ const withChecklists = editor => {
selection &&
Range.isCollapsed(selection)
) {
const { anchor } = selection
const match = Editor.match(editor, anchor, {
type: 'check-list-item',
const [match] = Editor.nodes(editor, {
match: { type: 'check-list-item' },
})
if (match) {
const [, path] = match
const start = Editor.start(editor, path)
if (Point.equals(anchor, start)) {
if (Point.equals(selection.anchor, start)) {
Editor.setNodes(
editor,
{ type: 'paragraph' },

View File

@ -57,9 +57,8 @@ const withMarks = editor => {
}
const isMarkActive = (editor, type) => {
const marks = Editor.activeMarks(editor)
const isActive = marks.some(m => m.type === type)
return isActive
const [mark] = Editor.marks(editor, { match: { type }, mode: 'universal' })
return !!mark
}
const Mark = ({ attributes, children, mark }) => {

View File

@ -61,8 +61,8 @@ const withLinks = editor => {
}
const isLinkActive = editor => {
const { selection } = editor
return !!(selection && Editor.match(editor, selection, { type: 'link' }))
const [link] = Editor.nodes(editor, { match: { type: 'link' } })
return !!link
}
const unwrapLink = editor => {

View File

@ -47,7 +47,7 @@ const withShortcuts = editor => {
Range.isCollapsed(selection)
) {
const { anchor } = selection
const block = Editor.match(editor, anchor, 'block')
const [block] = Editor.nodes(editor, { match: 'block' })
const path = block ? block[1] : []
const start = Editor.start(editor, path)
const range = { anchor, focus: start }
@ -73,14 +73,16 @@ const withShortcuts = editor => {
selection &&
Range.isCollapsed(selection)
) {
const { anchor } = selection
const match = Editor.match(editor, anchor, 'block')
const [match] = Editor.nodes(editor, { match: 'block' })
if (match) {
const [block, path] = match
const start = Editor.start(editor, path)
if (block.type !== 'paragraph' && Point.equals(anchor, start)) {
if (
block.type !== 'paragraph' &&
Point.equals(selection.anchor, start)
) {
Editor.setNodes(editor, { type: 'paragraph' })
if (match.type === 'list-item') {

View File

@ -75,10 +75,8 @@ const withMentions = editor => {
}
const isMentionActive = editor => {
const match = Editor.match(editor, editor.selection, {
type: 'mention',
})
return !!match
const [mention] = Editor.nodes(editor, { match: { type: 'mention' } })
return !!mention
}
const Element = props => {

View File

@ -92,15 +92,12 @@ const withRichText = editor => {
}
const isMarkActive = (editor, type) => {
const marks = Editor.activeMarks(editor)
const isActive = marks.some(m => m.type === type)
return isActive
const [mark] = Editor.marks(editor, { match: { type }, mode: 'universal' })
return !!mark
}
const isBlockActive = (editor, type) => {
const { selection } = editor
if (!selection) return false
const match = Editor.match(editor, selection, { type })
const [match] = Editor.nodes(editor, { match: { type } })
return !!match
}

View File

@ -29,8 +29,7 @@ const withTables = editor => {
selection &&
Range.isCollapsed(selection)
) {
const { anchor } = selection
const cell = Editor.match(editor, anchor, { type: 'table-cell' })
const [cell] = Editor.nodes(editor, { match: { type: 'table-cell' } })
if (cell) {
const [, cellPath] = cell
@ -39,19 +38,18 @@ const withTables = editor => {
? Editor.start(editor, cellPath)
: Editor.end(editor, cellPath)
if (Point.equals(anchor, edge)) {
if (Point.equals(selection.anchor, edge)) {
return
}
}
}
if (
type === 'insert_break' &&
selection &&
(Editor.match(editor, selection.anchor, { type: 'table' }) ||
Editor.match(editor, selection.focus, { type: 'table' }))
) {
return
if (type === 'insert_break' && selection) {
const [table] = Editor.nodes(editor, { match: { type: 'table' } })
if (table) {
return
}
}
exec(command)

View File

@ -10128,7 +10128,7 @@ tiny-invariant@^1.0.2:
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.0.6.tgz#b3f9b38835e36a41c843a3b0907a5a7b3755de73"
integrity sha512-FOyLWWVjG+aC0UqG76V53yAWdXfH8bO6FNmyZOuUrzDzK8DI3/JRY25UD7+g49JWM1LXwymsKERB+DzI0dTEQA==
tiny-warning@^1.0.0, tiny-warning@^1.0.2:
tiny-warning@^1.0.0, tiny-warning@^1.0.2, tiny-warning@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==