Created
March 16, 2022 17:07
-
-
Save AdventureBeard/4393adfbb8c7645c80d480b6237e53ee to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as Y from 'yjs' | |
import {AbstractType} from 'yjs' | |
import {YXmlFragment} from "yjs/dist/src/types/YXmlFragment"; | |
import { isEqual } from 'lodash' | |
type CopyParams = { | |
fromDoc: Y.Doc, | |
toDoc: Y.Doc | |
} | |
/** | |
* | |
* Apply destructive transformation so that {to} becomes equivalent to {from}. | |
* | |
* Ignore keys in ignore | |
* | |
* @param fromDoc | |
* @param toDoc | |
*/ | |
export const copy = ({ fromDoc, toDoc }: CopyParams) => { | |
let changed = false | |
toDoc.transact(() => { | |
toDoc.share.forEach((value, key) => { | |
if (!fromDoc.share.has(key)) { | |
if (value instanceof Y.Map) { | |
value.forEach((v, k) => value.delete(k)) | |
changed = true | |
} else if (value instanceof Y.Array) { | |
value.delete(0, value.length) | |
changed = true | |
} else if (value instanceof Y.Text) { | |
value.delete(0, value.length) | |
changed = true | |
} else if (value instanceof Y.XmlFragment) { | |
value.delete(0, value.length) | |
} | |
} | |
}) | |
fromDoc.share.forEach((from, key) => { | |
if (from instanceof Y.Map) { | |
let to = toDoc.getMap(key) | |
if (deepEqual(from, to)) return | |
copyMap(from, to) | |
changed = true | |
} else if (from instanceof Y.Array) { | |
let to = toDoc.getArray(key) | |
if (deepEqual(from, to)) return | |
copyArray(from, to) | |
changed = true | |
} else if (from instanceof Y.Text) { | |
let to = toDoc.getText(key) | |
if (deepEqual(from, to)) return | |
copyText(from, to) | |
changed = true | |
} else if (from instanceof Y.XmlFragment) { | |
let to = toDoc.getXmlFragment(key) | |
if (deepEqual(from, to)) return | |
copyXmlFragment(from, to) | |
changed = true | |
} | |
}) | |
}) | |
return { doc: toDoc, changed } | |
} | |
const copyArray = (from: Y.Array<any>, to: Y.Array<any>) => { | |
to.delete(0, to.length) | |
to.insert(0, from.toArray().map( el => | |
el instanceof AbstractType ? el.clone() : el | |
)) | |
return to | |
} | |
const copyMap = (from: Y.Map<any>, to: Y.Map<any>) => { | |
to.forEach((value, key) => { | |
to.delete(key) | |
}) | |
from.forEach((value, key) => { | |
to.set(key, value instanceof AbstractType ? value.clone() : value) | |
}) | |
return to | |
} | |
const copyText = (from: Y.Text, to: Y.Text) => { | |
to.delete(0, to.length) | |
to.applyDelta(from.toDelta()) | |
return to | |
} | |
const copyXmlFragment = (from: YXmlFragment, to: YXmlFragment) => { | |
to.delete(0, to.length) | |
// @ts-ignore | |
to.insert(0, from.toArray().map(item => item instanceof AbstractType ? item.clone() : item)) | |
return to | |
} | |
const deepEqual = (a: AbstractType<any>, b: AbstractType<any>) => { | |
let objA = a.toJSON() | |
let objB = b.toJSON() | |
return isEqual(objA, objB) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment