Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/purple-tigers-leave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'slate': patch
---

Removed the last traces of immer and eliminated it as a dependency
4 changes: 0 additions & 4 deletions packages/slate/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@
"files": [
"dist/"
],
"dependencies": {
"immer": "^10.0.3",
"tiny-warning": "^1.0.3"
},
"devDependencies": {
"@babel/runtime": "^7.23.2",
"lodash": "^4.17.21",
Expand Down
52 changes: 27 additions & 25 deletions packages/slate/src/interfaces/node.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { produce } from 'immer'
import { Editor, Path, Range, Scrubber, Text } from '..'
import { Element, ElementEntry } from './element'
import { modifyChildren, modifyLeaf, removeChildren } from '../utils/modify'

/**
* The `Node` union type represents all of the different types of nodes that
Expand Down Expand Up @@ -357,35 +357,37 @@ export const Node: NodeInterface = {
},

fragment<T extends Ancestor = Editor>(root: T, range: Range): T['children'] {
const newRoot = produce({ children: root.children }, r => {
const [start, end] = Range.edges(range)
const nodeEntries = Node.nodes(r, {
reverse: true,
pass: ([, path]) => !Range.includes(range, path),
})

for (const [, path] of nodeEntries) {
if (!Range.includes(range, path)) {
const parent = Node.parent(r, path)
const index = path[path.length - 1]
parent.children.splice(index, 1)
}
const newRoot = { children: root.children }

if (Path.equals(path, end.path)) {
const leaf = Node.leaf(r, path)
leaf.text = leaf.text.slice(0, end.offset)
}
const [start, end] = Range.edges(range)
const nodeEntries = Node.nodes(newRoot, {
reverse: true,
pass: ([, path]) => !Range.includes(range, path),
})

if (Path.equals(path, start.path)) {
const leaf = Node.leaf(r, path)
leaf.text = leaf.text.slice(start.offset)
}
for (const [, path] of nodeEntries) {
if (!Range.includes(range, path)) {
const index = path[path.length - 1]

modifyChildren(newRoot, Path.parent(path), children =>
removeChildren(children, index, 1)
)
}

if (Editor.isEditor(r)) {
r.selection = null
if (Path.equals(path, end.path)) {
modifyLeaf(newRoot, path, node => {
const before = node.text.slice(0, end.offset)
return { ...node, text: before }
})
}
})

if (Path.equals(path, start.path)) {
modifyLeaf(newRoot, path, node => {
const before = node.text.slice(start.offset)
return { ...node, text: before }
})
}
}

return newRoot.children
},
Expand Down
95 changes: 8 additions & 87 deletions packages/slate/src/interfaces/transforms/general.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
Ancestor,
Descendant,
Editor,
Element,
Expand All @@ -13,6 +12,14 @@ import {
Selection,
Text,
} from '../../index'
import {
insertChildren,
modifyChildren,
modifyDescendant,
modifyLeaf,
removeChildren,
replaceChildren,
} from '../../utils/modify'

export interface GeneralTransforms {
/**
Expand All @@ -21,92 +28,6 @@ export interface GeneralTransforms {
transform: (editor: Editor, op: Operation) => void
}

const insertChildren = <T>(xs: T[], index: number, ...newValues: T[]) => [
...xs.slice(0, index),
...newValues,
...xs.slice(index),
]

const replaceChildren = <T>(
xs: T[],
index: number,
removeCount: number,
...newValues: T[]
) => [...xs.slice(0, index), ...newValues, ...xs.slice(index + removeCount)]

const removeChildren = replaceChildren

/**
* Replace a descendant with a new node, replacing all ancestors
*/
const modifyDescendant = <N extends Descendant>(
editor: Editor,
path: Path,
f: (node: N) => N
) => {
if (path.length === 0) {
throw new Error('Cannot modify the editor')
}

const node = Node.get(editor, path) as N
const slicedPath = path.slice()
let modifiedNode: Node = f(node)

while (slicedPath.length > 1) {
const index = slicedPath.pop()!
const ancestorNode = Node.get(editor, slicedPath) as Ancestor

modifiedNode = {
...ancestorNode,
children: replaceChildren(ancestorNode.children, index, 1, modifiedNode),
}
}

const index = slicedPath.pop()!
editor.children = replaceChildren(editor.children, index, 1, modifiedNode)
}

/**
* Replace the children of a node, replacing all ancestors
*/
const modifyChildren = (
editor: Editor,
path: Path,
f: (children: Descendant[]) => Descendant[]
) => {
if (path.length === 0) {
editor.children = f(editor.children)
} else {
modifyDescendant<Element>(editor, path, node => {
if (Text.isText(node)) {
throw new Error(
`Cannot get the element at path [${path}] because it refers to a leaf node: ${Scrubber.stringify(
node
)}`
)
}

return { ...node, children: f(node.children) }
})
}
}

/**
* Replace a leaf, replacing all ancestors
*/
const modifyLeaf = (editor: Editor, path: Path, f: (leaf: Text) => Text) =>
modifyDescendant(editor, path, node => {
if (!Text.isText(node)) {
throw new Error(
`Cannot get the leaf node at path [${path}] because it refers to a non-leaf node: ${Scrubber.stringify(
node
)}`
)
}

return f(node)
})

// eslint-disable-next-line no-redeclare
export const GeneralTransforms: GeneralTransforms = {
transform(editor: Editor, op: Operation): void {
Expand Down
99 changes: 99 additions & 0 deletions packages/slate/src/utils/modify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import {
Ancestor,
Descendant,
Element,
Node,
Path,
Scrubber,
Text,
} from '../interfaces'

export const insertChildren = <T>(
xs: T[],
index: number,
...newValues: T[]
) => [...xs.slice(0, index), ...newValues, ...xs.slice(index)]

export const replaceChildren = <T>(
xs: T[],
index: number,
removeCount: number,
...newValues: T[]
) => [...xs.slice(0, index), ...newValues, ...xs.slice(index + removeCount)]

export const removeChildren = replaceChildren

/**
* Replace a descendant with a new node, replacing all ancestors
*/
export const modifyDescendant = <N extends Descendant>(
root: Ancestor,
path: Path,
f: (node: N) => N
) => {
if (path.length === 0) {
throw new Error('Cannot modify the editor')
}

const node = Node.get(root, path) as N
const slicedPath = path.slice()
let modifiedNode: Node = f(node)

while (slicedPath.length > 1) {
const index = slicedPath.pop()!
const ancestorNode = Node.get(root, slicedPath) as Ancestor

modifiedNode = {
...ancestorNode,
children: replaceChildren(ancestorNode.children, index, 1, modifiedNode),
}
}

const index = slicedPath.pop()!
root.children = replaceChildren(root.children, index, 1, modifiedNode)
}

/**
* Replace the children of a node, replacing all ancestors
*/
export const modifyChildren = (
root: Ancestor,
path: Path,
f: (children: Descendant[]) => Descendant[]
) => {
if (path.length === 0) {
root.children = f(root.children)
} else {
modifyDescendant<Element>(root, path, node => {
if (Text.isText(node)) {
throw new Error(
`Cannot get the element at path [${path}] because it refers to a leaf node: ${Scrubber.stringify(
node
)}`
)
}

return { ...node, children: f(node.children) }
})
}
}

/**
* Replace a leaf, replacing all ancestors
*/
export const modifyLeaf = (
root: Ancestor,
path: Path,
f: (leaf: Text) => Text
) =>
modifyDescendant(root, path, node => {
if (!Text.isText(node)) {
throw new Error(
`Cannot get the leaf node at path [${path}] because it refers to a non-leaf node: ${Scrubber.stringify(
node
)}`
)
}

return f(node)
})
16 changes: 0 additions & 16 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8228,13 +8228,6 @@ __metadata:
languageName: node
linkType: hard

"immer@npm:^10.0.3":
version: 10.0.3
resolution: "immer@npm:10.0.3"
checksum: 0be07be2f278bd1988112613648e0cf9a64fc316d5b4817f273b519fbfed0f1714275b041911f0b8c560c199b2e3430824ce620c23262c96c9d4efc9909ff1cc
languageName: node
linkType: hard

"import-fresh@npm:^3.2.1, import-fresh@npm:^3.3.0":
version: 3.3.0
resolution: "import-fresh@npm:3.3.0"
Expand Down Expand Up @@ -13714,11 +13707,9 @@ __metadata:
resolution: "slate@workspace:packages/slate"
dependencies:
"@babel/runtime": "npm:^7.23.2"
immer: "npm:^10.0.3"
lodash: "npm:^4.17.21"
slate-hyperscript: "npm:^0.115.0"
source-map-loader: "npm:^4.0.1"
tiny-warning: "npm:^1.0.3"
languageName: unknown
linkType: soft

Expand Down Expand Up @@ -14485,13 +14476,6 @@ __metadata:
languageName: node
linkType: hard

"tiny-warning@npm:^1.0.3":
version: 1.0.3
resolution: "tiny-warning@npm:1.0.3"
checksum: da62c4acac565902f0624b123eed6dd3509bc9a8d30c06e017104bedcf5d35810da8ff72864400ad19c5c7806fc0a8323c68baf3e326af7cb7d969f846100d71
languageName: node
linkType: hard

"titleize@npm:^3.0.0":
version: 3.0.0
resolution: "titleize@npm:3.0.0"
Expand Down
Loading