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:
parent
0da1dd128c
commit
68569f286e
@ -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' }
|
||||
)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -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": {
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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)),
|
||||
|
@ -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' }]
|
@ -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' }]
|
@ -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' }]
|
@ -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' }]
|
@ -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' }]
|
@ -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 = []
|
@ -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 = []
|
@ -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 = []
|
@ -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' }]
|
@ -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 = []
|
@ -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' }]
|
@ -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 = []
|
@ -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]],
|
||||
]
|
@ -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 = [
|
@ -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]],
|
||||
]
|
@ -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 = []
|
@ -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]]]
|
@ -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 = [
|
@ -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',
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@ -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]]]
|
@ -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]],
|
||||
]
|
@ -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 = [
|
@ -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]],
|
||||
]
|
@ -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 = [
|
@ -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 = [
|
@ -1,7 +1,7 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { Editor } from 'slate'
|
||||
import { jsx } from '../..'
|
||||
import { jsx } from '../../..'
|
||||
|
||||
export const input = (
|
||||
<editor>
|
@ -1,7 +1,7 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { Editor } from 'slate'
|
||||
import { jsx } from '../..'
|
||||
import { jsx } from '../../..'
|
||||
|
||||
export const input = (
|
||||
<editor>
|
@ -1,7 +1,7 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { Editor } from 'slate'
|
||||
import { jsx } from '../..'
|
||||
import { jsx } from '../../..'
|
||||
|
||||
export const input = (
|
||||
<editor>
|
@ -1,7 +1,7 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { Editor } from 'slate'
|
||||
import { jsx } from '../..'
|
||||
import { jsx } from '../../..'
|
||||
|
||||
export const input = (
|
||||
<editor>
|
@ -1,7 +1,7 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { Editor } from 'slate'
|
||||
import { jsx } from '../..'
|
||||
import { jsx } from '../../..'
|
||||
|
||||
export const input = (
|
||||
<editor>
|
@ -1,7 +1,7 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { Editor } from 'slate'
|
||||
import { jsx } from '../..'
|
||||
import { jsx } from '../../..'
|
||||
|
||||
export const input = (
|
||||
<editor>
|
@ -1,7 +1,7 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { Editor } from 'slate'
|
||||
import { jsx } from '../..'
|
||||
import { jsx } from '../../..'
|
||||
|
||||
export const input = (
|
||||
<editor>
|
@ -1,7 +1,7 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { Editor } from 'slate'
|
||||
import { jsx } from '../..'
|
||||
import { jsx } from '../../..'
|
||||
|
||||
export const input = (
|
||||
<editor>
|
@ -1,7 +1,7 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { Editor } from 'slate'
|
||||
import { jsx } from '../..'
|
||||
import { jsx } from '../../..'
|
||||
|
||||
export const input = (
|
||||
<editor>
|
@ -1,7 +1,7 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { Editor } from 'slate'
|
||||
import { jsx } from '../..'
|
||||
import { jsx } from '../../..'
|
||||
|
||||
export const input = (
|
||||
<editor>
|
@ -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' },
|
||||
|
@ -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 }) => {
|
||||
|
@ -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 => {
|
||||
|
@ -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') {
|
||||
|
@ -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 => {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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==
|
||||
|
Loading…
x
Reference in New Issue
Block a user