+
-
-
+
+
diff --git a/packages/slate/src/commands/at-range.js b/packages/slate/src/commands/at-range.js
index 84d6836e8..04d3e95e0 100644
--- a/packages/slate/src/commands/at-range.js
+++ b/packages/slate/src/commands/at-range.js
@@ -21,10 +21,10 @@ function deleteExpandedAtRange(editor, range) {
const { document } = value
const { start, end } = range
- if (document.hasDescendant(start.key)) {
+ if (document.hasDescendant(start.path)) {
range = range.moveToStart()
} else {
- range = range.moveTo(end.key, 0).normalize(document)
+ range = range.moveTo(end.path, 0).normalize(document)
}
return range
@@ -186,8 +186,8 @@ Commands.deleteAtRange = (editor, range) => {
const endLength = endOffset
const ancestor = document.getCommonAncestor(startKey, endKey)
- const startChild = ancestor.getFurthestAncestor(startKey)
- const endChild = ancestor.getFurthestAncestor(endKey)
+ const startChild = ancestor.getFurthestChild(startKey)
+ const endChild = ancestor.getFurthestChild(endKey)
const startParent = document.getParent(startBlock.key)
const startParentIndex = startParent.nodes.indexOf(startBlock)
@@ -248,7 +248,15 @@ Commands.deleteAtRange = (editor, range) => {
// into the start block.
if (startBlock.key !== endBlock.key) {
document = editor.value.document
- const lonely = document.getFurthestOnlyChildAncestor(endBlock.key)
+ let onlyChildAncestor
+
+ for (const [node] of document.ancestors(endBlock.key)) {
+ if (node.nodes.size > 1) {
+ break
+ } else {
+ onlyChildAncestor = node
+ }
+ }
// Move the end block to be right after the start block.
if (endParentIndex !== startParentIndex + 1) {
@@ -268,8 +276,8 @@ Commands.deleteAtRange = (editor, range) => {
}
// If nested empty blocks are left over above the end block, remove them.
- if (lonely) {
- editor.removeNodeByKey(lonely.key)
+ if (onlyChildAncestor) {
+ editor.removeNodeByKey(onlyChildAncestor.key)
}
}
}
@@ -296,7 +304,7 @@ Commands.deleteBackwardAtRange = (editor, range, n = 1) => {
return
}
- const voidParent = document.getClosestVoid(start.key, editor)
+ const voidParent = document.getClosestVoid(start.path, editor)
// If there is a void parent, delete it.
if (voidParent) {
@@ -309,7 +317,7 @@ Commands.deleteBackwardAtRange = (editor, range, n = 1) => {
return
}
- const block = document.getClosestBlock(start.key)
+ const block = document.getClosestBlock(start.path)
// PERF: If the closest block is empty, remove it. This is just a shortcut,
// since merging it would result in the same outcome.
@@ -325,7 +333,7 @@ Commands.deleteBackwardAtRange = (editor, range, n = 1) => {
// If the range is at the start of the text node, we need to figure out what
// is behind it to know how to delete...
- const text = document.getDescendant(start.key)
+ const text = document.getDescendant(start.path)
if (start.isAtStartOfNode(text)) {
let prev = document.getPreviousText(text.key)
@@ -401,7 +409,7 @@ Commands.deleteCharBackwardAtRange = (editor, range) => {
const { value } = editor
const { document } = value
const { start } = range
- const startBlock = document.getClosestBlock(start.key)
+ const startBlock = document.getClosestBlock(start.path)
const offset = startBlock.getOffset(start.key)
const o = offset + start.offset
const { text } = startBlock
@@ -425,7 +433,7 @@ Commands.deleteCharForwardAtRange = (editor, range) => {
const { value } = editor
const { document } = value
const { start } = range
- const startBlock = document.getClosestBlock(start.key)
+ const startBlock = document.getClosestBlock(start.path)
const offset = startBlock.getOffset(start.key)
const o = offset + start.offset
const { text } = startBlock
@@ -453,7 +461,7 @@ Commands.deleteForwardAtRange = (editor, range, n = 1) => {
return
}
- const voidParent = document.getClosestVoid(start.key, editor)
+ const voidParent = document.getClosestVoid(start.path, editor)
// If the node has a void parent, delete it.
if (voidParent) {
@@ -461,7 +469,7 @@ Commands.deleteForwardAtRange = (editor, range, n = 1) => {
return
}
- const block = document.getClosestBlock(start.key)
+ const block = document.getClosestBlock(start.path)
// If the closest is not void, but empty, remove it
if (
@@ -487,7 +495,7 @@ Commands.deleteForwardAtRange = (editor, range, n = 1) => {
// If the range is at the start of the text node, we need to figure out what
// is behind it to know how to delete...
- const text = document.getDescendant(start.key)
+ const text = document.getDescendant(start.path)
if (start.isAtEndOfNode(text)) {
const next = document.getNextText(text.key)
@@ -555,7 +563,7 @@ Commands.deleteLineBackwardAtRange = (editor, range) => {
const { value } = editor
const { document } = value
const { start } = range
- const startBlock = document.getClosestBlock(start.key)
+ const startBlock = document.getClosestBlock(start.path)
const offset = startBlock.getOffset(start.key)
const o = offset + start.offset
editor.deleteBackwardAtRange(range, o)
@@ -577,7 +585,7 @@ Commands.deleteLineForwardAtRange = (editor, range) => {
const { value } = editor
const { document } = value
const { start } = range
- const startBlock = document.getClosestBlock(start.key)
+ const startBlock = document.getClosestBlock(start.path)
const offset = startBlock.getOffset(start.key)
const o = offset + start.offset
editor.deleteForwardAtRange(range, startBlock.text.length - o)
@@ -599,7 +607,7 @@ Commands.deleteWordBackwardAtRange = (editor, range) => {
const { value } = editor
const { document } = value
const { start } = range
- const startBlock = document.getClosestBlock(start.key)
+ const startBlock = document.getClosestBlock(start.path)
const offset = startBlock.getOffset(start.key)
const o = offset + start.offset
const { text } = startBlock
@@ -623,7 +631,7 @@ Commands.deleteWordForwardAtRange = (editor, range) => {
const { value } = editor
const { document } = value
const { start } = range
- const startBlock = document.getClosestBlock(start.key)
+ const startBlock = document.getClosestBlock(start.path)
const offset = startBlock.getOffset(start.key)
const o = offset + start.offset
const { text } = startBlock
@@ -710,9 +718,9 @@ Commands.insertFragmentAtRange = (editor, range, fragment) => {
const { start } = range
const { value } = editor
let { document } = value
- let startText = document.getDescendant(start.key)
+ let startText = document.getDescendant(start.path)
let startBlock = document.getClosestBlock(startText.key)
- let startChild = startBlock.getFurthestAncestor(startText.key)
+ let startChild = startBlock.getFurthestChild(startText.key)
const isAtStart = start.isAtStartOfNode(startBlock)
const parent = document.getParent(startBlock.key)
const index = parent.nodes.indexOf(startBlock)
@@ -768,7 +776,7 @@ Commands.insertFragmentAtRange = (editor, range, fragment) => {
document = editor.value.document
startText = document.getDescendant(start.key)
startBlock = document.getClosestBlock(start.key)
- startChild = startBlock.getFurthestAncestor(startText.key)
+ startChild = startBlock.getFurthestChild(startText.key)
// If the first and last block aren't the same, we need to move any of the
// starting block's children after the split into the last block of the
@@ -800,7 +808,7 @@ Commands.insertFragmentAtRange = (editor, range, fragment) => {
} else {
// Otherwise, we maintain the starting block, and insert all of the first
// block's inline nodes into it at the split point.
- const inlineChild = startBlock.getFurthestAncestor(startText.key)
+ const inlineChild = startBlock.getFurthestChild(startText.key)
const inlineIndex = startBlock.nodes.indexOf(inlineChild)
firstBlock.nodes.forEach((inline, i) => {
@@ -861,15 +869,15 @@ Commands.insertInlineAtRange = (editor, range, inline) => {
const { value } = editor
const { document } = value
const { start } = range
- const parent = document.getParent(start.key)
- const startText = document.assertDescendant(start.key)
+ const parent = document.getParent(start.path)
+ const startText = document.assertDescendant(start.path)
const index = parent.nodes.indexOf(startText)
if (editor.isVoid(parent)) {
return
}
- editor.splitNodeByKey(start.key, start.offset)
+ editor.splitNodeByPath(start.path, start.offset)
editor.insertNodeByKey(parent.key, index + 1, inline)
})
}
@@ -891,13 +899,13 @@ Commands.insertTextAtRange = (editor, range, text, marks) => {
const { document } = value
const { start } = range
const offset = start.offset
- const parent = document.getParent(start.key)
+ const parent = document.getParent(start.path)
if (editor.isVoid(parent)) {
return
}
- editor.insertTextByKey(start.key, offset, text, marks)
+ editor.insertTextByPath(start.path, offset, text, marks)
})
}
@@ -947,8 +955,8 @@ Commands.setBlocksAtRange = (editor, range, properties) => {
const blocks = document.getLeafBlocksAtRange(range)
const { start, end, isCollapsed } = range
- const isStartVoid = document.hasVoidParent(start.key, editor)
- const startBlock = document.getClosestBlock(start.key)
+ const isStartVoid = document.hasVoidParent(start.path, editor)
+ const startBlock = document.getClosestBlock(start.path)
const endBlock = document.getClosestBlock(end.key)
// Check if we have a "hanging" selection case where the even though the
@@ -1006,7 +1014,7 @@ Commands.splitBlockAtRange = (editor, range, height = 1) => {
const { start, end } = range
let { value } = editor
let { document } = value
- let node = document.assertDescendant(start.key)
+ let node = document.assertDescendant(start.path)
let parent = document.getClosestBlock(node.key)
let h = 0
@@ -1017,7 +1025,7 @@ Commands.splitBlockAtRange = (editor, range, height = 1) => {
}
editor.withoutNormalizing(() => {
- editor.splitDescendantsByKey(node.key, start.key, start.offset)
+ editor.splitDescendantsByKey(node.key, start.path, start.offset)
value = editor.value
document = value.document
@@ -1028,7 +1036,7 @@ Commands.splitBlockAtRange = (editor, range, height = 1) => {
range = range.moveAnchorToStartOfNode(nextBlock)
range = range.setFocus(range.focus.setPath(null))
- if (start.key === end.key) {
+ if (start.path.equals(end.path)) {
range = range.moveFocusTo(range.anchor.key, end.offset - start.offset)
}
@@ -1052,7 +1060,7 @@ Commands.splitInlineAtRange = (editor, range, height = Infinity) => {
const { start } = range
const { value } = editor
const { document } = value
- let node = document.assertDescendant(start.key)
+ let node = document.assertDescendant(start.path)
let parent = document.getClosestInline(node.key)
let h = 0
@@ -1062,7 +1070,7 @@ Commands.splitInlineAtRange = (editor, range, height = Infinity) => {
h++
}
- editor.splitDescendantsByKey(node.key, start.key, start.offset)
+ editor.splitDescendantsByKey(node.key, start.path, start.offset)
}
/**
@@ -1294,7 +1302,7 @@ Commands.wrapInlineAtRange = (editor, range, inline) => {
if (range.isCollapsed) {
// Wrapping an inline void
- const inlineParent = document.getClosestInline(start.key)
+ const inlineParent = document.getClosestInline(start.path)
if (!inlineParent) {
return
@@ -1311,12 +1319,12 @@ Commands.wrapInlineAtRange = (editor, range, inline) => {
inline = inline.set('nodes', inline.nodes.clear())
const blocks = document.getLeafBlocksAtRange(range)
- let startBlock = document.getClosestBlock(start.key)
- let endBlock = document.getClosestBlock(end.key)
- const startInline = document.getClosestInline(start.key)
- const endInline = document.getClosestInline(end.key)
- let startChild = startBlock.getFurthestAncestor(start.key)
- let endChild = endBlock.getFurthestAncestor(end.key)
+ let startBlock = document.getClosestBlock(start.path)
+ let endBlock = document.getClosestBlock(end.path)
+ const startInline = document.getClosestInline(start.path)
+ const endInline = document.getClosestInline(end.path)
+ let startChild = startBlock.getFurthestChild(start.key)
+ let endChild = endBlock.getFurthestChild(end.key)
editor.withoutNormalizing(() => {
if (!startInline || startInline !== endInline) {
@@ -1327,8 +1335,8 @@ Commands.wrapInlineAtRange = (editor, range, inline) => {
document = editor.value.document
startBlock = document.getDescendant(startBlock.key)
endBlock = document.getDescendant(endBlock.key)
- startChild = startBlock.getFurthestAncestor(start.key)
- endChild = endBlock.getFurthestAncestor(end.key)
+ startChild = startBlock.getFurthestChild(start.key)
+ endChild = endBlock.getFurthestChild(end.key)
const startIndex = startBlock.nodes.indexOf(startChild)
const endIndex = endBlock.nodes.indexOf(endChild)
@@ -1353,14 +1361,14 @@ Commands.wrapInlineAtRange = (editor, range, inline) => {
} else if (startBlock === endBlock) {
document = editor.value.document
startBlock = document.getClosestBlock(start.key)
- startChild = startBlock.getFurthestAncestor(start.key)
+ startChild = startBlock.getFurthestChild(start.key)
const startInner = document.getNextSibling(startChild.key)
const startInnerIndex = startBlock.nodes.indexOf(startInner)
const endInner =
start.key === end.key
? startInner
- : startBlock.getFurthestAncestor(end.key)
+ : startBlock.getFurthestChild(end.key)
const inlines = startBlock.nodes
.skipUntil(n => n === startInner)
.takeUntil(n => n === endInner)
@@ -1416,7 +1424,7 @@ Commands.wrapTextAtRange = (editor, range, prefix, suffix = prefix) => {
const startRange = range.moveToStart()
let endRange = range.moveToEnd()
- if (start.key === end.key) {
+ if (start.path.equals(end.path)) {
endRange = endRange.moveForward(prefix.length)
}
diff --git a/packages/slate/src/commands/by-path.js b/packages/slate/src/commands/by-path.js
index ff08ea026..56ddfaacc 100644
--- a/packages/slate/src/commands/by-path.js
+++ b/packages/slate/src/commands/by-path.js
@@ -109,28 +109,28 @@ Commands.insertNodeByPath = (editor, path, index, node) => {
Commands.insertTextByPath = (editor, path, offset, text, marks) => {
marks = Mark.createSet(marks)
const { value } = editor
- const { decorations, document } = value
- const node = document.assertNode(path)
- const { key } = node
- let updated = false
-
- const decs = decorations.filter(dec => {
- const { start, end, mark } = dec
- const isAtomic = editor.isAtomic(mark)
- if (!isAtomic) return true
- if (start.key !== key) return true
-
- if (start.offset < offset && (end.key !== key || end.offset > offset)) {
- updated = true
- return false
- }
-
- return true
- })
+ const { annotations, document } = value
+ document.assertNode(path)
editor.withoutNormalizing(() => {
- if (updated) {
- editor.setDecorations(decs)
+ for (const annotation of annotations.values()) {
+ const { start, end } = annotation
+ const isAtomic = editor.isAtomic(annotation)
+
+ if (!isAtomic) {
+ continue
+ }
+
+ if (!start.path.equals(path)) {
+ continue
+ }
+
+ if (
+ start.offset < offset &&
+ (!end.path.equals(path) || end.offset > offset)
+ ) {
+ editor.removeAnnotation(annotation)
+ }
}
editor.applyOperation({
@@ -275,12 +275,17 @@ Commands.removeAllMarksByPath = (editor, path) => {
const { state } = editor
const { document } = state
const node = document.assertNode(path)
- const texts = node.object === 'text' ? [node] : node.getTextsAsArray()
- texts.forEach(text => {
- text.marks.forEach(mark => {
- editor.removeMarkByKey(text.key, 0, text.text.length, mark)
- })
+ editor.withoutNormalizing(() => {
+ if (node.object === 'text') {
+ editor.removeMarksByPath(path, 0, node.text.length, node.marks)
+ return
+ }
+
+ for (const [n, p] of node.texts()) {
+ const pth = path.concat(p)
+ editor.removeMarksByPath(pth, 0, n.text.length, n.marks)
+ }
})
}
@@ -314,45 +319,36 @@ Commands.removeNodeByPath = (editor, path) => {
Commands.removeTextByPath = (editor, path, offset, length) => {
const { value } = editor
- const { document, decorations } = value
+ const { document, annotations } = value
const node = document.assertNode(path)
-
- const { text } = node
- const string = text.slice(offset, offset + length)
-
- const { key } = node
- let updated = false
-
- const decs = decorations.filter(dec => {
- const { start, end, mark } = dec
- const isAtomic = editor.isAtomic(mark)
-
- if (!isAtomic) {
- return true
- }
-
- if (start.key !== key) {
- return true
- }
-
- if (start.offset < offset && (end.key !== key || end.offset > offset)) {
- updated = true
- return false
- }
-
- return true
- })
+ const text = node.text.slice(offset, offset + length)
editor.withoutNormalizing(() => {
- if (updated) {
- editor.setDecorations(decs)
+ for (const annotation of annotations.values()) {
+ const { start, end } = annotation
+ const isAtomic = editor.isAtomic(annotation)
+
+ if (!isAtomic) {
+ continue
+ }
+
+ if (!start.path.equals(path)) {
+ continue
+ }
+
+ if (
+ start.offset < offset &&
+ (!end.path.equals(path) || end.offset > offset)
+ ) {
+ editor.removeAnnotation(annotation)
+ }
}
editor.applyOperation({
type: 'remove_text',
path,
offset,
- text: string,
+ text,
})
})
}
@@ -528,24 +524,22 @@ Commands.splitDescendantsByPath = (editor, path, textPath, textOffset) => {
const { value } = editor
const { document } = value
- const node = document.assertNode(path)
- const text = document.assertNode(textPath)
- const ancestors = document.getAncestors(textPath)
- const nodes = ancestors
- .skipUntil(a => a.key === node.key)
- .reverse()
- .unshift(text)
-
- let previous
- let index
+ let index = textOffset
+ let lastPath = textPath
editor.withoutNormalizing(() => {
- nodes.forEach(n => {
- const prevIndex = index == null ? null : index
- index = previous ? n.nodes.indexOf(previous) + 1 : textOffset
- previous = n
- editor.splitNodeByKey(n.key, index, { target: prevIndex })
- })
+ editor.splitNodeByKey(textPath, textOffset)
+
+ for (const [, ancestorPath] of document.ancestors(textPath)) {
+ const target = index
+ index = lastPath.last() + 1
+ lastPath = ancestorPath
+ editor.splitNodeByPath(ancestorPath, index, { target })
+
+ if (ancestorPath.equals(path)) {
+ break
+ }
+ }
})
}
diff --git a/packages/slate/src/commands/on-value.js b/packages/slate/src/commands/on-value.js
index 5077e8177..4d877be18 100644
--- a/packages/slate/src/commands/on-value.js
+++ b/packages/slate/src/commands/on-value.js
@@ -1,4 +1,5 @@
import pick from 'lodash/pick'
+import Annotation from '../models/annotation'
import Value from '../models/value'
/**
@@ -28,21 +29,31 @@ Commands.setData = (editor, data = {}) => {
})
}
-/**
- * Set `properties` on the value.
- *
- * @param {Editor} editor
- * @param {Object|Value} properties
- */
-
-Commands.setDecorations = (editor, decorations = []) => {
- const { value } = editor
- const newProperties = Value.createProperties({ decorations })
- const prevProperties = pick(value, Object.keys(newProperties))
+Commands.addAnnotation = (editor, annotation) => {
+ annotation = Annotation.create(annotation)
editor.applyOperation({
- type: 'set_value',
- properties: prevProperties,
+ type: 'add_annotation',
+ annotation,
+ })
+}
+
+Commands.removeAnnotation = (editor, annotation) => {
+ annotation = Annotation.create(annotation)
+
+ editor.applyOperation({
+ type: 'remove_annotation',
+ annotation,
+ })
+}
+
+Commands.setAnnotation = (editor, annotation, newProperties) => {
+ annotation = Annotation.create(annotation)
+ newProperties = Annotation.createProperties(newProperties)
+
+ editor.applyOperation({
+ type: 'set_annotation',
+ properties: annotation,
newProperties,
})
}
diff --git a/packages/slate/src/commands/with-intent.js b/packages/slate/src/commands/with-intent.js
index c38b371dc..977a101de 100644
--- a/packages/slate/src/commands/with-intent.js
+++ b/packages/slate/src/commands/with-intent.js
@@ -259,7 +259,7 @@ Commands.insertFragment = (editor, fragment) => {
const lastBlock = fragment.getClosestBlock(lastText.key)
const firstChild = fragment.nodes.first()
const lastChild = fragment.nodes.last()
- const keys = document.getTexts().map(text => text.key)
+ const keys = Array.from(document.texts(), ([text]) => text.key)
const isAppending =
!startInline ||
(start.isAtStartOfNode(startText) || end.isAtStartOfNode(startText)) ||
diff --git a/packages/slate/src/controllers/editor.js b/packages/slate/src/controllers/editor.js
index 9a4904562..9ad88d624 100644
--- a/packages/slate/src/controllers/editor.js
+++ b/packages/slate/src/controllers/editor.js
@@ -639,7 +639,7 @@ function normalizeNodeByPath(editor, path) {
* Register a `plugin` with the editor.
*
* @param {Editor} editor
- * @param {Object|Array} plugin
+ * @param {Object|Array|Null} plugin
*/
function registerPlugin(editor, plugin) {
@@ -648,6 +648,10 @@ function registerPlugin(editor, plugin) {
return
}
+ if (plugin == null) {
+ return
+ }
+
const { commands, queries, schema, ...rest } = plugin
if (commands) {
diff --git a/packages/slate/src/index.js b/packages/slate/src/index.js
index 8b85a6afe..23531b0c7 100644
--- a/packages/slate/src/index.js
+++ b/packages/slate/src/index.js
@@ -4,6 +4,7 @@ import './interfaces/node'
import './interfaces/element'
import './interfaces/range'
+import Annotation from './models/annotation'
import Block from './models/block'
import Change from './models/change'
import Data from './models/data'
@@ -32,6 +33,7 @@ import { resetMemoization, useMemoization } from './utils/memoize'
*/
export {
+ Annotation,
Block,
Change,
Data,
@@ -56,6 +58,7 @@ export {
}
export default {
+ Annotation,
Block,
Change,
Data,
diff --git a/packages/slate/src/interfaces/element.js b/packages/slate/src/interfaces/element.js
index a0b02bee9..f1a501d7d 100644
--- a/packages/slate/src/interfaces/element.js
+++ b/packages/slate/src/interfaces/element.js
@@ -1,20 +1,22 @@
-import direction from 'direction'
+import getDirection from 'direction'
import invariant from 'tiny-invariant'
import warning from 'tiny-warning'
-import { List, OrderedSet, Set, Stack } from 'immutable'
+import { List, OrderedSet, Set } from 'immutable'
-import mixin from '../utils/mixin'
+import Annotation from '../models/annotation'
import Block from '../models/block'
import Decoration from '../models/decoration'
import Document from '../models/document'
import Inline from '../models/inline'
-import memoize from '../utils/memoize'
+import Operation from '../models/operation'
import PathUtils from '../utils/path-utils'
import Point from '../models/point'
import Range from '../models/range'
import Selection from '../models/selection'
import Value from '../models/value'
-import Operation from '../models/operation'
+import identity from '../utils/identity'
+import memoize from '../utils/memoize'
+import mixin from '../utils/mixin'
/**
* The interface that `Document`, `Block` and `Inline` all implement, to make
@@ -50,6 +52,69 @@ class ElementInterface {
return ret
}
+ /**
+ * Create an iteratable for all of the ancestors of the node.
+ *
+ * @return {Iterable}
+ */
+
+ ancestors(path) {
+ const iterable = this.createIterable({
+ path,
+ direction: null,
+ downward: false,
+ includeTargetAncestors: true,
+ includeRoot: true,
+ })
+
+ return iterable
+ }
+
+ /**
+ * Create an iteratable for all of the blocks of a node with `options`.
+ *
+ * @param {Options}
+ * @return {Iterable}
+ */
+
+ blocks(options = {}) {
+ const { onlyLeaves, onlyRoots, onlyTypes, match, ...rest } = options
+ const iterable = this.descendants({
+ includeDocument: false,
+ includeInlines: false,
+ includeTexts: false,
+ ...rest,
+ match: (node, path) => {
+ if (onlyTypes && !onlyTypes.includes(node.type)) {
+ return false
+ } else if (onlyRoots && path.size !== 1) {
+ return false
+ } else if (onlyLeaves && !node.isLeafBlock()) {
+ return false
+ } else if (match && !match(node, path)) {
+ return false
+ } else {
+ return true
+ }
+ },
+ })
+
+ return iterable
+ }
+
+ /**
+ * Create an annotation with `properties` relative to the node.
+ *
+ * @param {Object|Annotation} properties
+ * @return {Annotation}
+ */
+
+ createAnnotation(properties) {
+ properties = Annotation.createProperties(properties)
+ const annotation = this.resolveAnnotation(properties)
+ return annotation
+ }
+
/**
* Create a decoration with `properties` relative to the node.
*
@@ -63,6 +128,193 @@ class ElementInterface {
return decoration
}
+ /**
+ * Create an iteratable function starting at `target` path with `options`.
+ *
+ * @param {Object} options (optional)
+ * @return {Function}
+ */
+
+ createIterable(options = {}) {
+ const {
+ direction = 'forward',
+ downward = true,
+ upward = true,
+ includeBlocks = true,
+ includeDocument = true,
+ includeInlines = true,
+ includeRoot = false,
+ includeTarget = !!options.range,
+ includeTargetAncestors = false,
+ includeTexts = true,
+ match = null,
+ } = options
+
+ const root = this
+ let targetPath = null
+ let targetRange = null
+
+ // You can iterate over either a range or a path, but not both.
+ if (options.range) {
+ targetRange = root.resolveRange(options.range)
+ targetPath = root.resolvePath(targetRange.start.path)
+ } else if (options.path) {
+ targetPath = root.resolvePath(options.path)
+ }
+
+ const targetNode = targetPath && root.assertNode(targetPath)
+ const NativeSet = typeof window === 'undefined' ? global.Set : window.Set
+
+ // Return an object that implements the iterable interface.
+ return {
+ [Symbol.iterator]() {
+ const visited = new NativeSet()
+ const startPath = targetRange && targetRange.start.path
+ const endPath = targetRange && targetRange.end.path
+ let path = targetPath
+ let node = targetNode
+ let includedTarget = false
+ let includedStart = false
+ let includingStart = false
+
+ const result = () => {
+ // When these are nulled out we've finished iterating.
+ if (!path || !node) {
+ return { done: true }
+ }
+
+ // We often don't want to include the root node itself.
+ if (!includeRoot && node === root) {
+ return next()
+ }
+
+ if (!includeBlocks && node.object === 'block') {
+ return next()
+ }
+
+ if (!includeDocument && node.object === 'document') {
+ return next()
+ }
+
+ if (!includeInlines && node.object === 'inline') {
+ return next()
+ }
+
+ if (!includeTexts && node.object === 'text') {
+ return next()
+ }
+
+ if (match && !match(node, path)) {
+ return next()
+ }
+
+ return { value: [node, path], done: false }
+ }
+
+ const next = () => {
+ if (!path || !node) {
+ return result()
+ }
+
+ // When iterating over a range, we need to include the specific
+ // ancestors in the start path of the range manually.
+ if (startPath && !includedStart) {
+ if (!includingStart) {
+ includingStart = true
+ path = PathUtils.create([])
+ node = root
+ return result()
+ }
+
+ if (path.size === startPath.size - 1) {
+ includedStart = true
+ path = targetPath
+ node = targetNode
+ return next()
+ }
+
+ path = startPath.slice(0, path.size + 1)
+ node = root.assertNode(path)
+ return result()
+ }
+
+ // Sometimes we want to include the target itself.
+ if (includeTarget && !includedTarget) {
+ includedTarget = true
+ return result()
+ }
+
+ // When iterating over a range, if we get to the end path then exit.
+ if (endPath && path.equals(endPath)) {
+ node = null
+ path = null
+ return next()
+ }
+
+ // If we're allowed to go downward, and we haven't decsended yet, do so.
+ if (downward && node.nodes && node.nodes.size && !visited.has(node)) {
+ visited.add(node)
+ const nextIndex = direction === 'forward' ? 0 : node.nodes.size - 1
+ path = path.push(nextIndex)
+ node = root.assertNode(path)
+ return result()
+ }
+
+ // If we're going forward...
+ if (direction === 'forward') {
+ const newPath = PathUtils.increment(path)
+ const newNode = root.getNode(newPath)
+
+ if (newNode) {
+ path = newPath
+ node = newNode
+ return result()
+ }
+ }
+
+ // If we're going backward...
+ if (direction === 'backward' && path.last() !== 0) {
+ const newPath = PathUtils.decrement(path)
+ const newNode = root.getNode(newPath)
+
+ if (newNode) {
+ path = newPath
+ node = newNode
+ return result()
+ }
+ }
+
+ // If we're going upward...
+ if (upward && path.size) {
+ path = PathUtils.lift(path)
+ node = root.assertNode(path)
+
+ // Sometimes we'll have already visited the node on the way down
+ // so we don't want to double count it.
+ if (visited.has(node)) {
+ return next()
+ }
+
+ visited.add(node)
+
+ // If ancestors of the target node shouldn't be included, skip them.
+ if (!includeTargetAncestors) {
+ return next()
+ } else {
+ return result()
+ }
+ }
+
+ path = null
+ node = null
+ return next()
+ }
+
+ return { next }
+ },
+ }
+ }
+
/**
* Create a point with `properties` relative to the node.
*
@@ -103,141 +355,76 @@ class ElementInterface {
}
/**
- * Recursively filter all descendant nodes with `iterator`.
+ * Create an iteratable for all of the descendants of the node.
*
- * @param {Function} iterator
+ * @param {Object} options
+ * @return {Iterable}
+ */
+
+ descendants(options) {
+ const iterable = this.createIterable({ path: [], ...options })
+ return iterable
+ }
+
+ /**
+ * Find all of the descendants that match a `predicate`.
+ *
+ * @param {Function} predicate
* @return {List
}
*/
- filterDescendants(iterator) {
+ filterDescendants(predicate = identity) {
const matches = []
- this.forEachDescendant((node, i, nodes) => {
- if (iterator(node, i, nodes)) matches.push(node)
- })
+ for (const [node, path] of this.descendants()) {
+ if (predicate(node, path)) {
+ matches.push(node)
+ }
+ }
return List(matches)
}
/**
- * Recursively find a descendant node by `iterator`.
+ * Find the first descendant that matches a `predicate`.
*
- * @param {Function} iterator
+ * @param {Function} predicate
* @return {Node|Null}
*/
- findDescendant(iterator) {
- let found = null
-
- this.forEachDescendant((node, i, nodes) => {
- if (iterator(node, i, nodes)) {
- found = node
- return false
+ findDescendant(predicate = identity) {
+ for (const [node, path] of this.descendants()) {
+ if (predicate(node, path)) {
+ return node
}
- })
+ }
- return found
+ return null
}
/**
- * Recursively find a descendant node and its path by `iterator`.
+ * Iterate over all descendants, breaking if `predicate` returns false.
*
- * @param {Function} iterator
- * @return {Null|[Node, List]}
+ * @param {Function} predicate
*/
- findDescendantAndPath(
- iterator,
- pathToThisNode = PathUtils.create([]),
- findLast = false
- ) {
- let found
- let foundPath
+ forEachDescendant(predicate = identity) {
+ for (const next of this.descendants()) {
+ const ret = predicate(...next)
- this.forEachDescendantWithPath(
- (node, path, nodes) => {
- if (iterator(node, path, nodes)) {
- found = node
- foundPath = path
- return false
- }
- },
- pathToThisNode,
- findLast
- )
-
- return found ? [found, foundPath] : null
- }
-
- // Easy helpers to avoid needing to pass findLast boolean
- findFirstDescendantAndPath(iterator, pathToThisNode) {
- return this.findDescendantAndPath(iterator, pathToThisNode, false)
- }
-
- findLastDescendantAndPath(iterator, pathToThisNode) {
- return this.findDescendantAndPath(iterator, pathToThisNode, true)
+ if (ret === false) {
+ return
+ }
+ }
}
/**
- * Recursively iterate over all descendant nodes with `iterator`. If the
- * iterator returns false it will break the loop.
+ * Get a set of the active marks in a `range`. Active marks are marks that are
+ * on every text node in a given range. This is a common distinction for
+ * highlighting toolbar buttons for example.
*
- * @param {Function} iterator
- */
-
- forEachDescendant(iterator) {
- let ret
-
- this.nodes.forEach((child, i, nodes) => {
- if (iterator(child, i, nodes) === false) {
- ret = false
- return false
- }
-
- if (child.object !== 'text') {
- ret = child.forEachDescendant(iterator)
- return ret
- }
- })
-
- return ret
- }
-
- /**
- * Recursively iterate over all descendant nodes with `iterator`. If the
- * iterator returns false it will break the loop.
- * Calls iterator with node and path.
- *
- * @param {Function} iterator
- * @param {List} path
- * @param {Boolean} findLast - whether to iterate in reverse order
- */
-
- forEachDescendantWithPath(iterator, path = PathUtils.create([]), findLast) {
- let nodes = this.nodes
- let ret
-
- if (findLast) nodes = nodes.reverse()
-
- nodes.forEach((child, i) => {
- const childPath = path.concat(i)
-
- if (iterator(child, childPath, nodes) === false) {
- ret = false
- return false
- }
-
- if (child.object !== 'text') {
- ret = child.forEachDescendantWithPath(iterator, childPath, findLast)
- return ret
- }
- })
-
- return ret
- }
-
- /**
- * Get a set of the active marks in a `range`.
+ * TODO: this method needs to be cleaned up, it's very hard to follow and
+ * probably doing unnecessary work.
*
* @param {Range} range
* @return {Set}
@@ -245,11 +432,14 @@ class ElementInterface {
getActiveMarksAtRange(range) {
range = this.resolveRange(range)
- if (range.isUnset) return Set()
+
+ if (range.isUnset) {
+ return Set()
+ }
if (range.isCollapsed) {
const { start } = range
- return this.getMarksAtPosition(start.path, start.offset).toSet()
+ return this.getInsertMarksAtPoint(start)
}
const { start, end } = range
@@ -260,22 +450,26 @@ class ElementInterface {
let startText = this.getDescendant(startPath)
let endText = this.getDescendant(endPath)
- if (!PathUtils.isEqual(startPath, endPath)) {
- while (!PathUtils.isEqual(startPath, endPath) && endOffset === 0) {
- ;[endText, endPath] = this.getPreviousTextAndPath(endPath)
+ if (!startPath.equals(endPath)) {
+ while (!startPath.equals(endPath) && endOffset === 0) {
+ ;[[endText, endPath]] = this.texts({
+ path: endPath,
+ direction: 'backward',
+ })
+
endOffset = endText.text.length
}
while (
- !PathUtils.isEqual(startPath, endPath) &&
+ !startPath.equals(endPath) &&
startOffset === startText.text.length
) {
- ;[startText, startPath] = this.getNextTextAndPath(startPath)
+ ;[[startText, startPath]] = this.texts({ path: startPath })
startOffset = 0
}
}
- if (PathUtils.isEqual(startPath, endPath)) {
+ if (startPath.equals(endPath)) {
return startText.marks
}
@@ -294,9 +488,9 @@ class ElementInterface {
return marks
}
- ;[startText, startPath] = this.getNextTextAndPath(startPath)
+ ;[[startText, startPath]] = this.texts({ path: startPath })
- while (!PathUtils.isEqual(startPath, endPath)) {
+ while (!startPath.equals(endPath)) {
if (startText.text.length !== 0) {
marks = marks.intersect(startText.marks)
@@ -305,7 +499,7 @@ class ElementInterface {
}
}
- ;[startText, startPath] = this.getNextTextAndPath(startPath)
+ ;[[startText, startPath]] = this.texts({ path: startPath })
}
return marks
@@ -319,18 +513,10 @@ class ElementInterface {
*/
getAncestors(path) {
- path = this.resolvePath(path)
- if (!path) return null
-
- const ancestors = []
-
- path.forEach((p, i) => {
- const current = path.slice(0, i)
- const parent = this.getNode(current)
- ancestors.push(parent)
- })
-
- return List(ancestors)
+ const iterable = this.ancestors(path)
+ const array = Array.from(iterable, ([node]) => node).reverse()
+ const list = List(array)
+ return list
}
/**
@@ -340,55 +526,10 @@ class ElementInterface {
*/
getBlocks() {
- const array = this.getBlocksAsArray()
- return List(array)
- }
-
- /**
- * Get the leaf block descendants of the node.
- *
- * @return {List}
- */
-
- getBlocksAsArray() {
- return this.nodes.reduce((array, child) => {
- if (child.object !== 'block') return array
- if (!child.isLeafBlock()) return array.concat(child.getBlocksAsArray())
- array.push(child)
- return array
- }, [])
- }
-
- /**
- * Get the leaf block descendants in a `range`.
- *
- * @param {Range} range
- * @return {List}
- */
-
- getBlocksAtRange(range) {
- warning(
- false,
- 'As of slate@0.44 the `node.getBlocksAtRange` method has been renamed to `getLeafBlocksAtRange`.'
- )
-
- return this.getLeafBlocksAtRange(range)
- }
-
- /**
- * Get the bottom-most block descendants in a `range` as an array
- *
- * @param {Range} range
- * @return {Array}
- */
-
- getBlocksAtRangeAsArray(range) {
- warning(
- false,
- 'As of slate@0.44 the `node.getBlocksAtRangeAsArray` method has been renamed to `getLeafBlocksAtRangeAsArray`.'
- )
-
- return this.getLeafBlocksAtRangeAsArray(range)
+ const iterable = this.blocks({ onlyLeaves: true })
+ const array = Array.from(iterable, ([node]) => node)
+ const list = List(array)
+ return list
}
/**
@@ -399,28 +540,10 @@ class ElementInterface {
*/
getBlocksByType(type) {
- const array = this.getBlocksByTypeAsArray(type)
- return List(array)
- }
-
- /**
- * Get all of the leaf blocks that match a `type` as an array
- *
- * @param {String} type
- * @return {Array}
- */
-
- getBlocksByTypeAsArray(type) {
- return this.nodes.reduce((array, node) => {
- if (node.object !== 'block') {
- return array
- } else if (node.isLeafBlock() && node.type === type) {
- array.push(node)
- return array
- } else {
- return array.concat(node.getBlocksByTypeAsArray(type))
- }
- }, [])
+ const iterable = this.blocks({ onlyLeaves: true, onlyTypes: [type] })
+ const array = Array.from(iterable, ([node]) => node)
+ const list = List(array)
+ return list
}
/**
@@ -432,30 +555,31 @@ class ElementInterface {
getChild(path) {
path = this.resolvePath(path)
- if (!path || path.size > 1) return null
+
+ if (!path || path.size > 1) {
+ return null
+ }
+
const child = this.nodes.get(path.first())
return child
}
/**
- * Get closest parent of node that matches an `iterator`.
+ * Get closest parent of node that matches a `predicate`.
*
* @param {List|String} path
- * @param {Function} iterator
+ * @param {Function} predicate
* @return {Node|Null}
*/
- getClosest(path, iterator) {
- const ancestors = this.getAncestors(path)
- if (!ancestors) return null
+ getClosest(path, predicate) {
+ for (const [n, p] of this.ancestors(path)) {
+ if (predicate(n, p)) {
+ return n
+ }
+ }
- const closest = ancestors.findLast((node, ...args) => {
- // We never want to include the top-level node.
- if (node === this) return false
- return iterator(node, ...args)
- })
-
- return closest || null
+ return null
}
/**
@@ -496,11 +620,8 @@ class ElementInterface {
'As of Slate 0.42.0, the `node.getClosestVoid` method takes an `editor` instead of a `value`.'
)
- const ancestors = this.getAncestors(path)
- if (!ancestors) return null
-
- const ancestor = ancestors.findLast(a => editor.query('isVoid', a))
- return ancestor
+ const closest = this.getClosest(path, n => editor.isVoid(n))
+ return closest
}
/**
@@ -514,7 +635,10 @@ class ElementInterface {
getCommonAncestor(a, b) {
a = this.resolvePath(a)
b = this.resolvePath(b)
- if (!a || !b) return null
+
+ if (!a || !b) {
+ return null
+ }
const path = PathUtils.relate(a, b)
const node = this.getNode(path)
@@ -529,13 +653,8 @@ class ElementInterface {
*/
getDecorations(editor) {
- invariant(
- !Value.isValue(editor),
- 'As of Slate 0.42.0, the `node.getDecorations` method takes an `editor` instead of a `value`.'
- )
-
- const array = editor.run('decorateNode', this)
- const decorations = Decoration.createList(array)
+ let decorations = editor.run('decorateNode', this)
+ decorations = Decoration.createList(decorations)
return decorations
}
@@ -549,7 +668,10 @@ class ElementInterface {
getDepth(path, startAt = 1) {
path = this.resolvePath(path)
- if (!path) return null
+
+ if (!path) {
+ return null
+ }
const node = this.getNode(path)
const depth = node ? path.size - 1 + startAt : null
@@ -565,7 +687,10 @@ class ElementInterface {
getDescendant(path) {
path = this.resolvePath(path)
- if (!path || !path.size) return null
+
+ if (!path || !path.size) {
+ return null
+ }
let node = this
@@ -577,6 +702,20 @@ class ElementInterface {
return node
}
+ /**
+ * Get all of the descendant nodes in a `range`.
+ *
+ * @param {Range} range
+ * @return {List}
+ */
+
+ getDescendantsAtRange(range) {
+ const iterable = this.descendants({ range })
+ const array = Array.from(iterable, ([node]) => node)
+ const list = List(array)
+ return list
+ }
+
/**
* Get a fragment of the node at a `range`.
*
@@ -595,7 +734,7 @@ class ElementInterface {
let node = this
let targetPath = end.path
let targetPosition = end.offset
- let mode = 'end'
+ let side = 'end'
while (targetPath.size) {
const index = targetPath.last()
@@ -603,10 +742,10 @@ class ElementInterface {
targetPosition = index + 1
targetPath = PathUtils.lift(targetPath)
- if (!targetPath.size && mode === 'end') {
+ if (!targetPath.size && side === 'end') {
targetPath = start.path
targetPosition = start.offset
- mode = 'start'
+ side = 'start'
}
}
@@ -618,38 +757,24 @@ class ElementInterface {
}
/**
- * Get the furthest parent of a node that matches an `iterator`.
+ * Get the furthest ancestors of a node that matches a `predicate`.
*
* @param {Path} path
- * @param {Function} iterator
+ * @param {Function} predicate
* @return {Node|Null}
*/
- getFurthest(path, iterator) {
- const ancestors = this.getAncestors(path)
- if (!ancestors) return null
+ getFurthest(path, predicate = identity) {
+ const iterable = this.ancestors(path)
+ const results = Array.from(iterable).reverse()
- const furthest = ancestors.find((node, ...args) => {
- // We never want to include the top-level node.
- if (node === this) return false
- return iterator(node, ...args)
- })
+ for (const [n, p] of results) {
+ if (predicate(n, p)) {
+ return n
+ }
+ }
- return furthest || null
- }
-
- /**
- * Get the furthest ancestor of a node.
- *
- * @param {List|String} path
- * @return {Node|Null}
- */
-
- getFurthestAncestor(path) {
- path = this.resolvePath(path)
- if (!path || !path.size) return null
- const furthest = this.nodes.get(path.first())
- return furthest
+ return null
}
/**
@@ -664,6 +789,24 @@ class ElementInterface {
return furthest
}
+ /**
+ * Get the furthest child ancestor of a node at `path`.
+ *
+ * @param {List|String} path
+ * @return {Node|Null}
+ */
+
+ getFurthestChild(path) {
+ path = this.resolvePath(path)
+
+ if (!path || !path.size) {
+ return null
+ }
+
+ const furthest = this.nodes.get(path.first())
+ return furthest
+ }
+
/**
* Get the furthest inline parent of a node.
*
@@ -676,26 +819,6 @@ class ElementInterface {
return furthest
}
- /**
- * Get the furthest ancestor of a node, where all ancestors to that point only have one child.
- *
- * @param {Path} path
- * @return {Node|Null}
- */
-
- getFurthestOnlyChildAncestor(path) {
- const ancestors = this.getAncestors(path)
- if (!ancestors) return null
-
- const furthest = ancestors
- .rest()
- .reverse()
- .takeUntil(p => p.nodes.size > 1)
- .last()
-
- return furthest || null
- }
-
/**
* Get the closest inline nodes for each text node in the node.
*
@@ -703,65 +826,12 @@ class ElementInterface {
*/
getInlines() {
- const array = this.getInlinesAsArray()
+ const iterable = this.inlines({ onlyLeaves: true })
+ const array = Array.from(iterable, ([node]) => node)
const list = List(array)
return list
}
- /**
- * Get the closest inline nodes for each text node in the node, as an array.
- *
- * @return {Array}
- */
-
- getInlinesAsArray() {
- let array = []
-
- this.nodes.forEach(child => {
- if (child.object === 'text') return
-
- if (child.isLeafInline()) {
- array.push(child)
- } else {
- array = array.concat(child.getInlinesAsArray())
- }
- })
-
- return array
- }
-
- /**
- * Get the bottom-most inline nodes for each text node in a `range`.
- *
- * @param {Range} range
- * @return {List}
- */
-
- getInlinesAtRange(range) {
- warning(
- false,
- 'As of slate@0.44 the `node.getInlinesAtRange` method has been renamed to `getLeafInlinesAtRange`.'
- )
-
- return this.getLeafInlinesAtRange(range)
- }
-
- /**
- * Get the bottom-most inline nodes for each text node in a `range` as an array.
- *
- * @param {Range} range
- * @return {Array}
- */
-
- getInlinesAtRangeAsArray(range) {
- warning(
- false,
- 'As of slate@0.44 the `node.getInlinesAtRangeAsArray` method has been renamed to `getLeafInlinesAtRangeAsArray`.'
- )
-
- return this.getLeafInlinesAtRangeAsArray(range)
- }
-
/**
* Get all of the leaf inline nodes that match a `type`.
*
@@ -770,35 +840,62 @@ class ElementInterface {
*/
getInlinesByType(type) {
- const array = this.getInlinesByTypeAsArray(type)
+ const iterable = this.inlines({ onlyLeaves: true, onlyTypes: [type] })
+ const array = Array.from(iterable, ([node]) => node)
const list = List(array)
return list
}
/**
- * Get all of the leaf inline nodes that match a `type` as an array.
+ * Get a set of marks that would occur on the next insert at a `point` in the
+ * node. This mimics expected rich text editing behaviors of mark contiuation.
*
- * @param {String} type
- * @return {Array}
+ * @param {Point} point
+ * @return {Set}
*/
- getInlinesByTypeAsArray(type) {
- const array = this.nodes.reduce((inlines, node) => {
- if (node.object === 'text') {
- return inlines
- } else if (node.isLeafInline() && node.type === type) {
- inlines.push(node)
- return inlines
- } else {
- return inlines.concat(node.getInlinesByTypeAsArray(type))
- }
- }, [])
+ getInsertMarksAtPoint(point) {
+ point = this.resolvePoint(point)
+ const { path, offset } = point
+ const text = this.getDescendant(path)
- return array
+ // PERF: we can exit early if the offset isn't at the start of the node.
+ if (offset !== 0) {
+ return text.marks
+ }
+
+ let blockNode
+ let blockPath
+
+ for (const entry of this.ancestors(path)) {
+ const [n, p] = entry
+
+ if (n.object === 'block') {
+ blockNode = n
+ blockPath = p
+ }
+ }
+
+ const relativePath = PathUtils.drop(path, blockPath.size)
+ const [previous] = blockNode.texts({
+ path: relativePath,
+ direction: 'backward',
+ })
+
+ // If there's no previous text, we're at the start of the block, so use
+ // the current text nodes marks.
+ if (!previous) {
+ return text.marks
+ }
+
+ // Otherwise, continue with the previous text node's marks instead.
+ const [previousText] = previous
+ return previousText.marks
}
/**
- * Get a set of the marks in a `range`.
+ * Get a set of marks that would occur on the next insert at a `range`.
+ * This mimics expected rich text editing behaviors of mark contiuation.
*
* @param {Range} range
* @return {Set}
@@ -813,13 +910,11 @@ class ElementInterface {
}
if (range.isCollapsed) {
- // PERF: range is not cachable, use key and offset as proxies for cache
- return this.getMarksAtPosition(start.path, start.offset)
+ return this.getInsertMarksAtPoint(start)
}
const text = this.getDescendant(start.path)
- const { marks } = text
- return marks
+ return text.marks
}
/**
@@ -830,74 +925,10 @@ class ElementInterface {
*/
getLeafBlocksAtRange(range) {
- const array = this.getLeafBlocksAtRangeAsArray(range)
- // Eliminate duplicates by converting to an `OrderedSet` first.
- return List(OrderedSet(array))
- }
-
- /**
- * Get the bottom-most descendants in a `range` as an array
- *
- * @param {Range} range
- * @return {Array}
- */
-
- getLeafBlocksAtRangeAsArray(range) {
- range = this.resolveRange(range)
- if (range.isUnset) return []
-
- const { start, end } = range
-
- return this.getLeafBlocksBetweenPathPositionsAsArray(start.path, end.path)
- }
-
- /**
- * Get the bottom-most descendants between two paths as an array
- *
- * @param {List|Null} startPath
- * @param {List|Null} endPath
- * @return {Array}
- */
-
- getLeafBlocksBetweenPathPositionsAsArray(startPath, endPath) {
- // PERF: the most common case is when the range is in a single block node,
- // where we can avoid a lot of iterating of the tree.
- if (startPath && endPath && PathUtils.isEqual(startPath, endPath)) {
- return [this.getClosestBlock(startPath)]
- } else if (!startPath && !endPath) {
- return this.getBlocksAsArray()
- }
-
- const startIndex = startPath ? startPath.get(0, 0) : 0
- const endIndex = endPath
- ? endPath.get(0, this.nodes.size - 1)
- : this.nodes.size - 1
-
- let array = []
-
- this.nodes.slice(startIndex, endIndex + 1).forEach((node, i) => {
- if (node.object !== 'block') {
- return
- } else if (node.isLeafBlock()) {
- array.push(node)
- } else {
- const childStartPath =
- startPath && i === 0 ? PathUtils.drop(startPath) : null
- const childEndPath =
- endPath && i === endIndex - startIndex
- ? PathUtils.drop(endPath)
- : null
-
- array = array.concat(
- node.getLeafBlocksBetweenPathPositionsAsArray(
- childStartPath,
- childEndPath
- )
- )
- }
- })
-
- return array
+ const iterable = this.blocks({ range, onlyLeaves: true })
+ const array = Array.from(iterable, ([node]) => node)
+ const list = List(array)
+ return list
}
/**
@@ -908,139 +939,68 @@ class ElementInterface {
*/
getLeafInlinesAtRange(range) {
- const array = this.getLeafInlinesAtRangeAsArray(range)
- // Remove duplicates by converting it to an `OrderedSet` first.
- const list = List(OrderedSet(array))
+ const iterable = this.inlines({ range, onlyLeaves: true })
+ const array = Array.from(iterable, ([node]) => node)
+ const list = List(array)
return list
}
/**
- * Get the bottom-most inline nodes for each text node in a `range` as an array.
+ * Get an object mapping all the keys in the node to their paths.
*
- * @param {Range} range
- * @return {Array}
+ * @return {Map}
*/
- getLeafInlinesAtRangeAsArray(range) {
- range = this.resolveRange(range)
- if (range.isUnset) return []
+ getNodesToPathsMap() {
+ const root = this
+ const map =
+ typeof window === 'undefined' ? new global.Map() : new window.Map()
- const array = this.getTextsAtRangeAsArray(range)
- .map(text => this.getClosestInline(text.key))
- .filter(exists => exists)
+ map.set(root, PathUtils.create([]))
- return array
+ root.forEachDescendant((node, path) => {
+ map.set(node, path)
+ })
+
+ return map
}
/**
* Get all of the marks for all of the characters of every text node.
*
- * @return {Set}
+ * @return {OrderedSet}
*/
getMarks() {
- const array = this.getMarksAsArray()
- return Set(array)
- }
-
- /**
- * Get all of the marks as an array.
- *
- * @return {Array}
- */
-
- getMarksAsArray() {
- const result = []
-
- this.nodes.forEach(node => {
- result.push(
- node.object === 'text' ? node.marks.toArray() : node.getMarksAsArray()
- )
- })
-
- // PERF: use only one concat rather than multiple for speed.
- const array = [].concat(...result)
- return array
- }
-
- /**
- * Get a set of marks in a `position`, the equivalent of a collapsed range
- *
- * @param {List|string} key
- * @param {number} offset
- * @return {Set}
- */
-
- getMarksAtPosition(path, offset) {
- path = this.resolvePath(path)
- const text = this.getDescendant(path)
- const currentMarks = text.marks
-
- if (offset !== 0) {
- return currentMarks
- }
-
- const closestBlock = this.getClosestBlock(path)
-
- // insert mark for empty block; the empty block are often created by split node or add marks in a range including empty blocks
- if (closestBlock.text === '') {
- return currentMarks
- }
-
- const previous = this.getPreviousTextAndPath(path)
-
- if (!previous) {
- return Set()
- }
-
- const [previousText, previousPath] = previous
-
- if (closestBlock.hasDescendant(previousPath)) {
- return previousText.marks
- }
-
- return currentMarks
+ const iterable = this.marks()
+ const array = Array.from(iterable, ([mark]) => mark)
+ return OrderedSet(array)
}
/**
* Get a set of the marks in a `range`.
*
* @param {Range} range
- * @return {Set}
+ * @return {OrderedSet}
*/
getMarksAtRange(range) {
- const marks = Set(this.getOrderedMarksAtRange(range))
- return marks
+ const iterable = this.marks({ range })
+ const array = Array.from(iterable, ([mark]) => mark)
+ return OrderedSet(array)
}
/**
* Get all of the marks that match a `type`.
*
* @param {String} type
- * @return {Set}
+ * @return {OrderedSet}
*/
getMarksByType(type) {
- const array = this.getMarksByTypeAsArray(type)
- return Set(array)
- }
-
- /**
- * Get all of the marks that match a `type` as an array.
- *
- * @param {String} type
- * @return {Array}
- */
-
- getMarksByTypeAsArray(type) {
- const array = this.nodes.reduce((memo, node) => {
- return node.object === 'text'
- ? memo.concat(node.getMarksAsArray().filter(m => m.type === type))
- : memo.concat(node.getMarksByTypeAsArray(type))
- }, [])
-
- return array
+ const iterable = this.marks({ onlyTypes: [type] })
+ const array = Array.from(iterable, ([mark]) => mark)
+ return OrderedSet(array)
}
/**
@@ -1051,106 +1011,23 @@ class ElementInterface {
*/
getNextBlock(path) {
- path = this.resolvePath(path)
- const match = this.getNextDeepMatchingNodeAndPath(
- path,
- n => n.object === 'block'
- )
-
- return match ? match[0] : null
+ const [entry] = this.blocks({ path, onlyLeaves: true })
+ const block = entry ? entry[0] : null
+ return block
}
/**
- * Get the next node in the tree from a node.
- *
- * This will not only check for siblings but instead move up the tree
- * returning the next ancestor if no sibling is found.
+ * Get the next node in the tree, returning siblings or ancestor siblings.
*
* @param {List|String} path
* @return {Node|Null}
*/
getNextNode(path) {
- path = this.resolvePath(path)
- if (!path) return null
- if (!path.size) return null
-
- for (let i = path.size; i > 0; i--) {
- const p = path.slice(0, i)
- const target = PathUtils.increment(p)
- const node = this.getNode(target)
- if (node) return node
- }
-
- return null
- }
-
- /**
- * Get the next node in the tree from a node that matches iterator
- *
- * This will not only check for siblings but instead move up the tree
- * returning the next ancestor if no sibling is found.
- *
- * @param {List} path
- * @return {Node|Null}
- */
-
- getNextMatchingNodeAndPath(path, iterator = () => true) {
- if (!path) return null
-
- for (let i = path.size; i > 0; i--) {
- const p = path.slice(0, i)
-
- let nextPath = PathUtils.increment(p)
- let nextNode = this.getNode(nextPath)
-
- while (nextNode && !iterator(nextNode)) {
- nextPath = PathUtils.increment(nextPath)
- nextNode = this.getNode(nextPath)
- }
-
- if (nextNode) return [nextNode, nextPath]
- }
-
- return null
- }
-
- /**
- * Get the next, deepest node in the tree from a node that matches iterator
- *
- * This will not only check for siblings but instead move up the tree
- * returning the next ancestor if no sibling is found.
- *
- * @param {List} path
- * @param {Function} iterator
- * @return {Node|Null}
- */
-
- getNextDeepMatchingNodeAndPath(path, iterator = () => true) {
- const match = this.getNextMatchingNodeAndPath(path)
-
- if (!match) return null
-
- let [nextNode, nextPath] = match
-
- let childMatch
-
- const assign = () => {
- childMatch =
- nextNode.object !== 'text' &&
- nextNode.findFirstDescendantAndPath(iterator, nextPath)
- return childMatch
- }
-
- while (assign(childMatch)) {
- ;[nextNode, nextPath] = childMatch
- }
-
- if (!nextNode) return null
-
- return iterator(nextNode)
- ? [nextNode, nextPath]
- : this.getNextDeepMatchingNodeAndPath(match[1], iterator)
+ const iterable = this.createIterable({ path, downward: false })
+ const [entry] = iterable
+ const node = entry ? entry[0] : null
+ return node
}
/**
@@ -1161,12 +1038,9 @@ class ElementInterface {
*/
getNextSibling(path) {
- path = this.resolvePath(path)
- if (!path) return null
- if (!path.size) return null
- const p = PathUtils.increment(path)
- const sibling = this.getNode(p)
- return sibling
+ const [entry] = this.siblings(path)
+ const node = entry ? entry[0] : null
+ return node
}
/**
@@ -1177,92 +1051,9 @@ class ElementInterface {
*/
getNextText(path) {
- path = this.resolvePath(path)
- if (!path) return null
- if (!path.size) return null
- const next = this.getNextNode(path)
- if (!next) return null
- const text = next.getFirstText()
- return text
- }
-
- getNextTextAndPath(path) {
- if (!path) return null
- if (!path.size) return null
- const match = this.getNextDeepMatchingNodeAndPath(
- path,
- n => n.object === 'text'
- )
- return match
- }
-
- /**
- * Get all of the nodes in a `range`. This includes all of the
- * text nodes inside the range and all ancestors of those text
- * nodes up to this node.
- *
- * @param {Range} range
- * @return {List}
- */
-
- getNodesAtRange(range) {
- range = this.resolveRange(range)
- if (range.isUnset) return List()
- const { start, end } = range
-
- // Do a depth-first stack-based search for all nodes in the range
- // Nodes that are pushed to the stack are inside the range
-
- // Start with the nodes that are on the highest level in the tree
- let stack = Stack(
- this.nodes
- .slice(start.path.get(0), end.path.get(0) + 1)
- .map((node, index) => ({
- node,
- onStartEdge: index === 0,
- onEndEdge: index === end.path.get(0) - start.path.get(0),
- relativeStartPath: start.path.slice(1),
- relativeEndPath: end.path.slice(1),
- }))
- )
-
- const result = []
-
- while (stack.size > 0) {
- const {
- node,
- onStartEdge,
- onEndEdge,
- relativeStartPath,
- relativeEndPath,
- } = stack.peek()
-
- stack = stack.shift()
- result.push(node)
-
- if (node.object === 'text') continue
-
- // Modify indexes to exclude children that are outside of the range
- const startIndex = onStartEdge ? relativeStartPath.get(0) : 0
- const endIndex = onEndEdge ? relativeEndPath.get(0) : node.nodes.size - 1
-
- // Push children that are inside the range to the stack
- stack = stack.pushAll(
- node.nodes.slice(startIndex, endIndex + 1).map((n, i) => ({
- node: n,
- onStartEdge: onStartEdge && i === 0,
- onEndEdge: onEndEdge && i === endIndex - startIndex,
- relativeStartPath:
- onStartEdge && i === 0 ? relativeStartPath.slice(1) : null,
- relativeEndPath:
- onEndEdge && i === endIndex - startIndex
- ? relativeEndPath.slice(1)
- : null,
- }))
- )
- }
-
- return List(result)
+ const [entry] = this.texts({ path })
+ const node = entry ? entry[0] : null
+ return node
}
/**
@@ -1288,6 +1079,7 @@ class ElementInterface {
path.size === 1
? offset
: offset + this.nodes.get(index).getOffset(PathUtils.drop(path))
+
return ret
}
@@ -1314,89 +1106,6 @@ class ElementInterface {
return offset
}
- /**
- * Get all of the marks for all of the characters of every text node.
- *
- * @return {OrderedSet}
- */
-
- getOrderedMarks() {
- const array = this.getMarksAsArray()
- return OrderedSet(array)
- }
-
- /**
- * Get a set of the marks in a `range`.
- *
- * @param {Range} range
- * @return {OrderedSet}
- */
-
- getOrderedMarksAtRange(range) {
- range = this.resolveRange(range)
- const { start, end } = range
-
- if (range.isUnset) {
- return OrderedSet()
- }
-
- if (range.isCollapsed) {
- // PERF: range is not cachable, use path? and offset as proxies for cache
- return this.getMarksAtPosition(start.path, start.offset)
- }
-
- const marks = this.getOrderedMarksBetweenPositions(
- start.path,
- start.offset,
- end.path,
- end.offset
- )
-
- return marks
- }
-
- /**
- * Get a set of the marks in a `range`.
- * PERF: arguments use key and offset for utilizing cache
- *
- * @param {List|string} startPath
- * @param {number} startOffset
- * @param {List|string} endPath
- * @param {number} endOffset
- * @returns {OrderedSet}
- */
-
- getOrderedMarksBetweenPositions(startPath, startOffset, endPath, endOffset) {
- startPath = this.resolvePath(startPath)
- endPath = this.resolvePath(endPath)
- const startText = this.getDescendant(startPath)
-
- // PERF: if the paths are equal, we can just use the start.
- if (PathUtils.isEqual(startPath, endPath)) {
- return startText.marks
- }
-
- const texts = this.getTextsBetweenPathPositionsAsArray(startPath, endPath)
-
- return OrderedSet().withMutations(result => {
- texts.forEach(text => {
- result.union(text.marks)
- })
- })
- }
-
- /**
- * Get all of the marks that match a `type`.
- *
- * @param {String} type
- * @return {OrderedSet}
- */
-
- getOrderedMarksByType(type) {
- const array = this.getMarksByTypeAsArray(type)
- return OrderedSet(array)
- }
-
/**
* Get the parent of a descendant node.
*
@@ -1421,61 +1130,13 @@ class ElementInterface {
*/
getPreviousBlock(path) {
- path = this.resolvePath(path)
- const match = this.getPreviousDeepMatchingNodeAndPath(
+ const [entry] = this.blocks({
path,
- n => n.object === 'block'
- )
-
- return match ? match[0] : null
- }
-
- /**
- * Get the highest block descendants in a `range`.
- *
- * @param {Range} range
- * @return {List}
- */
-
- getRootBlocksAtRange(range) {
- range = this.resolveRange(range)
- if (range.isUnset) return List()
-
- const { start, end } = range
-
- return this.nodes.slice(start.path.first(), end.path.first() + 1)
- }
-
- /**
- * Get the top-most inline nodes for each text node in a `range`.
- *
- * @param {Range} range
- * @return {List}
- */
-
- getRootInlinesAtRange(range) {
- const array = this.getRootInlinesAtRangeAsArray(range)
- // Remove duplicates by converting it to an `OrderedSet` first.
- const list = List(OrderedSet(array))
- return list
- }
-
- /**
- * Get the top-most inline nodes for each text node in a `range` as an array.
- *
- * @param {Range} range
- * @return {Array}
- */
-
- getRootInlinesAtRangeAsArray(range) {
- range = this.resolveRange(range)
- if (range.isUnset) return List()
-
- const array = this.getTextsAtRangeAsArray(range)
- .map(text => this.getFurthestInline(text.key))
- .filter(exists => exists)
-
- return array
+ onlyLeaves: true,
+ direction: 'backward',
+ })
+ const block = entry ? entry[0] : null
+ return block
}
/**
@@ -1489,90 +1150,15 @@ class ElementInterface {
*/
getPreviousNode(path) {
- path = this.resolvePath(path)
- if (!path) return null
- if (!path.size) return null
+ const iterable = this.createIterable({
+ path,
+ downward: false,
+ direction: 'backward',
+ })
- for (let i = path.size; i > 0; i--) {
- const p = path.slice(0, i)
- if (p.last() === 0) continue
-
- const target = PathUtils.decrement(p)
- const node = this.getNode(target)
- if (node) return node
- }
-
- return null
- }
-
- /**
- * Get the previous node in the tree from a node that matches iterator
- *
- * This will not only check for siblings but instead move up the tree
- * returning the previous ancestor if no sibling is found.
- *
- * @param {List} path
- * @return {Node|Null}
- */
-
- getPreviousMatchingNodeAndPath(path, iterator = () => true) {
- if (!path) return null
-
- for (let i = path.size; i > 0; i--) {
- const p = path.slice(0, i)
- if (p.last() === 0) continue
-
- let previousPath = PathUtils.decrement(p)
- let previousNode = this.getNode(previousPath)
-
- while (previousNode && !iterator(previousNode)) {
- previousPath = PathUtils.decrement(previousPath)
- previousNode = this.getNode(previousPath)
- }
-
- if (previousNode) return [previousNode, previousPath]
- }
-
- return null
- }
-
- /**
- * Get the next previous in the tree from a node that matches iterator
- *
- * This will not only check for siblings but instead move up the tree
- * returning the previous ancestor if no sibling is found.
- * Once a node is found, the last deepest child matching is returned
- *
- * @param {List} path
- * @param {Function} iterator
- * @return {Node|Null}
- */
-
- getPreviousDeepMatchingNodeAndPath(path, iterator = () => true) {
- const match = this.getPreviousMatchingNodeAndPath(path)
-
- if (!match) return null
-
- let [previousNode, previousPath] = match
-
- let childMatch
-
- const assign = () => {
- childMatch =
- previousNode.object !== 'text' &&
- previousNode.findLastDescendantAndPath(iterator, previousPath)
- return childMatch
- }
-
- while (assign(childMatch)) {
- ;[previousNode, previousPath] = childMatch
- }
-
- if (!previousNode) return null
-
- return iterator(previousNode)
- ? [previousNode, previousPath]
- : this.getPreviousDeepMatchingNodeAndPath(match[1], iterator)
+ const [entry] = iterable
+ const node = entry ? entry[0] : null
+ return node
}
/**
@@ -1583,13 +1169,9 @@ class ElementInterface {
*/
getPreviousSibling(path) {
- path = this.resolvePath(path)
- if (!path) return null
- if (!path.size) return null
- if (path.last() === 0) return null
- const p = PathUtils.decrement(path)
- const sibling = this.getNode(p)
- return sibling
+ const [entry] = this.siblings(path, { direction: 'backward' })
+ const node = entry ? entry[0] : null
+ return node
}
/**
@@ -1600,76 +1182,37 @@ class ElementInterface {
*/
getPreviousText(path) {
- path = this.resolvePath(path)
- if (!path) return null
- if (!path.size) return null
- const previous = this.getPreviousNode(path)
- if (!previous) return null
- const match = previous.getLastText()
- return match
- }
-
- getPreviousTextAndPath(path) {
- if (!path) return null
- if (!path.size) return null
- const match = this.getPreviousDeepMatchingNodeAndPath(
- path,
- n => n.object === 'text'
- )
- return match
+ const [entry] = this.texts({ path, direction: 'backward' })
+ const node = entry ? entry[0] : null
+ return node
}
/**
- * Get the indexes of the selection for a `range`, given an extra flag for
- * whether the node `isSelected`, to determine whether not finding matches
- * means everything is selected or nothing is.
+ * Get only the root block nodes in a `range`.
*
* @param {Range} range
- * @param {Boolean} isSelected
- * @return {Object|Null}
+ * @return {List}
*/
- getSelectionIndexes(range, isSelected = true) {
- const { start, end } = range
+ getRootBlocksAtRange(range) {
+ const iterable = this.blocks({ range, onlyRoots: true })
+ const array = Array.from(iterable, ([node]) => node)
+ const list = List(array)
+ return list
+ }
- // PERF: if we're not selected, we can exit early.
- if (!isSelected) {
- return null
- }
+ /**
+ * Get only the root inline nodes in a `range`.
+ *
+ * @param {Range} range
+ * @return {List}
+ */
- // if we've been given an invalid selection we can exit early.
- if (range.isUnset) {
- return null
- }
-
- // PERF: if the start and end keys are the same, just check for the child
- // that contains that single key.
- if (start.key === end.key) {
- const child = this.getFurthestAncestor(start.key)
- const index = child ? this.nodes.indexOf(child) : null
- return { start: index, end: index + 1 }
- }
-
- // Otherwise, check all of the children...
- let startIndex = null
- let endIndex = null
-
- this.nodes.forEach((child, i) => {
- if (child.object === 'text') {
- if (startIndex == null && child.key === start.key) startIndex = i
- if (endIndex == null && child.key === end.key) endIndex = i + 1
- } else {
- if (startIndex == null && child.hasDescendant(start.key)) startIndex = i
- if (endIndex == null && child.hasDescendant(end.key)) endIndex = i + 1
- }
-
- // PERF: exit early if both start and end have been found.
- return startIndex == null || endIndex == null
- })
-
- if (isSelected && startIndex == null) startIndex = 0
- if (isSelected && endIndex == null) endIndex = this.nodes.size
- return startIndex == null ? null : { start: startIndex, end: endIndex }
+ getRootInlinesAtRange(range) {
+ const iterable = this.inlines({ range, onlyRoots: true })
+ const array = Array.from(iterable, ([node]) => node)
+ const list = List(array)
+ return list
}
/**
@@ -1686,12 +1229,16 @@ class ElementInterface {
if (offset < 0 || offset > this.text.length) return null
let length = 0
- const text = this.getTexts().find((node, i, nodes) => {
- length += node.text.length
- return length > offset
- })
- return text
+ for (const [node] of this.texts()) {
+ length += node.text.length
+
+ if (length > offset) {
+ return node
+ }
+ }
+
+ return null
}
/**
@@ -1701,7 +1248,7 @@ class ElementInterface {
*/
getTextDirection() {
- const dir = direction(this.text)
+ const dir = getDirection(this.text)
return dir === 'neutral' ? null : dir
}
@@ -1712,28 +1259,10 @@ class ElementInterface {
*/
getTexts() {
- const array = this.getTextsAsArray()
- return List(array)
- }
-
- /**
- * Recursively get all the leaf text nodes in order of appearance, as array.
- *
- * @return {List}
- */
-
- getTextsAsArray() {
- let array = []
-
- this.nodes.forEach(node => {
- if (node.object === 'text') {
- array.push(node)
- } else {
- array = array.concat(node.getTextsAsArray())
- }
- })
-
- return array
+ const iterable = this.texts()
+ const array = Array.from(iterable, ([node]) => node)
+ const list = List(array)
+ return list
}
/**
@@ -1744,85 +1273,10 @@ class ElementInterface {
*/
getTextsAtRange(range) {
- const arr = this.getTextsAtRangeAsArray(range)
- return List(arr)
- }
-
- /**
- * Get all of the text nodes in a `range` as an array.
- *
- * @param {Range} range
- * @return {Array}
- */
-
- getTextsAtRangeAsArray(range) {
- range = this.resolveRange(range)
- if (range.isUnset) return []
- const { start, end } = range
- const texts = this.getTextsBetweenPathPositionsAsArray(start.path, end.path)
- return texts
- }
-
- /**
- * Get all of the text nodes in a `range` as an array.
- * PERF: use key / path in arguments for cache
- *
- * @param {List|string} startPath
- * @param {List|string} endPath
- * @returns {Array}
- */
-
- getTextsBetweenPositionsAsArray(startPath, endPath) {
- startPath = this.resolvePath(startPath)
- endPath = this.resolvePath(endPath)
-
- return this.getTextsBetweenPathPositionsAsArray(startPath, endPath)
- }
-
- /**
- * Get all of the text nodes in a `range` as an array.
- *
- * @param {List|falsey} startPath
- * @param {List|falsey} endPath
- * @returns {Array}
- */
-
- getTextsBetweenPathPositionsAsArray(startPath, endPath) {
- // PERF: the most common case is when the range is in a single text node,
- // where we can avoid a lot of iterating of the tree.
- if (startPath && endPath && PathUtils.isEqual(startPath, endPath)) {
- return [this.getDescendant(startPath)]
- } else if (!startPath && !endPath) {
- return this.getTextsAsArray()
- }
-
- const startIndex = startPath ? startPath.get(0, 0) : 0
- const endIndex = endPath
- ? endPath.get(0, this.nodes.size - 1)
- : this.nodes.size - 1
-
- let array = []
-
- this.nodes.slice(startIndex, endIndex + 1).forEach((node, i) => {
- if (node.object === 'text') {
- array.push(node)
- } else {
- // For the node at start and end of this list, we want to provide a start and end path
- // For other nodes, we can just get all their text nodes, they are between the paths
- const childStartPath =
- startPath && i === 0 ? PathUtils.drop(startPath) : null
- const childEndPath =
- endPath && i === endIndex - startIndex
- ? PathUtils.drop(endPath)
- : null
-
- array = array.concat(
- node.getTextsBetweenPathPositionsAsArray(childStartPath, childEndPath)
- )
- }
- })
-
- return array
+ const iterable = this.texts({ range })
+ const array = Array.from(iterable, ([node]) => node)
+ const list = List(array)
+ return list
}
/**
@@ -1890,6 +1344,38 @@ class ElementInterface {
return !!closest
}
+ /**
+ * Create an iteratable for all of the inlines of a node with `options`.
+ *
+ * @param {Options}
+ * @return {Iterable}
+ */
+
+ inlines(options = {}) {
+ const { onlyLeaves, onlyRoots, onlyTypes, match, ...rest } = options
+ const iterable = this.descendants({
+ includeBlocks: false,
+ includeTexts: false,
+ includeDocument: false,
+ ...rest,
+ match: (node, path) => {
+ if (onlyTypes && !onlyTypes.includes(node.type)) {
+ return false
+ } else if (onlyLeaves && !node.isLeafInline()) {
+ return false
+ } else if (onlyRoots && this.getParent(path).object !== 'block') {
+ return false
+ } else if (match && !match(node, path)) {
+ return false
+ } else {
+ return true
+ }
+ },
+ })
+
+ return iterable
+ }
+
/**
* Insert a `node`.
*
@@ -1933,11 +1419,15 @@ class ElementInterface {
*/
isLeafBlock() {
- const { object, nodes } = this
- if (object !== 'block') return false
- if (!nodes.size) return true
+ if (this.object !== 'block') {
+ return false
+ }
- return nodes.first().object !== 'block'
+ if (this.nodes.some(n => n.object === 'block')) {
+ return false
+ }
+
+ return true
}
/**
@@ -1947,51 +1437,52 @@ class ElementInterface {
*/
isLeafInline() {
- const { object, nodes } = this
- if (object !== 'inline') return false
- if (!nodes.size) return true
+ if (this.object !== 'inline') {
+ return false
+ }
- return nodes.first().object !== 'inline'
+ if (this.nodes.some(n => n.object === 'inline')) {
+ return false
+ }
+
+ return true
}
/**
- * Check whether a descendant node is inside a range. This will return true for all
- * text nodes inside the range and all ancestors of those text nodes up to this node.
+ * Check whether a descendant node is inside a `range` by `path`.
*
- * @param {List|string} path
+ * @param {List|String} path
* @param {Range} range
* @return {Node}
*/
- isNodeInRange(path, range) {
- this.assertDescendant(path)
+ isInRange(path, range) {
path = this.resolvePath(path)
range = this.resolveRange(range)
- if (range.isUnset) return false
+
+ if (range.isUnset) {
+ return false
+ }
const toStart = PathUtils.compare(path, range.start.path)
- const toEnd =
- range.start.key === range.end.key
- ? toStart
- : PathUtils.compare(path, range.end.path)
-
- const is = toStart !== -1 && toEnd !== 1
- return is
+ const toEnd = PathUtils.compare(path, range.end.path)
+ const isInRange = toStart !== -1 && toEnd !== 1
+ return isInRange
}
/**
* Map all child nodes, updating them in their parents. This method is
* optimized to not return a new node if no changes are made.
*
- * @param {Function} iterator
+ * @param {Function} predicate
* @return {Node}
*/
- mapChildren(iterator) {
+ mapChildren(predicate = identity) {
let { nodes } = this
nodes.forEach((node, i) => {
- const ret = iterator(node, i, this.nodes)
+ const ret = predicate(node, i, this.nodes)
if (ret !== node) nodes = nodes.set(ret.key, ret)
})
@@ -2003,17 +1494,17 @@ class ElementInterface {
* Map all descendant nodes, updating them in their parents. This method is
* optimized to not return a new node if no changes are made.
*
- * @param {Function} iterator
+ * @param {Function} predicate
* @return {Node}
*/
- mapDescendants(iterator) {
+ mapDescendants(predicate = identity) {
let { nodes } = this
nodes.forEach((node, index) => {
let ret = node
- if (ret.object !== 'text') ret = ret.mapDescendants(iterator)
- ret = iterator(ret, index, this.nodes)
+ if (ret.object !== 'text') ret = ret.mapDescendants(predicate)
+ ret = predicate(ret, index, this.nodes)
if (ret === node) return
nodes = nodes.set(index, ret)
@@ -2023,6 +1514,53 @@ class ElementInterface {
return ret
}
+ /**
+ * Create an iteratable for all the marks in text nodes with `options`.
+ *
+ * @param {Options}
+ * @return {Iterable}
+ */
+
+ marks(options = {}) {
+ const { onlyTypes = null, match, ...rest } = options
+ const texts = this.texts(rest)
+
+ return {
+ [Symbol.iterator]() {
+ const iterator = texts[Symbol.iterator]()
+ let node = null
+ let path = null
+ let remaining = []
+
+ const next = () => {
+ if (remaining.length) {
+ const mark = remaining.shift()
+
+ if (onlyTypes && !onlyTypes.includes(mark.type)) {
+ return next()
+ } else if (match && !match(mark, node, path)) {
+ return next()
+ }
+
+ return { value: [mark, node, path], done: false }
+ }
+
+ const { value, done } = iterator.next()
+
+ if (done) {
+ return { done: true }
+ }
+
+ ;[node, path] = value
+ remaining = node.marks.toArray()
+ return next()
+ }
+
+ return { next }
+ },
+ }
+ }
+
/**
* Merge a node backwards its previous sibling.
*
@@ -2168,6 +1706,20 @@ class ElementInterface {
return ret
}
+ /**
+ * Resolve a `annotation`, relative to the node, ensuring that the keys and
+ * offsets in the annotation exist and that they are synced with the paths.
+ *
+ * @param {Annotation|Object} annotation
+ * @return {Annotation}
+ */
+
+ resolveAnnotation(annotation) {
+ annotation = Annotation.create(annotation)
+ annotation = annotation.normalize(this)
+ return annotation
+ }
+
/**
* Resolve a `decoration`, relative to the node, ensuring that the keys and
* offsets in the decoration exist and that they are synced with the paths.
@@ -2258,6 +1810,24 @@ class ElementInterface {
return ret
}
+ /**
+ * Create an iteratable for the siblings in the tree at `path`.
+ *
+ * @param {List|Array} path
+ * @return {Iterable}
+ */
+
+ siblings(path, options) {
+ const iterable = this.createIterable({
+ path,
+ upward: false,
+ downward: false,
+ ...options,
+ })
+
+ return iterable
+ }
+
/**
* Split a node by `path` at `position` with optional `properties` to apply
* to the newly split node.
@@ -2293,6 +1863,710 @@ class ElementInterface {
ret = ret.insertNode(path, a)
return ret
}
+
+ /**
+ * Create an iteratable for all the text node descendants.
+ *
+ * @param {Object} options
+ * @return {Iterable}
+ */
+
+ texts(options) {
+ const iterable = this.descendants({
+ includeBlocks: false,
+ includeInlines: false,
+ includeDocument: false,
+ ...options,
+ })
+
+ return iterable
+ }
+
+ /**
+ * Deprecated.
+ */
+
+ getBlocksAtRange(range) {
+ warning(
+ false,
+ 'As of slate@0.44 the `node.getBlocksAtRange` method has been renamed to `getLeafBlocksAtRange`.'
+ )
+
+ return this.getLeafBlocksAtRange(range)
+ }
+
+ getBlocksAtRangeAsArray(range) {
+ warning(
+ false,
+ 'As of slate@0.44 the `node.getBlocksAtRangeAsArray` method has been renamed to `getLeafBlocksAtRangeAsArray`.'
+ )
+
+ return this.getLeafBlocksAtRangeAsArray(range)
+ }
+
+ getInlinesAtRange(range) {
+ warning(
+ false,
+ 'As of slate@0.44 the `node.getInlinesAtRange` method has been renamed to `getLeafInlinesAtRange`.'
+ )
+
+ return this.getLeafInlinesAtRange(range)
+ }
+
+ getInlinesAtRangeAsArray(range) {
+ warning(
+ false,
+ 'As of slate@0.44 the `node.getInlinesAtRangeAsArray` method has been renamed to `getLeafInlinesAtRangeAsArray`.'
+ )
+
+ return this.getLeafInlinesAtRangeAsArray(range)
+ }
+
+ getNextTextAndPath(path) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getNextTextAndPath` method has been renamed to `getNextTextEntry`.'
+ )
+
+ return this.getNextTextEntry(path)
+ }
+
+ getNextDeepMatchingNodeAndPath(path, iterator = () => true) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getNextDeepMatchingNodeAndPath` method is deprecated.'
+ )
+
+ const match = this.getNextMatchingNodeAndPath(path)
+
+ if (!match) return null
+
+ let [nextNode, nextPath] = match
+
+ let childMatch
+
+ const assign = () => {
+ childMatch =
+ nextNode.object !== 'text' &&
+ nextNode.findFirstDescendantAndPath(iterator, nextPath)
+ return childMatch
+ }
+
+ while (assign(childMatch)) {
+ ;[nextNode, nextPath] = childMatch
+ }
+
+ if (!nextNode) return null
+
+ return iterator(nextNode)
+ ? [nextNode, nextPath]
+ : this.getNextDeepMatchingNodeAndPath(match[1], iterator)
+ }
+
+ getPreviousTextAndPath(path) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getPreviousTextAndPath` method has been renamed to `getPreviousTextEntry`.'
+ )
+
+ return this.getPreviousTextEntry(path)
+ }
+
+ findFirstDescendantAndPath(iterator, pathToThisNode) {
+ warning(
+ false,
+ 'As of slate@0.47, the `findFirstDescendantAndPath` method is deprecated.'
+ )
+
+ return this.findDescendantAndPath(iterator, pathToThisNode, false)
+ }
+
+ getPreviousMatchingNodeAndPath(path, iterator = () => true) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getPreviousMatchingNodeAndPath` method is deprecated.'
+ )
+
+ if (!path) return null
+
+ for (let i = path.size; i > 0; i--) {
+ const p = path.slice(0, i)
+ if (p.last() === 0) continue
+
+ let previousPath = PathUtils.decrement(p)
+ let previousNode = this.getNode(previousPath)
+
+ while (previousNode && !iterator(previousNode)) {
+ previousPath = PathUtils.decrement(previousPath)
+ previousNode = this.getNode(previousPath)
+ }
+
+ if (previousNode) return [previousNode, previousPath]
+ }
+
+ return null
+ }
+
+ getPreviousDeepMatchingNodeAndPath(path, iterator = () => true) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getPreviousDeepMatchingNodeAndPath` method is deprecated.'
+ )
+
+ const match = this.getPreviousMatchingNodeAndPath(path)
+
+ if (!match) return null
+
+ let [previousNode, previousPath] = match
+
+ let childMatch
+
+ const assign = () => {
+ childMatch =
+ previousNode.object !== 'text' &&
+ previousNode.findLastDescendantAndPath(iterator, previousPath)
+ return childMatch
+ }
+
+ while (assign(childMatch)) {
+ ;[previousNode, previousPath] = childMatch
+ }
+
+ if (!previousNode) return null
+
+ return iterator(previousNode)
+ ? [previousNode, previousPath]
+ : this.getPreviousDeepMatchingNodeAndPath(match[1], iterator)
+ }
+
+ findLastDescendantAndPath(iterator, pathToThisNode) {
+ warning(
+ false,
+ 'As of slate@0.47, the `findLastDescendantAndPath` method is deprecated.'
+ )
+
+ return this.findDescendantAndPath(iterator, pathToThisNode, true)
+ }
+
+ findDescendantAndPath(
+ iterator,
+ pathToThisNode = PathUtils.create([]),
+ findLast = false
+ ) {
+ warning(
+ false,
+ 'As of slate@0.47, the `findDescendantAndPath` method is deprecated.'
+ )
+
+ let found
+ let foundPath
+
+ this.forEachDescendantWithPath(
+ (node, path, nodes) => {
+ if (iterator(node, path, nodes)) {
+ found = node
+ foundPath = path
+ return false
+ }
+ },
+ pathToThisNode,
+ findLast
+ )
+
+ return found ? [found, foundPath] : null
+ }
+
+ forEachDescendantWithPath(iterator, path = PathUtils.create([]), findLast) {
+ warning(
+ false,
+ 'As of slate@0.47, the `forEachDescendantWithPath` method is deprecated.'
+ )
+
+ let nodes = this.nodes
+ let ret
+
+ if (findLast) nodes = nodes.reverse()
+
+ nodes.forEach((child, i) => {
+ const childPath = path.concat(i)
+
+ if (iterator(child, childPath, nodes) === false) {
+ ret = false
+ return false
+ }
+
+ if (child.object !== 'text') {
+ ret = child.forEachDescendantWithPath(iterator, childPath, findLast)
+ return ret
+ }
+ })
+
+ return ret
+ }
+
+ getNextMatchingNodeAndPath(path, iterator = () => true) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getNextMatchingNodeAndPath` method is deprecated.'
+ )
+
+ if (!path) return null
+
+ for (let i = path.size; i > 0; i--) {
+ const p = path.slice(0, i)
+
+ let nextPath = PathUtils.increment(p)
+ let nextNode = this.getNode(nextPath)
+
+ while (nextNode && !iterator(nextNode)) {
+ nextPath = PathUtils.increment(nextPath)
+ nextNode = this.getNode(nextPath)
+ }
+
+ if (nextNode) return [nextNode, nextPath]
+ }
+
+ return null
+ }
+
+ getSelectionIndexes(range, isSelected = true) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getSelectionIndexes` method is deprecated.'
+ )
+
+ const { start, end } = range
+
+ // PERF: if we're not selected, we can exit early.
+ if (!isSelected) {
+ return null
+ }
+
+ // PERF: if we've been given an invalid selection we can exit early.
+ if (range.isUnset) {
+ return null
+ }
+
+ // PERF: if the start and end keys are the same, just check for the child
+ // that contains that single key.
+ if (start.path.equals(end.path)) {
+ const child = this.getFurthestAncestor(start.path)
+ const index = child ? this.nodes.indexOf(child) : null
+ return { start: index, end: index + 1 }
+ }
+
+ // Otherwise, check all of the children...
+ let startIndex = null
+ let endIndex = null
+
+ this.nodes.forEach((child, i) => {
+ if (child.object === 'text') {
+ if (startIndex == null && child.key === start.key) startIndex = i
+ if (endIndex == null && child.key === end.key) endIndex = i + 1
+ } else {
+ if (startIndex == null && child.hasDescendant(start.key)) startIndex = i
+ if (endIndex == null && child.hasDescendant(end.key)) endIndex = i + 1
+ }
+
+ // PERF: exit early if both start and end have been found.
+ return startIndex == null || endIndex == null
+ })
+
+ if (isSelected && startIndex == null) {
+ startIndex = 0
+ }
+
+ if (isSelected && endIndex == null) {
+ endIndex = this.nodes.size
+ }
+
+ if (startIndex == null) {
+ return null
+ }
+
+ return { start: startIndex, end: endIndex }
+ }
+
+ getTextsBetweenPositionsAsArray(startPath, endPath) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getTextsBetweenPositionsAsArray` method is deprecated.'
+ )
+
+ startPath = this.resolvePath(startPath)
+ endPath = this.resolvePath(endPath)
+
+ return this.getTextsBetweenPathPositionsAsArray(startPath, endPath)
+ }
+
+ getOrderedMarksBetweenPositions(startPath, startOffset, endPath, endOffset) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getOrderedMarksBetweenPositions` method is deprecated.'
+ )
+
+ startPath = this.resolvePath(startPath)
+ endPath = this.resolvePath(endPath)
+ const startText = this.getDescendant(startPath)
+
+ // PERF: if the paths are equal, we can just use the start.
+ if (PathUtils.isEqual(startPath, endPath)) {
+ return startText.marks
+ }
+
+ const texts = this.getTextsBetweenPathPositionsAsArray(startPath, endPath)
+
+ return OrderedSet().withMutations(result => {
+ texts.forEach(text => {
+ result.union(text.marks)
+ })
+ })
+ }
+
+ getTextsBetweenPathPositionsAsArray(startPath, endPath) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getTextsBetweenPathPositionsAsArray` method is deprecated.'
+ )
+
+ // PERF: the most common case is when the range is in a single text node,
+ // where we can avoid a lot of iterating of the tree.
+ if (startPath && endPath && PathUtils.isEqual(startPath, endPath)) {
+ return [this.getDescendant(startPath)]
+ } else if (!startPath && !endPath) {
+ return this.getTextsAsArray()
+ }
+
+ const startIndex = startPath ? startPath.get(0, 0) : 0
+ const endIndex = endPath
+ ? endPath.get(0, this.nodes.size - 1)
+ : this.nodes.size - 1
+
+ let array = []
+
+ this.nodes.slice(startIndex, endIndex + 1).forEach((node, i) => {
+ if (node.object === 'text') {
+ array.push(node)
+ } else {
+ // For the node at start and end of this list, we want to provide a start and end path
+ // For other nodes, we can just get all their text nodes, they are between the paths
+ const childStartPath =
+ startPath && i === 0 ? PathUtils.drop(startPath) : null
+ const childEndPath =
+ endPath && i === endIndex - startIndex
+ ? PathUtils.drop(endPath)
+ : null
+
+ array = array.concat(
+ node.getTextsBetweenPathPositionsAsArray(childStartPath, childEndPath)
+ )
+ }
+ })
+
+ return array
+ }
+
+ getFurthestAncestor(path) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getFurthestAncestor` method has been renamed to `getFurthestChild`.'
+ )
+
+ return this.getFurthestChild(path)
+ }
+
+ getLeafBlocksAtRangeAsArray(range) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getLeafBlocksAtRangeAsArray` method is deprecated.'
+ )
+
+ range = this.resolveRange(range)
+ if (range.isUnset) return []
+
+ const { start, end } = range
+
+ return this.getLeafBlocksBetweenPathPositionsAsArray(start.path, end.path)
+ }
+
+ getLeafBlocksBetweenPathPositionsAsArray(startPath, endPath) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getLeafBlocksBetweenPathPositionsAsArray` method is deprecated.'
+ )
+
+ // PERF: the most common case is when the range is in a single block node,
+ // where we can avoid a lot of iterating of the tree.
+ if (startPath && endPath && PathUtils.isEqual(startPath, endPath)) {
+ return [this.getClosestBlock(startPath)]
+ } else if (!startPath && !endPath) {
+ return this.getBlocksAsArray()
+ }
+
+ const startIndex = startPath ? startPath.get(0, 0) : 0
+ const endIndex = endPath
+ ? endPath.get(0, this.nodes.size - 1)
+ : this.nodes.size - 1
+
+ let array = []
+
+ this.nodes.slice(startIndex, endIndex + 1).forEach((node, i) => {
+ if (node.object !== 'block') {
+ return
+ } else if (node.isLeafBlock()) {
+ array.push(node)
+ } else {
+ const childStartPath =
+ startPath && i === 0 ? PathUtils.drop(startPath) : null
+ const childEndPath =
+ endPath && i === endIndex - startIndex
+ ? PathUtils.drop(endPath)
+ : null
+
+ array = array.concat(
+ node.getLeafBlocksBetweenPathPositionsAsArray(
+ childStartPath,
+ childEndPath
+ )
+ )
+ }
+ })
+
+ return array
+ }
+
+ getBlocksAsArray() {
+ warning(
+ false,
+ 'As of slate@0.47, the `getBlocksAsArray` method is deprecated.'
+ )
+
+ const iterable = this.blocks({ onlyLeaves: true })
+ const array = Array.from(iterable, ([node]) => node)
+ return array
+ }
+
+ getBlocksByTypeAsArray(type) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getBlocksByTypeAsArray` method is deprecated.'
+ )
+
+ const iterable = this.blocks({ onlyLeaves: true, onlyTypes: [type] })
+ const array = Array.from(iterable, ([node]) => node)
+ return array
+ }
+
+ getFurthestOnlyChildAncestor(path) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getFurthestOnlyChildAncestor` method is deprecated.'
+ )
+
+ const ancestors = this.getAncestors(path)
+ if (!ancestors) return null
+
+ const furthest = ancestors
+ .rest()
+ .reverse()
+ .takeUntil(p => p.nodes.size > 1)
+ .last()
+
+ return furthest || null
+ }
+
+ getInlinesAsArray() {
+ warning(
+ false,
+ 'As of slate@0.47, the `getInlinesAsArray` method is deprecated.'
+ )
+
+ const array = Array.from(
+ this.inlines({ onlyLeaves: true }),
+ ([node]) => node
+ )
+ return array
+ }
+
+ getInlinesByTypeAsArray(type) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getInlinesByTypeAsArray` method is deprecated.'
+ )
+
+ const array = Array.from(
+ this.inlines({ onlyLeaves: true, onlyTypes: [type] }),
+ ([node]) => node
+ )
+ return array
+ }
+
+ getLeafInlinesAtRangeAsArray(range) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getLeafInlinesAtRangeAsArray` method is deprecated.'
+ )
+
+ range = this.resolveRange(range)
+ if (range.isUnset) return []
+
+ const array = this.getTextsAtRangeAsArray(range)
+ .map(text => this.getClosestInline(text.key))
+ .filter(exists => exists)
+
+ return array
+ }
+
+ getOrderedMarks() {
+ warning(
+ false,
+ 'As of slate@0.47, the `getOrderedMarks` method has been folded into `getMarks`, which will now return an ordered set.'
+ )
+ return this.getMarks()
+ }
+
+ getOrderedMarksAtRange(range) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getOrderedMarksAtRange` method has been folded into `getMarksAtRange`, which will now return an ordered set.'
+ )
+ return this.getMarksAtRange(range)
+ }
+
+ getOrderedMarksByType(type) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getOrderedMarksByType` method has been folded into `getMarksByType`, which will now return an ordered set.'
+ )
+ return this.getMarksByType(type)
+ }
+
+ getMarksByTypeAsArray(type) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getMarksByTypeAsArray` method is deprecated.'
+ )
+
+ const array = this.nodes.reduce((memo, node) => {
+ return node.object === 'text'
+ ? memo.concat(node.marks.filter(m => m.type === type))
+ : memo.concat(node.getMarksByTypeAsArray(type))
+ }, [])
+
+ return array
+ }
+
+ getMarksAsArray() {
+ warning(
+ false,
+ 'As of slate@0.47, the `getMarksAsArray` method is deprecated.'
+ )
+
+ const result = []
+
+ for (const [node] of this.texts()) {
+ result.push(node.marks.toArray())
+ }
+
+ // PERF: use only one concat rather than multiple for speed.
+ const array = [].concat(...result)
+ return array
+ }
+
+ getRootInlinesAtRangeAsArray(range) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getRootInlinesAtRangeAsArray` method is deprecated.'
+ )
+
+ range = this.resolveRange(range)
+ if (range.isUnset) return List()
+
+ const array = this.getTextsAtRangeAsArray(range)
+ .map(text => this.getFurthestInline(text.key))
+ .filter(exists => exists)
+
+ return array
+ }
+
+ getTextsAsArray() {
+ warning(
+ false,
+ 'As of slate@0.47, the `getTextsAsArray` method is deprecated.'
+ )
+
+ const iterable = this.texts()
+ const array = Array.from(iterable, ([node]) => node)
+ return array
+ }
+
+ getTextsAtRangeAsArray(range) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getTextsAtRangeAsArray` method is deprecated.'
+ )
+
+ const iterable = this.texts({ range })
+ const array = Array.from(iterable, ([node]) => node)
+ return array
+ }
+
+ getMarksAtPosition(path, offset) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getMarksAtPosition` method is deprecated.'
+ )
+
+ path = this.resolvePath(path)
+ const text = this.getDescendant(path)
+ const currentMarks = text.marks
+
+ if (offset !== 0) {
+ return OrderedSet(currentMarks)
+ }
+
+ const closestBlock = this.getClosestBlock(path)
+
+ // insert mark for empty block; the empty block are often created by split node or add marks in a range including empty blocks
+ if (closestBlock.text === '') {
+ return OrderedSet(currentMarks)
+ }
+
+ const [previous] = this.texts({ path, direction: 'backward' })
+
+ if (!previous) {
+ return OrderedSet()
+ }
+
+ const [previousText, previousPath] = previous
+
+ if (closestBlock.hasDescendant(previousPath)) {
+ return OrderedSet(previousText.marks)
+ }
+
+ return OrderedSet(currentMarks)
+ }
+
+ getNodesAtRange(range) {
+ warning(
+ false,
+ 'As of slate@0.47, the `getNodesAtRange` method has been renamed to `getDescendantsAtRange`.'
+ )
+
+ const iterable = this.descendants({ range })
+ const array = Array.from(iterable, ([node]) => node)
+ const list = List(array)
+ return list
+ }
+
+ isNodeInRange(path, range) {
+ warning(
+ false,
+ 'As of slate@0.47, the `isNodeInRange` method has been renamed to `isInRange`.'
+ )
+
+ return this.isInRange(path, range)
+ }
}
/**
@@ -2321,23 +2595,24 @@ for (const method of ASSERTS) {
memoize(ElementInterface.prototype, [
'getBlocksAsArray',
- 'getLeafBlocksAtRangeAsArray',
'getBlocksByTypeAsArray',
'getDecorations',
'getFragmentAtRange',
'getInlinesAsArray',
'getInlinesByTypeAsArray',
+ 'getInsertMarksAtRange',
+ 'getLeafBlocksAtRangeAsArray',
'getLeafBlocksAtRangeAsArray',
'getLeafInlinesAtRangeAsArray',
'getMarksAsArray',
'getMarksAtPosition',
- 'getNodesAtRange',
- 'getOrderedMarksBetweenPositions',
- 'getInsertMarksAtRange',
'getMarksByTypeAsArray',
'getNextBlock',
+ 'getNodesAtRange',
+ 'getNodesToPathsMap',
'getOffset',
'getOffsetAtRange',
+ 'getOrderedMarksBetweenPositions',
'getPreviousBlock',
'getRootBlocksAtRange',
'getRootInlinesAtRangeAsArray',
diff --git a/packages/slate/src/interfaces/model.js b/packages/slate/src/interfaces/model.js
index c93d0fe59..02ddc53bb 100644
--- a/packages/slate/src/interfaces/model.js
+++ b/packages/slate/src/interfaces/model.js
@@ -1,4 +1,5 @@
import mixin from '../utils/mixin'
+import Annotation from '../models/annotation'
import Block from '../models/block'
import Decoration from '../models/decoration'
import Document from '../models/document'
@@ -44,6 +45,7 @@ class ModelInterface {
*/
mixin(ModelInterface, [
+ Annotation,
Block,
Decoration,
Document,
diff --git a/packages/slate/src/interfaces/node.js b/packages/slate/src/interfaces/node.js
index 7b4d1bdaf..5a1e2a9a8 100644
--- a/packages/slate/src/interfaces/node.js
+++ b/packages/slate/src/interfaces/node.js
@@ -5,6 +5,7 @@ import mixin from '../utils/mixin'
import Block from '../models/block'
import Document from '../models/document'
import Inline from '../models/inline'
+import Node from '../models/node'
import KeyUtils from '../utils/key-utils'
import memoize from '../utils/memoize'
import PathUtils from '../utils/path-utils'
@@ -116,8 +117,18 @@ class NodeInterface {
*/
getPath(key) {
- // Handle the case of passing in a path directly, to match other methods.
- if (List.isList(key)) return key
+ // COMPAT: Handle passing in a path, to match other methods.
+ if (List.isList(key)) {
+ return key
+ }
+
+ // COMPAT: Handle a node object by iterating the descendants tree, so that
+ // we avoid using keys for the future.
+ if (Node.isNode(key) && this.descendants) {
+ for (const [node, path] of this.descendants()) {
+ if (key === node) return path
+ }
+ }
const dict = this.getKeysToPathsTable()
const path = dict[key]
diff --git a/packages/slate/src/interfaces/object.js b/packages/slate/src/interfaces/object.js
index 0b895d8dd..6f4599ae3 100644
--- a/packages/slate/src/interfaces/object.js
+++ b/packages/slate/src/interfaces/object.js
@@ -1,3 +1,4 @@
+import Annotation from '../models/annotation'
import Block from '../models/block'
import Change from '../models/change'
import Decoration from '../models/decoration'
@@ -49,6 +50,7 @@ function create(type) {
*/
Object.entries({
+ Annotation,
Block,
Change,
Decoration,
diff --git a/packages/slate/src/interfaces/range.js b/packages/slate/src/interfaces/range.js
index a342d1dfd..fa290872d 100644
--- a/packages/slate/src/interfaces/range.js
+++ b/packages/slate/src/interfaces/range.js
@@ -1,4 +1,5 @@
import mixin from '../utils/mixin'
+import Annotation from '../models/annotation'
import Decoration from '../models/decoration'
import PathUtils from '../utils/path-utils'
import Point from '../models/point'
@@ -652,4 +653,4 @@ class RangeInterface {
* @param {Record}
*/
-mixin(RangeInterface, [Decoration, Range, Selection])
+mixin(RangeInterface, [Annotation, Decoration, Range, Selection])
diff --git a/packages/slate/src/models/annotation.js b/packages/slate/src/models/annotation.js
new file mode 100644
index 000000000..777d274cb
--- /dev/null
+++ b/packages/slate/src/models/annotation.js
@@ -0,0 +1,193 @@
+import isPlainObject from 'is-plain-object'
+import { Map, Record } from 'immutable'
+
+import Point from './point'
+import Range from './range'
+import Data from './data'
+
+/**
+ * Default properties.
+ *
+ * @type {Object}
+ */
+
+const DEFAULTS = {
+ key: undefined,
+ type: undefined,
+ data: undefined,
+ anchor: undefined,
+ focus: undefined,
+}
+
+/**
+ * Annotation.
+ *
+ * @type {Annotation}
+ */
+
+class Annotation extends Record(DEFAULTS) {
+ /**
+ * Create a new `Annotation` with `attrs`.
+ *
+ * @param {Object|Annotation} attrs
+ * @return {Annotation}
+ */
+
+ static create(attrs = {}) {
+ if (Annotation.isAnnotation(attrs)) {
+ return attrs
+ }
+
+ if (Range.isRange(attrs)) {
+ return Annotation.fromJSON(Range.createProperties(attrs))
+ }
+
+ if (isPlainObject(attrs)) {
+ return Annotation.fromJSON(attrs)
+ }
+
+ throw new Error(
+ `\`Annotation.create\` only accepts objects or annotations, but you passed it: ${attrs}`
+ )
+ }
+
+ /**
+ * Create a map of annotations from `elements`.
+ *
+ * @param {Object|Map} elements
+ * @return {Map}
+ */
+
+ static createMap(elements = []) {
+ if (Map.isMap(elements)) {
+ return elements
+ }
+
+ if (isPlainObject(elements)) {
+ const obj = {}
+
+ for (const key in elements) {
+ const value = elements[key]
+ const annotation = Annotation.create(value)
+ obj[key] = annotation
+ }
+
+ return Map(obj)
+ }
+
+ throw new Error(
+ `\`Annotation.createMap\` only accepts arrays or lists, but you passed it: ${elements}`
+ )
+ }
+
+ /**
+ * Create a dictionary of settable annotation properties from `attrs`.
+ *
+ * @param {Object|String|Annotation} attrs
+ * @return {Object}
+ */
+
+ static createProperties(a = {}) {
+ if (Annotation.isAnnotation(a)) {
+ return {
+ key: a.key,
+ type: a.type,
+ data: a.data,
+ anchor: Point.createProperties(a.anchor),
+ focus: Point.createProperties(a.focus),
+ }
+ }
+
+ if (isPlainObject(a)) {
+ const p = {}
+ if ('key' in a) p.key = a.key
+ if ('type' in a) p.type = a.type
+ if ('data' in a) p.data = Data.create(a.data)
+ if ('anchor' in a) p.anchor = Point.create(a.anchor)
+ if ('focus' in a) p.focus = Point.create(a.focus)
+ return p
+ }
+
+ throw new Error(
+ `\`Annotation.createProperties\` only accepts objects or annotations, but you passed it: ${a}`
+ )
+ }
+
+ /**
+ * Create a `Annotation` from a JSON `object`.
+ *
+ * @param {Object} object
+ * @return {Annotation}
+ */
+
+ static fromJSON(object) {
+ const { key, type, data, anchor, focus } = object
+
+ if (!key) {
+ throw new Error(
+ `Annotations must be created with a \`key\`, but you passed: ${JSON.stringify(
+ object
+ )}`
+ )
+ }
+
+ if (!type) {
+ throw new Error(
+ `Annotations must be created with a \`type\`, but you passed: ${JSON.stringify(
+ object
+ )}`
+ )
+ }
+
+ const annotation = new Annotation({
+ key,
+ type,
+ data: Data.create(data || {}),
+ anchor: Point.fromJSON(anchor || {}),
+ focus: Point.fromJSON(focus || {}),
+ })
+
+ return annotation
+ }
+
+ /**
+ * Set new `properties` on the annotation.
+ *
+ * @param {Object|Range|Selection} properties
+ * @return {Range}
+ */
+
+ setProperties(properties) {
+ properties = Annotation.createProperties(properties)
+ const annotation = this.merge(properties)
+ return annotation
+ }
+
+ /**
+ * Return a JSON representation of the annotation.
+ *
+ * @param {Object} options
+ * @return {Object}
+ */
+
+ toJSON(options = {}) {
+ const object = {
+ object: this.object,
+ key: this.key,
+ type: this.type,
+ data: this.data.toJSON(),
+ anchor: this.anchor.toJSON(options),
+ focus: this.focus.toJSON(options),
+ }
+
+ return object
+ }
+}
+
+/**
+ * Export.
+ *
+ * @type {Annotation}
+ */
+
+export default Annotation
diff --git a/packages/slate/src/models/decoration.js b/packages/slate/src/models/decoration.js
index 1d2eab7e4..9adeef27c 100644
--- a/packages/slate/src/models/decoration.js
+++ b/packages/slate/src/models/decoration.js
@@ -3,6 +3,7 @@ import { List, Record } from 'immutable'
import Mark from './mark'
import Point from './point'
+import Data from './data'
import Range from './range'
/**
@@ -12,9 +13,10 @@ import Range from './range'
*/
const DEFAULTS = {
+ type: undefined,
+ data: undefined,
anchor: undefined,
focus: undefined,
- mark: undefined,
}
/**
@@ -77,6 +79,8 @@ class Decoration extends Record(DEFAULTS) {
static createProperties(a = {}) {
if (Decoration.isDecoration(a)) {
return {
+ type: a.type,
+ data: a.data,
anchor: Point.createProperties(a.anchor),
focus: Point.createProperties(a.focus),
mark: Mark.create(a.mark),
@@ -85,9 +89,10 @@ class Decoration extends Record(DEFAULTS) {
if (isPlainObject(a)) {
const p = {}
+ if ('type' in a) p.type = a.type
+ if ('data' in a) p.data = Data.create(a.data)
if ('anchor' in a) p.anchor = Point.create(a.anchor)
if ('focus' in a) p.focus = Point.create(a.focus)
- if ('mark' in a) p.mark = Mark.create(a.mark)
return p
}
@@ -104,20 +109,21 @@ class Decoration extends Record(DEFAULTS) {
*/
static fromJSON(object) {
- const { anchor, focus, mark } = object
+ const { type, data, anchor, focus } = object
- if (!mark) {
+ if (!type) {
throw new Error(
- `Decorations must be created with a \`mark\`, but you passed: ${JSON.stringify(
+ `Decorations must be created with a \`type\`, but you passed: ${JSON.stringify(
object
)}`
)
}
const decoration = new Decoration({
+ type,
+ data: Data.create(data || {}),
anchor: Point.fromJSON(anchor || {}),
focus: Point.fromJSON(focus || {}),
- mark: Mark.fromJSON(mark),
})
return decoration
@@ -132,22 +138,7 @@ class Decoration extends Record(DEFAULTS) {
setProperties(properties) {
properties = Decoration.createProperties(properties)
- const { anchor, focus, mark } = properties
- const props = {}
-
- if (anchor) {
- props.anchor = Point.create(anchor)
- }
-
- if (focus) {
- props.focus = Point.create(focus)
- }
-
- if (mark) {
- props.mark = Mark.create(mark)
- }
-
- const decoration = this.merge(props)
+ const decoration = this.merge(properties)
return decoration
}
@@ -161,9 +152,10 @@ class Decoration extends Record(DEFAULTS) {
toJSON(options = {}) {
const object = {
object: this.object,
+ type: this.type,
+ data: this.data.toJSON(),
anchor: this.anchor.toJSON(options),
focus: this.focus.toJSON(options),
- mark: this.mark.toJSON(options),
}
return object
diff --git a/packages/slate/src/models/leaf.js b/packages/slate/src/models/leaf.js
index bbb370487..6712ae6e8 100644
--- a/packages/slate/src/models/leaf.js
+++ b/packages/slate/src/models/leaf.js
@@ -1,4 +1,5 @@
import isPlainObject from 'is-plain-object'
+import warning from 'tiny-warning'
import { List, Record, Set } from 'immutable'
import Mark from './mark'
@@ -29,6 +30,8 @@ class Leaf extends Record(DEFAULTS) {
*/
static create(attrs = {}) {
+ warning(false, 'As of slate@0.47 the `Leaf` model is deprecated.')
+
if (Leaf.isLeaf(attrs)) {
return attrs
}
diff --git a/packages/slate/src/models/operation.js b/packages/slate/src/models/operation.js
index ef8ea2342..0f76aeac4 100644
--- a/packages/slate/src/models/operation.js
+++ b/packages/slate/src/models/operation.js
@@ -1,6 +1,7 @@
import isPlainObject from 'is-plain-object'
import { List, Record, Map } from 'immutable'
+import Annotation from './annotation'
import Mark from './mark'
import Node from './node'
import PathUtils from '../utils/path-utils'
@@ -17,13 +18,16 @@ import invert from '../operations/invert'
const OPERATION_ATTRIBUTES = {
add_mark: ['path', 'mark', 'data'],
+ add_annotation: ['annotation', 'data'],
insert_node: ['path', 'node', 'data'],
insert_text: ['path', 'offset', 'text', 'data'],
merge_node: ['path', 'position', 'properties', 'target', 'data'],
move_node: ['path', 'newPath', 'data'],
+ remove_annotation: ['annotation', 'data'],
remove_mark: ['path', 'mark', 'data'],
remove_node: ['path', 'node', 'data'],
remove_text: ['path', 'offset', 'text', 'data'],
+ set_annotation: ['properties', 'newProperties', 'data'],
set_mark: ['path', 'properties', 'newProperties', 'data'],
set_node: ['path', 'properties', 'newProperties', 'data'],
set_selection: ['properties', 'newProperties', 'data'],
@@ -38,20 +42,21 @@ const OPERATION_ATTRIBUTES = {
*/
const DEFAULTS = {
+ annotation: undefined,
+ data: undefined,
length: undefined,
mark: undefined,
marks: undefined,
newPath: undefined,
+ newProperties: undefined,
node: undefined,
offset: undefined,
path: undefined,
position: undefined,
properties: undefined,
- newProperties: undefined,
target: undefined,
text: undefined,
type: undefined,
- data: undefined,
}
/**
@@ -136,6 +141,10 @@ class Operation extends Record(DEFAULTS) {
)
}
+ if (key === 'annotation') {
+ v = Annotation.create(v)
+ }
+
if (key === 'path' || key === 'newPath') {
v = PathUtils.create(v)
}
@@ -144,16 +153,15 @@ class Operation extends Record(DEFAULTS) {
v = Mark.create(v)
}
- if (key === 'marks' && v != null) {
- v = Mark.createSet(v)
- }
-
if (key === 'node') {
v = Node.create(v)
}
- if (key === 'properties' && type === 'merge_node') {
- v = Node.createProperties(v)
+ if (
+ (key === 'properties' || key === 'newProperties') &&
+ type === 'set_annotation'
+ ) {
+ v = Annotation.createProperties(v)
}
if (
@@ -165,7 +173,7 @@ class Operation extends Record(DEFAULTS) {
if (
(key === 'properties' || key === 'newProperties') &&
- type === 'set_node'
+ (type === 'set_node' || type === 'merge_node' || type === 'split_node')
) {
v = Node.createProperties(v)
}
@@ -184,10 +192,6 @@ class Operation extends Record(DEFAULTS) {
v = Value.createProperties(v)
}
- if (key === 'properties' && type === 'split_node') {
- v = Node.createProperties(v)
- }
-
if (key === 'data') {
v = Map(v)
}
@@ -195,8 +199,8 @@ class Operation extends Record(DEFAULTS) {
attrs[key] = v
}
- const node = new Operation(attrs)
- return node
+ const op = new Operation(attrs)
+ return op
}
/**
@@ -249,6 +253,7 @@ class Operation extends Record(DEFAULTS) {
let value = this[key]
if (
+ key === 'annotation' ||
key === 'mark' ||
key === 'marks' ||
key === 'node' ||
@@ -265,6 +270,18 @@ class Operation extends Record(DEFAULTS) {
value = v
}
+ if (
+ (key === 'properties' || key === 'newProperties') &&
+ type === 'set_annotation'
+ ) {
+ const v = {}
+ if ('anchor' in value) v.anchor = value.anchor.toJS()
+ if ('focus' in value) v.focus = value.focus.toJS()
+ if ('key' in value) v.key = value.key
+ if ('mark' in value) v.mark = value.mark.toJS()
+ value = v
+ }
+
if (
(key === 'properties' || key === 'newProperties') &&
type === 'set_mark'
@@ -303,7 +320,6 @@ class Operation extends Record(DEFAULTS) {
) {
const v = {}
if ('data' in value) v.data = value.data.toJS()
- if ('decorations' in value) v.decorations = value.decorations.toJS()
value = v
}
diff --git a/packages/slate/src/models/point.js b/packages/slate/src/models/point.js
index 89fed1788..029c93825 100644
--- a/packages/slate/src/models/point.js
+++ b/packages/slate/src/models/point.js
@@ -419,6 +419,7 @@ class Point extends Record(DEFAULTS) {
// enforce that if there is a following text node, we always move it there.
if (point.offset === target.text.length) {
const block = node.getClosestBlock(point.path)
+ // TODO: this next line is broken because `getNextText` takes a path
const next = block.getNextText()
if (next) {
diff --git a/packages/slate/src/models/range.js b/packages/slate/src/models/range.js
index f3d16d8ae..bbf77e6e0 100644
--- a/packages/slate/src/models/range.js
+++ b/packages/slate/src/models/range.js
@@ -90,7 +90,7 @@ class Range extends Record(DEFAULTS) {
}
throw new Error(
- `\`Range.createProperties\` only accepts objects, decorations, ranges or selections, but you passed it: ${a}`
+ `\`Range.createProperties\` only accepts objects, annotations, decorations, ranges or selections, but you passed it: ${a}`
)
}
diff --git a/packages/slate/src/models/text.js b/packages/slate/src/models/text.js
index e4bca47ed..f9875ba8c 100644
--- a/packages/slate/src/models/text.js
+++ b/packages/slate/src/models/text.js
@@ -2,7 +2,6 @@ import isPlainObject from 'is-plain-object'
import invariant from 'tiny-invariant'
import { List, Record } from 'immutable'
-import Leaf from './leaf'
import Mark from './mark'
import KeyUtils from '../utils/key-utils'
@@ -18,6 +17,13 @@ const DEFAULTS = {
text: undefined,
}
+const Leaf = Record({
+ text: undefined,
+ marks: undefined,
+ annotations: undefined,
+ decorations: undefined,
+})
+
/**
* Text.
*
@@ -135,55 +141,109 @@ class Text extends Record(DEFAULTS) {
}
/**
- * Get the leaves for the text node, with `decorations`.
+ * Get a list of uniquely-formatted leaves for the text node, given its
+ * existing marks, and its current `annotations` and `decorations`.
*
+ * @param {Map} annotations
* @param {List} decorations
* @return {List}
*/
- getLeaves(decorations) {
- const { key, text, marks } = this
- const leaf = Leaf.create({ text, marks })
- let leaves = Leaf.createList([leaf])
+ getLeaves(annotations, decorations) {
+ const { text, marks } = this
+ let leaves = [{ text, marks, annotations: [], decorations: [] }]
- // PERF: We can exit early without decorations.
- if (!decorations || decorations.size === 0) {
- return leaves
+ // Helper to split a leaf into two `at` an offset.
+ const split = (leaf, at) => {
+ return [
+ {
+ text: leaf.text.slice(0, at),
+ marks: leaf.marks,
+ annotations: [...leaf.annotations],
+ decorations: [...leaf.decorations],
+ },
+ {
+ text: leaf.text.slice(at),
+ marks: leaf.marks,
+ annotations: [...leaf.annotations],
+ decorations: [...leaf.decorations],
+ },
+ ]
}
- // HACK: this shouldn't be necessary, because the loop below should handle
- // the `0` case without failures. It may already even, not sure.
- if (text === '') {
- const decMarks = decorations.map(d => d.mark)
- const l = Leaf.create({ marks: decMarks })
- return List([l])
- }
+ // Helper to compile the leaves for a `kind` of format.
+ const compile = kind => {
+ const formats =
+ kind === 'annotations' ? annotations.values() : decorations
- decorations.forEach(dec => {
- const { start, end, mark } = dec
- const hasStart = start.key === key
- const hasEnd = end.key === key
+ for (const format of formats) {
+ const { start, end } = format
+ const next = []
+ let o = 0
- if (hasStart && hasEnd) {
- const index = hasStart ? start.offset : 0
- const length = hasEnd ? end.offset - index : text.length - index
+ for (const leaf of leaves) {
+ const { length } = leaf.text
+ const offset = o
+ o += length
- if (length < 1) return
- if (index >= text.length) return
+ // If the range starts after the leaf, or ends before it, continue.
+ if (start.offset > offset + length || end.offset <= offset) {
+ next.push(leaf)
+ continue
+ }
- if (index !== 0 || length < text.length) {
- const [before, bundle] = Leaf.splitLeaves(leaves, index)
- const [middle, after] = Leaf.splitLeaves(bundle, length)
- leaves = before.concat(middle.map(x => x.addMark(mark)), after)
- return
+ // If the range encompases the entire leaf, add the format.
+ if (start.offset <= offset && end.offset >= offset + length) {
+ leaf[kind].push(format)
+ next.push(leaf)
+ continue
+ }
+
+ // Otherwise we need to split the leaf, at the start, end, or both,
+ // and add the format to the middle intersecting section. Do the end
+ // split first since we don't need to update the offset that way.
+ let middle = leaf
+ let before
+ let after
+
+ if (end.offset < offset + length) {
+ ;[middle, after] = split(middle, end.offset - offset)
+ }
+
+ if (start.offset > offset) {
+ ;[before, middle] = split(middle, start.offset - offset)
+ }
+
+ middle[kind].push(format)
+
+ if (before) {
+ next.push(before)
+ }
+
+ next.push(middle)
+
+ if (after) {
+ next.push(after)
+ }
}
- }
- leaves = leaves.map(x => x.addMark(mark))
+ leaves = next
+ }
+ }
+
+ compile('annotations')
+ compile('decorations')
+
+ leaves = leaves.map(leaf => {
+ return new Leaf({
+ ...leaf,
+ annotations: List(leaf.annotations),
+ decorations: List(leaf.decorations),
+ })
})
- if (leaves === this.leaves) return leaves
- return Leaf.createLeaves(leaves)
+ const list = List(leaves)
+ return list
}
/**
diff --git a/packages/slate/src/models/value.js b/packages/slate/src/models/value.js
index 6cb89dcb7..12ccb375d 100644
--- a/packages/slate/src/models/value.js
+++ b/packages/slate/src/models/value.js
@@ -2,11 +2,11 @@ import isPlainObject from 'is-plain-object'
import invariant from 'tiny-invariant'
import { Record, Set, List } from 'immutable'
+import Annotation from './annotation'
+import Data from './data'
+import Document from './document'
import Mark from './mark'
import PathUtils from '../utils/path-utils'
-import Data from './data'
-import Decoration from './decoration'
-import Document from './document'
/**
* Default properties.
@@ -15,8 +15,8 @@ import Document from './document'
*/
const DEFAULTS = {
+ annotations: undefined,
data: undefined,
- decorations: undefined,
document: undefined,
selection: undefined,
}
@@ -60,16 +60,16 @@ class Value extends Record(DEFAULTS) {
static createProperties(a = {}) {
if (Value.isValue(a)) {
return {
+ annotations: a.annotations,
data: a.data,
- decorations: a.decorations,
}
}
if (isPlainObject(a)) {
const p = {}
+ if ('annotations' in a)
+ p.annotations = Annotation.createList(a.annotations)
if ('data' in a) p.data = Data.create(a.data)
- if ('decorations' in a)
- p.decorations = Decoration.createList(a.decorations)
return p
}
@@ -89,11 +89,11 @@ class Value extends Record(DEFAULTS) {
*/
static fromJSON(object, options = {}) {
- let { data = {}, decorations = [], document = {}, selection = {} } = object
+ let { data = {}, annotations = {}, document = {}, selection = {} } = object
data = Data.fromJSON(data)
document = Document.fromJSON(document)
selection = document.createSelection(selection)
- decorations = List(decorations.map(d => Decoration.fromJSON(d)))
+ annotations = Annotation.createMap(annotations)
if (selection.isUnset) {
const text = document.getFirstText()
@@ -102,8 +102,8 @@ class Value extends Record(DEFAULTS) {
}
const value = new Value({
+ annotations,
data,
- decorations,
document,
selection,
})
@@ -418,6 +418,24 @@ class Value extends Record(DEFAULTS) {
: this.document.getTextsAtRange(this.selection)
}
+ /**
+ * Add an `annotation` to the value.
+ *
+ * @param {Annotation} annotation
+ * @param {Mark} mark
+ * @return {Value}
+ */
+
+ addAnnotation(annotation) {
+ annotation = Annotation.create(annotation)
+ let value = this
+ let { annotations } = value
+ const { key } = annotation
+ annotations = annotations.set(key, annotation)
+ value = value.set('annotations', annotations)
+ return value
+ }
+
/**
* Add `mark` to text at `path`.
*
@@ -548,6 +566,24 @@ class Value extends Record(DEFAULTS) {
return value
}
+ /**
+ * Remove an `annotation` from the value.
+ *
+ * @param {Annotation} annotation
+ * @param {Mark} mark
+ * @return {Value}
+ */
+
+ removeAnnotation(annotation) {
+ annotation = Annotation.create(annotation)
+ let value = this
+ let { annotations } = value
+ const { key } = annotation
+ annotations = annotations.delete(key)
+ value = value.set('annotations', annotations)
+ return value
+ }
+
/**
* Remove `mark` at `path`.
*
@@ -646,6 +682,26 @@ class Value extends Record(DEFAULTS) {
return value
}
+ /**
+ * Add an `annotation` to the value.
+ *
+ * @param {Annotation} annotation
+ * @param {Mark} mark
+ * @return {Value}
+ */
+
+ setAnnotation(properties, newProperties) {
+ newProperties = Annotation.createProperties(newProperties)
+ const annotation = Annotation.create(properties)
+ const next = annotation.merge(newProperties)
+ let value = this
+ let { annotations } = value
+ const { key } = annotation
+ annotations = annotations.set(key, next)
+ value = value.set('annotations', annotations)
+ return value
+ }
+
/**
* Set `properties` on a node.
*
@@ -689,16 +745,16 @@ class Value extends Record(DEFAULTS) {
setProperties(properties) {
let value = this
const { document } = value
- const { data, decorations } = properties
+ const { data, annotations } = properties
const props = {}
if (data) {
props.data = data
}
- if (decorations) {
- props.decorations = decorations.map(d => {
- return d.isSet ? d : document.resolveDecoration(d)
+ if (annotations) {
+ props.annotations = annotations.map(a => {
+ return a.isSet ? a : document.resolveAnnotation(a)
})
}
@@ -771,21 +827,21 @@ class Value extends Record(DEFAULTS) {
mapRanges(iterator) {
let value = this
- const { document, selection, decorations } = value
+ const { document, selection, annotations } = value
let sel = selection.isSet ? iterator(selection) : selection
if (!sel) sel = selection.unset()
if (sel !== selection) sel = document.createSelection(sel)
value = value.set('selection', sel)
- let decs = decorations.map(decoration => {
- let n = decoration.isSet ? iterator(decoration) : decoration
- if (n && n !== decoration) n = document.createDecoration(n)
+ let anns = annotations.map(annotation => {
+ let n = annotation.isSet ? iterator(annotation) : annotation
+ if (n && n !== annotation) n = document.createAnnotation(n)
return n
})
- decs = decs.filter(decoration => !!decoration)
- value = value.set('decorations', decs)
+ anns = anns.filter(annotation => !!annotation)
+ value = value.set('annotations', anns)
return value
}
@@ -810,10 +866,10 @@ class Value extends Record(DEFAULTS) {
object.data = this.data.toJSON(options)
}
- if (options.preserveDecorations) {
- object.decorations = this.decorations
+ if (options.preserveAnnotations) {
+ object.annotations = this.annotations
.toArray()
- .map(d => d.toJSON(options))
+ .map(a => a.toJSON(options))
}
if (options.preserveSelection) {
diff --git a/packages/slate/src/operations/apply.js b/packages/slate/src/operations/apply.js
index d99c952ab..252746f04 100644
--- a/packages/slate/src/operations/apply.js
+++ b/packages/slate/src/operations/apply.js
@@ -24,6 +24,12 @@ function applyOperation(value, op) {
debug(type, op)
switch (type) {
+ case 'add_annotation': {
+ const { annotation } = op
+ const next = value.addAnnotation(annotation)
+ return next
+ }
+
case 'add_mark': {
const { path, mark } = op
const next = value.addMark(path, mark)
@@ -54,6 +60,12 @@ function applyOperation(value, op) {
return next
}
+ case 'remove_annotation': {
+ const { annotation } = op
+ const next = value.removeAnnotation(annotation)
+ return next
+ }
+
case 'remove_mark': {
const { path, mark } = op
const next = value.removeMark(path, mark)
@@ -72,6 +84,12 @@ function applyOperation(value, op) {
return next
}
+ case 'set_annotation': {
+ const { properties, newProperties } = op
+ const next = value.setAnnotation(properties, newProperties)
+ return next
+ }
+
case 'set_mark': {
const { path, properties, newProperties } = op
const next = value.setMark(path, properties, newProperties)
diff --git a/packages/slate/src/operations/invert.js b/packages/slate/src/operations/invert.js
index 9f7e5467e..c4bf30696 100644
--- a/packages/slate/src/operations/invert.js
+++ b/packages/slate/src/operations/invert.js
@@ -24,38 +24,26 @@ function invertOperation(op) {
debug(type, op)
switch (type) {
- case 'insert_node': {
- const inverse = op.set('type', 'remove_node')
- return inverse
- }
-
- case 'remove_node': {
- const inverse = op.set('type', 'insert_node')
- return inverse
- }
-
case 'move_node': {
const { newPath, path } = op
+ // PERF: this case can exit early.
if (PathUtils.isEqual(newPath, path)) {
return op
}
- // Get the true path that the moved node ended up at
const inversePath = PathUtils.transform(path, op).first()
// Get the true path we are trying to move back to
// We transform the right-sibling of the path
// This will end up at the operation.path most of the time
// But if the newPath is a left-sibling or left-ancestor-sibling, this will account for it
- const transformedSibling = PathUtils.transform(
+ const inverseNewPath = PathUtils.transform(
PathUtils.increment(path),
op
).first()
- const inverse = op
- .set('path', inversePath)
- .set('newPath', transformedSibling)
+ const inverse = op.set('path', inversePath).set('newPath', inverseNewPath)
return inverse
}
@@ -73,6 +61,7 @@ function invertOperation(op) {
return inverse
}
+ case 'set_annotation':
case 'set_node':
case 'set_value':
case 'set_selection':
@@ -84,23 +73,27 @@ function invertOperation(op) {
return inverse
}
+ case 'insert_node':
case 'insert_text': {
- const inverse = op.set('type', 'remove_text')
+ const inverse = op.set('type', type.replace('insert_', 'remove_'))
return inverse
}
+ case 'remove_node':
case 'remove_text': {
- const inverse = op.set('type', 'insert_text')
+ const inverse = op.set('type', type.replace('remove_', 'insert_'))
return inverse
}
+ case 'add_annotation':
case 'add_mark': {
- const inverse = op.set('type', 'remove_mark')
+ const inverse = op.set('type', type.replace('add_', 'remove_'))
return inverse
}
+ case 'remove_annotation':
case 'remove_mark': {
- const inverse = op.set('type', 'add_mark')
+ const inverse = op.set('type', type.replace('remove_', 'add_'))
return inverse
}
diff --git a/packages/slate/src/plugins/schema.js b/packages/slate/src/plugins/schema.js
index e16c4fab0..ad3338ba4 100644
--- a/packages/slate/src/plugins/schema.js
+++ b/packages/slate/src/plugins/schema.js
@@ -9,7 +9,15 @@ import Queries from './queries'
*/
function SchemaPlugin(schema) {
- const { rules, document, blocks, inlines, marks } = schema
+ const {
+ rules,
+ document,
+ blocks,
+ inlines,
+ marks,
+ annotations,
+ decorations,
+ } = schema
let schemaRules = []
if (rules) {
@@ -50,17 +58,35 @@ function SchemaPlugin(schema) {
}
}
+ if (annotations) {
+ for (const key in annotations) {
+ schemaRules.push({
+ match: [{ object: 'annotation', type: key }],
+ ...annotations[key],
+ })
+ }
+ }
+
+ if (decorations) {
+ for (const key in decorations) {
+ schemaRules.push({
+ match: [{ object: 'decoration', type: key }],
+ ...decorations[key],
+ })
+ }
+ }
+
/**
- * Check if a `mark` is void based on the schema rules.
+ * Check if a `format` is atomic based on the schema rules.
*
* @param {Editor} editor
- * @param {Mark} mark
+ * @param {Format} format
* @return {Boolean}
*/
- function isAtomic(editor, mark) {
+ function isAtomic(editor, format) {
const rule = schemaRules.find(
- r => 'isAtomic' in r && testRules(mark, r.match)
+ r => 'isAtomic' in r && testRules(format, r.match)
)
return rule && rule.isAtomic
diff --git a/packages/slate/src/utils/identity.js b/packages/slate/src/utils/identity.js
new file mode 100644
index 000000000..f80f0cd10
--- /dev/null
+++ b/packages/slate/src/utils/identity.js
@@ -0,0 +1,3 @@
+export default function identity() {
+ return true
+}
diff --git a/packages/slate/src/utils/is-object.js b/packages/slate/src/utils/is-object.js
index 2fc0ea7eb..aff4b3432 100644
--- a/packages/slate/src/utils/is-object.js
+++ b/packages/slate/src/utils/is-object.js
@@ -5,6 +5,7 @@
*/
export const TYPES = {
+ annotation: '@@__SLATE_ANNOTATION__@@',
block: '@@__SLATE_BLOCK__@@',
change: '@@__SLATE_CHANGE__@@',
decoration: '@@__SLATE_DECORATION__@@',
diff --git a/packages/slate/src/utils/path-utils.js b/packages/slate/src/utils/path-utils.js
index 2e35ddcaa..aa51213a9 100644
--- a/packages/slate/src/utils/path-utils.js
+++ b/packages/slate/src/utils/path-utils.js
@@ -176,6 +176,20 @@ function isOlder(path, target) {
return isEqual(p, t) && pl > tl
}
+/**
+ * Is an `any` object a path?
+ *
+ * @param {Mixed} any
+ * @return {Boolean}
+ */
+
+function isPath(any) {
+ return (
+ (List.isList(any) || Array.isArray(any)) &&
+ any.every(n => typeof n === 'number')
+ )
+}
+
/**
* Is a `path` a sibling of a `target` path?
*
@@ -209,26 +223,27 @@ function isYounger(path, target) {
}
/**
- * Lift a `path` to refer to its parent.
+ * Lift a `path` to refer to its `n`th ancestor.
*
* @param {List} path
* @return {List}
*/
-function lift(path) {
- const parent = path.slice(0, -1)
- return parent
+function lift(path, n = 1) {
+ const ancestor = path.slice(0, -1 * n)
+ return ancestor
}
/**
- * Drop a `path`, returning the path from the first child.
+ * Drop a `path`, returning a relative path from a depth of `n`.
*
* @param {List} path
+ * @param {Number} n
* @return {List}
*/
-function drop(path) {
- const relative = path.slice(1)
+function drop(path, n = 1) {
+ const relative = path.slice(n)
return relative
}
@@ -400,6 +415,7 @@ export default {
isBefore,
isEqual,
isOlder,
+ isPath,
isSibling,
isYounger,
lift,
diff --git a/packages/slate/test/commands/at-current-range/toggle-mark/add-collapsed-selection-beginning.js b/packages/slate/test/commands/at-current-range/toggle-mark/add-collapsed-selection-start.js
similarity index 100%
rename from packages/slate/test/commands/at-current-range/toggle-mark/add-collapsed-selection-beginning.js
rename to packages/slate/test/commands/at-current-range/toggle-mark/add-collapsed-selection-start.js
diff --git a/packages/slate/test/helpers/h.js b/packages/slate/test/helpers/h.js
index e7eee36a4..99cb807ec 100644
--- a/packages/slate/test/helpers/h.js
+++ b/packages/slate/test/helpers/h.js
@@ -22,7 +22,7 @@ const h = createHyperscript({
u: 'underline',
fontSize: 'font-size',
},
- decorations: {
+ annotations: {
result: 'result',
highlight: 'highlight',
},
@@ -37,7 +37,7 @@ const h = createHyperscript({
isVoid: true,
},
},
- marks: {
+ annotations: {
result: {
isAtomic: true,
},
diff --git a/packages/slate/test/index.js b/packages/slate/test/index.js
index c71019e00..5ae66d641 100644
--- a/packages/slate/test/index.js
+++ b/packages/slate/test/index.js
@@ -1,6 +1,7 @@
import assert from 'assert'
import { fixtures } from 'slate-dev-test-utils'
import { Node, Editor, Value } from 'slate'
+import { List } from 'immutable'
const plugins = [
{
@@ -25,14 +26,6 @@ const plugins = [
]
describe('slate', () => {
- fixtures(__dirname, 'models/leaf', ({ module }) => {
- const { input, output } = module
- const fn = module.default
- const actual = fn(input).toJSON()
- const expected = output.toJSON()
- assert.deepEqual(actual, expected)
- })
-
fixtures(__dirname, 'models/operation', ({ module }) => {
const { input, output } = module
const fn = module.default
@@ -67,10 +60,18 @@ describe('slate', () => {
actual = actual.toJSON()
}
+ if (List.isList(actual)) {
+ actual = actual.toJSON()
+ }
+
if (Node.isNode(expected)) {
expected = expected.toJSON()
}
+ if (List.isList(expected)) {
+ expected = expected.toJSON()
+ }
+
assert.deepEqual(actual, expected)
})
diff --git a/packages/slate/test/models/leaf/split-leaves/after-end.js b/packages/slate/test/models/leaf/split-leaves/after-end.js
deleted file mode 100644
index ea68062c6..000000000
--- a/packages/slate/test/models/leaf/split-leaves/after-end.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/** @jsx h */
-
-import { List } from 'immutable'
-import { Leaf } from 'slate'
-
-export const input = List([
- Leaf.create({
- text: 'Cat',
- }),
- Leaf.create({
- text: 'is',
- }),
- Leaf.create({
- text: 'Cute',
- }),
-])
-
-export default function(leaves) {
- return List(Leaf.splitLeaves(leaves, 'Cat is Cute'.length))
-}
-
-export const output = List([
- List([
- Leaf.create({
- text: 'Cat',
- }),
- Leaf.create({
- text: 'is',
- }),
- Leaf.create({
- text: 'Cute',
- }),
- ]),
- List([]),
-])
diff --git a/packages/slate/test/models/leaf/split-leaves/before-start.js b/packages/slate/test/models/leaf/split-leaves/before-start.js
deleted file mode 100644
index 59cec9c43..000000000
--- a/packages/slate/test/models/leaf/split-leaves/before-start.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/** @jsx h */
-
-import { List } from 'immutable'
-import { Leaf } from 'slate'
-
-export const input = List([
- Leaf.create({
- text: 'Cat',
- }),
- Leaf.create({
- text: 'is',
- }),
- Leaf.create({
- text: 'Cute',
- }),
-])
-
-export default function(leaves) {
- return List(Leaf.splitLeaves(leaves, 'CatisCute'.length + 1))
-}
-
-export const output = List([
- List([
- Leaf.create({
- text: 'Cat',
- }),
- Leaf.create({
- text: 'is',
- }),
- Leaf.create({
- text: 'Cute',
- }),
- ]),
- List([]),
-])
diff --git a/packages/slate/test/models/leaf/split-leaves/end.js b/packages/slate/test/models/leaf/split-leaves/end.js
deleted file mode 100644
index 64d03abac..000000000
--- a/packages/slate/test/models/leaf/split-leaves/end.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/** @jsx h */
-
-import { List } from 'immutable'
-import { Leaf } from 'slate'
-
-export const input = List([
- Leaf.create({
- text: 'Cat',
- }),
- Leaf.create({
- text: 'is',
- }),
- Leaf.create({
- text: 'Cute',
- }),
-])
-
-export default function(leaves) {
- return List(Leaf.splitLeaves(leaves, 'CatisCute'.length))
-}
-
-export const output = List([
- List([
- Leaf.create({
- text: 'Cat',
- }),
- Leaf.create({
- text: 'is',
- }),
- Leaf.create({
- text: 'Cute',
- }),
- ]),
- List([
- Leaf.create({
- text: '',
- }),
- ]),
-])
diff --git a/packages/slate/test/models/leaf/split-leaves/middle.js b/packages/slate/test/models/leaf/split-leaves/middle.js
deleted file mode 100644
index 9143f91f2..000000000
--- a/packages/slate/test/models/leaf/split-leaves/middle.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/** @jsx h */
-
-import { List } from 'immutable'
-import { Leaf } from 'slate'
-
-export const input = List([
- Leaf.create({
- text: 'Cat',
- }),
- Leaf.create({
- text: 'is',
- }),
- Leaf.create({
- text: 'Cute',
- }),
-])
-
-export default function(leaves) {
- return List(Leaf.splitLeaves(leaves, 4))
-}
-
-export const output = List([
- List([
- Leaf.create({
- text: 'Cat',
- }),
- Leaf.create({
- text: 'i',
- }),
- ]),
- List([
- Leaf.create({
- text: 's',
- }),
- Leaf.create({
- text: 'Cute',
- }),
- ]),
-])
diff --git a/packages/slate/test/models/leaf/split-leaves/start.js b/packages/slate/test/models/leaf/split-leaves/start.js
deleted file mode 100644
index 71392f073..000000000
--- a/packages/slate/test/models/leaf/split-leaves/start.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/** @jsx h */
-
-import { List } from 'immutable'
-import { Leaf } from 'slate'
-
-export const input = List([
- Leaf.create({
- text: 'Cat',
- }),
- Leaf.create({
- text: 'is',
- }),
- Leaf.create({
- text: 'Cute',
- }),
-])
-
-export default function(leaves) {
- return List(Leaf.splitLeaves(leaves, 0))
-}
-
-export const output = List([
- List([Leaf.create()]),
- List([
- Leaf.create({
- text: 'Cat',
- }),
- Leaf.create({
- text: 'is',
- }),
- Leaf.create({
- text: 'Cute',
- }),
- ]),
-])
diff --git a/packages/slate/test/models/node/get-ancestors/from-block.js b/packages/slate/test/models/node/get-ancestors/from-block.js
new file mode 100644
index 000000000..78897b845
--- /dev/null
+++ b/packages/slate/test/models/node/get-ancestors/from-block.js
@@ -0,0 +1,26 @@
+/** @jsx h */
+
+import h from '../../../helpers/h'
+import { PathUtils } from 'slate'
+
+export const input = (
+
+
+ one
+
+ two
+
+ three
+
+
+)
+
+export default function({ document, selection }) {
+ const parentPath = PathUtils.lift(selection.start.path)
+ return document
+ .getAncestors(parentPath)
+ .toArray()
+ .map(n => `${n.object}:${n.data.get('k')}`)
+}
+
+export const output = [`document:a`]
diff --git a/packages/slate/test/models/node/get-ancestors/from-document.js b/packages/slate/test/models/node/get-ancestors/from-document.js
new file mode 100644
index 000000000..9f6032d86
--- /dev/null
+++ b/packages/slate/test/models/node/get-ancestors/from-document.js
@@ -0,0 +1,24 @@
+/** @jsx h */
+
+import h from '../../../helpers/h'
+
+export const input = (
+
+
+ one
+
+ two
+
+ three
+
+
+)
+
+export default function({ document, selection }) {
+ return document
+ .getAncestors([])
+ .toArray()
+ .map(n => `${n.object}:${n.data.get('k')}`)
+}
+
+export const output = []
diff --git a/packages/slate/test/models/node/get-ancestors/from-inline.js b/packages/slate/test/models/node/get-ancestors/from-inline.js
new file mode 100644
index 000000000..a93223f39
--- /dev/null
+++ b/packages/slate/test/models/node/get-ancestors/from-inline.js
@@ -0,0 +1,30 @@
+/** @jsx h */
+
+import h from '../../../helpers/h'
+import { PathUtils } from 'slate'
+
+export const input = (
+
+
+ one
+
+
+
+ two
+
+
+
+ three
+
+
+)
+
+export default function({ document, selection }) {
+ const parentPath = PathUtils.lift(selection.start.path)
+ return document
+ .getAncestors(parentPath)
+ .toArray()
+ .map(n => `${n.object}:${n.data.get('k')}`)
+}
+
+export const output = [`document:a`, `block:c`]
diff --git a/packages/slate/test/models/node/get-ancestors/from-text-blocks-nested.js b/packages/slate/test/models/node/get-ancestors/from-text-blocks-nested.js
new file mode 100644
index 000000000..6acab7c39
--- /dev/null
+++ b/packages/slate/test/models/node/get-ancestors/from-text-blocks-nested.js
@@ -0,0 +1,26 @@
+/** @jsx h */
+
+import h from '../../../helpers/h'
+
+export const input = (
+
+
+ one
+
+
+ two
+
+
+ three
+
+
+)
+
+export default function({ document, selection }) {
+ return document
+ .getAncestors(selection.start.path)
+ .toArray()
+ .map(n => `${n.object}:${n.data.get('k')}`)
+}
+
+export const output = [`document:a`, `block:c`, `block:d`]
diff --git a/packages/slate/test/models/node/get-ancestors/from-text-inline.js b/packages/slate/test/models/node/get-ancestors/from-text-inline.js
new file mode 100644
index 000000000..79ad3a585
--- /dev/null
+++ b/packages/slate/test/models/node/get-ancestors/from-text-inline.js
@@ -0,0 +1,28 @@
+/** @jsx h */
+
+import h from '../../../helpers/h'
+
+export const input = (
+
+
+ one
+
+
+
+ two
+
+
+
+ three
+
+
+)
+
+export default function({ document, selection }) {
+ return document
+ .getAncestors(selection.start.path)
+ .toArray()
+ .map(n => `${n.object}:${n.data.get('k')}`)
+}
+
+export const output = [`document:a`, `block:c`, `inline:d`]
diff --git a/packages/slate/test/models/node/get-ancestors/from-text.js b/packages/slate/test/models/node/get-ancestors/from-text.js
new file mode 100644
index 000000000..ed450b453
--- /dev/null
+++ b/packages/slate/test/models/node/get-ancestors/from-text.js
@@ -0,0 +1,24 @@
+/** @jsx h */
+
+import h from '../../../helpers/h'
+
+export const input = (
+
+
+ one
+
+ two
+
+ three
+
+
+)
+
+export default function({ document, selection }) {
+ return document
+ .getAncestors(selection.start.path)
+ .toArray()
+ .map(n => `${n.object}:${n.data.get('k')}`)
+}
+
+export const output = [`document:a`, `block:c`]
diff --git a/packages/slate/test/models/node/get-nodes-at-range/multiple-blocks.js b/packages/slate/test/models/node/get-descendants-at-range/multiple-blocks.js
similarity index 95%
rename from packages/slate/test/models/node/get-nodes-at-range/multiple-blocks.js
rename to packages/slate/test/models/node/get-descendants-at-range/multiple-blocks.js
index 39289d0d3..30d4c55a5 100644
--- a/packages/slate/test/models/node/get-nodes-at-range/multiple-blocks.js
+++ b/packages/slate/test/models/node/get-descendants-at-range/multiple-blocks.js
@@ -30,7 +30,7 @@ export const input = (
export default function({ document, selection }) {
return document
- .getNodesAtRange(selection)
+ .getDescendantsAtRange(selection)
.map(n => n.key)
.toArray()
}
diff --git a/packages/slate/test/models/node/get-nodes-at-range/nested-blocks-cursor-in-first-leaf-of-first-parent.js b/packages/slate/test/models/node/get-descendants-at-range/nested-blocks-cursor-in-first-leaf-of-first-parent.js
similarity index 93%
rename from packages/slate/test/models/node/get-nodes-at-range/nested-blocks-cursor-in-first-leaf-of-first-parent.js
rename to packages/slate/test/models/node/get-descendants-at-range/nested-blocks-cursor-in-first-leaf-of-first-parent.js
index 3daf0a861..1f42cf0bd 100644
--- a/packages/slate/test/models/node/get-nodes-at-range/nested-blocks-cursor-in-first-leaf-of-first-parent.js
+++ b/packages/slate/test/models/node/get-descendants-at-range/nested-blocks-cursor-in-first-leaf-of-first-parent.js
@@ -23,7 +23,7 @@ export const input = (
export default function({ document, selection }) {
return document
- .getNodesAtRange(selection)
+ .getDescendantsAtRange(selection)
.map(n => n.key)
.toArray()
}
diff --git a/packages/slate/test/models/node/get-nodes-at-range/nested-blocks-cursor-in-first-leaf-of-second-parent.js b/packages/slate/test/models/node/get-descendants-at-range/nested-blocks-cursor-in-first-leaf-of-second-parent.js
similarity index 95%
rename from packages/slate/test/models/node/get-nodes-at-range/nested-blocks-cursor-in-first-leaf-of-second-parent.js
rename to packages/slate/test/models/node/get-descendants-at-range/nested-blocks-cursor-in-first-leaf-of-second-parent.js
index 2d9dc6255..54aed46f7 100644
--- a/packages/slate/test/models/node/get-nodes-at-range/nested-blocks-cursor-in-first-leaf-of-second-parent.js
+++ b/packages/slate/test/models/node/get-descendants-at-range/nested-blocks-cursor-in-first-leaf-of-second-parent.js
@@ -29,7 +29,7 @@ export const input = (
export default function({ document, selection }) {
return document
- .getNodesAtRange(selection)
+ .getDescendantsAtRange(selection)
.map(n => n.key)
.toArray()
}
diff --git a/packages/slate/test/models/node/get-nodes-at-range/nested-blocks-cursor-in-second-leaf-of-first-parent.js b/packages/slate/test/models/node/get-descendants-at-range/nested-blocks-cursor-in-second-leaf-of-first-parent.js
similarity index 94%
rename from packages/slate/test/models/node/get-nodes-at-range/nested-blocks-cursor-in-second-leaf-of-first-parent.js
rename to packages/slate/test/models/node/get-descendants-at-range/nested-blocks-cursor-in-second-leaf-of-first-parent.js
index a8315eb63..2f0e04bd2 100644
--- a/packages/slate/test/models/node/get-nodes-at-range/nested-blocks-cursor-in-second-leaf-of-first-parent.js
+++ b/packages/slate/test/models/node/get-descendants-at-range/nested-blocks-cursor-in-second-leaf-of-first-parent.js
@@ -27,7 +27,7 @@ export const input = (
export default function({ document, selection }) {
return document
- .getNodesAtRange(selection)
+ .getDescendantsAtRange(selection)
.map(n => n.key)
.toArray()
}
diff --git a/packages/slate/test/models/node/get-nodes-at-range/nested-blocks-selection-overlapping-multiple-blocks.js b/packages/slate/test/models/node/get-descendants-at-range/nested-blocks-selection-overlapping-multiple-blocks.js
similarity index 96%
rename from packages/slate/test/models/node/get-nodes-at-range/nested-blocks-selection-overlapping-multiple-blocks.js
rename to packages/slate/test/models/node/get-descendants-at-range/nested-blocks-selection-overlapping-multiple-blocks.js
index ada57f8a7..dbca13d2e 100644
--- a/packages/slate/test/models/node/get-nodes-at-range/nested-blocks-selection-overlapping-multiple-blocks.js
+++ b/packages/slate/test/models/node/get-descendants-at-range/nested-blocks-selection-overlapping-multiple-blocks.js
@@ -38,7 +38,7 @@ export const input = (
export default function({ document, selection }) {
return document
- .getNodesAtRange(selection)
+ .getDescendantsAtRange(selection)
.map(n => n.key)
.toArray()
}
diff --git a/packages/slate/test/models/node/get-nodes-at-range/nested-blocks-selection-overlapping-texts-in-second-parent.js b/packages/slate/test/models/node/get-descendants-at-range/nested-blocks-selection-overlapping-texts-in-second-parent.js
similarity index 96%
rename from packages/slate/test/models/node/get-nodes-at-range/nested-blocks-selection-overlapping-texts-in-second-parent.js
rename to packages/slate/test/models/node/get-descendants-at-range/nested-blocks-selection-overlapping-texts-in-second-parent.js
index c89b2eafc..54adf553e 100644
--- a/packages/slate/test/models/node/get-nodes-at-range/nested-blocks-selection-overlapping-texts-in-second-parent.js
+++ b/packages/slate/test/models/node/get-descendants-at-range/nested-blocks-selection-overlapping-texts-in-second-parent.js
@@ -36,7 +36,7 @@ export const input = (
export default function({ document, selection }) {
return document
- .getNodesAtRange(selection)
+ .getDescendantsAtRange(selection)
.map(n => n.key)
.toArray()
}
diff --git a/packages/slate/test/models/node/get-nodes-at-range/nested-blocks-selection-spanning-first-text.js b/packages/slate/test/models/node/get-descendants-at-range/nested-blocks-selection-spanning-first-text.js
similarity index 93%
rename from packages/slate/test/models/node/get-nodes-at-range/nested-blocks-selection-spanning-first-text.js
rename to packages/slate/test/models/node/get-descendants-at-range/nested-blocks-selection-spanning-first-text.js
index bf300c59f..15e6bc6f9 100644
--- a/packages/slate/test/models/node/get-nodes-at-range/nested-blocks-selection-spanning-first-text.js
+++ b/packages/slate/test/models/node/get-descendants-at-range/nested-blocks-selection-spanning-first-text.js
@@ -23,7 +23,7 @@ export const input = (
export default function({ document, selection }) {
return document
- .getNodesAtRange(selection)
+ .getDescendantsAtRange(selection)
.map(n => n.key)
.toArray()
}
diff --git a/packages/slate/test/models/node/get-nodes-at-range/single-block-cursor-beginning-of-text.js b/packages/slate/test/models/node/get-descendants-at-range/single-block-cursor-beginning-of-text.js
similarity index 92%
rename from packages/slate/test/models/node/get-nodes-at-range/single-block-cursor-beginning-of-text.js
rename to packages/slate/test/models/node/get-descendants-at-range/single-block-cursor-beginning-of-text.js
index 8c2cf67c7..34c286060 100644
--- a/packages/slate/test/models/node/get-nodes-at-range/single-block-cursor-beginning-of-text.js
+++ b/packages/slate/test/models/node/get-descendants-at-range/single-block-cursor-beginning-of-text.js
@@ -20,7 +20,7 @@ export const input = (
export default function({ document, selection }) {
return document
- .getNodesAtRange(selection)
+ .getDescendantsAtRange(selection)
.map(n => n.key)
.toArray()
}
diff --git a/packages/slate/test/models/node/get-nodes-at-range/single-block-cursor-end-of-text.js b/packages/slate/test/models/node/get-descendants-at-range/single-block-cursor-end-of-text.js
similarity index 93%
rename from packages/slate/test/models/node/get-nodes-at-range/single-block-cursor-end-of-text.js
rename to packages/slate/test/models/node/get-descendants-at-range/single-block-cursor-end-of-text.js
index 95cd00d9a..dd9dce448 100644
--- a/packages/slate/test/models/node/get-nodes-at-range/single-block-cursor-end-of-text.js
+++ b/packages/slate/test/models/node/get-descendants-at-range/single-block-cursor-end-of-text.js
@@ -23,7 +23,7 @@ export const input = (
export default function({ document, selection }) {
return document
- .getNodesAtRange(selection)
+ .getDescendantsAtRange(selection)
.map(n => n.key)
.toArray()
}
diff --git a/packages/slate/test/models/node/get-nodes-at-range/single-block-cursor-middle-of-text.js b/packages/slate/test/models/node/get-descendants-at-range/single-block-cursor-middle-of-text.js
similarity index 92%
rename from packages/slate/test/models/node/get-nodes-at-range/single-block-cursor-middle-of-text.js
rename to packages/slate/test/models/node/get-descendants-at-range/single-block-cursor-middle-of-text.js
index 82834efe4..061252a36 100644
--- a/packages/slate/test/models/node/get-nodes-at-range/single-block-cursor-middle-of-text.js
+++ b/packages/slate/test/models/node/get-descendants-at-range/single-block-cursor-middle-of-text.js
@@ -19,7 +19,7 @@ export const input = (
export default function({ document, selection }) {
return document
- .getNodesAtRange(selection)
+ .getDescendantsAtRange(selection)
.map(n => n.key)
.toArray()
}
diff --git a/packages/slate/test/models/node/get-nodes-at-range/single-block-with-inline.js b/packages/slate/test/models/node/get-descendants-at-range/single-block-with-inline.js
similarity index 92%
rename from packages/slate/test/models/node/get-nodes-at-range/single-block-with-inline.js
rename to packages/slate/test/models/node/get-descendants-at-range/single-block-with-inline.js
index c9cd8dd0c..a67febbef 100644
--- a/packages/slate/test/models/node/get-nodes-at-range/single-block-with-inline.js
+++ b/packages/slate/test/models/node/get-descendants-at-range/single-block-with-inline.js
@@ -19,7 +19,7 @@ export const input = (
export default function({ document, selection }) {
return document
- .getNodesAtRange(selection)
+ .getDescendantsAtRange(selection)
.map(n => n.key)
.toArray()
}
diff --git a/packages/slate/test/models/node/get-nodes-at-range/single-void-block.js b/packages/slate/test/models/node/get-descendants-at-range/single-void-block.js
similarity index 92%
rename from packages/slate/test/models/node/get-nodes-at-range/single-void-block.js
rename to packages/slate/test/models/node/get-descendants-at-range/single-void-block.js
index a3c88b465..d2abcb79e 100644
--- a/packages/slate/test/models/node/get-nodes-at-range/single-void-block.js
+++ b/packages/slate/test/models/node/get-descendants-at-range/single-void-block.js
@@ -18,7 +18,7 @@ export const input = (
export default function({ document, selection }) {
return document
- .getNodesAtRange(selection)
+ .getDescendantsAtRange(selection)
.map(n => n.key)
.toArray()
}
diff --git a/packages/slate/test/models/node/get-furthest-only-child/block-nested.js b/packages/slate/test/models/node/get-furthest-only-child/block-nested.js
deleted file mode 100644
index 95801c146..000000000
--- a/packages/slate/test/models/node/get-furthest-only-child/block-nested.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
- word
-
-
-
-)
-
-export default function(value) {
- const { document } = value
- return document.getFurthestOnlyChildAncestor('a')
-}
-
-export const output = (
-
- word
-
-)
diff --git a/packages/slate/test/models/node/get-furthest-only-child/block.js b/packages/slate/test/models/node/get-furthest-only-child/block.js
deleted file mode 100644
index 548ea6fa0..000000000
--- a/packages/slate/test/models/node/get-furthest-only-child/block.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
- word
-
-
-)
-
-export default function({ document }) {
- return document.getFurthestOnlyChildAncestor('a')
-}
-
-export const output = null
diff --git a/packages/slate/test/models/node/get-furthest-only-child/inline.js b/packages/slate/test/models/node/get-furthest-only-child/inline.js
deleted file mode 100644
index 3f9042976..000000000
--- a/packages/slate/test/models/node/get-furthest-only-child/inline.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
- one
- two
- three
-
-
-
-)
-
-export default function(value) {
- const { document } = value
- return document.getFurthestOnlyChildAncestor('a')
-}
-
-export const output = two
diff --git a/packages/slate/test/models/node/get-furthest-only-child/multiple-nodes-in-nested-block.js b/packages/slate/test/models/node/get-furthest-only-child/multiple-nodes-in-nested-block.js
deleted file mode 100644
index 9dd10a117..000000000
--- a/packages/slate/test/models/node/get-furthest-only-child/multiple-nodes-in-nested-block.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
-
- one
- two
-
-
-
-
-)
-
-export default function(value) {
- const { document } = value
- return document.getFurthestOnlyChildAncestor('a')
-}
-
-export const output = null
diff --git a/packages/slate/test/models/node/get-furthest-only-child/multiple-nodes.js b/packages/slate/test/models/node/get-furthest-only-child/multiple-nodes.js
deleted file mode 100644
index a4c867b2e..000000000
--- a/packages/slate/test/models/node/get-furthest-only-child/multiple-nodes.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
- one
- two
-
-
-
-)
-
-export default function(value) {
- const { document } = value
- return document.getFurthestOnlyChildAncestor('a')
-}
-
-export const output = null
diff --git a/packages/slate/test/models/node/get-furthest-only-child/text-nested.js b/packages/slate/test/models/node/get-furthest-only-child/text-nested.js
deleted file mode 100644
index f9d139d8c..000000000
--- a/packages/slate/test/models/node/get-furthest-only-child/text-nested.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
-
- word
-
-
-
-
-)
-
-export default function(value) {
- const { document } = value
- return document.getFurthestOnlyChildAncestor('a')
-}
-
-export const output = (
-
- word
-
-)
diff --git a/packages/slate/test/models/node/get-furthest-only-child/text.js b/packages/slate/test/models/node/get-furthest-only-child/text.js
deleted file mode 100644
index 5255f9b9f..000000000
--- a/packages/slate/test/models/node/get-furthest-only-child/text.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
- word
-
-
-
-)
-
-export default function(value) {
- const { document } = value
- return document.getFurthestOnlyChildAncestor('a')
-}
-
-export const output = word
diff --git a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/multiple-blocks.js b/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/multiple-blocks.js
deleted file mode 100644
index 739b90f21..000000000
--- a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/multiple-blocks.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
- one
-
-
-
- two
-
-
-
-
-
-
-
- three
-
-
- four
-
-
-
-
-)
-
-export default function({ document, selection }) {
- return document.getLeafBlocksAtRangeAsArray(selection).map(n => n.key)
-}
-
-export const output = ['c', 'e', 'g']
diff --git a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/nested-blocks-cursor-in-first-leaf-of-first-parent.js b/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/nested-blocks-cursor-in-first-leaf-of-first-parent.js
deleted file mode 100644
index fa8d4fa04..000000000
--- a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/nested-blocks-cursor-in-first-leaf-of-first-parent.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
-
-
-
- one
-
-
-
-
-
- two
-
-
-
-)
-
-export default function({ document, selection }) {
- return document.getLeafBlocksAtRangeAsArray(selection).map(n => n.key)
-}
-
-export const output = ['c']
diff --git a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/nested-blocks-cursor-in-first-leaf-of-second-parent.js b/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/nested-blocks-cursor-in-first-leaf-of-second-parent.js
deleted file mode 100644
index 5a9219c44..000000000
--- a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/nested-blocks-cursor-in-first-leaf-of-second-parent.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
-
-
- one
-
-
- two
-
-
-
-
-
- three
-
-
-
-
-
-
-
-)
-
-export default function({ document, selection }) {
- return document.getLeafBlocksAtRangeAsArray(selection).map(n => n.key)
-}
-
-export const output = ['h']
diff --git a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/nested-blocks-cursor-in-second-leaf-of-first-parent.js b/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/nested-blocks-cursor-in-second-leaf-of-first-parent.js
deleted file mode 100644
index e2f60715b..000000000
--- a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/nested-blocks-cursor-in-second-leaf-of-first-parent.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
-
-
- one
-
-
-
-
- two
-
-
-
-
-
- three
-
-
-
-)
-
-export default function({ document, selection }) {
- return document.getLeafBlocksAtRangeAsArray(selection).map(n => n.key)
-}
-
-export const output = ['e']
diff --git a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/nested-blocks-selection-overlapping-multiple-blocks.js b/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/nested-blocks-selection-overlapping-multiple-blocks.js
deleted file mode 100644
index df22f0114..000000000
--- a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/nested-blocks-selection-overlapping-multiple-blocks.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
-
-
- one
-
-
-
-
-
- two
-
-
-
-
- three
-
-
-
-
- four
-
-
-
- five
-
-
-
-
-
-)
-
-export default function({ document, selection }) {
- return document.getLeafBlocksAtRangeAsArray(selection).map(n => n.key)
-}
-
-export const output = ['a', 'e', 'h', 'j']
diff --git a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/nested-blocks-selection-overlapping-texts-in-second-parent.js b/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/nested-blocks-selection-overlapping-texts-in-second-parent.js
deleted file mode 100644
index 5531b416a..000000000
--- a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/nested-blocks-selection-overlapping-texts-in-second-parent.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
-
-
- one
-
-
-
-
-
- two
-
-
-
- three
-
-
-
- four
-
-
-
-
-
- five
-
-
-
-)
-
-export default function({ document, selection }) {
- return document.getLeafBlocksAtRangeAsArray(selection).map(n => n.key)
-}
-
-export const output = ['f', 'h', 'j']
diff --git a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/nested-blocks-selection-spanning-first-text.js b/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/nested-blocks-selection-spanning-first-text.js
deleted file mode 100644
index d7e8d131a..000000000
--- a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/nested-blocks-selection-spanning-first-text.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
-
-
-
- one
-
-
-
-
-
- two
-
-
-
-)
-
-export default function({ document, selection }) {
- return document.getLeafBlocksAtRangeAsArray(selection).map(n => n.key)
-}
-
-export const output = ['c']
diff --git a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/single-block-with-inline.js b/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/single-block-with-inline.js
deleted file mode 100644
index 4700826a6..000000000
--- a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/single-block-with-inline.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
- one
-
-
- two
-
-
-
-
-
-)
-
-export default function({ document, selection }) {
- return document.getLeafBlocksAtRangeAsArray(selection).map(n => n.key)
-}
-
-export const output = ['a']
diff --git a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/single-block.js b/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/single-block.js
deleted file mode 100644
index 67eb099b2..000000000
--- a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/single-block.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
- one
-
-
-
-
- two
-
-
-
-
-)
-
-export default function({ document, selection }) {
- return document.getLeafBlocksAtRangeAsArray(selection).map(n => n.key)
-}
-
-export const output = ['c']
diff --git a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/single-void-block.js b/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/single-void-block.js
deleted file mode 100644
index 854021989..000000000
--- a/packages/slate/test/models/node/get-leaf-blocks-at-range-as-array/single-void-block.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
-
-
-
-
-
-
-
-
-)
-
-export default function({ document, selection }) {
- return document.getLeafBlocksAtRangeAsArray(selection).map(n => n.key)
-}
-
-export const output = ['a']
diff --git a/packages/slate/test/models/node/get-leaf-blocks-at-range/nested-blocks-selection-overlapping-multiple-blocks.js b/packages/slate/test/models/node/get-leaf-blocks-at-range/nested-blocks-selection-overlapping-multiple-blocks.js
index c00d3b91f..587349f13 100644
--- a/packages/slate/test/models/node/get-leaf-blocks-at-range/nested-blocks-selection-overlapping-multiple-blocks.js
+++ b/packages/slate/test/models/node/get-leaf-blocks-at-range/nested-blocks-selection-overlapping-multiple-blocks.js
@@ -1,11 +1,10 @@
/** @jsx h */
-import { List } from 'immutable'
import h from '../../../helpers/h'
export const input = (
-
+
@@ -38,7 +37,10 @@ export const input = (
)
export default function({ document, selection }) {
- return document.getLeafBlocksAtRange(selection).map(n => n.key)
+ return document
+ .getLeafBlocksAtRange(selection)
+ .map(n => n.key)
+ .toArray()
}
-export const output = List(['a', 'e', 'h', 'j'])
+export const output = ['a', 'e', 'h', 'j']
diff --git a/packages/slate/test/models/node/get-leaf-inlines-at-range-as-array/multiple-blocks-no-inline.js b/packages/slate/test/models/node/get-leaf-inlines-at-range-as-array/multiple-blocks-no-inline.js
deleted file mode 100644
index 6e1c05129..000000000
--- a/packages/slate/test/models/node/get-leaf-inlines-at-range-as-array/multiple-blocks-no-inline.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
- one
-
-
-
- two
-
-
-
-
-
-
-
- four
-
-
-
-
-)
-
-export default function({ document, selection }) {
- return document.getLeafInlinesAtRangeAsArray(selection).map(n => n.key)
-}
-
-export const output = []
diff --git a/packages/slate/test/models/node/get-leaf-inlines-at-range-as-array/multiple-blocks.js b/packages/slate/test/models/node/get-leaf-inlines-at-range-as-array/multiple-blocks.js
deleted file mode 100644
index b78d0d708..000000000
--- a/packages/slate/test/models/node/get-leaf-inlines-at-range-as-array/multiple-blocks.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
- one
-
-
-
- two
-
-
- three
-
-
-
-
-
-
-
-
- four
-
-
- five
-
-
-
- six
-
-
-
-
-)
-
-export default function({ document, selection }) {
- return document.getLeafInlinesAtRangeAsArray(selection).map(n => n.key)
-}
-
-export const output = ['e', 'k', 'm']
diff --git a/packages/slate/test/models/node/get-leaf-inlines-at-range-as-array/nested-with-text-on-every-level.js b/packages/slate/test/models/node/get-leaf-inlines-at-range-as-array/nested-with-text-on-every-level.js
deleted file mode 100644
index 4a30b32fc..000000000
--- a/packages/slate/test/models/node/get-leaf-inlines-at-range-as-array/nested-with-text-on-every-level.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
-
-
-
-
- one
-
-
-
-
-
- two
-
- three
-
-
- four
-
-
-
-
-
-)
-
-export default function({ document, selection }) {
- return document.getLeafInlinesAtRangeAsArray(selection).map(n => n.key)
-}
-
-export const output = ['d', 'g', 'f', 'b']
diff --git a/packages/slate/test/models/node/get-leaf-inlines-at-range/nested-with-text-on-every-level.js b/packages/slate/test/models/node/get-leaf-inlines-at-range/nested-with-text-on-every-level.js
index 0853016cf..7608bfab3 100644
--- a/packages/slate/test/models/node/get-leaf-inlines-at-range/nested-with-text-on-every-level.js
+++ b/packages/slate/test/models/node/get-leaf-inlines-at-range/nested-with-text-on-every-level.js
@@ -34,4 +34,4 @@ export default function({ document, selection }) {
return document.getLeafInlinesAtRange(selection).map(n => n.key)
}
-export const output = List(['d', 'g', 'f', 'b'])
+export const output = List(['d', 'g'])
diff --git a/packages/slate/test/models/node/get-marks-at-position/unmarked-text.js b/packages/slate/test/models/node/get-marks-at-point/marked-text-with-zero-offset-with-no-previous-text.js
similarity index 55%
rename from packages/slate/test/models/node/get-marks-at-position/unmarked-text.js
rename to packages/slate/test/models/node/get-marks-at-point/marked-text-with-zero-offset-with-no-previous-text.js
index 1bc1e448f..049632a4c 100644
--- a/packages/slate/test/models/node/get-marks-at-position/unmarked-text.js
+++ b/packages/slate/test/models/node/get-marks-at-point/marked-text-with-zero-offset-with-no-previous-text.js
@@ -2,22 +2,22 @@
import h from '../../../helpers/h'
import { Set } from 'immutable'
-import PathUtils from '../../../../src/utils/path-utils'
-
-const path = PathUtils.create([0, 0])
+import { Mark } from 'slate'
export const input = (
- Cat is Cute
+
+ Cat is Cute
+
)
export default function({ document, selection }) {
- return document.getMarksAtPosition(path, 1)
+ return document.getInsertMarksAtPoint(selection.start)
}
-export const output = Set.of()
+export const output = Set.of(Mark.create('bold'))
diff --git a/packages/slate/test/models/node/get-marks-at-position/marked-text-with-zero-offset-with-previous-text-not-in-the-same-block.js b/packages/slate/test/models/node/get-marks-at-point/marked-text-with-zero-offset-with-previous-text-not-in-the-same-block.js
similarity index 65%
rename from packages/slate/test/models/node/get-marks-at-position/marked-text-with-zero-offset-with-previous-text-not-in-the-same-block.js
rename to packages/slate/test/models/node/get-marks-at-point/marked-text-with-zero-offset-with-previous-text-not-in-the-same-block.js
index 3ecbc54ff..451bfcc37 100644
--- a/packages/slate/test/models/node/get-marks-at-position/marked-text-with-zero-offset-with-previous-text-not-in-the-same-block.js
+++ b/packages/slate/test/models/node/get-marks-at-point/marked-text-with-zero-offset-with-previous-text-not-in-the-same-block.js
@@ -3,9 +3,6 @@
import h from '../../../helpers/h'
import { Set } from 'immutable'
import { Mark } from 'slate'
-import PathUtils from '../../../../src/utils/path-utils'
-
-const path = PathUtils.create([1, 0])
export const input = (
@@ -14,16 +11,16 @@ export const input = (
Cat is Cute
-
- Dog is Delightful
-
+
+ Dog is Delightful
+
)
export default function({ document, selection }) {
- return document.getMarksAtPosition(path, 0)
+ return document.getInsertMarksAtPoint(selection.start)
}
export const output = Set.of(Mark.create('bold'))
diff --git a/packages/slate/test/models/node/get-marks-at-position/marked-text.js b/packages/slate/test/models/node/get-marks-at-point/marked-text.js
similarity index 69%
rename from packages/slate/test/models/node/get-marks-at-position/marked-text.js
rename to packages/slate/test/models/node/get-marks-at-point/marked-text.js
index 9fe37b291..cc7f105b0 100644
--- a/packages/slate/test/models/node/get-marks-at-position/marked-text.js
+++ b/packages/slate/test/models/node/get-marks-at-point/marked-text.js
@@ -3,15 +3,14 @@
import h from '../../../helpers/h'
import { Set } from 'immutable'
import { Mark } from 'slate'
-import PathUtils from '../../../../src/utils/path-utils'
-
-const path = PathUtils.create([0, 0])
export const input = (
- Cat
+
+ Cat{' '}
+
is
Cute
@@ -20,7 +19,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.getMarksAtPosition(path, 1)
+ return document.getInsertMarksAtPoint(selection.start)
}
export const output = Set.of(Mark.create('italic'))
diff --git a/packages/slate/test/models/node/get-marks-at-position/text-with-zero-offset.js b/packages/slate/test/models/node/get-marks-at-point/text-with-zero-offset.js
similarity index 64%
rename from packages/slate/test/models/node/get-marks-at-position/text-with-zero-offset.js
rename to packages/slate/test/models/node/get-marks-at-point/text-with-zero-offset.js
index 186704122..5e869bf4b 100644
--- a/packages/slate/test/models/node/get-marks-at-position/text-with-zero-offset.js
+++ b/packages/slate/test/models/node/get-marks-at-point/text-with-zero-offset.js
@@ -3,9 +3,6 @@
import h from '../../../helpers/h'
import { Set } from 'immutable'
import { Mark } from 'slate'
-import PathUtils from '../../../../src/utils/path-utils'
-
-const path = PathUtils.create([1, 1, 0])
export const input = (
@@ -14,19 +11,20 @@ export const input = (
Cat is Cute
-
- Dog is
-
+ Dog is
- Delightful
+
+ Delightful
+
+
)
export default function({ document, selection }) {
- return document.getMarksAtPosition(path, 0)
+ return document.getInsertMarksAtPoint(selection.start)
}
export const output = Set.of(Mark.create('bold'))
diff --git a/packages/slate/test/models/node/get-marks-at-position/marked-text-with-zero-offset-with-no-previous-text.js b/packages/slate/test/models/node/get-marks-at-point/unmarked-text.js
similarity index 64%
rename from packages/slate/test/models/node/get-marks-at-position/marked-text-with-zero-offset-with-no-previous-text.js
rename to packages/slate/test/models/node/get-marks-at-point/unmarked-text.js
index f60ce87d6..d5d850c44 100644
--- a/packages/slate/test/models/node/get-marks-at-position/marked-text-with-zero-offset-with-no-previous-text.js
+++ b/packages/slate/test/models/node/get-marks-at-point/unmarked-text.js
@@ -2,16 +2,13 @@
import h from '../../../helpers/h'
import { Set } from 'immutable'
-import PathUtils from '../../../../src/utils/path-utils'
-
-const path = PathUtils.create([0, 0])
export const input = (
- Cat is Cute
+ Cat is Cute
@@ -19,7 +16,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.getMarksAtPosition(path, 0)
+ return document.getInsertMarksAtPoint(selection.start)
}
export const output = Set.of()
diff --git a/packages/slate/test/models/node/get-root-inlines-at-range-as-array/multiple-blocks-no-inline.js b/packages/slate/test/models/node/get-root-inlines-at-range-as-array/multiple-blocks-no-inline.js
deleted file mode 100644
index da00c2f14..000000000
--- a/packages/slate/test/models/node/get-root-inlines-at-range-as-array/multiple-blocks-no-inline.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
- one
-
-
-
- two
-
-
-
-
-
-
-
- four
-
-
-
-
-)
-
-export default function({ document, selection }) {
- return document.getRootInlinesAtRangeAsArray(selection).map(n => n.key)
-}
-
-export const output = []
diff --git a/packages/slate/test/models/node/get-root-inlines-at-range-as-array/multiple-blocks.js b/packages/slate/test/models/node/get-root-inlines-at-range-as-array/multiple-blocks.js
deleted file mode 100644
index 7c8fdb1e2..000000000
--- a/packages/slate/test/models/node/get-root-inlines-at-range-as-array/multiple-blocks.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
- one
-
-
-
- two
-
-
- three
-
-
-
-
-
-
-
-
- four
-
-
- five
-
-
-
- six
-
-
-
-
-)
-
-export default function({ document, selection }) {
- return document.getRootInlinesAtRangeAsArray(selection).map(n => n.key)
-}
-
-export const output = ['e', 'j', 'j']
diff --git a/packages/slate/test/models/node/get-root-inlines-at-range-as-array/nested-with-text-on-every-level.js b/packages/slate/test/models/node/get-root-inlines-at-range-as-array/nested-with-text-on-every-level.js
deleted file mode 100644
index 2b51348f4..000000000
--- a/packages/slate/test/models/node/get-root-inlines-at-range-as-array/nested-with-text-on-every-level.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
-
-
-
-
- one
-
-
-
-
-
- two
-
- three
-
-
- four
-
-
-
-
-
-)
-
-export default function({ document, selection }) {
- return document.getRootInlinesAtRangeAsArray(selection).map(n => n.key)
-}
-
-export const output = ['b', 'b', 'b', 'b']
diff --git a/packages/slate/test/models/node/get-selection-indexes/across-blocks-from-nested-node.js b/packages/slate/test/models/node/get-selection-indexes/across-blocks-from-nested-node.js
deleted file mode 100644
index 86fd70b7a..000000000
--- a/packages/slate/test/models/node/get-selection-indexes/across-blocks-from-nested-node.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-import PathUtils from '../../../../src/utils/path-utils'
-
-export const input = (
-
-
-
- wo
- rd
-
-
-
- middle
-
-
-
- unmarked
-
-
- another
-
- unselected marked text
-
-
-
-)
-
-export default function({ document, selection }) {
- const node = document.getDescendant(PathUtils.create([1]))
- return node.getSelectionIndexes(selection, [1])
-}
-
-export const output = { start: 0, end: 2 }
diff --git a/packages/slate/test/models/node/get-selection-indexes/across-blocks.js b/packages/slate/test/models/node/get-selection-indexes/across-blocks.js
deleted file mode 100644
index 25a690991..000000000
--- a/packages/slate/test/models/node/get-selection-indexes/across-blocks.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
- wo
- rd
-
-
-
- middle
-
-
-
- unmarked
-
-
- another
-
- unselected marked text
-
-
-
-)
-
-export default function({ document, selection }) {
- return document.getSelectionIndexes(selection)
-}
-
-export const output = { start: 0, end: 4 }
diff --git a/packages/slate/test/models/node/get-selection-indexes/in-single-block-from-middle-nested-node.js b/packages/slate/test/models/node/get-selection-indexes/in-single-block-from-middle-nested-node.js
deleted file mode 100644
index 903bddb0d..000000000
--- a/packages/slate/test/models/node/get-selection-indexes/in-single-block-from-middle-nested-node.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-import PathUtils from '../../../../src/utils/path-utils'
-
-export const input = (
-
-
-
- before
- start
-
- inline text
- end
- after
-
-
-
-)
-
-export default function({ document, selection }) {
- const node = document.getDescendant(PathUtils.create([0, 2]))
- return node.getSelectionIndexes(selection, [0, 2])
-}
-
-export const output = { start: 0, end: 1 }
diff --git a/packages/slate/test/models/node/get-selection-indexes/in-single-block-from-parent-node.js b/packages/slate/test/models/node/get-selection-indexes/in-single-block-from-parent-node.js
deleted file mode 100644
index ec1ac4ad9..000000000
--- a/packages/slate/test/models/node/get-selection-indexes/in-single-block-from-parent-node.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-import PathUtils from '../../../../src/utils/path-utils'
-
-export const input = (
-
-
-
- before
- start
-
- inline text
- end
- after
-
-
-
-)
-
-export default function({ document, selection }) {
- const node = document.getDescendant(PathUtils.create([0]))
- return node.getSelectionIndexes(selection, [0])
-}
-
-export const output = { start: 0, end: 4 }
diff --git a/packages/slate/test/models/node/get-selection-indexes/in-single-block.js b/packages/slate/test/models/node/get-selection-indexes/in-single-block.js
deleted file mode 100644
index 5b65f07e8..000000000
--- a/packages/slate/test/models/node/get-selection-indexes/in-single-block.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/** @jsx h */
-
-import h from '../../../helpers/h'
-
-export const input = (
-
-
-
- before
- start
-
- inline text
- end
- after
-
-
-
-)
-
-export default function({ document, selection }) {
- return document.getSelectionIndexes(selection)
-}
-
-export const output = { start: 0, end: 1 }
diff --git a/packages/slate/test/models/node/is-node-in-range/block-above-using-key.js b/packages/slate/test/models/node/is-in-range/block-above-using-key.js
similarity index 93%
rename from packages/slate/test/models/node/is-node-in-range/block-above-using-key.js
rename to packages/slate/test/models/node/is-in-range/block-above-using-key.js
index b091f70ac..b4f3337a0 100644
--- a/packages/slate/test/models/node/is-node-in-range/block-above-using-key.js
+++ b/packages/slate/test/models/node/is-in-range/block-above-using-key.js
@@ -29,7 +29,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.isNodeInRange('a', selection)
+ return document.isInRange('a', selection)
}
export const output = false
diff --git a/packages/slate/test/models/node/is-node-in-range/block-above.js b/packages/slate/test/models/node/is-in-range/block-above.js
similarity index 93%
rename from packages/slate/test/models/node/is-node-in-range/block-above.js
rename to packages/slate/test/models/node/is-in-range/block-above.js
index 9209d16b6..850568878 100644
--- a/packages/slate/test/models/node/is-node-in-range/block-above.js
+++ b/packages/slate/test/models/node/is-in-range/block-above.js
@@ -29,7 +29,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.isNodeInRange([0], selection)
+ return document.isInRange([0], selection)
}
export const output = false
diff --git a/packages/slate/test/models/node/is-node-in-range/block-below-using-key.js b/packages/slate/test/models/node/is-in-range/block-below-using-key.js
similarity index 94%
rename from packages/slate/test/models/node/is-node-in-range/block-below-using-key.js
rename to packages/slate/test/models/node/is-in-range/block-below-using-key.js
index d8cb8decc..5f1ead620 100644
--- a/packages/slate/test/models/node/is-node-in-range/block-below-using-key.js
+++ b/packages/slate/test/models/node/is-in-range/block-below-using-key.js
@@ -32,7 +32,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.isNodeInRange('k', selection)
+ return document.isInRange('k', selection)
}
export const output = false
diff --git a/packages/slate/test/models/node/is-node-in-range/block-below.js b/packages/slate/test/models/node/is-in-range/block-below.js
similarity index 94%
rename from packages/slate/test/models/node/is-node-in-range/block-below.js
rename to packages/slate/test/models/node/is-in-range/block-below.js
index a6759d9b9..769db5c69 100644
--- a/packages/slate/test/models/node/is-node-in-range/block-below.js
+++ b/packages/slate/test/models/node/is-in-range/block-below.js
@@ -32,7 +32,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.isNodeInRange([4], selection)
+ return document.isInRange([4], selection)
}
export const output = false
diff --git a/packages/slate/test/models/node/is-node-in-range/first-block-inside-using-key.js b/packages/slate/test/models/node/is-in-range/first-block-inside-using-key.js
similarity index 93%
rename from packages/slate/test/models/node/is-node-in-range/first-block-inside-using-key.js
rename to packages/slate/test/models/node/is-in-range/first-block-inside-using-key.js
index 01f769fa1..f61a92f2f 100644
--- a/packages/slate/test/models/node/is-node-in-range/first-block-inside-using-key.js
+++ b/packages/slate/test/models/node/is-in-range/first-block-inside-using-key.js
@@ -29,7 +29,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.isNodeInRange('c', selection)
+ return document.isInRange('c', selection)
}
export const output = true
diff --git a/packages/slate/test/models/node/is-node-in-range/first-block-inside.js b/packages/slate/test/models/node/is-in-range/first-block-inside.js
similarity index 93%
rename from packages/slate/test/models/node/is-node-in-range/first-block-inside.js
rename to packages/slate/test/models/node/is-in-range/first-block-inside.js
index fa0fde294..dbd2dbe86 100644
--- a/packages/slate/test/models/node/is-node-in-range/first-block-inside.js
+++ b/packages/slate/test/models/node/is-in-range/first-block-inside.js
@@ -29,7 +29,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.isNodeInRange([1], selection)
+ return document.isInRange([1], selection)
}
export const output = true
diff --git a/packages/slate/test/models/node/is-node-in-range/first-text-inside-using-key.js b/packages/slate/test/models/node/is-in-range/first-text-inside-using-key.js
similarity index 93%
rename from packages/slate/test/models/node/is-node-in-range/first-text-inside-using-key.js
rename to packages/slate/test/models/node/is-in-range/first-text-inside-using-key.js
index 4898a0d2d..64a428a78 100644
--- a/packages/slate/test/models/node/is-node-in-range/first-text-inside-using-key.js
+++ b/packages/slate/test/models/node/is-in-range/first-text-inside-using-key.js
@@ -29,7 +29,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.isNodeInRange('d', selection)
+ return document.isInRange('d', selection)
}
export const output = true
diff --git a/packages/slate/test/models/node/is-node-in-range/first-text-inside.js b/packages/slate/test/models/node/is-in-range/first-text-inside.js
similarity index 93%
rename from packages/slate/test/models/node/is-node-in-range/first-text-inside.js
rename to packages/slate/test/models/node/is-in-range/first-text-inside.js
index bd15b9418..a7a34d9bc 100644
--- a/packages/slate/test/models/node/is-node-in-range/first-text-inside.js
+++ b/packages/slate/test/models/node/is-in-range/first-text-inside.js
@@ -29,7 +29,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.isNodeInRange([1, 0], selection)
+ return document.isInRange([1, 0], selection)
}
export const output = true
diff --git a/packages/slate/test/models/node/is-node-in-range/last-block-inside-using-key.js b/packages/slate/test/models/node/is-in-range/last-block-inside-using-key.js
similarity index 93%
rename from packages/slate/test/models/node/is-node-in-range/last-block-inside-using-key.js
rename to packages/slate/test/models/node/is-in-range/last-block-inside-using-key.js
index 8b4968820..3d1004e2e 100644
--- a/packages/slate/test/models/node/is-node-in-range/last-block-inside-using-key.js
+++ b/packages/slate/test/models/node/is-in-range/last-block-inside-using-key.js
@@ -29,7 +29,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.isNodeInRange('g', selection)
+ return document.isInRange('g', selection)
}
export const output = true
diff --git a/packages/slate/test/models/node/is-node-in-range/last-block-inside.js b/packages/slate/test/models/node/is-in-range/last-block-inside.js
similarity index 93%
rename from packages/slate/test/models/node/is-node-in-range/last-block-inside.js
rename to packages/slate/test/models/node/is-in-range/last-block-inside.js
index 6aecf2897..d087cb8b3 100644
--- a/packages/slate/test/models/node/is-node-in-range/last-block-inside.js
+++ b/packages/slate/test/models/node/is-in-range/last-block-inside.js
@@ -29,7 +29,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.isNodeInRange([3], selection)
+ return document.isInRange([3], selection)
}
export const output = true
diff --git a/packages/slate/test/models/node/is-node-in-range/last-text-inside-using-key.js b/packages/slate/test/models/node/is-in-range/last-text-inside-using-key.js
similarity index 93%
rename from packages/slate/test/models/node/is-node-in-range/last-text-inside-using-key.js
rename to packages/slate/test/models/node/is-in-range/last-text-inside-using-key.js
index 8796ac2f2..4cc16ec48 100644
--- a/packages/slate/test/models/node/is-node-in-range/last-text-inside-using-key.js
+++ b/packages/slate/test/models/node/is-in-range/last-text-inside-using-key.js
@@ -29,7 +29,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.isNodeInRange('j', selection)
+ return document.isInRange('j', selection)
}
export const output = true
diff --git a/packages/slate/test/models/node/is-node-in-range/last-text-inside.js b/packages/slate/test/models/node/is-in-range/last-text-inside.js
similarity index 93%
rename from packages/slate/test/models/node/is-node-in-range/last-text-inside.js
rename to packages/slate/test/models/node/is-in-range/last-text-inside.js
index 0096163ec..2999650e8 100644
--- a/packages/slate/test/models/node/is-node-in-range/last-text-inside.js
+++ b/packages/slate/test/models/node/is-in-range/last-text-inside.js
@@ -29,7 +29,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.isNodeInRange([3, 1], selection)
+ return document.isInRange([3, 1], selection)
}
export const output = true
diff --git a/packages/slate/test/models/node/is-node-in-range/text-above-using-key.js b/packages/slate/test/models/node/is-in-range/text-above-using-key.js
similarity index 93%
rename from packages/slate/test/models/node/is-node-in-range/text-above-using-key.js
rename to packages/slate/test/models/node/is-in-range/text-above-using-key.js
index 736e48a6d..c8fa0a374 100644
--- a/packages/slate/test/models/node/is-node-in-range/text-above-using-key.js
+++ b/packages/slate/test/models/node/is-in-range/text-above-using-key.js
@@ -29,7 +29,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.isNodeInRange('b', selection)
+ return document.isInRange('b', selection)
}
export const output = false
diff --git a/packages/slate/test/models/node/is-node-in-range/text-above.js b/packages/slate/test/models/node/is-in-range/text-above.js
similarity index 93%
rename from packages/slate/test/models/node/is-node-in-range/text-above.js
rename to packages/slate/test/models/node/is-in-range/text-above.js
index f1fc3785a..3f7bd23c0 100644
--- a/packages/slate/test/models/node/is-node-in-range/text-above.js
+++ b/packages/slate/test/models/node/is-in-range/text-above.js
@@ -29,7 +29,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.isNodeInRange([0, 0], selection)
+ return document.isInRange([0, 0], selection)
}
export const output = false
diff --git a/packages/slate/test/models/node/is-node-in-range/text-below-using-key.js b/packages/slate/test/models/node/is-in-range/text-below-using-key.js
similarity index 94%
rename from packages/slate/test/models/node/is-node-in-range/text-below-using-key.js
rename to packages/slate/test/models/node/is-in-range/text-below-using-key.js
index d56c4330f..b4dfbab9f 100644
--- a/packages/slate/test/models/node/is-node-in-range/text-below-using-key.js
+++ b/packages/slate/test/models/node/is-in-range/text-below-using-key.js
@@ -32,7 +32,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.isNodeInRange('l', selection)
+ return document.isInRange('l', selection)
}
export const output = false
diff --git a/packages/slate/test/models/node/is-node-in-range/text-below.js b/packages/slate/test/models/node/is-in-range/text-below.js
similarity index 93%
rename from packages/slate/test/models/node/is-node-in-range/text-below.js
rename to packages/slate/test/models/node/is-in-range/text-below.js
index 530dee811..a299a697d 100644
--- a/packages/slate/test/models/node/is-node-in-range/text-below.js
+++ b/packages/slate/test/models/node/is-in-range/text-below.js
@@ -32,7 +32,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.isNodeInRange([4, 0], selection)
+ return document.isInRange([4, 0], selection)
}
export const output = false
diff --git a/packages/slate/test/models/node/is-node-in-range/text-in-middle-inside-using-key.js b/packages/slate/test/models/node/is-in-range/text-in-middle-inside-using-key.js
similarity index 93%
rename from packages/slate/test/models/node/is-node-in-range/text-in-middle-inside-using-key.js
rename to packages/slate/test/models/node/is-in-range/text-in-middle-inside-using-key.js
index dea69471f..8c12975f9 100644
--- a/packages/slate/test/models/node/is-node-in-range/text-in-middle-inside-using-key.js
+++ b/packages/slate/test/models/node/is-in-range/text-in-middle-inside-using-key.js
@@ -29,7 +29,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.isNodeInRange('f', selection)
+ return document.isInRange('f', selection)
}
export const output = true
diff --git a/packages/slate/test/models/node/is-node-in-range/text-in-middle-inside.js b/packages/slate/test/models/node/is-in-range/text-in-middle-inside.js
similarity index 93%
rename from packages/slate/test/models/node/is-node-in-range/text-in-middle-inside.js
rename to packages/slate/test/models/node/is-in-range/text-in-middle-inside.js
index dfde7b784..c44f3c407 100644
--- a/packages/slate/test/models/node/is-node-in-range/text-in-middle-inside.js
+++ b/packages/slate/test/models/node/is-in-range/text-in-middle-inside.js
@@ -29,7 +29,7 @@ export const input = (
)
export default function({ document, selection }) {
- return document.isNodeInRange([2, 0], selection)
+ return document.isInRange([2, 0], selection)
}
export const output = true
diff --git a/packages/slate/test/operations/apply/insert-text/decoration-before.js b/packages/slate/test/operations/apply/insert-text/annotation-before.js
similarity index 100%
rename from packages/slate/test/operations/apply/insert-text/decoration-before.js
rename to packages/slate/test/operations/apply/insert-text/annotation-before.js
diff --git a/packages/slate/test/operations/apply/merge-node/decoration-across-blocks.js b/packages/slate/test/operations/apply/merge-node/annotation-across-blocks.js
similarity index 100%
rename from packages/slate/test/operations/apply/merge-node/decoration-across-blocks.js
rename to packages/slate/test/operations/apply/merge-node/annotation-across-blocks.js
diff --git a/packages/slate/test/operations/apply/remove-node/decoration-across-blocks.js b/packages/slate/test/operations/apply/remove-node/annotation-across-blocks.js
similarity index 100%
rename from packages/slate/test/operations/apply/remove-node/decoration-across-blocks.js
rename to packages/slate/test/operations/apply/remove-node/annotation-across-blocks.js
diff --git a/packages/slate/test/operations/apply/remove-text/decoration-after.js b/packages/slate/test/operations/apply/remove-text/annotation-after.js
similarity index 100%
rename from packages/slate/test/operations/apply/remove-text/decoration-after.js
rename to packages/slate/test/operations/apply/remove-text/annotation-after.js
diff --git a/packages/slate/test/operations/apply/remove-text/decoration-before.js b/packages/slate/test/operations/apply/remove-text/annotation-before.js
similarity index 100%
rename from packages/slate/test/operations/apply/remove-text/decoration-before.js
rename to packages/slate/test/operations/apply/remove-text/annotation-before.js
diff --git a/packages/slate/test/operations/apply/remove-text/decoration-middle.js b/packages/slate/test/operations/apply/remove-text/annotation-middle.js
similarity index 100%
rename from packages/slate/test/operations/apply/remove-text/decoration-middle.js
rename to packages/slate/test/operations/apply/remove-text/annotation-middle.js
diff --git a/yarn.lock b/yarn.lock
index 8abb99bdc..e4637a127 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -24,12 +24,12 @@
dependencies:
"@babel/types" "7.0.0-beta.36"
-"@babel/helper-module-imports@7.0.0-beta.40":
- version "7.0.0-beta.40"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.40.tgz#251cbb6404599282e8f7356a5b32c9381bef5d2d"
+"@babel/helper-module-imports@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d"
+ integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==
dependencies:
- "@babel/types" "7.0.0-beta.40"
- lodash "^4.2.0"
+ "@babel/types" "^7.0.0"
"@babel/template@7.0.0-beta.36":
version "7.0.0-beta.36"
@@ -61,59 +61,70 @@
lodash "^4.2.0"
to-fast-properties "^2.0.0"
-"@babel/types@7.0.0-beta.40":
- version "7.0.0-beta.40"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.40.tgz#25c3d7aae14126abe05fcb098c65a66b6d6b8c14"
+"@babel/types@^7.0.0":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.4.4.tgz#8db9e9a629bb7c29370009b4b779ed93fe57d5f0"
+ integrity sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==
dependencies:
esutils "^2.0.2"
- lodash "^4.2.0"
+ lodash "^4.17.11"
to-fast-properties "^2.0.0"
-"@emotion/babel-utils@^0.6.4":
- version "0.6.4"
- resolved "https://registry.yarnpkg.com/@emotion/babel-utils/-/babel-utils-0.6.4.tgz#2eac69eb31ae944fbe4a2a0e736a35db5f810866"
+"@emotion/cache@^10.0.9":
+ version "10.0.9"
+ resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.9.tgz#e0c7b7a289f7530edcfad4dcf3858bd2e5700a6f"
+ integrity sha512-f7MblpE2xoimC4fCMZ9pivmsIn7hyWRIvY75owMDi8pdOSeh+w5tH3r4hBJv/LLrwiMM7cTQURqTPcYoL5pWnw==
dependencies:
- "@emotion/hash" "^0.6.3"
- "@emotion/memoize" "^0.6.2"
- "@emotion/serialize" "^0.8.2"
- convert-source-map "^1.5.1"
- find-root "^1.1.0"
- source-map "^0.7.2"
+ "@emotion/sheet" "0.9.2"
+ "@emotion/stylis" "0.8.3"
+ "@emotion/utils" "0.11.1"
+ "@emotion/weak-memoize" "0.2.2"
-"@emotion/hash@^0.6.2", "@emotion/hash@^0.6.3":
- version "0.6.3"
- resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.6.3.tgz#0e7a5604626fc6c6d4ac4061a2f5ac80d50262a4"
-
-"@emotion/is-prop-valid@^0.6.1":
- version "0.6.2"
- resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.6.2.tgz#a76a16b174ff03f8e3a27faf6259bacd21a02adc"
- dependencies:
- "@emotion/memoize" "^0.6.2"
-
-"@emotion/memoize@^0.6.1", "@emotion/memoize@^0.6.2":
- version "0.6.2"
- resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.6.2.tgz#138e00b332d519b4e307bded6159e5ba48aba3ae"
-
-"@emotion/serialize@^0.8.2":
- version "0.8.2"
- resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.8.2.tgz#d3b2caddfc93107d63c79fc6bbc11e555e3b762e"
- dependencies:
- "@emotion/hash" "^0.6.3"
- "@emotion/memoize" "^0.6.2"
- "@emotion/unitless" "^0.6.3"
- "@emotion/utils" "^0.7.1"
-
-"@emotion/stylis@^0.6.10":
- version "0.6.10"
- resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.6.10.tgz#7d321e639ebc8ba23ace5990c20e94dcebb8f3dd"
-
-"@emotion/unitless@^0.6.2", "@emotion/unitless@^0.6.3":
- version "0.6.3"
- resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.6.3.tgz#65682e68a82701c70eefb38d7f941a2c0bfa90de"
-
-"@emotion/utils@^0.7.1":
+"@emotion/hash@0.7.1":
version "0.7.1"
- resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.7.1.tgz#e44e596d03c9f16ba3b127ad333a8a072bcb5a0a"
+ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.1.tgz#9833722341379fb7d67f06a4b00ab3c37913da53"
+ integrity sha512-OYpa/Sg+2GDX+jibUfpZVn1YqSVRpYmTLF2eyAfrFTIJSbwyIrc+YscayoykvaOME/wV4BV0Sa0yqdMrgse6mA==
+
+"@emotion/memoize@0.7.1":
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.1.tgz#e93c13942592cf5ef01aa8297444dc192beee52f"
+ integrity sha512-Qv4LTqO11jepd5Qmlp3M1YEjBumoTHcHFdgPTQ+sFlIL5myi/7xu/POwP7IRu6odBdmLXdtIs1D6TuW6kbwbbg==
+
+"@emotion/serialize@^0.11.6":
+ version "0.11.6"
+ resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.6.tgz#78be8b9ee9ff49e0196233ba6ec1c1768ba1e1fc"
+ integrity sha512-n4zVv2qGLmspF99jaEUwnMV0fnEGsyUMsC/8KZKUSUTZMYljHE+j+B6rSD8PIFtaUIhHaxCG2JawN6L+OgLN0Q==
+ dependencies:
+ "@emotion/hash" "0.7.1"
+ "@emotion/memoize" "0.7.1"
+ "@emotion/unitless" "0.7.3"
+ "@emotion/utils" "0.11.1"
+ csstype "^2.5.7"
+
+"@emotion/sheet@0.9.2":
+ version "0.9.2"
+ resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.2.tgz#74e5c6b5e489a1ba30ab246ab5eedd96916487c4"
+ integrity sha512-pVBLzIbC/QCHDKJF2E82V2H/W/B004mDFQZiyo/MSR+VC4pV5JLG0TF/zgQDFvP3fZL/5RTPGEmXlYJBMUuJ+A==
+
+"@emotion/stylis@0.8.3":
+ version "0.8.3"
+ resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.3.tgz#3ca7e9bcb31b3cb4afbaeb66156d86ee85e23246"
+ integrity sha512-M3nMfJ6ndJMYloSIbYEBq6G3eqoYD41BpDOxreE8j0cb4fzz/5qvmqU9Mb2hzsXcCnIlGlWhS03PCzVGvTAe0Q==
+
+"@emotion/unitless@0.7.3":
+ version "0.7.3"
+ resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.3.tgz#6310a047f12d21a1036fb031317219892440416f"
+ integrity sha512-4zAPlpDEh2VwXswwr/t8xGNDGg8RQiPxtxZ3qQEXyQsBV39ptTdESCjuBvGze1nLMVrxmTIKmnO/nAV8Tqjjzg==
+
+"@emotion/utils@0.11.1":
+ version "0.11.1"
+ resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.1.tgz#8529b7412a6eb4b48bdf6e720cc1b8e6e1e17628"
+ integrity sha512-8M3VN0hetwhsJ8dH8VkVy7xo5/1VoBsDOk/T4SJOeXwTO1c4uIqVNx2qyecLFnnUWD5vvUqHQ1gASSeUN6zcTg==
+
+"@emotion/weak-memoize@0.2.2":
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.2.tgz#63985d3d8b02530e0869962f4da09142ee8e200e"
+ integrity sha512-n/VQ4mbfr81aqkx/XmVicOLjviMuy02eenSdJY33SVA7S2J42EU0P1H0mOogfYedb3wXA0d/LVtBrgTSm04WEA==
"@types/node@^6.0.46":
version "6.0.83"
@@ -685,22 +696,21 @@ babel-plugin-check-es2015-constants@^6.22.0:
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-emotion@^9.2.4:
- version "9.2.4"
- resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-9.2.4.tgz#a4e54a8097f6ba06cbbc7a9063927afafe9fe73a"
+babel-plugin-emotion@^10.0.9:
+ version "10.0.9"
+ resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.0.9.tgz#04a0404d5a4084d5296357a393d344c0f8303ae4"
+ integrity sha512-IfWP12e9/wHtWHxVTzD692Nbcmrmcz2tip7acp6YUqtrP7slAyr5B+69hyZ8jd55GsyNSZwryNnmuDEVe0j+7w==
dependencies:
- "@babel/helper-module-imports" "7.0.0-beta.40"
- "@emotion/babel-utils" "^0.6.4"
- "@emotion/hash" "^0.6.2"
- "@emotion/memoize" "^0.6.1"
- "@emotion/stylis" "^0.6.10"
+ "@babel/helper-module-imports" "^7.0.0"
+ "@emotion/hash" "0.7.1"
+ "@emotion/memoize" "0.7.1"
+ "@emotion/serialize" "^0.11.6"
babel-plugin-macros "^2.0.0"
babel-plugin-syntax-jsx "^6.18.0"
convert-source-map "^1.5.0"
+ escape-string-regexp "^1.0.5"
find-root "^1.1.0"
- mkdirp "^0.5.1"
source-map "^0.5.7"
- touch "^1.0.0"
babel-plugin-external-helpers@^6.22.0:
version "6.22.0"
@@ -2094,7 +2104,7 @@ conventional-recommended-bump@^1.0.1:
meow "^3.3.0"
object-assign "^4.0.1"
-convert-source-map@^1.5.0, convert-source-map@^1.5.1:
+convert-source-map@^1.5.0:
version "1.5.1"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5"
@@ -2166,23 +2176,15 @@ create-ecdh@^4.0.0:
bn.js "^4.1.0"
elliptic "^6.0.0"
-create-emotion-styled@^9.2.3:
- version "9.2.3"
- resolved "https://registry.yarnpkg.com/create-emotion-styled/-/create-emotion-styled-9.2.3.tgz#17fb13b3ae4c165ea6e5a11356ab8b9ca1dad9c5"
+create-emotion@^10.0.9:
+ version "10.0.9"
+ resolved "https://registry.yarnpkg.com/create-emotion/-/create-emotion-10.0.9.tgz#290c2036126171c9566fa24f49c9241d54625138"
+ integrity sha512-sLKD4bIiTs8PpEqr5vlCoV5lsYE4QOBYEUWaD0R+VGRMCvBKHmYlvLJXsL99Kdc4YEFAFwipi2bbncnvv6UxRg==
dependencies:
- "@emotion/is-prop-valid" "^0.6.1"
-
-create-emotion@^9.2.4:
- version "9.2.4"
- resolved "https://registry.yarnpkg.com/create-emotion/-/create-emotion-9.2.4.tgz#0a4379f6bf0708c54fe26bfcd6b6bd3592e8cf23"
- dependencies:
- "@emotion/hash" "^0.6.2"
- "@emotion/memoize" "^0.6.1"
- "@emotion/stylis" "^0.6.10"
- "@emotion/unitless" "^0.6.2"
- csstype "^2.5.2"
- stylis "^3.5.0"
- stylis-rule-sheet "^0.0.10"
+ "@emotion/cache" "^10.0.9"
+ "@emotion/serialize" "^0.11.6"
+ "@emotion/sheet" "0.9.2"
+ "@emotion/utils" "0.11.1"
create-error-class@^3.0.0:
version "3.0.2"
@@ -2349,9 +2351,10 @@ cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
dependencies:
cssom "0.3.x"
-csstype@^2.5.2:
- version "2.5.5"
- resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.5.5.tgz#4125484a3d42189a863943f23b9e4b80fedfa106"
+csstype@^2.5.7:
+ version "2.6.4"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.4.tgz#d585a6062096e324e7187f80e04f92bd0f00e37f"
+ integrity sha512-lAJUJP3M6HxFXbqtGRc0iZrdyeN+WzOWeY0q/VnFzI+kqVrYIzC7bWlKqCW7oCIdzoPkvfp82EVvrTlQ8zsWQg==
currently-unhandled@^0.4.1:
version "0.4.1"
@@ -2726,12 +2729,13 @@ emojis@^1.0.10:
version "1.0.10"
resolved "https://registry.yarnpkg.com/emojis/-/emojis-1.0.10.tgz#2558133df0dff13313c99531647f693d7adb57da"
-emotion@^9.2.4:
- version "9.2.4"
- resolved "https://registry.yarnpkg.com/emotion/-/emotion-9.2.4.tgz#0139e7cc154b2845f4b9afaa996dd4de13bb90e3"
+emotion@^10.0.9:
+ version "10.0.9"
+ resolved "https://registry.yarnpkg.com/emotion/-/emotion-10.0.9.tgz#2c37598af13df31dcd35a1957eaa8830f368c066"
+ integrity sha512-IMFwwWlU2TDt7eh4v6dm58E8VHAYOitqRbVoazQdxIu9/0CAH4a3UrTMnZSlWQAo09MrRRlKfgQFHswnj40meQ==
dependencies:
- babel-plugin-emotion "^9.2.4"
- create-emotion "^9.2.4"
+ babel-plugin-emotion "^10.0.9"
+ create-emotion "^10.0.9"
encodeurl@~1.0.1:
version "1.0.2"
@@ -4954,6 +4958,11 @@ lodash@^4.1.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.3, l
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
+lodash@^4.17.11:
+ version "4.17.11"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
+ integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
+
loglevel@^1.4.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa"
@@ -5434,12 +5443,6 @@ nopt@^4.0.1:
abbrev "1"
osenv "^0.1.4"
-nopt@~1.0.10:
- version "1.0.10"
- resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee"
- dependencies:
- abbrev "1"
-
normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5:
version "2.4.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
@@ -6401,21 +6404,15 @@ react-deep-force-update@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-2.1.1.tgz#8ea4263cd6455a050b37445b3f08fd839d86e909"
-react-dom@^16.4.1:
- version "16.4.1"
- resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.4.1.tgz#7f8b0223b3a5fbe205116c56deb85de32685dad6"
+react-dom@^16.6.3:
+ version "16.8.6"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f"
+ integrity sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA==
dependencies:
- fbjs "^0.8.16"
loose-envify "^1.1.0"
object-assign "^4.1.1"
- prop-types "^15.6.0"
-
-react-emotion@^9.2.4:
- version "9.2.4"
- resolved "https://registry.yarnpkg.com/react-emotion/-/react-emotion-9.2.4.tgz#98e00f70ce2ca4ee13923460123e763e492c013a"
- dependencies:
- babel-plugin-emotion "^9.2.4"
- create-emotion-styled "^9.2.3"
+ prop-types "^15.6.2"
+ scheduler "^0.13.6"
react-hot-loader@^3.1.3:
version "3.1.3"
@@ -6483,14 +6480,15 @@ react-values@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/react-values/-/react-values-0.3.0.tgz#ae592c368ea50bfa6063029e31430598026f5287"
-react@^16.4.1:
- version "16.4.1"
- resolved "https://registry.yarnpkg.com/react/-/react-16.4.1.tgz#de51ba5764b5dbcd1f9079037b862bd26b82fe32"
+react@^16.6.3:
+ version "16.8.6"
+ resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe"
+ integrity sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw==
dependencies:
- fbjs "^0.8.16"
loose-envify "^1.1.0"
object-assign "^4.1.1"
- prop-types "^15.6.0"
+ prop-types "^15.6.2"
+ scheduler "^0.13.6"
read-cmd-shim@^1.0.1:
version "1.0.1"
@@ -7010,6 +7008,14 @@ scheduler@^0.11.2:
loose-envify "^1.1.0"
object-assign "^4.1.1"
+scheduler@^0.13.6:
+ version "0.13.6"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.6.tgz#466a4ec332467b31a91b9bf74e5347072e4cd889"
+ integrity sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+
schema-utils@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf"
@@ -7299,10 +7305,6 @@ source-map@^0.6.1, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
-source-map@^0.7.2:
- version "0.7.3"
- resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
-
sourcemapped-stacktrace@^1.1.6:
version "1.1.8"
resolved "https://registry.yarnpkg.com/sourcemapped-stacktrace/-/sourcemapped-stacktrace-1.1.8.tgz#6b7a3f1a6fb15f6d40e701e23ce404553480d688"
@@ -7558,14 +7560,6 @@ style-loader@^0.20.2:
loader-utils "^1.1.0"
schema-utils "^0.4.3"
-stylis-rule-sheet@^0.0.10:
- version "0.0.10"
- resolved "https://registry.yarnpkg.com/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430"
-
-stylis@^3.5.0:
- version "3.5.1"
- resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.1.tgz#fd341d59f57f9aeb412bc14c9d8a8670b438e03b"
-
supports-color@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.2.0.tgz#ff1ed1e61169d06b3cf2d588e188b18d8847e17e"
@@ -7807,12 +7801,6 @@ toposort@^1.0.0:
version "1.0.6"
resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.6.tgz#c31748e55d210effc00fdcdc7d6e68d7d7bb9cec"
-touch@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/touch/-/touch-1.0.0.tgz#449cbe2dbae5a8c8038e30d71fa0ff464947c4de"
- dependencies:
- nopt "~1.0.10"
-
tough-cookie@>=2.3.3, tough-cookie@^2.3.3, tough-cookie@~2.3.0, tough-cookie@~2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561"