@kerebron/extension-yjs 0.4.26 → 0.4.27
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/package.json +4 -3
- package/esm/ExtensionYjs.d.ts +0 -17
- package/esm/ExtensionYjs.d.ts.map +0 -1
- package/esm/ExtensionYjs.js +0 -33
- package/esm/convertUtils.d.ts +0 -59
- package/esm/convertUtils.d.ts.map +0 -1
- package/esm/convertUtils.js +0 -88
- package/esm/keys.d.ts +0 -11
- package/esm/keys.d.ts.map +0 -1
- package/esm/keys.js +0 -9
- package/esm/lib.d.ts +0 -15
- package/esm/lib.d.ts.map +0 -1
- package/esm/lib.js +0 -190
- package/esm/package.json +0 -3
- package/esm/userColors.d.ts +0 -5
- package/esm/userColors.d.ts.map +0 -1
- package/esm/userColors.js +0 -10
- package/esm/utils.d.ts +0 -2
- package/esm/utils.d.ts.map +0 -1
- package/esm/utils.js +0 -10
- package/esm/yPositionPlugin.d.ts +0 -14
- package/esm/yPositionPlugin.d.ts.map +0 -1
- package/esm/yPositionPlugin.js +0 -121
- package/esm/ySyncPlugin.d.ts +0 -102
- package/esm/ySyncPlugin.d.ts.map +0 -1
- package/esm/ySyncPlugin.js +0 -937
- package/esm/yUndoPlugin.d.ts +0 -21
- package/esm/yUndoPlugin.d.ts.map +0 -1
- package/esm/yUndoPlugin.js +0 -89
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kerebron/extension-yjs",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.27",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"module": "./esm/ExtensionYjs.js",
|
|
6
6
|
"exports": {
|
|
@@ -12,9 +12,10 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"scripts": {},
|
|
15
|
+
"files": [],
|
|
15
16
|
"dependencies": {
|
|
16
|
-
"@kerebron/editor": "0.4.
|
|
17
|
-
"@kerebron/extension-basic-editor": "0.4.
|
|
17
|
+
"@kerebron/editor": "0.4.27",
|
|
18
|
+
"@kerebron/extension-basic-editor": "0.4.27",
|
|
18
19
|
"lib0": "0.2.109",
|
|
19
20
|
"prosemirror-model": "1.25.3",
|
|
20
21
|
"prosemirror-state": "1.4.3",
|
package/esm/ExtensionYjs.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { Plugin } from 'prosemirror-state';
|
|
2
|
-
import * as awarenessProtocol from 'y-protocols/awareness';
|
|
3
|
-
import { Extension } from '@kerebron/editor';
|
|
4
|
-
import type { CommandFactories, CommandShortcuts } from '@kerebron/editor/commands';
|
|
5
|
-
export interface YjsProvider {
|
|
6
|
-
on(eventName: string, callback: (event: any) => void): void;
|
|
7
|
-
awareness: awarenessProtocol.Awareness;
|
|
8
|
-
}
|
|
9
|
-
export declare class ExtensionYjs extends Extension {
|
|
10
|
-
name: string;
|
|
11
|
-
conflicts: string[];
|
|
12
|
-
requires: string[];
|
|
13
|
-
getCommandFactories(): Partial<CommandFactories>;
|
|
14
|
-
getKeyboardShortcuts(): Partial<CommandShortcuts>;
|
|
15
|
-
getProseMirrorPlugins(): Plugin[];
|
|
16
|
-
}
|
|
17
|
-
//# sourceMappingURL=ExtensionYjs.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ExtensionYjs.d.ts","sourceRoot":"","sources":["../src/ExtensionYjs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,KAAK,iBAAiB,MAAM,uBAAuB,CAAC;AAE3D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AAMnC,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC;IAC5D,SAAS,EAAE,iBAAiB,CAAC,SAAS,CAAC;CACxC;AAED,qBAAa,YAAa,SAAQ,SAAS;IACzC,IAAI,SAAS;IAEJ,SAAS,WAAe;IACjC,QAAQ,WAAwB;IAGvB,mBAAmB,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAOhD,oBAAoB,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAOjD,qBAAqB,IAAI,MAAM,EAAE;CAY3C"}
|
package/esm/ExtensionYjs.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { Extension } from '@kerebron/editor';
|
|
2
|
-
import { ySyncPlugin } from './ySyncPlugin.js';
|
|
3
|
-
import { yPositionPlugin } from './yPositionPlugin.js';
|
|
4
|
-
import { redo, undo, yUndoPlugin } from './yUndoPlugin.js';
|
|
5
|
-
import { initProseMirrorDoc } from './convertUtils.js';
|
|
6
|
-
export class ExtensionYjs extends Extension {
|
|
7
|
-
name = 'yjs';
|
|
8
|
-
conflicts = ['history'];
|
|
9
|
-
requires = ['remote-selection'];
|
|
10
|
-
// declare type Command = (state: EditorState, dispatch?: (tr: Transaction) => void, view?: EditorView) => boolean;
|
|
11
|
-
getCommandFactories() {
|
|
12
|
-
return {
|
|
13
|
-
'undo': () => undo,
|
|
14
|
-
'redo': () => redo,
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
getKeyboardShortcuts() {
|
|
18
|
-
return {
|
|
19
|
-
'Mod-z': 'undo',
|
|
20
|
-
'Mod-y': 'redo',
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
getProseMirrorPlugins() {
|
|
24
|
-
const ydoc = this.config.ydoc;
|
|
25
|
-
const fragment = ydoc.getXmlFragment('prosemirror');
|
|
26
|
-
const { mapping } = initProseMirrorDoc(fragment, this.editor.schema);
|
|
27
|
-
return [
|
|
28
|
-
ySyncPlugin(fragment, { mapping }),
|
|
29
|
-
yPositionPlugin(this.config.provider.awareness, this.editor),
|
|
30
|
-
yUndoPlugin(),
|
|
31
|
-
];
|
|
32
|
-
}
|
|
33
|
-
}
|
package/esm/convertUtils.d.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"convertUtils.d.ts","sourceRoot":"","sources":["../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"}
|
package/esm/convertUtils.js
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
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
|
-
}
|
package/esm/keys.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { PluginKey } from 'prosemirror-state';
|
|
2
|
-
import { UndoPluginState } from './yUndoPlugin.js';
|
|
3
|
-
/**
|
|
4
|
-
* The unique prosemirror plugin key for syncPlugin
|
|
5
|
-
*/
|
|
6
|
-
export declare const ySyncPluginKey: PluginKey<any>;
|
|
7
|
-
/**
|
|
8
|
-
* The unique prosemirror plugin key for undoPlugin
|
|
9
|
-
*/
|
|
10
|
-
export declare const yUndoPluginKey: PluginKey<UndoPluginState>;
|
|
11
|
-
//# sourceMappingURL=keys.d.ts.map
|
package/esm/keys.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;GAEG;AACH,eAAO,MAAM,cAAc,gBAA0B,CAAC;AAEtD;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,CAAC,eAAe,CAErD,CAAC"}
|
package/esm/keys.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { PluginKey } from 'prosemirror-state';
|
|
2
|
-
/**
|
|
3
|
-
* The unique prosemirror plugin key for syncPlugin
|
|
4
|
-
*/
|
|
5
|
-
export const ySyncPluginKey = new PluginKey('y-sync');
|
|
6
|
-
/**
|
|
7
|
-
* The unique prosemirror plugin key for undoPlugin
|
|
8
|
-
*/
|
|
9
|
-
export const yUndoPluginKey = new PluginKey('y-undo');
|
package/esm/lib.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
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
|
package/esm/lib.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../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,MA2DT,CAAC"}
|
package/esm/lib.js
DELETED
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import * as Y from 'yjs';
|
|
2
|
-
import { ySyncPluginKey } from './keys.js';
|
|
3
|
-
/**
|
|
4
|
-
* Is null if no timeout is in progress.
|
|
5
|
-
* Is defined if a timeout is in progress.
|
|
6
|
-
* Maps from view
|
|
7
|
-
*/
|
|
8
|
-
let viewsToUpdate = null;
|
|
9
|
-
const updateMetas = () => {
|
|
10
|
-
const ups = viewsToUpdate;
|
|
11
|
-
viewsToUpdate = null;
|
|
12
|
-
if (!ups) {
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
ups.forEach((metas, view) => {
|
|
16
|
-
const tr = view.state.tr;
|
|
17
|
-
const syncState = ySyncPluginKey.getState(view.state);
|
|
18
|
-
if (syncState && syncState.binding && !syncState.binding.isDestroyed) {
|
|
19
|
-
metas.forEach((val, key) => {
|
|
20
|
-
tr.setMeta(key, val);
|
|
21
|
-
});
|
|
22
|
-
view.dispatch(tr);
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
};
|
|
26
|
-
export const setMeta = (view, key, value) => {
|
|
27
|
-
if (!viewsToUpdate) {
|
|
28
|
-
viewsToUpdate = new Map();
|
|
29
|
-
setTimeout(updateMetas, 0);
|
|
30
|
-
}
|
|
31
|
-
let subMap = viewsToUpdate.get(view);
|
|
32
|
-
if (subMap === undefined) {
|
|
33
|
-
subMap = new Map();
|
|
34
|
-
viewsToUpdate.set(view, subMap);
|
|
35
|
-
}
|
|
36
|
-
subMap.set(key, value);
|
|
37
|
-
};
|
|
38
|
-
/**
|
|
39
|
-
* Transforms a Prosemirror based absolute position to a Yjs Cursor (relative position in the Yjs model).
|
|
40
|
-
*/
|
|
41
|
-
export const absolutePositionToRelativePosition = (pos, type, mapping) => {
|
|
42
|
-
if (pos === 0) {
|
|
43
|
-
// if the type is later populated, we want to retain the 0 position (hence assoc=-1)
|
|
44
|
-
return Y.createRelativePositionFromTypeIndex(type, 0, type.length === 0 ? -1 : 0);
|
|
45
|
-
}
|
|
46
|
-
let n = type._first === null
|
|
47
|
-
? null
|
|
48
|
-
: /** @type {Y.ContentType} */ (type._first.content).type;
|
|
49
|
-
while (n !== null && type !== n) {
|
|
50
|
-
if (n instanceof Y.XmlText) {
|
|
51
|
-
if (n._length >= pos) {
|
|
52
|
-
return Y.createRelativePositionFromTypeIndex(n, pos, type.length === 0 ? -1 : 0);
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
pos -= n._length;
|
|
56
|
-
}
|
|
57
|
-
if (n._item !== null && n._item.next !== null) {
|
|
58
|
-
n = /** @type {Y.ContentType} */ (n._item.next.content).type;
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
do {
|
|
62
|
-
n = n._item === null ? null : n._item.parent;
|
|
63
|
-
pos--;
|
|
64
|
-
} while (n !== type && n !== null && n._item !== null && n._item.next === null);
|
|
65
|
-
if (n !== null && n !== type) {
|
|
66
|
-
// @ts-gnore we know that n.next !== null because of above loop conditition
|
|
67
|
-
n = n._item === null
|
|
68
|
-
? null
|
|
69
|
-
: /** @type {Y.ContentType} */ ( /** @type Y.Item */(n._item.next)
|
|
70
|
-
.content).type;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
const pNodeSize =
|
|
76
|
-
/** @type {any} */ (mapping.get(n) || { nodeSize: 0 }).nodeSize;
|
|
77
|
-
if (n._first !== null && pos < pNodeSize) {
|
|
78
|
-
n = /** @type {Y.ContentType} */ (n._first.content).type;
|
|
79
|
-
pos--;
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
82
|
-
if (pos === 1 && n._length === 0 && pNodeSize > 1) {
|
|
83
|
-
// edge case, should end in this paragraph
|
|
84
|
-
return new Y.RelativePosition(n._item === null ? null : n._item.id, n._item === null ? Y.findRootTypeKey(n) : null, null);
|
|
85
|
-
}
|
|
86
|
-
pos -= pNodeSize;
|
|
87
|
-
if (n._item !== null && n._item.next !== null) {
|
|
88
|
-
n = /** @type {Y.ContentType} */ (n._item.next.content).type;
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
if (pos === 0) {
|
|
92
|
-
// set to end of n.parent
|
|
93
|
-
n = n._item === null ? n : n._item.parent;
|
|
94
|
-
return new Y.RelativePosition(n._item === null ? null : n._item.id, n._item === null ? Y.findRootTypeKey(n) : null, null);
|
|
95
|
-
}
|
|
96
|
-
do {
|
|
97
|
-
n = n._item.parent;
|
|
98
|
-
pos--;
|
|
99
|
-
} while (n !== type && /** @type {Y.Item} */ (n._item).next === null);
|
|
100
|
-
// if n is null at this point, we have an unexpected case
|
|
101
|
-
if (n !== type) {
|
|
102
|
-
// We know that n._item.next is defined because of above loop condition
|
|
103
|
-
n =
|
|
104
|
-
/** @type {Y.ContentType} */ ( /** @type {Y.Item} */( /** @type {Y.Item} */(n
|
|
105
|
-
._item).next).content).type;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
if (n === null) {
|
|
111
|
-
throw new Error('Unexpected case');
|
|
112
|
-
}
|
|
113
|
-
if (pos === 0 && n.constructor !== Y.XmlText && n !== type) { // TODO: set to <= 0
|
|
114
|
-
return createRelativePosition(n._item.parent, n._item);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
return Y.createRelativePositionFromTypeIndex(type, type._length, type.length === 0 ? -1 : 0);
|
|
118
|
-
};
|
|
119
|
-
const createRelativePosition = (type, item) => {
|
|
120
|
-
let typeid = null;
|
|
121
|
-
let tname = null;
|
|
122
|
-
if (type._item === null) {
|
|
123
|
-
tname = Y.findRootTypeKey(type);
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
typeid = Y.createID(type._item.id.client, type._item.id.clock);
|
|
127
|
-
}
|
|
128
|
-
return new Y.RelativePosition(typeid, tname, item.id);
|
|
129
|
-
};
|
|
130
|
-
export const relativePositionToAbsolutePosition = (yDoc, documentType, relPos, mapping) => {
|
|
131
|
-
const decodedPos = Y.createAbsolutePositionFromRelativePosition(relPos, yDoc);
|
|
132
|
-
if (decodedPos === null ||
|
|
133
|
-
(decodedPos.type !== documentType &&
|
|
134
|
-
!Y.isParentOf(documentType, decodedPos.type._item))) {
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
137
|
-
let type = decodedPos.type;
|
|
138
|
-
let pos = 0;
|
|
139
|
-
if (type instanceof Y.XmlText) {
|
|
140
|
-
pos = decodedPos.index;
|
|
141
|
-
}
|
|
142
|
-
else if (type._item === null || !type._item.deleted) {
|
|
143
|
-
let n = type._first;
|
|
144
|
-
let i = 0;
|
|
145
|
-
while (i < type._length && i < decodedPos.index && n !== null) {
|
|
146
|
-
if (!n.deleted) {
|
|
147
|
-
const t = n.content.type;
|
|
148
|
-
i++;
|
|
149
|
-
if (t instanceof Y.XmlText) {
|
|
150
|
-
pos += t._length;
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
const node = mapping.get(t);
|
|
154
|
-
pos += node?.nodeSize || 0;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
n = n.right;
|
|
158
|
-
}
|
|
159
|
-
pos += 1; // increase because we go out of n
|
|
160
|
-
}
|
|
161
|
-
while (type !== documentType && type._item !== null) {
|
|
162
|
-
const parent = type._item.parent;
|
|
163
|
-
if (parent instanceof Y.ID || parent === null) {
|
|
164
|
-
continue;
|
|
165
|
-
}
|
|
166
|
-
if (parent._item === null || !parent._item.deleted) {
|
|
167
|
-
pos += 1; // the start tag
|
|
168
|
-
let n = /** @type {Y.AbstractType} */ (parent)._first;
|
|
169
|
-
// now iterate until we found type
|
|
170
|
-
while (n !== null) {
|
|
171
|
-
const contentType = n.content.type;
|
|
172
|
-
if (contentType === type) {
|
|
173
|
-
break;
|
|
174
|
-
}
|
|
175
|
-
if (!n.deleted) {
|
|
176
|
-
if (contentType instanceof Y.XmlText) {
|
|
177
|
-
pos += contentType._length;
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
const node = mapping.get(contentType);
|
|
181
|
-
pos += node?.nodeSize || 0;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
n = n.right;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
type = parent;
|
|
188
|
-
}
|
|
189
|
-
return pos - 1; // we don't count the most outer tag, because it is a fragment
|
|
190
|
-
};
|
package/esm/package.json
DELETED
package/esm/userColors.d.ts
DELETED
package/esm/userColors.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"userColors.d.ts","sourceRoot":"","sources":["../src/userColors.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU;;;GAStB,CAAC"}
|
package/esm/userColors.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export const userColors = [
|
|
2
|
-
{ color: '#30bced', light: '#30bced33' },
|
|
3
|
-
{ color: '#6eeb83', light: '#6eeb8333' },
|
|
4
|
-
{ color: '#ffbc42', light: '#ffbc4233' },
|
|
5
|
-
{ color: '#ecd444', light: '#ecd44433' },
|
|
6
|
-
{ color: '#ee6352', light: '#ee635233' },
|
|
7
|
-
{ color: '#9ac2c9', light: '#9ac2c933' },
|
|
8
|
-
{ color: '#8acb88', light: '#8acb8833' },
|
|
9
|
-
{ color: '#1be7ff', light: '#1be7ff33' },
|
|
10
|
-
];
|
package/esm/utils.d.ts
DELETED
package/esm/utils.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,UAAU,GAAI,MAAM,GAAG,WAC0B,CAAC"}
|
package/esm/utils.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import * as sha256 from 'lib0/hash/sha256';
|
|
2
|
-
import * as buf from 'lib0/buffer';
|
|
3
|
-
const _convolute = (digest) => {
|
|
4
|
-
const N = 6;
|
|
5
|
-
for (let i = N; i < digest.length; i++) {
|
|
6
|
-
digest[i % N] = digest[i % N] ^ digest[i];
|
|
7
|
-
}
|
|
8
|
-
return digest.slice(0, N);
|
|
9
|
-
};
|
|
10
|
-
export const hashOfJSON = (json) => buf.toBase64(_convolute(sha256.digest(buf.encodeAny(json))));
|
package/esm/yPositionPlugin.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import * as awarenessProtocol from 'y-protocols/awareness';
|
|
2
|
-
import { Plugin, PluginKey } from 'prosemirror-state';
|
|
3
|
-
import type { CoreEditor } from '@kerebron/editor';
|
|
4
|
-
export declare const yPositionPluginKey: PluginKey<any>;
|
|
5
|
-
interface PositionPluginConfig {
|
|
6
|
-
getSelection?: (arg0: any) => any;
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Default awareness state filter
|
|
10
|
-
*/
|
|
11
|
-
export declare const defaultAwarenessStateFilter: (currentClientId: number, userClientId: number, _user: any) => boolean;
|
|
12
|
-
export declare const yPositionPlugin: (awareness: awarenessProtocol.Awareness, editor: CoreEditor, { getSelection, }?: PositionPluginConfig, cursorStateField?: string) => Plugin<any>;
|
|
13
|
-
export {};
|
|
14
|
-
//# sourceMappingURL=yPositionPlugin.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"yPositionPlugin.d.ts","sourceRoot":"","sources":["../src/yPositionPlugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,iBAAiB,MAAM,uBAAuB,CAAC;AAE3D,OAAO,EAAe,MAAM,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAcnD,eAAO,MAAM,kBAAkB,gBAAgC,CAAC;AAYhE,UAAU,oBAAoB;IAC5B,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,GAAG,CAAC;CACnC;AAED;;GAEG;AACH,eAAO,MAAM,2BAA2B,GACtC,iBAAiB,MAAM,EACvB,cAAc,MAAM,EACpB,OAAO,GAAG,KACT,OAA2C,CAAC;AAE/C,eAAO,MAAM,eAAe,GAC1B,WAAW,iBAAiB,CAAC,SAAS,EACtC,QAAQ,UAAU,EAClB,oBAEG,oBAAyB,EAC5B,mBAAkB,MAAiB,gBAiLpC,CAAC"}
|
package/esm/yPositionPlugin.js
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import * as Y from 'yjs';
|
|
2
|
-
import { Plugin, PluginKey } from 'prosemirror-state';
|
|
3
|
-
import { remoteSelectionPluginKey } from '@kerebron/extension-basic-editor/ExtensionRemoteSelection';
|
|
4
|
-
import { absolutePositionToRelativePosition, relativePositionToAbsolutePosition, setMeta, } from './lib.js';
|
|
5
|
-
import { ySyncPluginKey } from './keys.js';
|
|
6
|
-
export const yPositionPluginKey = new PluginKey('yjs-position');
|
|
7
|
-
/**
|
|
8
|
-
* Default awareness state filter
|
|
9
|
-
*/
|
|
10
|
-
export const defaultAwarenessStateFilter = (currentClientId, userClientId, _user) => currentClientId !== userClientId;
|
|
11
|
-
export const yPositionPlugin = (awareness, editor, { getSelection = (state) => state.selection, } = {}, cursorStateField = 'cursor') => {
|
|
12
|
-
return new Plugin({
|
|
13
|
-
key: yPositionPluginKey,
|
|
14
|
-
view: (view) => {
|
|
15
|
-
const extension = editor.getExtension('remote-selection');
|
|
16
|
-
const awarenessListener = ({ added, updated, removed }) => {
|
|
17
|
-
const clients = added.concat(updated).concat(removed);
|
|
18
|
-
if (clients.findIndex((id) => id !== awareness.doc.clientID) ===
|
|
19
|
-
-1) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
if (view.docView) {
|
|
23
|
-
setMeta(view, remoteSelectionPluginKey, {
|
|
24
|
-
remotePositionUpdated: true,
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
const remoteStates = [];
|
|
28
|
-
const ystate = ySyncPluginKey.getState(view.state);
|
|
29
|
-
const y = ystate.doc;
|
|
30
|
-
awareness.getStates().forEach((aw, clientId) => {
|
|
31
|
-
if (!defaultAwarenessStateFilter(y.clientID, clientId, aw)) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
if (!aw.cursor) {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
let anchor = relativePositionToAbsolutePosition(y, ystate.type, Y.createRelativePositionFromJSON(aw.cursor.anchor), ystate.binding.mapping);
|
|
38
|
-
let head = relativePositionToAbsolutePosition(y, ystate.type, Y.createRelativePositionFromJSON(aw.cursor.head), ystate.binding.mapping);
|
|
39
|
-
if (anchor !== null && head !== null) {
|
|
40
|
-
remoteStates.push({
|
|
41
|
-
clientId,
|
|
42
|
-
user: {
|
|
43
|
-
name: aw.user?.name,
|
|
44
|
-
color: aw.user?.color,
|
|
45
|
-
colorLight: aw.user?.colorLight,
|
|
46
|
-
},
|
|
47
|
-
cursor: {
|
|
48
|
-
anchor,
|
|
49
|
-
head,
|
|
50
|
-
},
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
extension.setRemoteStates(remoteStates);
|
|
55
|
-
// view.dispatch({ annotations: [yRemoteSelectionsAnnotation.of([])] });
|
|
56
|
-
};
|
|
57
|
-
{
|
|
58
|
-
// if (
|
|
59
|
-
// ystate.snapshot != null || ystate.prevSnapshot != null ||
|
|
60
|
-
// ystate.binding.mapping.size === 0
|
|
61
|
-
// ) {
|
|
62
|
-
// // do not render cursors while snapshot is active
|
|
63
|
-
// return DecorationSet.create(state.doc, []);
|
|
64
|
-
// }
|
|
65
|
-
}
|
|
66
|
-
const updateAwareness = (selectionAnchor, selectionHead) => {
|
|
67
|
-
const ystate = ySyncPluginKey.getState(view.state);
|
|
68
|
-
const current = awareness.getLocalState() || {};
|
|
69
|
-
const anchor = absolutePositionToRelativePosition(selectionAnchor, ystate.type, ystate.binding.mapping);
|
|
70
|
-
const head = absolutePositionToRelativePosition(selectionHead, ystate.type, ystate.binding.mapping);
|
|
71
|
-
if (current.cursor == null ||
|
|
72
|
-
!Y.compareRelativePositions(Y.createRelativePositionFromJSON(current.cursor.anchor), anchor) ||
|
|
73
|
-
!Y.compareRelativePositions(Y.createRelativePositionFromJSON(current.cursor.head), head)) {
|
|
74
|
-
awareness.setLocalStateField(cursorStateField, {
|
|
75
|
-
anchor,
|
|
76
|
-
head,
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
const clearAwareness = () => {
|
|
81
|
-
const ystate = ySyncPluginKey.getState(view.state);
|
|
82
|
-
const current = awareness.getLocalState() || {};
|
|
83
|
-
if (current.cursor != null &&
|
|
84
|
-
relativePositionToAbsolutePosition(ystate.doc, ystate.type, Y.createRelativePositionFromJSON(current.cursor.anchor), ystate.binding.mapping) !== null) {
|
|
85
|
-
// delete cursor information if current cursor information is owned by this editor binding
|
|
86
|
-
awareness.setLocalStateField(cursorStateField, null);
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
const updateCursorInfo = () => {
|
|
90
|
-
if (view.hasFocus()) {
|
|
91
|
-
const selection = getSelection(view.state);
|
|
92
|
-
updateAwareness(selection.anchor, selection.head);
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
// clearAwareness();
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
const localPositionChangedListener = (event) => {
|
|
99
|
-
const { detail } = event;
|
|
100
|
-
updateAwareness(detail.anchor, detail.head);
|
|
101
|
-
};
|
|
102
|
-
editor.addEventListener('localPositionChanged', localPositionChangedListener);
|
|
103
|
-
awareness.on('change', awarenessListener);
|
|
104
|
-
view.dom.addEventListener('focusin', updateCursorInfo);
|
|
105
|
-
view.dom.addEventListener('focusout', updateCursorInfo);
|
|
106
|
-
return {
|
|
107
|
-
update: updateCursorInfo,
|
|
108
|
-
destroy: () => {
|
|
109
|
-
view.dom.removeEventListener('focusin', updateCursorInfo);
|
|
110
|
-
view.dom.removeEventListener('focusout', updateCursorInfo);
|
|
111
|
-
awareness.off('change', awarenessListener);
|
|
112
|
-
awareness.setLocalStateField(cursorStateField, null);
|
|
113
|
-
editor.removeEventListener('localPositionChanged', localPositionChangedListener);
|
|
114
|
-
},
|
|
115
|
-
};
|
|
116
|
-
},
|
|
117
|
-
updateCursorInfo(state) {
|
|
118
|
-
throw new Error('TODO: merge with updateCursorInfo above');
|
|
119
|
-
},
|
|
120
|
-
});
|
|
121
|
-
};
|