mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-07-31 20:40:19 +02:00
Customize get dirty paths (#5069)
* Move getDirtyPaths to the Editor object to allow for customization * Add changeset for getDirtyPaths customization Co-authored-by: Tom Krenzke <tom@daybreakhealth.com>
This commit is contained in:
5
.changeset/spotty-mirrors-matter.md
Normal file
5
.changeset/spotty-mirrors-matter.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'slate': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Expose getDirtyPaths method on Editor object to allow for customization
|
@@ -71,7 +71,7 @@ export const createEditor = (): Editor => {
|
|||||||
dirtyPathKeys = oldDirtyPathKeys
|
dirtyPathKeys = oldDirtyPathKeys
|
||||||
}
|
}
|
||||||
|
|
||||||
const newDirtyPaths = getDirtyPaths(op)
|
const newDirtyPaths = editor.getDirtyPaths(op)
|
||||||
for (const path of newDirtyPaths) {
|
for (const path of newDirtyPaths) {
|
||||||
add(path)
|
add(path)
|
||||||
}
|
}
|
||||||
@@ -296,83 +296,83 @@ export const createEditor = (): Editor => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the "dirty" paths generated from an operation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
getDirtyPaths: (op: Operation): Path[] => {
|
||||||
|
switch (op.type) {
|
||||||
|
case 'insert_text':
|
||||||
|
case 'remove_text':
|
||||||
|
case 'set_node': {
|
||||||
|
const { path } = op
|
||||||
|
return Path.levels(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'insert_node': {
|
||||||
|
const { node, path } = op
|
||||||
|
const levels = Path.levels(path)
|
||||||
|
const descendants = Text.isText(node)
|
||||||
|
? []
|
||||||
|
: Array.from(Node.nodes(node), ([, p]) => path.concat(p))
|
||||||
|
|
||||||
|
return [...levels, ...descendants]
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'merge_node': {
|
||||||
|
const { path } = op
|
||||||
|
const ancestors = Path.ancestors(path)
|
||||||
|
const previousPath = Path.previous(path)
|
||||||
|
return [...ancestors, previousPath]
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'move_node': {
|
||||||
|
const { path, newPath } = op
|
||||||
|
|
||||||
|
if (Path.equals(path, newPath)) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldAncestors: Path[] = []
|
||||||
|
const newAncestors: Path[] = []
|
||||||
|
|
||||||
|
for (const ancestor of Path.ancestors(path)) {
|
||||||
|
const p = Path.transform(ancestor, op)
|
||||||
|
oldAncestors.push(p!)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const ancestor of Path.ancestors(newPath)) {
|
||||||
|
const p = Path.transform(ancestor, op)
|
||||||
|
newAncestors.push(p!)
|
||||||
|
}
|
||||||
|
|
||||||
|
const newParent = newAncestors[newAncestors.length - 1]
|
||||||
|
const newIndex = newPath[newPath.length - 1]
|
||||||
|
const resultPath = newParent.concat(newIndex)
|
||||||
|
|
||||||
|
return [...oldAncestors, ...newAncestors, resultPath]
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'remove_node': {
|
||||||
|
const { path } = op
|
||||||
|
const ancestors = Path.ancestors(path)
|
||||||
|
return [...ancestors]
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'split_node': {
|
||||||
|
const { path } = op
|
||||||
|
const levels = Path.levels(path)
|
||||||
|
const nextPath = Path.next(path)
|
||||||
|
return [...levels, nextPath]
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return editor
|
return editor
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the "dirty" paths generated from an operation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const getDirtyPaths = (op: Operation): Path[] => {
|
|
||||||
switch (op.type) {
|
|
||||||
case 'insert_text':
|
|
||||||
case 'remove_text':
|
|
||||||
case 'set_node': {
|
|
||||||
const { path } = op
|
|
||||||
return Path.levels(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'insert_node': {
|
|
||||||
const { node, path } = op
|
|
||||||
const levels = Path.levels(path)
|
|
||||||
const descendants = Text.isText(node)
|
|
||||||
? []
|
|
||||||
: Array.from(Node.nodes(node), ([, p]) => path.concat(p))
|
|
||||||
|
|
||||||
return [...levels, ...descendants]
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'merge_node': {
|
|
||||||
const { path } = op
|
|
||||||
const ancestors = Path.ancestors(path)
|
|
||||||
const previousPath = Path.previous(path)
|
|
||||||
return [...ancestors, previousPath]
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'move_node': {
|
|
||||||
const { path, newPath } = op
|
|
||||||
|
|
||||||
if (Path.equals(path, newPath)) {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
const oldAncestors: Path[] = []
|
|
||||||
const newAncestors: Path[] = []
|
|
||||||
|
|
||||||
for (const ancestor of Path.ancestors(path)) {
|
|
||||||
const p = Path.transform(ancestor, op)
|
|
||||||
oldAncestors.push(p!)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const ancestor of Path.ancestors(newPath)) {
|
|
||||||
const p = Path.transform(ancestor, op)
|
|
||||||
newAncestors.push(p!)
|
|
||||||
}
|
|
||||||
|
|
||||||
const newParent = newAncestors[newAncestors.length - 1]
|
|
||||||
const newIndex = newPath[newPath.length - 1]
|
|
||||||
const resultPath = newParent.concat(newIndex)
|
|
||||||
|
|
||||||
return [...oldAncestors, ...newAncestors, resultPath]
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'remove_node': {
|
|
||||||
const { path } = op
|
|
||||||
const ancestors = Path.ancestors(path)
|
|
||||||
return [...ancestors]
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'split_node': {
|
|
||||||
const { path } = op
|
|
||||||
const levels = Path.levels(path)
|
|
||||||
const nextPath = Path.next(path)
|
|
||||||
return [...levels, nextPath]
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@@ -77,6 +77,7 @@ export interface BaseEditor {
|
|||||||
insertNode: (node: Node) => void
|
insertNode: (node: Node) => void
|
||||||
insertText: (text: string) => void
|
insertText: (text: string) => void
|
||||||
removeMark: (key: string) => void
|
removeMark: (key: string) => void
|
||||||
|
getDirtyPaths: (op: Operation) => Path[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Editor = ExtendedType<'Editor', BaseEditor>
|
export type Editor = ExtendedType<'Editor', BaseEditor>
|
||||||
@@ -626,6 +627,7 @@ export const Editor: EditorInterface = {
|
|||||||
typeof value.normalizeNode === 'function' &&
|
typeof value.normalizeNode === 'function' &&
|
||||||
typeof value.onChange === 'function' &&
|
typeof value.onChange === 'function' &&
|
||||||
typeof value.removeMark === 'function' &&
|
typeof value.removeMark === 'function' &&
|
||||||
|
typeof value.getDirtyPaths === 'function' &&
|
||||||
(value.marks === null || isPlainObject(value.marks)) &&
|
(value.marks === null || isPlainObject(value.marks)) &&
|
||||||
(value.selection === null || Range.isRange(value.selection)) &&
|
(value.selection === null || Range.isRange(value.selection)) &&
|
||||||
Node.isNodeList(value.children) &&
|
Node.isNodeList(value.children) &&
|
||||||
|
@@ -20,6 +20,7 @@ export const input = {
|
|||||||
normalizeNode() {},
|
normalizeNode() {},
|
||||||
onChange() {},
|
onChange() {},
|
||||||
removeMark() {},
|
removeMark() {},
|
||||||
|
getDirtyPaths() {},
|
||||||
}
|
}
|
||||||
export const test = value => {
|
export const test = value => {
|
||||||
return Element.isElement(value)
|
return Element.isElement(value)
|
||||||
|
@@ -21,6 +21,7 @@ export const input = [
|
|||||||
normalizeNode() {},
|
normalizeNode() {},
|
||||||
onChange() {},
|
onChange() {},
|
||||||
removeMark() {},
|
removeMark() {},
|
||||||
|
getDirtyPaths() {},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
export const test = value => {
|
export const test = value => {
|
||||||
|
Reference in New Issue
Block a user