|
|
|
import * as Automerge from 'automerge'
|
|
|
|
|
|
|
|
import { toSlatePath, toJS } from '../utils'
|
|
|
|
|
|
|
|
import { SyncDoc } from '../model'
|
|
|
|
|
|
|
|
const insertTextOp = ({ index, path, value }: Automerge.Diff) => () => ({
|
|
|
|
type: 'insert_text',
|
|
|
|
path: toSlatePath(path),
|
|
|
|
offset: index,
|
|
|
|
text: value,
|
|
|
|
marks: []
|
|
|
|
})
|
|
|
|
|
|
|
|
const insertNodeOp = (
|
|
|
|
{ value, obj, index, path }: Automerge.Diff,
|
|
|
|
doc: any
|
|
|
|
) => (map: any) => {
|
|
|
|
const ops: any = []
|
|
|
|
|
|
|
|
const iterate = ({ children, ...json }: any, path: any) => {
|
|
|
|
const node = children ? { ...json, children: [] } : json
|
|
|
|
|
|
|
|
ops.push({
|
|
|
|
type: 'insert_node',
|
|
|
|
path,
|
|
|
|
node
|
|
|
|
})
|
|
|
|
|
|
|
|
children &&
|
|
|
|
children.forEach((n: any, i: any) => {
|
|
|
|
const node = map[n] || Automerge.getObjectById(doc, n)
|
|
|
|
|
|
|
|
iterate((node && toJS(node)) || n, [...path, i])
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
const source =
|
|
|
|
map[value] || toJS(map[obj] || Automerge.getObjectById(doc, value))
|
|
|
|
|
|
|
|
source && iterate(source, [...toSlatePath(path), index])
|
|
|
|
|
|
|
|
return ops
|
|
|
|
}
|
|
|
|
|
|
|
|
const insertByType = {
|
|
|
|
text: insertTextOp,
|
|
|
|
list: insertNodeOp
|
|
|
|
}
|
|
|
|
|
|
|
|
const opInsert = (op: Automerge.Diff, [map, ops]: any, doc: SyncDoc) => {
|
|
|
|
try {
|
|
|
|
const { link, obj, path, index, type, value } = op
|
|
|
|
|
|
|
|
if (link && map.hasOwnProperty(obj)) {
|
|
|
|
map[obj].splice(index, 0, map[value] || value)
|
|
|
|
} else if ((type === 'text' || type === 'list') && !path) {
|
|
|
|
map[obj] = map[obj]
|
|
|
|
? map[obj]
|
|
|
|
.slice(0, index)
|
|
|
|
.concat(value)
|
|
|
|
.concat(map[obj].slice(index))
|
|
|
|
: value
|
|
|
|
} else {
|
|
|
|
const insert = insertByType[type]
|
|
|
|
|
|
|
|
const operation = insert && insert(op, doc)
|
|
|
|
|
|
|
|
ops.push(operation)
|
|
|
|
}
|
|
|
|
|
|
|
|
return [map, ops]
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e, op, toJS(map))
|
|
|
|
|
|
|
|
return [map, ops]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default opInsert
|