mirror of
https://github.com/cudr/slate-collaborative.git
synced 2025-06-13 12:54:04 +00:00
fix: remove node and remove text errors
This commit is contained in:
parent
89dafd78b9
commit
eb6f39679b
@ -22,6 +22,10 @@ export const removeText = (
|
|||||||
): SyncValue => {
|
): SyncValue => {
|
||||||
const node = getTarget(doc, op.path)
|
const node = getTarget(doc, op.path)
|
||||||
|
|
||||||
|
// if we are removing text for a node that no longer exists
|
||||||
|
// treat this as a noop
|
||||||
|
if (!node) return doc
|
||||||
|
|
||||||
const offset = Math.min(node.text.length, op.offset)
|
const offset = Math.min(node.text.length, op.offset)
|
||||||
|
|
||||||
node.text.deleteAt(offset, op.text.length)
|
node.text.deleteAt(offset, op.text.length)
|
||||||
|
@ -10,12 +10,12 @@ const removeTextOp = (op: Automerge.Diff) => (map: any, doc: Element) => {
|
|||||||
|
|
||||||
const slatePath = toSlatePath(path).slice(0, path?.length)
|
const slatePath = toSlatePath(path).slice(0, path?.length)
|
||||||
|
|
||||||
let node
|
const node = getTarget(doc, slatePath) || map[obj]
|
||||||
|
|
||||||
try {
|
// if we are removing text for a node that has already been removed
|
||||||
node = getTarget(doc, slatePath) || map[obj]
|
// treat this as a noop
|
||||||
} catch (e) {
|
if (!node) {
|
||||||
console.error(e, op, doc)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof index !== 'number') return
|
if (typeof index !== 'number') return
|
||||||
@ -41,6 +41,11 @@ const removeNodeOp = ({ index, obj, path }: Automerge.Diff) => (
|
|||||||
const slatePath = toSlatePath(path)
|
const slatePath = toSlatePath(path)
|
||||||
|
|
||||||
const parent = getTarget(doc, slatePath)
|
const parent = getTarget(doc, slatePath)
|
||||||
|
|
||||||
|
// if we are removing a node that has already been removed
|
||||||
|
// treat this as a noop
|
||||||
|
if (!parent) return
|
||||||
|
|
||||||
const target = parent?.children?.[index as number] || { children: [] }
|
const target = parent?.children?.[index as number] || { children: [] }
|
||||||
|
|
||||||
if (!map.hasOwnProperty(obj)) {
|
if (!map.hasOwnProperty(obj)) {
|
||||||
|
@ -6,10 +6,8 @@ export const isTree = (node: Node): boolean => Boolean(node?.children)
|
|||||||
|
|
||||||
export const getTarget = (doc: SyncValue | Element, path: Path) => {
|
export const getTarget = (doc: SyncValue | Element, path: Path) => {
|
||||||
const iterate = (current: any, idx: number) => {
|
const iterate = (current: any, idx: number) => {
|
||||||
if (!(isTree(current) || current[idx])) {
|
if (current === null || !(isTree(current) || current[idx])) {
|
||||||
throw new TypeError(
|
return null
|
||||||
`path ${path.toString()} does not match tree ${JSON.stringify(current)}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current[idx] || current?.children[idx]
|
return current[idx] || current?.children[idx]
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
import Automerge, { Frontend } from 'automerge'
|
||||||
import { createServer } from 'http'
|
import { createServer } from 'http'
|
||||||
|
import fs from 'fs'
|
||||||
import isEqual from 'lodash/isEqual'
|
import isEqual from 'lodash/isEqual'
|
||||||
import { createEditor, Node, Transforms } from 'slate'
|
import { createEditor, Node, Transforms } from 'slate'
|
||||||
import { toJS } from '@hiveteams/collab-bridge'
|
import { SyncDoc, toJS, toSlateOp } from '@hiveteams/collab-bridge'
|
||||||
import AutomergeCollaboration from '@hiveteams/collab-backend/lib/AutomergeCollaboration'
|
import AutomergeCollaboration from '@hiveteams/collab-backend/lib/AutomergeCollaboration'
|
||||||
import withIOCollaboration from './withIOCollaboration'
|
import withIOCollaboration from './withIOCollaboration'
|
||||||
import { AutomergeOptions, SocketIOPluginOptions } from './interfaces'
|
import { AutomergeOptions, SocketIOPluginOptions } from './interfaces'
|
||||||
@ -186,6 +188,23 @@ describe('automerge editor client tests', () => {
|
|||||||
editor2.destroy()
|
editor2.destroy()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('deep nested tree error', () => {
|
||||||
|
// Ready from our test json file for the deep tree error
|
||||||
|
// This allows us to easily reproduce real production errors
|
||||||
|
// and create test cases that resolve those errors
|
||||||
|
const rawData = fs.readFileSync(
|
||||||
|
`${__dirname}/test-json/deep-tree.json`,
|
||||||
|
'utf-8'
|
||||||
|
)
|
||||||
|
const parsedData = JSON.parse(rawData)
|
||||||
|
const { current, operations } = parsedData
|
||||||
|
const currentDoc = Automerge.load<SyncDoc>(current)
|
||||||
|
|
||||||
|
// ensure no errors throw when removing a deep tree node
|
||||||
|
// that has already been removed
|
||||||
|
toSlateOp(operations, currentDoc)
|
||||||
|
})
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
collabBackend.destroy()
|
collabBackend.destroy()
|
||||||
server.close()
|
server.close()
|
||||||
|
403
packages/client/src/test-json/deep-tree.json
Normal file
403
packages/client/src/test-json/deep-tree.json
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user