mirror of
https://github.com/cudr/slate-collaborative.git
synced 2026-03-02 03:40:18 +00:00
Preserve external history option (#22)
* feat: handle node text in remove_text op * feat: add preserveExternalHistory option
This commit is contained in:
@@ -9,7 +9,9 @@ export const insertText = (
|
||||
): SyncValue => {
|
||||
const node = getTarget(doc, op.path)
|
||||
|
||||
node.text.insertAt(op.offset, ...op.text.split(''))
|
||||
const offset = Math.min(node.text.length, op.offset)
|
||||
|
||||
node.text.insertAt(offset, ...op.text.split(''))
|
||||
|
||||
return doc
|
||||
}
|
||||
@@ -20,7 +22,9 @@ export const removeText = (
|
||||
): SyncValue => {
|
||||
const node = getTarget(doc, op.path)
|
||||
|
||||
node.text.deleteAt(op.offset, op.text.length)
|
||||
const offset = Math.min(node.text.length, op.offset)
|
||||
|
||||
node.text.deleteAt(offset, op.text.length)
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
@@ -54,15 +54,13 @@ describe('convert operations to slatejs model', () => {
|
||||
{
|
||||
type: 'remove_node',
|
||||
path: [1],
|
||||
node: {
|
||||
text: '*'
|
||||
}
|
||||
node: createNode('paragraph', 'hello twice!')
|
||||
},
|
||||
{
|
||||
type: 'remove_node',
|
||||
path: [0, 0],
|
||||
node: {
|
||||
text: '*'
|
||||
children: []
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as Automerge from 'automerge'
|
||||
|
||||
const createByType = (type: any) =>
|
||||
const createByType = (type: Automerge.CollectionType) =>
|
||||
type === 'map' ? {} : type === 'list' ? [] : ''
|
||||
|
||||
const opCreate = ({ obj, type }: Automerge.Diff, [map, ops]: any) => {
|
||||
|
||||
@@ -5,6 +5,8 @@ import opRemove from './remove'
|
||||
import opSet from './set'
|
||||
import opCreate from './create'
|
||||
|
||||
import { toJS } from '../utils'
|
||||
|
||||
import { SyncDoc } from '../model'
|
||||
|
||||
const byAction = {
|
||||
@@ -32,7 +34,9 @@ const toSlateOp = (ops: Automerge.Diff[], doc: SyncDoc) => {
|
||||
[]
|
||||
])
|
||||
|
||||
return defer.flatMap(op => op(tempTree, doc)).filter(op => op)
|
||||
const tempDoc = toJS(doc)
|
||||
|
||||
return defer.flatMap(op => op(tempTree, tempDoc)).filter(op => op)
|
||||
}
|
||||
|
||||
export { toSlateOp }
|
||||
|
||||
@@ -1,33 +1,56 @@
|
||||
import * as Automerge from 'automerge'
|
||||
import { Element } from 'slate'
|
||||
|
||||
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),
|
||||
offset: index,
|
||||
text: '*',
|
||||
marks: []
|
||||
})
|
||||
const removeTextOp = (op: Automerge.Diff) => (map: any, doc: Element) => {
|
||||
const { index, path, obj } = op
|
||||
|
||||
const slatePath = toSlatePath(path).slice(0, path?.length)
|
||||
|
||||
let node
|
||||
|
||||
try {
|
||||
node = getTarget(doc, slatePath) || map[obj]
|
||||
} catch (e) {
|
||||
console.error(e, op, doc)
|
||||
}
|
||||
|
||||
if (typeof index !== 'number') return
|
||||
|
||||
const text = node?.text[index] || '*'
|
||||
|
||||
if (node) {
|
||||
node.text = node.text?.slice(0, index) + node.text?.slice(index + 1)
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'remove_text',
|
||||
path: slatePath,
|
||||
offset: index,
|
||||
text,
|
||||
marks: []
|
||||
}
|
||||
}
|
||||
|
||||
const removeNodeOp = ({ index, obj, path }: Automerge.Diff) => (
|
||||
map: any,
|
||||
doc: any
|
||||
doc: Element
|
||||
) => {
|
||||
const slatePath = toSlatePath(path)
|
||||
if (!map.hasOwnProperty(obj)) {
|
||||
const target = getTarget(doc, [...slatePath, index] as any)
|
||||
|
||||
const parent = getTarget(doc, slatePath)
|
||||
const target = parent?.children[index as number] || { children: [] }
|
||||
|
||||
if (!map.hasOwnProperty(obj)) {
|
||||
map[obj] = target
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'remove_node',
|
||||
path: slatePath.length ? slatePath.concat(index) : [index],
|
||||
node: {
|
||||
text: '*'
|
||||
}
|
||||
node: target
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Node, Path } from 'slate'
|
||||
import { Element, Node, Path } from 'slate'
|
||||
|
||||
import { SyncValue } from '../model'
|
||||
|
||||
export const isTree = (node: Node): boolean => Boolean(node?.children)
|
||||
|
||||
export const getTarget = (doc: SyncValue, path: Path) => {
|
||||
export const getTarget = (doc: SyncValue | Element, path: Path) => {
|
||||
const iterate = (current: any, idx: number) => {
|
||||
if (!(isTree(current) || current[idx])) {
|
||||
throw new TypeError(
|
||||
@@ -30,7 +30,7 @@ export const getParentPath = (
|
||||
}
|
||||
|
||||
export const getParent = (
|
||||
doc: SyncValue,
|
||||
doc: SyncValue | Element,
|
||||
path: Path,
|
||||
level = 1
|
||||
): [any, number] => {
|
||||
|
||||
Reference in New Issue
Block a user