diff --git a/packages/text-editor/src/components/Collaboration.svelte b/packages/text-editor/src/components/Collaboration.svelte
index 3e0a42bdb3..4923fc888c 100644
--- a/packages/text-editor/src/components/Collaboration.svelte
+++ b/packages/text-editor/src/components/Collaboration.svelte
@@ -1,6 +1,6 @@
diff --git a/packages/text-editor/src/components/CollaboratorEditor.svelte b/packages/text-editor/src/components/CollaboratorEditor.svelte
index 15dcaf72a1..4b75f4997e 100644
--- a/packages/text-editor/src/components/CollaboratorEditor.svelte
+++ b/packages/text-editor/src/components/CollaboratorEditor.svelte
@@ -19,7 +19,6 @@
import { DecorationSet } from 'prosemirror-view'
import { getContext, createEventDispatcher, onDestroy, onMount } from 'svelte'
import * as Y from 'yjs'
- import { HocuspocusProvider } from '@hocuspocus/provider'
import { AnyExtension, Editor, Extension, HTMLContent, getMarkRange, mergeAttributes } from '@tiptap/core'
import Collaboration, { isChangeOrigin } from '@tiptap/extension-collaboration'
import CollaborationCursor from '@tiptap/extension-collaboration-cursor'
@@ -30,15 +29,16 @@
import { Completion } from '../Completion'
import textEditorPlugin from '../plugin'
+ import { TiptapCollabProvider } from '../provider'
import { CollaborationIds, TextFormatCategory, TextNodeAction } from '../types'
import { calculateDecorations } from './diff/decorations'
+ import { defaultEditorAttributes } from './editor/editorProps'
import { completionConfig, defaultExtensions } from './extensions'
import { InlineStyleToolbar } from './extension/inlineStyleToolbar'
import { NodeUuidExtension } from './extension/nodeUuid'
import StyleButton from './StyleButton.svelte'
import TextEditorStyleToolbar from './TextEditorStyleToolbar.svelte'
- import { defaultEditorAttributes } from './editor/editorProps'
export let documentId: string
export let readonly = false
@@ -66,11 +66,11 @@
const ydoc = (getContext(CollaborationIds.Doc) as Y.Doc | undefined) ?? new Y.Doc()
- const contextProvider = getContext(CollaborationIds.Provider) as HocuspocusProvider | undefined
+ const contextProvider = getContext(CollaborationIds.Provider) as TiptapCollabProvider | undefined
const provider =
contextProvider ??
- new HocuspocusProvider({
+ new TiptapCollabProvider({
url: collaboratorURL,
name: documentId,
document: ydoc,
@@ -142,6 +142,10 @@
})
}
+ export function takeSnapshot (snapshotId: string) {
+ provider.copyContent(documentId, snapshotId)
+ }
+
let needFocus = false
let focused = false
@@ -274,7 +278,6 @@
editor.destroy()
} catch (err: any) {}
if (contextProvider === undefined) {
- provider.configuration.websocketProvider.disconnect()
provider.destroy()
}
}
diff --git a/packages/text-editor/src/provider.ts b/packages/text-editor/src/provider.ts
new file mode 100644
index 0000000000..b80a893c57
--- /dev/null
+++ b/packages/text-editor/src/provider.ts
@@ -0,0 +1,38 @@
+//
+// Copyright © 2023 Hardcore Engineering Inc.
+//
+// Licensed under the Eclipse Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License. You may
+// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+import { HocuspocusProvider, HocuspocusProviderConfiguration } from '@hocuspocus/provider'
+
+export type TiptapCollabProviderConfiguration = HocuspocusProviderConfiguration &
+Required>
+
+export class TiptapCollabProvider extends HocuspocusProvider {
+ constructor (configuration: TiptapCollabProviderConfiguration) {
+ super(configuration as HocuspocusProviderConfiguration)
+ }
+
+ copyContent (sourceId: string, targetId: string): void {
+ const payload = {
+ action: 'document.copy',
+ params: { sourceId, targetId }
+ }
+ this.sendStateless(JSON.stringify(payload))
+ }
+
+ destroy (): void {
+ this.configuration.websocketProvider.disconnect()
+ super.destroy()
+ }
+}
diff --git a/packages/text/src/node.ts b/packages/text/src/node.ts
index 9cf099b407..75fa1c47d5 100644
--- a/packages/text/src/node.ts
+++ b/packages/text/src/node.ts
@@ -38,3 +38,31 @@ export function yDocContentToNode (extensions: Extensions, content: ArrayBuffer,
return schema.node(schema.topNodeType)
}
}
+
+/**
+ * Get ProseMirror nodes from Y.Doc content
+ *
+ * @public
+ */
+export function yDocContentToNodes (extensions: Extensions, content: ArrayBuffer): Node[] {
+ const schema = getSchema(extensions)
+
+ const nodes: Node[] = []
+
+ try {
+ const ydoc = new Doc()
+ const uint8arr = new Uint8Array(content)
+ applyUpdate(ydoc, uint8arr)
+
+ for (const field of ydoc.share.keys()) {
+ try {
+ const body = yDocToProsemirrorJSON(ydoc, field)
+ nodes.push(schema.nodeFromJSON(body))
+ } catch {}
+ }
+ } catch (err: any) {
+ console.error(err)
+ }
+
+ return nodes
+}