@kerebron/extension-yjs 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Permission is hereby granted, free of charge, to any
2
+ person obtaining a copy of this software and associated
3
+ documentation files (the "Software"), to deal in the
4
+ Software without restriction, including without
5
+ limitation the rights to use, copy, modify, merge,
6
+ publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software
8
+ is furnished to do so, subject to the following
9
+ conditions:
10
+
11
+ The above copyright notice and this permission notice
12
+ shall be included in all copies or substantial portions
13
+ of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
16
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
18
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
19
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
22
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # Kerebron - Prosemirror based online editor kit
2
+
3
+ ## Watch a Demo
4
+
5
+ <a href="https://youtube.com/shorts/OdJjhAPj-wA?feature=share" target="_blank">
6
+ <img src="https://github.com/user-attachments/assets/b63ec84a-0ed2-4f98-920c-76f6d3215168" alt="Alt Text" width="200">
7
+ </a>
8
+
9
+ ## Playground Demo
10
+
11
+ [playground](https://demo.kerebron.com) - be nice.
12
+
13
+ ## Overview
14
+
15
+ Using vanilla Prosemirror modules is often impossible because of
16
+ incompatibilities.
17
+
18
+ Kerebron forks several prosemirror projects into one monorepo in order to keep
19
+ them in sync.
20
+
21
+ Project is inspired on https://tiptap.dev/, but instead of building wrapper
22
+ around a wrapper it borrows concept of extension and command manager.
23
+
24
+ It has simplified tooling (deno), fewer dependencies and resulting in lower
25
+ number of output npm modules.
26
+
27
+ **Work in progress**
28
+
29
+ ## Development
30
+
31
+ To start example server:
32
+
33
+ ```
34
+ deno task -f server-deno-hono start
35
+ ```
36
+
37
+ ## Examples
38
+
39
+ TODO
40
+
41
+ ## Build
42
+
43
+ ### Build static examples
44
+
45
+ ```shell
46
+ deno task -r build
47
+ ```
48
+
49
+ ### NPM packages are generated using DNT
50
+
51
+ - https://deno.com/blog/publish-esm-cjs-module-dnt - the easiest way to publish
52
+ a hybrid npm module for ESM and CommonJS
53
+ - https://github.com/denoland/dnt
54
+ - https://gaubee.com/article/Publishing-Your-Deno-Project-as-a-Monorepo-using-dnt/
55
+
56
+ To generate npm packages
57
+
58
+ ```shell
59
+ deno -A ./build/build_npm.ts
60
+ ```
61
+
62
+ ## Run through docker
63
+
64
+ ```
65
+ docker build . -t editor-test
66
+ docker run -it -p 8000:8000 -v $PWD:/usr/src/app editor-test
67
+ ```
@@ -8,7 +8,7 @@ export type AnyExtensionOrReq = AnyExtension | {
8
8
  };
9
9
  export type Content = JSONContent | JSONContent[] | null;
10
10
  export interface EditorOptions {
11
- element: Element;
11
+ element: HTMLElement;
12
12
  content: Content;
13
13
  parseOptions: ParseOptions;
14
14
  extensions: AnyExtensionOrReq[];
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/editor/src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,IAAI,eAAe,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;AACnD,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG;IAC7C,QAAQ,EAAE,KAAK,CAAC,iBAAiB,GAAG,MAAM,CAAC,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,WAAW,GAAG,WAAW,EAAE,GAAG,IAAI,CAAC;AAEzD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,EAAE,CAAC;IACJ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;IACzB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,CAAC,CAAC;IACtC,OAAO,EAAE,CAAC,CAAC;IACX,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,CAAC,CAAC;CACtC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/editor/src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,IAAI,eAAe,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;AACnD,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG;IAC7C,QAAQ,EAAE,KAAK,CAAC,iBAAiB,GAAG,MAAM,CAAC,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,WAAW,GAAG,WAAW,EAAE,GAAG,IAAI,CAAC;AAEzD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,WAAW,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,EAAE,CAAC;IACJ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;IACzB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,CAAC,CAAC;IACtC,OAAO,EAAE,CAAC,CAAC;IACX,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,CAAC,CAAC;CACtC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ExtensionYjs.d.ts","sourceRoot":"","sources":["../../../src/extension-yjs/src/ExtensionYjs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,KAAK,UAAU,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAErE,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,kCAAkC,CAAC;AAM1C,qBAAa,YAAa,SAAQ,SAAS;IACzC,IAAI,SAAS;IACb,GAAG,EAAE,GAAG,CAAC;IAGA,mBAAmB,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAOhD,oBAAoB,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAOjD,qBAAqB,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;CAY7E"}
1
+ {"version":3,"file":"ExtensionYjs.d.ts","sourceRoot":"","sources":["../../../src/extension-yjs/src/ExtensionYjs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EAAE,KAAK,UAAU,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAErE,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,kCAAkC,CAAC;AAM1C,qBAAa,YAAa,SAAQ,SAAS;IACzC,IAAI,SAAS;IACb,GAAG,EAAE,GAAG,CAAC;IAGA,mBAAmB,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAOhD,oBAAoB,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAOjD,qBAAqB,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;CAY7E"}
@@ -2,7 +2,7 @@ import { Extension } from '../../editor/src/mod.js';
2
2
  import { ySyncPlugin } from './ySyncPlugin.js';
3
3
  import { yCursorPlugin } from './yCursorPlugin.js';
4
4
  import { redo, undo, yUndoPlugin } from './yUndoPlugin.js';
5
- import { initProseMirrorDoc } from './lib.js';
5
+ import { initProseMirrorDoc } from './convertUtils.js';
6
6
  export class ExtensionYjs extends Extension {
7
7
  constructor() {
8
8
  super(...arguments);
@@ -0,0 +1,59 @@
1
+ import * as Y from 'yjs';
2
+ import { Fragment, Node, type Schema } from 'prosemirror-model';
3
+ import { BindingMetadata } from './ySyncPlugin.js';
4
+ export declare const createEmptyMeta: () => BindingMetadata;
5
+ /**
6
+ * Utility function for converting an Y.Fragment to a ProseMirror fragment.
7
+ */
8
+ export declare const yXmlFragmentToProseMirrorFragment: (yXmlFragment: Y.XmlFragment, schema: Schema) => Fragment;
9
+ /**
10
+ * Utility function for converting an Y.Fragment to a ProseMirror node.
11
+ */
12
+ export declare const yXmlFragmentToProseMirrorRootNode: (yXmlFragment: Y.XmlFragment, schema: Schema) => Node;
13
+ /**
14
+ * The initial ProseMirror content should be supplied by Yjs. This function transforms a Y.Fragment
15
+ * to a ProseMirror Doc node and creates a mapping that is used by the sync plugin.
16
+ *
17
+ * @todo deprecate mapping property
18
+ */
19
+ export declare const initProseMirrorDoc: (yXmlFragment: Y.XmlFragment, schema: Schema) => {
20
+ doc: Node;
21
+ meta: BindingMetadata;
22
+ mapping: Map<Y.AbstractType<any>, Node | Node[]>;
23
+ };
24
+ /**
25
+ * Utility method to convert a Prosemirror Doc Node into a Y.Doc.
26
+ *
27
+ * This can be used when importing existing content to Y.Doc for the first time,
28
+ * note that this should not be used to rehydrate a Y.Doc from a database once
29
+ * collaboration has begun as all history will be lost
30
+ */
31
+ export declare function prosemirrorToYDoc(doc: Node, xmlFragment?: string): Y.Doc;
32
+ /**
33
+ * Utility method to update an empty Y.XmlFragment with content from a Prosemirror Doc Node.
34
+ *
35
+ * This can be used when importing existing content to Y.Doc for the first time,
36
+ * note that this should not be used to rehydrate a Y.Doc from a database once
37
+ * collaboration has begun as all history will be lost
38
+ *
39
+ * Note: The Y.XmlFragment does not need to be part of a Y.Doc document at the time that this
40
+ * method is called, but it must be added before any other operations are performed on it.
41
+ */
42
+ export declare function prosemirrorToYXmlFragment(doc: Node, xmlFragment: Y.XmlFragment): Y.XmlFragment;
43
+ /**
44
+ * Utility method to convert Prosemirror compatible JSON into a Y.Doc.
45
+ *
46
+ * This can be used when importing existing content to Y.Doc for the first time,
47
+ * note that this should not be used to rehydrate a Y.Doc from a database once
48
+ * collaboration has begun as all history will be lost
49
+ */
50
+ export declare function prosemirrorJSONToYDoc(schema: Schema, state: any, xmlFragment?: string): Y.Doc;
51
+ /**
52
+ * Utility method to convert Prosemirror compatible JSON to a Y.XmlFragment
53
+ *
54
+ * This can be used when importing existing content to Y.Doc for the first time,
55
+ * note that this should not be used to rehydrate a Y.Doc from a database once
56
+ * collaboration has begun as all history will be lost
57
+ */
58
+ export declare function prosemirrorJSONToYXmlFragment(schema: Schema, state: any, xmlFragment: Y.XmlFragment): Y.XmlFragment;
59
+ //# sourceMappingURL=convertUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convertUtils.d.ts","sourceRoot":"","sources":["../../../src/extension-yjs/src/convertUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EACL,eAAe,EAIhB,MAAM,kBAAkB,CAAC;AAE1B,eAAO,MAAM,eAAe,QAAO,eAGjC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,iCAAiC,GAC5C,cAAc,CAAC,CAAC,WAAW,EAC3B,QAAQ,MAAM,aAUf,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iCAAiC,GAC5C,cAAc,CAAC,CAAC,WAAW,EAC3B,QAAQ,MAAM,SAKb,CAAC;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAC7B,cAAc,CAAC,CAAC,WAAW,EAC3B,QAAQ,MAAM;;;;CAef,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,IAAI,EACT,WAAW,GAAE,MAAsB,GAClC,CAAC,CAAC,GAAG,CAUP;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,IAAI,EACT,WAAW,EAAE,CAAC,CAAC,WAAW,GACzB,CAAC,CAAC,WAAW,CAOf;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,GAAG,EACV,WAAW,GAAE,MAAsB,GAClC,CAAC,CAAC,GAAG,CAGP;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,GAAG,EACV,WAAW,EAAE,CAAC,CAAC,WAAW,GACzB,CAAC,CAAC,WAAW,CAGf"}
@@ -0,0 +1,88 @@
1
+ import * as Y from 'yjs';
2
+ import { Fragment, Node } from 'prosemirror-model';
3
+ import { createNodeFromYElement, updateYFragment, } from './ySyncPlugin.js';
4
+ export const createEmptyMeta = () => ({
5
+ mapping: new Map(),
6
+ isOMark: new Map(),
7
+ });
8
+ /**
9
+ * Utility function for converting an Y.Fragment to a ProseMirror fragment.
10
+ */
11
+ export const yXmlFragmentToProseMirrorFragment = (yXmlFragment, schema) => {
12
+ const fragmentContent = yXmlFragment.toArray().map((t) => createNodeFromYElement(
13
+ /** @type {Y.XmlElement} */ (t), schema, createEmptyMeta())).filter((n) => n !== null);
14
+ return Fragment.fromArray(fragmentContent);
15
+ };
16
+ /**
17
+ * Utility function for converting an Y.Fragment to a ProseMirror node.
18
+ */
19
+ export const yXmlFragmentToProseMirrorRootNode = (yXmlFragment, schema) => schema.topNodeType.create(null, yXmlFragmentToProseMirrorFragment(yXmlFragment, schema));
20
+ /**
21
+ * The initial ProseMirror content should be supplied by Yjs. This function transforms a Y.Fragment
22
+ * to a ProseMirror Doc node and creates a mapping that is used by the sync plugin.
23
+ *
24
+ * @todo deprecate mapping property
25
+ */
26
+ export const initProseMirrorDoc = (yXmlFragment, schema) => {
27
+ const meta = createEmptyMeta();
28
+ const fragmentContent = yXmlFragment.toArray().map((t) => createNodeFromYElement(t, schema, meta)).filter((n) => n !== null);
29
+ const doc = schema.topNodeType.create(null, Fragment.fromArray(fragmentContent));
30
+ return { doc, meta, mapping: meta.mapping };
31
+ };
32
+ /**
33
+ * Utility method to convert a Prosemirror Doc Node into a Y.Doc.
34
+ *
35
+ * This can be used when importing existing content to Y.Doc for the first time,
36
+ * note that this should not be used to rehydrate a Y.Doc from a database once
37
+ * collaboration has begun as all history will be lost
38
+ */
39
+ export function prosemirrorToYDoc(doc, xmlFragment = 'prosemirror') {
40
+ const ydoc = new Y.Doc();
41
+ const type =
42
+ /** @type {Y.XmlFragment} */ (ydoc.get(xmlFragment, Y.XmlFragment));
43
+ if (!type.doc) {
44
+ return ydoc;
45
+ }
46
+ prosemirrorToYXmlFragment(doc, type);
47
+ return type.doc;
48
+ }
49
+ /**
50
+ * Utility method to update an empty Y.XmlFragment with content from a Prosemirror Doc Node.
51
+ *
52
+ * This can be used when importing existing content to Y.Doc for the first time,
53
+ * note that this should not be used to rehydrate a Y.Doc from a database once
54
+ * collaboration has begun as all history will be lost
55
+ *
56
+ * Note: The Y.XmlFragment does not need to be part of a Y.Doc document at the time that this
57
+ * method is called, but it must be added before any other operations are performed on it.
58
+ */
59
+ export function prosemirrorToYXmlFragment(doc, xmlFragment) {
60
+ const type = xmlFragment || new Y.XmlFragment();
61
+ const ydoc = type.doc
62
+ ? type.doc
63
+ : { transact: (transaction) => transaction(undefined) };
64
+ updateYFragment(ydoc, type, doc, { mapping: new Map(), isOMark: new Map() });
65
+ return type;
66
+ }
67
+ /**
68
+ * Utility method to convert Prosemirror compatible JSON into a Y.Doc.
69
+ *
70
+ * This can be used when importing existing content to Y.Doc for the first time,
71
+ * note that this should not be used to rehydrate a Y.Doc from a database once
72
+ * collaboration has begun as all history will be lost
73
+ */
74
+ export function prosemirrorJSONToYDoc(schema, state, xmlFragment = 'prosemirror') {
75
+ const doc = Node.fromJSON(schema, state);
76
+ return prosemirrorToYDoc(doc, xmlFragment);
77
+ }
78
+ /**
79
+ * Utility method to convert Prosemirror compatible JSON to a Y.XmlFragment
80
+ *
81
+ * This can be used when importing existing content to Y.Doc for the first time,
82
+ * note that this should not be used to rehydrate a Y.Doc from a database once
83
+ * collaboration has begun as all history will be lost
84
+ */
85
+ export function prosemirrorJSONToYXmlFragment(schema, state, xmlFragment) {
86
+ const doc = Node.fromJSON(schema, state);
87
+ return prosemirrorToYXmlFragment(doc, xmlFragment);
88
+ }
@@ -0,0 +1,15 @@
1
+ import * as Y from 'yjs';
2
+ import { type EditorView } from 'prosemirror-view';
3
+ import { type Node } from 'prosemirror-model';
4
+ /**
5
+ * Either a node if type is YXmlElement or an Array of text nodes if YXmlText
6
+ */
7
+ type ProsemirrorMapping = Map<Y.AbstractType<any>, Node>;
8
+ export declare const setMeta: (view: EditorView, key: any, value: any) => void;
9
+ /**
10
+ * Transforms a Prosemirror based absolute position to a Yjs Cursor (relative position in the Yjs model).
11
+ */
12
+ export declare const absolutePositionToRelativePosition: (pos: number, type: Y.XmlFragment, mapping: ProsemirrorMapping) => any;
13
+ export declare const relativePositionToAbsolutePosition: (yDoc: Y.Doc, documentType: Y.XmlFragment, relPos: any, mapping: ProsemirrorMapping) => null | number;
14
+ export {};
15
+ //# sourceMappingURL=lib.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../../../src/extension-yjs/src/lib.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAI9C;;GAEG;AACH,KAAK,kBAAkB,GAAG,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;AA2BzD,eAAO,MAAM,OAAO,GAAI,MAAM,UAAU,EAAE,QAAG,EAAE,UAAK,SAYnD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kCAAkC,GAC7C,KAAK,MAAM,EACX,MAAM,CAAC,CAAC,WAAW,EACnB,SAAS,kBAAkB,KAC1B,GA+FF,CAAC;AAaF,eAAO,MAAM,kCAAkC,GAC7C,MAAM,CAAC,CAAC,GAAG,EACX,cAAc,CAAC,CAAC,WAAW,EAC3B,QAAQ,GAAG,EACX,SAAS,kBAAkB,KAC1B,IAAI,GAAG,MA6DT,CAAC"}
@@ -1,9 +1,4 @@
1
1
  import * as Y from 'yjs';
2
- import { Fragment, Node } from 'prosemirror-model';
3
- import * as error from 'lib0/error';
4
- import * as map from 'lib0/map';
5
- import * as eventloop from 'lib0/eventloop';
6
- import { createEmptyMeta, createNodeFromYElement, updateYFragment, } from './ySyncPlugin.js';
7
2
  import { ySyncPluginKey } from './keys.js';
8
3
  /**
9
4
  * Is null if no timeout is in progress.
@@ -14,6 +9,9 @@ let viewsToUpdate = null;
14
9
  const updateMetas = () => {
15
10
  const ups = viewsToUpdate;
16
11
  viewsToUpdate = null;
12
+ if (!ups) {
13
+ return;
14
+ }
17
15
  ups.forEach((metas, view) => {
18
16
  const tr = view.state.tr;
19
17
  const syncState = ySyncPluginKey.getState(view.state);
@@ -28,9 +26,14 @@ const updateMetas = () => {
28
26
  export const setMeta = (view, key, value) => {
29
27
  if (!viewsToUpdate) {
30
28
  viewsToUpdate = new Map();
31
- eventloop.timeout(0, updateMetas);
29
+ setTimeout(updateMetas, 0);
30
+ }
31
+ let subMap = viewsToUpdate.get(view);
32
+ if (subMap === undefined) {
33
+ subMap = new Map();
34
+ viewsToUpdate.set(view, subMap);
32
35
  }
33
- map.setIfUndefined(viewsToUpdate, view, map.create).set(key, value);
36
+ subMap.set(key, value);
34
37
  };
35
38
  /**
36
39
  * Transforms a Prosemirror based absolute position to a Yjs Cursor (relative position in the Yjs model).
@@ -40,9 +43,6 @@ export const absolutePositionToRelativePosition = (pos, type, mapping) => {
40
43
  // if the type is later populated, we want to retain the 0 position (hence assoc=-1)
41
44
  return Y.createRelativePositionFromTypeIndex(type, 0, type.length === 0 ? -1 : 0);
42
45
  }
43
- /**
44
- * @type {any}
45
- */
46
46
  let n = type._first === null
47
47
  ? null
48
48
  : /** @type {Y.ContentType} */ (type._first.content).type;
@@ -94,7 +94,7 @@ export const absolutePositionToRelativePosition = (pos, type, mapping) => {
94
94
  return new Y.RelativePosition(n._item === null ? null : n._item.id, n._item === null ? Y.findRootTypeKey(n) : null, null);
95
95
  }
96
96
  do {
97
- n = /** @type {Y.Item} */ (n._item).parent;
97
+ n = n._item.parent;
98
98
  pos--;
99
99
  } while (n !== type && /** @type {Y.Item} */ (n._item).next === null);
100
100
  // if n is null at this point, we have an unexpected case
@@ -108,7 +108,7 @@ export const absolutePositionToRelativePosition = (pos, type, mapping) => {
108
108
  }
109
109
  }
110
110
  if (n === null) {
111
- throw error.unexpectedCase();
111
+ throw new Error('Unexpected case');
112
112
  }
113
113
  if (pos === 0 && n.constructor !== Y.XmlText && n !== type) { // TODO: set to <= 0
114
114
  return createRelativePosition(n._item.parent, n._item);
@@ -127,8 +127,8 @@ const createRelativePosition = (type, item) => {
127
127
  }
128
128
  return new Y.RelativePosition(typeid, tname, item.id);
129
129
  };
130
- export const relativePositionToAbsolutePosition = (y, documentType, relPos, mapping) => {
131
- const decodedPos = Y.createAbsolutePositionFromRelativePosition(relPos, y);
130
+ export const relativePositionToAbsolutePosition = (yDoc, documentType, relPos, mapping) => {
131
+ const decodedPos = Y.createAbsolutePositionFromRelativePosition(relPos, yDoc);
132
132
  if (decodedPos === null ||
133
133
  (decodedPos.type !== documentType &&
134
134
  !Y.isParentOf(documentType, decodedPos.type._item))) {
@@ -136,7 +136,7 @@ export const relativePositionToAbsolutePosition = (y, documentType, relPos, mapp
136
136
  }
137
137
  let type = decodedPos.type;
138
138
  let pos = 0;
139
- if (type.constructor === Y.XmlText) {
139
+ if (type instanceof Y.XmlText) {
140
140
  pos = decodedPos.index;
141
141
  }
142
142
  else if (type._item === null || !type._item.deleted) {
@@ -150,7 +150,8 @@ export const relativePositionToAbsolutePosition = (y, documentType, relPos, mapp
150
150
  pos += t._length;
151
151
  }
152
152
  else {
153
- pos += /** @type {any} */ (mapping.get(t)).nodeSize;
153
+ const node = mapping.get(t);
154
+ pos += node?.nodeSize || 0;
154
155
  }
155
156
  }
156
157
  n = n.right;
@@ -160,13 +161,16 @@ export const relativePositionToAbsolutePosition = (y, documentType, relPos, mapp
160
161
  while (type !== documentType && type._item !== null) {
161
162
  // @ts-ignore
162
163
  const parent = type._item.parent;
164
+ if (parent instanceof Y.ID || parent === null) {
165
+ continue;
166
+ }
163
167
  // @ts-ignore
164
168
  if (parent._item === null || !parent._item.deleted) {
165
169
  pos += 1; // the start tag
166
170
  let n = /** @type {Y.AbstractType} */ (parent)._first;
167
171
  // now iterate until we found type
168
172
  while (n !== null) {
169
- const contentType = /** @type {Y.ContentType} */ (n.content).type;
173
+ const contentType = n.content.type;
170
174
  if (contentType === type) {
171
175
  break;
172
176
  }
@@ -175,95 +179,14 @@ export const relativePositionToAbsolutePosition = (y, documentType, relPos, mapp
175
179
  pos += contentType._length;
176
180
  }
177
181
  else {
178
- pos += /** @type {any} */ (mapping.get(contentType)).nodeSize;
182
+ const node = mapping.get(contentType);
183
+ pos += node?.nodeSize || 0;
179
184
  }
180
185
  }
181
186
  n = n.right;
182
187
  }
183
188
  }
184
- type = /** @type {Y.AbstractType} */ (parent);
189
+ type = parent;
185
190
  }
186
191
  return pos - 1; // we don't count the most outer tag, because it is a fragment
187
192
  };
188
- /**
189
- * Utility function for converting an Y.Fragment to a ProseMirror fragment.
190
- */
191
- export const yXmlFragmentToProseMirrorFragment = (yXmlFragment, schema) => {
192
- const fragmentContent = yXmlFragment.toArray().map((t) => createNodeFromYElement(
193
- /** @type {Y.XmlElement} */ (t), schema, createEmptyMeta())).filter((n) => n !== null);
194
- return Fragment.fromArray(fragmentContent);
195
- };
196
- /**
197
- * Utility function for converting an Y.Fragment to a ProseMirror node.
198
- */
199
- export const yXmlFragmentToProseMirrorRootNode = (yXmlFragment, schema) => schema.topNodeType.create(null, yXmlFragmentToProseMirrorFragment(yXmlFragment, schema));
200
- /**
201
- * The initial ProseMirror content should be supplied by Yjs. This function transforms a Y.Fragment
202
- * to a ProseMirror Doc node and creates a mapping that is used by the sync plugin.
203
- *
204
- * @todo deprecate mapping property
205
- */
206
- export const initProseMirrorDoc = (yXmlFragment, schema) => {
207
- const meta = createEmptyMeta();
208
- const fragmentContent = yXmlFragment.toArray().map((t) => createNodeFromYElement(
209
- /** @type {Y.XmlElement} */ (t), schema, meta)).filter((n) => n !== null);
210
- const doc = schema.topNodeType.create(null, Fragment.fromArray(fragmentContent));
211
- return { doc, meta, mapping: meta.mapping };
212
- };
213
- /**
214
- * Utility method to convert a Prosemirror Doc Node into a Y.Doc.
215
- *
216
- * This can be used when importing existing content to Y.Doc for the first time,
217
- * note that this should not be used to rehydrate a Y.Doc from a database once
218
- * collaboration has begun as all history will be lost
219
- */
220
- export function prosemirrorToYDoc(doc, xmlFragment = 'prosemirror') {
221
- const ydoc = new Y.Doc();
222
- const type =
223
- /** @type {Y.XmlFragment} */ (ydoc.get(xmlFragment, Y.XmlFragment));
224
- if (!type.doc) {
225
- return ydoc;
226
- }
227
- prosemirrorToYXmlFragment(doc, type);
228
- return type.doc;
229
- }
230
- /**
231
- * Utility method to update an empty Y.XmlFragment with content from a Prosemirror Doc Node.
232
- *
233
- * This can be used when importing existing content to Y.Doc for the first time,
234
- * note that this should not be used to rehydrate a Y.Doc from a database once
235
- * collaboration has begun as all history will be lost
236
- *
237
- * Note: The Y.XmlFragment does not need to be part of a Y.Doc document at the time that this
238
- * method is called, but it must be added before any other operations are performed on it.
239
- */
240
- export function prosemirrorToYXmlFragment(doc, xmlFragment) {
241
- const type = xmlFragment || new Y.XmlFragment();
242
- const ydoc = type.doc
243
- ? type.doc
244
- : { transact: (transaction) => transaction(undefined) };
245
- updateYFragment(ydoc, type, doc, { mapping: new Map(), isOMark: new Map() });
246
- return type;
247
- }
248
- /**
249
- * Utility method to convert Prosemirror compatible JSON into a Y.Doc.
250
- *
251
- * This can be used when importing existing content to Y.Doc for the first time,
252
- * note that this should not be used to rehydrate a Y.Doc from a database once
253
- * collaboration has begun as all history will be lost
254
- */
255
- export function prosemirrorJSONToYDoc(schema, state, xmlFragment = 'prosemirror') {
256
- const doc = Node.fromJSON(schema, state);
257
- return prosemirrorToYDoc(doc, xmlFragment);
258
- }
259
- /**
260
- * Utility method to convert Prosemirror compatible JSON to a Y.XmlFragment
261
- *
262
- * This can be used when importing existing content to Y.Doc for the first time,
263
- * note that this should not be used to rehydrate a Y.Doc from a database once
264
- * collaboration has begun as all history will be lost
265
- */
266
- export function prosemirrorJSONToYXmlFragment(schema, state, xmlFragment) {
267
- const doc = Node.fromJSON(schema, state);
268
- return prosemirrorToYXmlFragment(doc, xmlFragment);
269
- }
@@ -1,13 +1,13 @@
1
1
  import * as Y from 'yjs';
2
2
  import * as PModel from 'prosemirror-model';
3
- import { Transaction } from 'prosemirror-state';
4
3
  import { MarkType, Node, Schema } from 'prosemirror-model';
5
4
  import { EditorState } from 'prosemirror-state';
6
- interface BindingMetadata {
5
+ import { EditorView } from 'prosemirror-view';
6
+ export type TransactFunc<T> = (f: (arg0?: Y.Transaction) => T, origin?: any) => T;
7
+ export interface BindingMetadata {
7
8
  mapping: ProsemirrorMapping;
8
9
  isOMark: Map<MarkType, boolean>;
9
10
  }
10
- export declare const createEmptyMeta: () => BindingMetadata;
11
11
  export declare const isVisible: (item: Y.Item, snapshot: Y.Snapshot) => boolean;
12
12
  type ProsemirrorMapping = Map<Y.AbstractType<any>, PModel.Node | Array<PModel.Node>>;
13
13
  interface ColorDef {
@@ -27,44 +27,51 @@ interface YSyncOpts {
27
27
  * This plugin also keeps references to the type and the shared document so other plugins can access it.
28
28
  */
29
29
  export declare const ySyncPlugin: (yXmlFragment: Y.XmlFragment, { colors, colorMapping, permanentUserData, onFirstRender, mapping, }?: YSyncOpts) => any;
30
- export declare const getRelativeSelection: (pmbinding: ProsemirrorBinding, state: EditorState) => {
31
- type: any;
32
- anchor: any;
33
- head: any;
34
- };
30
+ interface TransactionSelection {
31
+ type: string;
32
+ anchor: Y.RelativePosition;
33
+ head: Y.RelativePosition;
34
+ }
35
+ export declare const getRelativeSelection: (pmbinding: ProsemirrorBinding, state: EditorState) => TransactionSelection;
36
+ interface PluginState {
37
+ addToHistory: boolean;
38
+ isChangeOrigin: boolean;
39
+ restore: any;
40
+ snapshot?: Y.Snapshot;
41
+ prevSnapshot?: Y.Snapshot;
42
+ isUndoRedoOperation: boolean;
43
+ colors: Array<ColorDef>;
44
+ colorMapping: Map<string, ColorDef>;
45
+ permanentUserData: Y.PermanentUserData;
46
+ }
35
47
  /**
36
48
  * Binding for prosemirror.
37
49
  *
38
50
  * @protected
39
51
  */
40
- export declare class ProsemirrorBinding {
41
- doc: Y.Doc;
42
- private type;
52
+ export declare class ProsemirrorBinding implements BindingMetadata {
53
+ mapping: ProsemirrorMapping;
54
+ ydoc: Y.Doc;
55
+ isOMark: Map<MarkType, boolean>;
56
+ type: Y.XmlFragment;
43
57
  private mux;
44
- private prosemirrorView;
45
- private isOMark;
46
- private _observeFunction;
47
- private mapping;
58
+ prosemirrorView: EditorView | null;
48
59
  private _beforeTransactionSelection;
49
60
  private beforeAllTransactions;
50
61
  private afterAllTransactions;
62
+ private _observeFunction;
51
63
  private _domSelectionInView;
52
- get beforeTransactionSelection(): null;
53
- set beforeTransactionSelection(value: null);
64
+ get beforeTransactionSelection(): TransactionSelection;
65
+ set beforeTransactionSelection(value: TransactionSelection);
54
66
  constructor(yXmlFragment: Y.XmlFragment, mapping?: ProsemirrorMapping);
55
- /**
56
- * Create a transaction for changing the prosemirror state.
57
- *
58
- * @returns
59
- */
60
- get _tr(): Transaction;
61
- _isLocalCursorInView(): false | null;
67
+ debug(msg?: string): void;
68
+ _isLocalCursorInView(): boolean;
62
69
  _isDomSelectionInView(): boolean;
63
70
  renderSnapshot(snapshot: Y.Snapshot, prevSnapshot: Y.Snapshot): void;
64
71
  unrenderSnapshot(): void;
65
72
  _forceRerender(): void;
66
- _renderSnapshot(snapshot: Y.Snapshot | Uint8Array, prevSnapshot: Y.Snapshot | Uint8Array, pluginState: Object): void;
67
- _typeChanged(events: Array<Y.YEvent<any>>, transaction: Y.Transaction): void;
73
+ _renderSnapshot(snapshot: Y.Snapshot | Uint8Array, prevSnapshot: Y.Snapshot | Uint8Array, pluginState: PluginState): void;
74
+ yXmlChanged(events: Array<Y.YEvent<any>>, transaction: Y.Transaction): void;
68
75
  _prosemirrorChanged(doc: Node): void;
69
76
  /**
70
77
  * View is ready to listen to changes. Register observers.
@@ -72,7 +79,7 @@ export declare class ProsemirrorBinding {
72
79
  initView(prosemirrorView: any): void;
73
80
  destroy(): void;
74
81
  }
75
- export declare const createNodeFromYElement: (el: Y.XmlElement, schema: any, meta: BindingMetadata, snapshot: Y.Snapshot, prevSnapshot: Y.Snapshot, computeYChange: (arg0: "removed" | "added", arg1: Y.ID) => any) => PModel.Node | null;
82
+ export declare const createNodeFromYElement: (el: Y.XmlElement, schema: any, meta: BindingMetadata, snapshot?: Y.Snapshot, prevSnapshot?: Y.Snapshot, computeYChange?: (arg0: "removed" | "added", arg1: Y.ID) => any) => PModel.Node | null;
76
83
  export declare const yattr2markname: (attrName: string) => string;
77
84
  /**
78
85
  * @todo move this to markstoattributes
@@ -89,7 +96,7 @@ export declare const attributesToMarks: (attrs: {
89
96
  * @unstable
90
97
  */
91
98
  export declare const updateYFragment: (y: {
92
- transact: Function;
93
- }, yDomFragment: Y.XmlFragment, pNode: any, meta: BindingMetadata) => void;
99
+ transact: TransactFunc<void>;
100
+ }, yDomFragment: Y.XmlFragment, pNode: Node, meta: BindingMetadata) => void;
94
101
  export {};
95
102
  //# sourceMappingURL=ySyncPlugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ySyncPlugin.d.ts","sourceRoot":"","sources":["../../../src/extension-yjs/src/ySyncPlugin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ySyncPlugin.d.ts","sourceRoot":"","sources":["../../../src/extension-yjs/src/ySyncPlugin.ts"],"names":[],"mappings":"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"}
@@ -15,10 +15,6 @@ import * as map from 'lib0/map';
15
15
  import { ySyncPluginKey, yUndoPluginKey } from './keys.js';
16
16
  import * as utils from './utils.js';
17
17
  import { absolutePositionToRelativePosition, relativePositionToAbsolutePosition, } from './lib.js';
18
- export const createEmptyMeta = () => ({
19
- mapping: new Map(),
20
- isOMark: new Map(),
21
- });
22
18
  export const isVisible = (item, snapshot) => snapshot === undefined
23
19
  ? !item.deleted
24
20
  : (snapshot.sv.has(item.id.client) && /** @type {number} */
@@ -38,7 +34,7 @@ const getUserColor = (colorMapping, colors, user) => {
38
34
  }
39
35
  colorMapping.set(user, random.oneOf(colors));
40
36
  }
41
- return /** @type {ColorDef} */ (colorMapping.get(user));
37
+ return colorMapping.get(user);
42
38
  };
43
39
  /**
44
40
  * This plugin listens to changes in prosemirror view and keeps yXmlState and view in sync.
@@ -94,7 +90,7 @@ export const ySyncPlugin = (yXmlFragment, { colors = defaultColors, colorMapping
94
90
  if (change !== undefined &&
95
91
  (change.snapshot != null || change.prevSnapshot != null)) {
96
92
  // snapshot changed, rerender next
97
- eventloop.timeout(0, () => {
93
+ setTimeout(() => {
98
94
  if (binding.prosemirrorView == null) {
99
95
  return;
100
96
  }
@@ -111,7 +107,7 @@ export const ySyncPlugin = (yXmlFragment, { colors = defaultColors, colorMapping
111
107
  binding._prosemirrorChanged(binding.prosemirrorView.state.doc);
112
108
  });
113
109
  }
114
- });
110
+ }, 0);
115
111
  }
116
112
  }
117
113
  return pluginState;
@@ -138,14 +134,12 @@ export const ySyncPlugin = (yXmlFragment, { colors = defaultColors, colorMapping
138
134
  if (pluginState.addToHistory === false &&
139
135
  !pluginState.isChangeOrigin) {
140
136
  const yUndoPluginState = yUndoPluginKey.getState(view.state);
141
- const um = yUndoPluginState &&
142
- yUndoPluginState.undoManager;
143
- if (um) {
144
- um.stopCapturing();
137
+ if (yUndoPluginState?.undoManager) {
138
+ yUndoPluginState.undoManager.stopCapturing();
145
139
  }
146
140
  }
147
141
  binding.mux(() => {
148
- /** @type {Y.Doc} */ (pluginState.doc).transact((tr) => {
142
+ pluginState.doc.transact((tr) => {
149
143
  tr.meta.set('addToHistory', pluginState.addToHistory);
150
144
  binding._prosemirrorChanged(view.state.doc);
151
145
  }, ySyncPluginKey);
@@ -167,12 +161,12 @@ const restoreRelativeSelection = (tr, relSel, binding) => {
167
161
  tr.setSelection(new AllSelection(tr.doc));
168
162
  }
169
163
  else if (relSel.type === 'node') {
170
- const anchor = relativePositionToAbsolutePosition(binding.doc, binding.type, relSel.anchor, binding.mapping);
164
+ const anchor = relativePositionToAbsolutePosition(binding.ydoc, binding.type, relSel.anchor, binding.mapping);
171
165
  tr.setSelection(NodeSelection.create(tr.doc, anchor));
172
166
  }
173
167
  else {
174
- const anchor = relativePositionToAbsolutePosition(binding.doc, binding.type, relSel.anchor, binding.mapping);
175
- const head = relativePositionToAbsolutePosition(binding.doc, binding.type, relSel.head, binding.mapping);
168
+ const anchor = relativePositionToAbsolutePosition(binding.ydoc, binding.type, relSel.anchor, binding.mapping);
169
+ const head = relativePositionToAbsolutePosition(binding.ydoc, binding.type, relSel.head, binding.mapping);
176
170
  if (anchor !== null && head !== null) {
177
171
  const sel = TextSelection.between(tr.doc.resolve(anchor), tr.doc.resolve(head));
178
172
  tr.setSelection(sel);
@@ -180,8 +174,20 @@ const restoreRelativeSelection = (tr, relSel, binding) => {
180
174
  }
181
175
  }
182
176
  };
177
+ function getSelectionType(selection) {
178
+ if (selection instanceof TextSelection) {
179
+ return 'text';
180
+ }
181
+ if (selection instanceof AllSelection) {
182
+ return 'all';
183
+ }
184
+ if (selection instanceof NodeSelection) {
185
+ return 'node';
186
+ }
187
+ return 'other_selection';
188
+ }
183
189
  export const getRelativeSelection = (pmbinding, state) => ({
184
- type: /** @type {any} */ (state.selection).jsonID,
190
+ type: getSelectionType(state.selection),
185
191
  anchor: absolutePositionToRelativePosition(state.selection.anchor, pmbinding.type, pmbinding.mapping),
186
192
  head: absolutePositionToRelativePosition(state.selection.head, pmbinding.type, pmbinding.mapping),
187
193
  });
@@ -198,61 +204,61 @@ export class ProsemirrorBinding {
198
204
  this._beforeTransactionSelection = value;
199
205
  }
200
206
  constructor(yXmlFragment, mapping = new Map()) {
201
- Object.defineProperty(this, "doc", {
207
+ Object.defineProperty(this, "mapping", {
202
208
  enumerable: true,
203
209
  configurable: true,
204
210
  writable: true,
205
- value: void 0
211
+ value: mapping
206
212
  });
207
- Object.defineProperty(this, "type", {
213
+ Object.defineProperty(this, "ydoc", {
208
214
  enumerable: true,
209
215
  configurable: true,
210
216
  writable: true,
211
217
  value: void 0
212
218
  });
213
- Object.defineProperty(this, "mux", {
219
+ Object.defineProperty(this, "isOMark", {
214
220
  enumerable: true,
215
221
  configurable: true,
216
222
  writable: true,
217
223
  value: void 0
218
224
  });
219
- Object.defineProperty(this, "prosemirrorView", {
225
+ Object.defineProperty(this, "type", {
220
226
  enumerable: true,
221
227
  configurable: true,
222
228
  writable: true,
223
229
  value: void 0
224
230
  });
225
- Object.defineProperty(this, "isOMark", {
231
+ Object.defineProperty(this, "mux", {
226
232
  enumerable: true,
227
233
  configurable: true,
228
234
  writable: true,
229
235
  value: void 0
230
236
  });
231
- Object.defineProperty(this, "_observeFunction", {
237
+ Object.defineProperty(this, "prosemirrorView", {
232
238
  enumerable: true,
233
239
  configurable: true,
234
240
  writable: true,
235
241
  value: void 0
236
242
  });
237
- Object.defineProperty(this, "mapping", {
243
+ Object.defineProperty(this, "_beforeTransactionSelection", {
238
244
  enumerable: true,
239
245
  configurable: true,
240
246
  writable: true,
241
247
  value: void 0
242
248
  });
243
- Object.defineProperty(this, "_beforeTransactionSelection", {
249
+ Object.defineProperty(this, "beforeAllTransactions", {
244
250
  enumerable: true,
245
251
  configurable: true,
246
252
  writable: true,
247
253
  value: void 0
248
254
  });
249
- Object.defineProperty(this, "beforeAllTransactions", {
255
+ Object.defineProperty(this, "afterAllTransactions", {
250
256
  enumerable: true,
251
257
  configurable: true,
252
258
  writable: true,
253
259
  value: void 0
254
260
  });
255
- Object.defineProperty(this, "afterAllTransactions", {
261
+ Object.defineProperty(this, "_observeFunction", {
256
262
  enumerable: true,
257
263
  configurable: true,
258
264
  writable: true,
@@ -262,18 +268,17 @@ export class ProsemirrorBinding {
262
268
  enumerable: true,
263
269
  configurable: true,
264
270
  writable: true,
265
- value: void 0
271
+ value: false
266
272
  });
267
273
  this.type = yXmlFragment;
268
274
  this.prosemirrorView = null;
269
275
  this.mux = createMutex();
270
- this.mapping = mapping;
271
276
  /**
272
277
  * Is overlapping mark - i.e. mark does not exclude itself.
273
278
  */
274
279
  this.isOMark = new Map();
275
- this._observeFunction = this._typeChanged.bind(this);
276
- this.doc = yXmlFragment.doc;
280
+ this._observeFunction = (event, transaction) => this.yXmlChanged(event, transaction);
281
+ this.ydoc = yXmlFragment.doc;
277
282
  /**
278
283
  * current selection as relative positions in the Yjs model
279
284
  */
@@ -287,31 +292,26 @@ export class ProsemirrorBinding {
287
292
  this.afterAllTransactions = () => {
288
293
  this._beforeTransactionSelection = null;
289
294
  };
290
- this._domSelectionInView = null;
295
+ this._domSelectionInView = false;
291
296
  }
292
- /**
293
- * Create a transaction for changing the prosemirror state.
294
- *
295
- * @returns
296
- */
297
- get _tr() {
298
- return this.prosemirrorView.state.tr.setMeta('addToHistory', false);
297
+ debug(msg = 'ydoc.prosemirror') {
298
+ console.log(msg, this.type.toString());
299
299
  }
300
300
  _isLocalCursorInView() {
301
- if (!this.prosemirrorView.hasFocus())
301
+ if (!this.prosemirrorView?.hasFocus())
302
302
  return false;
303
- if (environment.isBrowser && this._domSelectionInView === null) {
303
+ if (environment.isBrowser && this._domSelectionInView === false) {
304
304
  // Calculate the domSelectionInView and clear by next tick after all events are finished
305
305
  eventloop.timeout(0, () => {
306
- this._domSelectionInView = null;
306
+ this._domSelectionInView = false;
307
307
  });
308
308
  this._domSelectionInView = this._isDomSelectionInView();
309
309
  }
310
310
  return this._domSelectionInView;
311
311
  }
312
312
  _isDomSelectionInView() {
313
- const selection = this.prosemirrorView.root.getSelection(); // https://stackoverflow.com/questions/62054839/shadowroot-getselection
314
- if (selection == null || selection.anchorNode == null)
313
+ const selection = this.prosemirrorView?.root?.getSelection(); // https://stackoverflow.com/questions/62054839/shadowroot-getselection
314
+ if (!selection || selection.anchorNode == null)
315
315
  return false;
316
316
  const range = dom.doc.createRange(); // https://github.com/yjs/y-prosemirror/pull/193
317
317
  range.setStart(selection.anchorNode, selection.anchorOffset);
@@ -337,15 +337,22 @@ export class ProsemirrorBinding {
337
337
  if (!prevSnapshot) {
338
338
  prevSnapshot = Y.createSnapshot(Y.createDeleteSet(), new Map());
339
339
  }
340
- this.prosemirrorView.dispatch(this._tr.setMeta(ySyncPluginKey, { snapshot, prevSnapshot }));
340
+ if (this.prosemirrorView) {
341
+ const _tr = this.prosemirrorView.state.tr.setMeta('addToHistory', false);
342
+ this.prosemirrorView.dispatch(_tr.setMeta(ySyncPluginKey, { snapshot, prevSnapshot }));
343
+ }
341
344
  }
342
345
  unrenderSnapshot() {
343
346
  this.mapping.clear();
344
347
  this.mux(() => {
345
- const fragmentContent = this.type.toArray().map((t) => createNodeFromYElement(
346
- /** @type {Y.XmlElement} */ (t), this.prosemirrorView.state.schema, this)).filter((n) => n !== null);
348
+ if (!this.prosemirrorView) {
349
+ return;
350
+ }
351
+ const state = this.prosemirrorView.state;
352
+ const fragmentContent = this.type.toArray().map((t) => createNodeFromYElement(t, state.schema, this)).filter((n) => n !== null);
347
353
  // @ts-ignore
348
- const tr = this._tr.replace(0, this.prosemirrorView.state.doc.content.size, new PModel.Slice(PModel.Fragment.from(fragmentContent), 0, 0));
354
+ const _tr = state.tr.setMeta('addToHistory', false);
355
+ const tr = _tr.replace(0, state.doc.content.size, new PModel.Slice(PModel.Fragment.from(fragmentContent), 0, 0));
349
356
  tr.setMeta(ySyncPluginKey, { snapshot: null, prevSnapshot: null });
350
357
  this.prosemirrorView.dispatch(tr);
351
358
  });
@@ -353,16 +360,21 @@ export class ProsemirrorBinding {
353
360
  _forceRerender() {
354
361
  this.mapping.clear();
355
362
  this.mux(() => {
363
+ if (!this.prosemirrorView) {
364
+ return;
365
+ }
366
+ const state = this.prosemirrorView.state;
356
367
  // If this is a forced rerender, this might neither happen as a pm change nor within a Yjs
357
368
  // transaction. Then the "before selection" doesn't exist. In this case, we need to create a
358
369
  // relative position before replacing content. Fixes #126
359
370
  const sel = this._beforeTransactionSelection !== null
360
371
  ? null
361
- : this.prosemirrorView.state.selection;
372
+ : state.selection;
362
373
  const fragmentContent = this.type.toArray().map((t) => createNodeFromYElement(
363
- /** @type {Y.XmlElement} */ (t), this.prosemirrorView.state.schema, this)).filter((n) => n !== null);
374
+ /** @type {Y.XmlElement} */ (t), state.schema, this)).filter((n) => n !== null);
364
375
  // @ts-ignore
365
- const tr = this._tr.replace(0, this.prosemirrorView.state.doc.content.size, new PModel.Slice(PModel.Fragment.from(fragmentContent), 0, 0));
376
+ const _tr = state.tr.setMeta('addToHistory', false);
377
+ const tr = _tr.replace(0, state.doc.content.size, new PModel.Slice(PModel.Fragment.from(fragmentContent), 0, 0));
366
378
  if (sel) {
367
379
  /**
368
380
  * If the Prosemirror document we just created from this.type is
@@ -380,10 +392,10 @@ export class ProsemirrorBinding {
380
392
  /**
381
393
  * The document that contains the full history of this document.
382
394
  */
383
- let historyDoc = this.doc;
395
+ let historyDoc = this.ydoc;
384
396
  let historyType = this.type;
385
397
  if (!snapshot) {
386
- snapshot = Y.snapshot(this.doc);
398
+ snapshot = Y.snapshot(this.ydoc);
387
399
  }
388
400
  if (snapshot instanceof Uint8Array || prevSnapshot instanceof Uint8Array) {
389
401
  if (!(snapshot instanceof Uint8Array) ||
@@ -401,7 +413,7 @@ export class ProsemirrorBinding {
401
413
  * If is a root type, we need to find the root key in the initial document
402
414
  * and use it to get the history type.
403
415
  */
404
- const rootKey = Array.from(this.doc.share.keys()).find((key) => this.doc.share.get(key) === this.type);
416
+ const rootKey = Array.from(this.ydoc.share.keys()).find((key) => this.ydoc.share.get(key) === this.type);
405
417
  historyType = historyDoc.getXmlFragment(rootKey);
406
418
  }
407
419
  else {
@@ -452,13 +464,13 @@ export class ProsemirrorBinding {
452
464
  return null;
453
465
  }
454
466
  }).filter((n) => n !== null);
455
- // @ts-ignore
456
- const tr = this._tr.replace(0, this.prosemirrorView.state.doc.content.size, new PModel.Slice(PModel.Fragment.from(fragmentContent), 0, 0));
467
+ const _tr = this.prosemirrorView.state.tr.setMeta('addToHistory', false);
468
+ const tr = _tr.replace(0, this.prosemirrorView.state.doc.content.size, new PModel.Slice(PModel.Fragment.from(fragmentContent), 0, 0));
457
469
  this.prosemirrorView.dispatch(tr.setMeta(ySyncPluginKey, { isChangeOrigin: true }));
458
470
  }, ySyncPluginKey);
459
471
  });
460
472
  }
461
- _typeChanged(events, transaction) {
473
+ yXmlChanged(events, transaction) {
462
474
  if (this.prosemirrorView == null)
463
475
  return;
464
476
  const syncState = ySyncPluginKey.getState(this.prosemirrorView.state);
@@ -480,11 +492,20 @@ export class ProsemirrorBinding {
480
492
  });
481
493
  transaction.changed.forEach(delType);
482
494
  transaction.changedParentTypes.forEach(delType);
495
+ if (!this.prosemirrorView) {
496
+ return;
497
+ }
498
+ const state = this.prosemirrorView.state;
483
499
  const fragmentContent = this.type.toArray().map((t) => createNodeIfNotExists(
484
- /** @type {Y.XmlElement | Y.XmlHook} */ (t), this.prosemirrorView.state.schema, this)).filter((n) => n !== null);
485
- // @ts-ignore
486
- let tr = this._tr.replace(0, this.prosemirrorView.state.doc.content.size, new PModel.Slice(PModel.Fragment.from(fragmentContent), 0, 0));
487
- restoreRelativeSelection(tr, this._beforeTransactionSelection, this);
500
+ /** @type {Y.XmlElement | Y.XmlHook} */ (t), state.schema, this)).filter((n) => n !== null);
501
+ const _tr = state.tr.setMeta('addToHistory', false);
502
+ let tr = _tr.replace(0, state.doc.content.size, new PModel.Slice(PModel.Fragment.from(fragmentContent), 0, 0));
503
+ try {
504
+ restoreRelativeSelection(tr, this._beforeTransactionSelection, this);
505
+ }
506
+ catch (err) {
507
+ console.warn(err);
508
+ }
488
509
  tr = tr.setMeta(ySyncPluginKey, {
489
510
  isChangeOrigin: true,
490
511
  isUndoRedoOperation: transaction.origin instanceof Y.UndoManager,
@@ -496,8 +517,8 @@ export class ProsemirrorBinding {
496
517
  });
497
518
  }
498
519
  _prosemirrorChanged(doc) {
499
- this.doc.transact(() => {
500
- updateYFragment(this.doc, this.type, doc, this);
520
+ this.ydoc.transact(() => {
521
+ updateYFragment(this.ydoc, this.type, doc, this);
501
522
  this._beforeTransactionSelection = getRelativeSelection(this, this.prosemirrorView.state);
502
523
  }, ySyncPluginKey);
503
524
  }
@@ -508,8 +529,8 @@ export class ProsemirrorBinding {
508
529
  if (this.prosemirrorView != null)
509
530
  this.destroy();
510
531
  this.prosemirrorView = prosemirrorView;
511
- this.doc.on('beforeAllTransactions', this.beforeAllTransactions);
512
- this.doc.on('afterAllTransactions', this.afterAllTransactions);
532
+ this.ydoc.on('beforeAllTransactions', this.beforeAllTransactions);
533
+ this.ydoc.on('afterAllTransactions', this.afterAllTransactions);
513
534
  this.type.observeDeep(this._observeFunction);
514
535
  }
515
536
  destroy() {
@@ -517,12 +538,12 @@ export class ProsemirrorBinding {
517
538
  return;
518
539
  this.prosemirrorView = null;
519
540
  this.type.unobserveDeep(this._observeFunction);
520
- this.doc.off('beforeAllTransactions', this.beforeAllTransactions);
521
- this.doc.off('afterAllTransactions', this.afterAllTransactions);
541
+ this.ydoc.off('beforeAllTransactions', this.beforeAllTransactions);
542
+ this.ydoc.off('afterAllTransactions', this.afterAllTransactions);
522
543
  }
523
544
  }
524
545
  const createNodeIfNotExists = (el, schema, meta, snapshot, prevSnapshot, computeYChange) => {
525
- const node = /** @type {PModel.Node} */ (meta.mapping.get(el));
546
+ const node = meta.mapping.get(el);
526
547
  if (node === undefined) {
527
548
  if (el instanceof Y.XmlElement) {
528
549
  return createNodeFromYElement(el, schema, meta, snapshot, prevSnapshot, computeYChange);
@@ -757,9 +778,6 @@ const computeChildEqualityFactor = (ytype, pnode, meta) => {
757
778
  };
758
779
  const ytextTrans = (ytext) => {
759
780
  let str = '';
760
- /**
761
- * @type {Y.Item|null}
762
- */
763
781
  let n = ytext._start;
764
782
  const nAttrs = {};
765
783
  while (n !== null) {
@@ -1 +1 @@
1
- {"version":3,"file":"yUndoPlugin.d.ts","sourceRoot":"","sources":["../../../src/extension-yjs/src/yUndoPlugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAA2B,WAAW,EAAc,MAAM,KAAK,CAAC;AAEvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAGxD,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,GAAG,IAAI,CAAC;IACxD,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,eAAO,MAAM,IAAI,GAAI,OAAO,WAAW,KAAG,OACmB,CAAC;AAE9D,eAAO,MAAM,IAAI,GAAI,OAAO,WAAW,KAAG,OACmB,CAAC;AAE9D,eAAO,MAAM,WAAW,EAAE,OAGT,CAAC;AAElB,eAAO,MAAM,WAAW,EAAE,OAGT,CAAC;AAElB,eAAO,MAAM,qBAAqB,aAAyB,CAAC;AAE5D,eAAO,MAAM,mBAAmB,GAC9B,MAAM,OAAO,KAAK,EAAE,IAAI,EACxB,gBAAgB,GAAG,CAAC,MAAM,CAAC,KAC1B,OAM8B,CAAC;AAElC,eAAO,MAAM,WAAW,GAAI,mDAIzB;IACD,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,cAAc,CAAC,EAAE,GAAG,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;CAC3C,gBAoEF,CAAC"}
1
+ {"version":3,"file":"yUndoPlugin.d.ts","sourceRoot":"","sources":["../../../src/extension-yjs/src/yUndoPlugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAA2B,WAAW,EAAc,MAAM,KAAK,CAAC;AAEvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAGxD,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,GAAG,IAAI,CAAC;IACxD,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,eAAO,MAAM,IAAI,GAAI,OAAO,WAAW,KAAG,OACmB,CAAC;AAE9D,eAAO,MAAM,IAAI,GAAI,OAAO,WAAW,KAAG,OACmB,CAAC;AAE9D,eAAO,MAAM,WAAW,EAAE,OAGT,CAAC;AAElB,eAAO,MAAM,WAAW,EAAE,OAGT,CAAC;AAElB,eAAO,MAAM,qBAAqB,aAAyB,CAAC;AAE5D,eAAO,MAAM,mBAAmB,GAC9B,MAAM,OAAO,KAAK,EAAE,IAAI,EACxB,gBAAgB,GAAG,CAAC,MAAM,CAAC,KAC1B,OAM8B,CAAC;AAElC,eAAO,MAAM,WAAW,GAAI,mDAIzB;IACD,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,cAAc,CAAC,EAAE,GAAG,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;CAC3C,gBAuEF,CAAC"}
@@ -63,23 +63,26 @@ export const yUndoPlugin = ({ protectedNodes = defaultProtectedNodes, trackedOri
63
63
  },
64
64
  view: (view) => {
65
65
  const ystate = ySyncPluginKey.getState(view.state);
66
- const undoManager = yUndoPluginKey.getState(view.state).undoManager;
67
- undoManager.on('stack-item-added', ({ stackItem }) => {
68
- const binding = ystate.binding;
69
- if (binding) {
70
- stackItem.meta.set(binding, yUndoPluginKey.getState(view.state).prevSel);
71
- }
72
- });
73
- undoManager.on('stack-item-popped', ({ stackItem }) => {
74
- const binding = ystate.binding;
75
- if (binding) {
76
- binding.beforeTransactionSelection = stackItem.meta.get(binding) ||
77
- binding.beforeTransactionSelection;
78
- }
79
- });
66
+ const yUndoPlugin = yUndoPluginKey.getState(view.state);
67
+ const undoManager = yUndoPlugin?.undoManager;
68
+ if (undoManager) {
69
+ undoManager.on('stack-item-added', ({ stackItem }) => {
70
+ const binding = ystate.binding;
71
+ if (binding) {
72
+ stackItem.meta.set(binding, yUndoPlugin.prevSel);
73
+ }
74
+ });
75
+ undoManager.on('stack-item-popped', ({ stackItem }) => {
76
+ const binding = ystate.binding;
77
+ if (binding) {
78
+ binding.beforeTransactionSelection = stackItem.meta.get(binding) ||
79
+ binding.beforeTransactionSelection;
80
+ }
81
+ });
82
+ }
80
83
  return {
81
84
  destroy: () => {
82
- undoManager.destroy();
85
+ undoManager?.destroy();
83
86
  },
84
87
  };
85
88
  },
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kerebron/extension-yjs",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "license": "MIT",
5
5
  "module": "./esm/extension-yjs/src/ExtensionYjs.js",
6
6
  "exports": {
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "scripts": {},
15
15
  "dependencies": {
16
- "prosemirror-model": "1.25.2",
16
+ "prosemirror-model": "1.25.3",
17
17
  "prosemirror-state": "1.4.3",
18
18
  "prosemirror-transform": "1.10.4",
19
19
  "prosemirror-view": "1.40.0",