cudr_slate-collaborative/packages/bridge/src/convert/remove.ts

125 lines
2.7 KiB
TypeScript
Raw Normal View History

2019-10-06 20:56:27 +00:00
import * as Automerge from 'automerge'
import { Element } from 'slate'
import { toSlatePath, toJS } from '../utils'
2019-10-05 21:24:52 +00:00
import { getTarget } from '../path'
import { setDataOp } from './set'
2019-10-05 08:44:49 +00:00
const removeTextOp = (op: Automerge.Diff) => (map: any, doc: Element) => {
try {
const { index, path, obj } = op
const slatePath = toSlatePath(path).slice(0, path?.length)
let node = map[obj]
try {
node = getTarget(doc, slatePath)
} catch (e) {
console.error(e, slatePath, op, map, toJS(doc))
}
if (typeof index !== 'number') return
const text = node?.text?.[index] || '*'
if (node) {
node.text = node?.text
? node.text.slice(0, index) + node.text.slice(index + 1)
: ''
}
return {
type: 'remove_text',
path: slatePath,
offset: index,
text,
marks: []
}
} catch (e) {
console.error(e, op, map, toJS(doc))
}
}
2019-10-05 08:44:49 +00:00
const removeNodeOp = (op: Automerge.Diff) => (map: any, doc: Element) => {
try {
const { index, obj, path } = op
2019-10-06 10:30:35 +00:00
const slatePath = toSlatePath(path)
const parent = getTarget(doc, slatePath)
const target = parent?.children?.[index as number] ||
parent?.[index as number] || { children: [] }
if (!target) {
throw new TypeError('Target is not found!')
}
if (!map.hasOwnProperty(obj)) {
map[obj] = target
}
2019-10-06 10:30:35 +00:00
if (!Number.isInteger(index)) {
throw new TypeError('Index is not a number')
}
if (parent?.children?.[index as number]) {
parent.children.splice(index, 1)
} else if (parent?.[index as number]) {
parent.splice(index, 1)
}
return {
type: 'remove_node',
path: slatePath.length ? slatePath.concat(index) : [index],
node: target
}
} catch (e) {
console.error(e, op, map, toJS(doc))
2019-10-05 08:44:49 +00:00
}
}
const opRemove = (
op: Automerge.Diff,
[map, ops]: any,
doc: any,
tmpDoc: Element
) => {
2019-10-05 08:44:49 +00:00
try {
const { index, path, obj, type } = op
2019-10-05 08:44:49 +00:00
if (type === 'map' && path) {
// remove a key from map, mapping to slate set a key's value to undefined.
ops.push(setDataOp(op, doc)(map, tmpDoc))
return [map, ops]
}
if (
map.hasOwnProperty(obj) &&
typeof map[obj] !== 'string' &&
type !== 'text' &&
map?.obj?.length
) {
2019-10-05 08:44:49 +00:00
map[obj].splice(index, 1)
return [map, ops]
}
if (!path) return [map, ops]
const key = path[path.length - 1]
if (key === 'cursors' || op.key === 'cursors') return [map, ops]
const fn = key === 'text' ? removeTextOp : removeNodeOp
2019-10-05 08:44:49 +00:00
return [map, [...ops, fn(op)(map, tmpDoc)]]
2019-10-05 08:44:49 +00:00
} catch (e) {
console.error(e, op, toJS(map))
return [map, ops]
}
}
export default opRemove