mirror of
https://github.com/cudr/slate-collaborative.git
synced 2026-03-02 03:40:18 +00:00
feat: update to slate 0.5x (#10)
Update Slate-Collaboration to be compatible with Slate 0.5x versions.
This commit is contained in:
@@ -1,15 +1,15 @@
|
||||
import * as Automerge from 'automerge'
|
||||
import { toSlateOp } from './index'
|
||||
import { createDoc, cloneDoc, createBlockJSON } from '../utils'
|
||||
import { createDoc, cloneDoc, createNode } from '../utils'
|
||||
|
||||
describe('convert operations to slatejs model', () => {
|
||||
it('convert insert operations', () => {
|
||||
const doc1 = createDoc()
|
||||
const doc2 = cloneDoc(doc1)
|
||||
|
||||
const change = Automerge.change(doc1, 'change', d => {
|
||||
d.document.nodes.push(createBlockJSON('paragraph', 'hello!'))
|
||||
d.document.nodes[1].nodes[0].text = 'hello!'
|
||||
const change = Automerge.change(doc1, d => {
|
||||
d.children.push(createNode('paragraph', 'hello!'))
|
||||
d.children[1].children[0].text = 'hello!'
|
||||
})
|
||||
|
||||
const operations = Automerge.diff(doc2, change)
|
||||
@@ -20,12 +20,12 @@ describe('convert operations to slatejs model', () => {
|
||||
{
|
||||
type: 'insert_node',
|
||||
path: [1],
|
||||
node: { object: 'block', type: 'paragraph', nodes: [] }
|
||||
node: { type: 'paragraph', children: [] }
|
||||
},
|
||||
{
|
||||
type: 'insert_node',
|
||||
path: [1, 0],
|
||||
node: { object: 'text', marks: [], text: 'hello!' }
|
||||
node: { text: 'hello!' }
|
||||
}
|
||||
]
|
||||
|
||||
@@ -33,17 +33,17 @@ describe('convert operations to slatejs model', () => {
|
||||
})
|
||||
|
||||
it('convert remove operations', () => {
|
||||
const doc1 = Automerge.change(createDoc(), 'change', d => {
|
||||
d.document.nodes.push(createBlockJSON('paragraph', 'hello!'))
|
||||
d.document.nodes.push(createBlockJSON('paragraph', 'hello twice!'))
|
||||
d.document.nodes[1].nodes[0].text = 'hello!'
|
||||
const doc1 = Automerge.change(createDoc(), d => {
|
||||
d.children.push(createNode('paragraph', 'hello!'))
|
||||
d.children.push(createNode('paragraph', 'hello twice!'))
|
||||
d.children[1].children[0].text = 'hello!'
|
||||
})
|
||||
|
||||
const doc2 = cloneDoc(doc1)
|
||||
|
||||
const change = Automerge.change(doc1, 'change', d => {
|
||||
delete d.document.nodes[1]
|
||||
delete d.document.nodes[0].nodes[0]
|
||||
const change = Automerge.change(doc1, d => {
|
||||
delete d.children[1]
|
||||
delete d.children[0].children[0]
|
||||
})
|
||||
|
||||
const operations = Automerge.diff(doc2, change)
|
||||
@@ -55,14 +55,14 @@ describe('convert operations to slatejs model', () => {
|
||||
type: 'remove_node',
|
||||
path: [1],
|
||||
node: {
|
||||
object: 'text'
|
||||
text: '*'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'remove_node',
|
||||
path: [0, 0],
|
||||
node: {
|
||||
object: 'text'
|
||||
text: '*'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import * as Automerge from 'automerge'
|
||||
|
||||
const createByType = type => (type === 'map' ? {} : type === 'list' ? [] : '')
|
||||
const createByType = (type: any) =>
|
||||
type === 'map' ? {} : type === 'list' ? [] : ''
|
||||
|
||||
const opCreate = ({ obj, type }: Automerge.Diff, [map, ops]) => {
|
||||
const opCreate = ({ obj, type }: Automerge.Diff, [map, ops]: any) => {
|
||||
map[obj] = createByType(type)
|
||||
|
||||
return [map, ops]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as Automerge from 'automerge'
|
||||
import { Node } from 'slate'
|
||||
|
||||
import opInsert from './insert'
|
||||
import opRemove from './remove'
|
||||
@@ -14,11 +15,11 @@ const byAction = {
|
||||
|
||||
const rootKey = '00000000-0000-0000-0000-000000000000'
|
||||
|
||||
const toSlateOp = (ops: Automerge.Diff[], doc) => {
|
||||
const iterate = (acc, op) => {
|
||||
const toSlateOp = (ops: Automerge.Diff[], doc: Automerge.Doc<Node>) => {
|
||||
const iterate = (acc: [any, any[]], op: Automerge.Diff): any => {
|
||||
const action = byAction[op.action]
|
||||
|
||||
const result = action ? action(op, acc) : acc
|
||||
const result = action ? action(op, acc, doc) : acc
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import * as Automerge from 'automerge'
|
||||
import { toSlatePath, toJS } from '../utils/index'
|
||||
|
||||
import { toSlatePath, toJS } from '../utils'
|
||||
|
||||
import { SyncDoc } from '../model'
|
||||
|
||||
const insertTextOp = ({ index, path, value }: Automerge.Diff) => () => ({
|
||||
type: 'insert_text',
|
||||
@@ -9,32 +12,31 @@ const insertTextOp = ({ index, path, value }: Automerge.Diff) => () => ({
|
||||
marks: []
|
||||
})
|
||||
|
||||
const insertNodeOp = ({ value, obj, index, path }: Automerge.Diff) => map => {
|
||||
const ops = []
|
||||
const insertNodeOp = (
|
||||
{ value, obj, index, path }: Automerge.Diff,
|
||||
doc: any
|
||||
) => (map: any) => {
|
||||
const ops: any = []
|
||||
|
||||
const iterate = ({ nodes, ...json }, path) => {
|
||||
const node = nodes ? { ...json, nodes: [] } : json
|
||||
const iterate = ({ children, ...json }: any, path: any) => {
|
||||
const node = children ? { ...json, children: [] } : json
|
||||
|
||||
if (node.object) {
|
||||
if (node.object === 'mark') {
|
||||
ops.push({
|
||||
type: 'add_mark',
|
||||
path: path.slice(0, -1),
|
||||
mark: node
|
||||
})
|
||||
} else {
|
||||
ops.push({
|
||||
type: 'insert_node',
|
||||
path,
|
||||
node
|
||||
})
|
||||
}
|
||||
}
|
||||
ops.push({
|
||||
type: 'insert_node',
|
||||
path,
|
||||
node
|
||||
})
|
||||
|
||||
nodes && nodes.forEach((n, i) => iterate(n, [...path, i]))
|
||||
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] || (map[obj] && toJS(map[obj]))
|
||||
const source =
|
||||
map[value] || toJS(map[obj] || Automerge.getObjectById(doc, value))
|
||||
|
||||
source && iterate(source, [...toSlatePath(path), index])
|
||||
|
||||
@@ -46,11 +48,11 @@ const insertByType = {
|
||||
list: insertNodeOp
|
||||
}
|
||||
|
||||
const opInsert = (op: Automerge.Diff, [map, ops]) => {
|
||||
const opInsert = (op: Automerge.Diff, [map, ops]: any, doc: SyncDoc) => {
|
||||
try {
|
||||
const { link, obj, path, index, type, value } = op
|
||||
|
||||
if (link && map[obj]) {
|
||||
if (link && map.hasOwnProperty(obj)) {
|
||||
map[obj].splice(index, 0, map[value] || value)
|
||||
} else if ((type === 'text' || type === 'list') && !path) {
|
||||
map[obj] = map[obj]
|
||||
@@ -62,7 +64,7 @@ const opInsert = (op: Automerge.Diff, [map, ops]) => {
|
||||
} else {
|
||||
const insert = insertByType[type]
|
||||
|
||||
const operation = insert && insert(op, map)
|
||||
const operation = insert && insert(op, doc)
|
||||
|
||||
ops.push(operation)
|
||||
}
|
||||
|
||||
@@ -1,29 +1,20 @@
|
||||
import * as Automerge from 'automerge'
|
||||
import { toSlatePath, toJS } from '../utils/index'
|
||||
|
||||
import { toSlatePath, toJS } from '../utils'
|
||||
import { getTarget } from '../path'
|
||||
|
||||
const removeTextOp = ({ index, path }: Automerge.Diff) => () => ({
|
||||
type: 'remove_text',
|
||||
path: toSlatePath(path).slice(0, path.length),
|
||||
path: toSlatePath(path).slice(0, path?.length),
|
||||
offset: index,
|
||||
text: '*',
|
||||
marks: []
|
||||
})
|
||||
|
||||
const removeMarkOp = ({ path, index }: Automerge.Diff) => (map, doc) => {
|
||||
const slatePath = toSlatePath(path)
|
||||
const target = getTarget(doc, slatePath)
|
||||
|
||||
return {
|
||||
type: 'remove_mark',
|
||||
path: slatePath,
|
||||
mark: {
|
||||
type: target.marks[index].type
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const removeNodesOp = ({ index, obj, path }: Automerge.Diff) => (map, doc) => {
|
||||
const removeNodeOp = ({ index, obj, path }: Automerge.Diff) => (
|
||||
map: any,
|
||||
doc: any
|
||||
) => {
|
||||
const slatePath = toSlatePath(path)
|
||||
if (!map.hasOwnProperty(obj)) {
|
||||
const target = getTarget(doc, [...slatePath, index] as any)
|
||||
@@ -35,34 +26,20 @@ const removeNodesOp = ({ index, obj, path }: Automerge.Diff) => (map, doc) => {
|
||||
type: 'remove_node',
|
||||
path: slatePath.length ? slatePath.concat(index) : [index],
|
||||
node: {
|
||||
object: 'text'
|
||||
text: '*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const removeAnnotationOp = ({ key }: Automerge.Diff) => (map, doc) => {
|
||||
const annotation = toJS(doc.annotations[key])
|
||||
|
||||
if (annotation) {
|
||||
return {
|
||||
type: 'remove_annotation',
|
||||
annotation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const removeByType = {
|
||||
text: removeTextOp,
|
||||
nodes: removeNodesOp,
|
||||
marks: removeMarkOp,
|
||||
annotations: removeAnnotationOp
|
||||
}
|
||||
|
||||
const opRemove = (op: Automerge.Diff, [map, ops]) => {
|
||||
const opRemove = (op: Automerge.Diff, [map, ops]: any) => {
|
||||
try {
|
||||
const { index, path, obj } = op
|
||||
const { index, path, obj, type } = op
|
||||
|
||||
if (map.hasOwnProperty(obj) && op.type !== 'text') {
|
||||
if (
|
||||
map.hasOwnProperty(obj) &&
|
||||
typeof map[obj] !== 'string' &&
|
||||
type !== 'text'
|
||||
) {
|
||||
map[obj].splice(index, 1)
|
||||
|
||||
return [map, ops]
|
||||
@@ -70,7 +47,11 @@ const opRemove = (op: Automerge.Diff, [map, ops]) => {
|
||||
|
||||
if (!path) return [map, ops]
|
||||
|
||||
const fn = removeByType[path[path.length - 1]]
|
||||
const key = path[path.length - 1]
|
||||
|
||||
if (key === 'cursors') return [map, ops]
|
||||
|
||||
const fn = key === 'text' ? removeTextOp : removeNodeOp
|
||||
|
||||
return [map, [...ops, fn(op)]]
|
||||
} catch (e) {
|
||||
|
||||
@@ -1,62 +1,31 @@
|
||||
import * as Automerge from 'automerge'
|
||||
import { toSlatePath, toJS } from '../utils/index'
|
||||
|
||||
const setDataOp = ({ path, value }: Automerge.Diff) => map => ({
|
||||
type: 'set_node',
|
||||
path: toSlatePath(path),
|
||||
properties: {},
|
||||
newProperties: {
|
||||
data: map[value]
|
||||
}
|
||||
})
|
||||
import { toSlatePath, toJS } from '../utils'
|
||||
|
||||
const AnnotationSetOp = ({ key, value }: Automerge.Diff) => (map, doc) => {
|
||||
if (!doc.annotations) {
|
||||
doc.annotations = {}
|
||||
}
|
||||
|
||||
let op
|
||||
|
||||
/**
|
||||
* Looks like set_annotation option is broken, temporary disabled
|
||||
*/
|
||||
|
||||
// if (!doc.annotations[key]) {
|
||||
op = {
|
||||
type: 'add_annotation',
|
||||
annotation: map[value]
|
||||
}
|
||||
// } else {
|
||||
// op = {
|
||||
// type: 'set_annotation',
|
||||
// properties: toJS(doc.annotations[key]),
|
||||
// newProperties: map[value]
|
||||
// }
|
||||
// }
|
||||
|
||||
return op
|
||||
}
|
||||
|
||||
const setByType = {
|
||||
data: setDataOp
|
||||
}
|
||||
|
||||
const opSet = (op: Automerge.Diff, [map, ops]) => {
|
||||
const { link, value, path, obj, key } = op
|
||||
try {
|
||||
const set = setByType[key]
|
||||
|
||||
if (set && path) {
|
||||
ops.push(set(op))
|
||||
} else if (map[obj]) {
|
||||
map[obj][key] = link ? map[value] : value
|
||||
const setDataOp = (
|
||||
{ key = '', obj, path, value }: Automerge.Diff,
|
||||
doc: any
|
||||
) => (map: any) => {
|
||||
return {
|
||||
type: 'set_node',
|
||||
path: toSlatePath(path),
|
||||
properties: {
|
||||
[key]: Automerge.getObjectById(doc, obj)?.[key]
|
||||
},
|
||||
newProperties: {
|
||||
[key]: value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Annotation
|
||||
*/
|
||||
if (path && path.length === 1 && path[0] === 'annotations') {
|
||||
ops.push(AnnotationSetOp(op))
|
||||
const opSet = (op: Automerge.Diff, [map, ops]: any, doc: any) => {
|
||||
const { link, value, path, obj, key } = op
|
||||
|
||||
try {
|
||||
if (path && path[0] !== 'cursors') {
|
||||
ops.push(setDataOp(op, doc))
|
||||
} else if (map[obj]) {
|
||||
map[obj][key as any] = link ? map[value] : value
|
||||
}
|
||||
|
||||
return [map, ops]
|
||||
|
||||
Reference in New Issue
Block a user