@jupyter/ydoc
Version:
Jupyter document structures for collaborative editing using YJS
183 lines • 4.64 kB
JavaScript
/* -----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
import { JSONExt } from '@lumino/coreutils';
import { Signal } from '@lumino/signaling';
import { Awareness } from 'y-protocols/awareness';
import * as Y from 'yjs';
/**
* Generic shareable document.
*/
export class YDocument {
constructor(options) {
var _a;
/**
* Handle a change to the ystate.
*/
this.onStateChanged = (event) => {
const stateChange = new Array();
event.keysChanged.forEach(key => {
const change = event.changes.keys.get(key);
if (change) {
stateChange.push({
name: key,
oldValue: change.oldValue,
newValue: this.ystate.get(key)
});
}
});
this._changed.emit({ stateChange });
};
this._changed = new Signal(this);
this._isDisposed = false;
this._disposed = new Signal(this);
this._ydoc = (_a = options === null || options === void 0 ? void 0 : options.ydoc) !== null && _a !== void 0 ? _a : new Y.Doc();
this._ystate = this._ydoc.getMap('state');
this._undoManager = new Y.UndoManager([], {
trackedOrigins: new Set([this]),
doc: this._ydoc
});
this._awareness = new Awareness(this._ydoc);
this._ystate.observe(this.onStateChanged);
}
/**
* YJS document.
*/
get ydoc() {
return this._ydoc;
}
/**
* Shared state
*/
get ystate() {
return this._ystate;
}
/**
* YJS document undo manager
*/
get undoManager() {
return this._undoManager;
}
/**
* Shared awareness
*/
get awareness() {
return this._awareness;
}
/**
* The changed signal.
*/
get changed() {
return this._changed;
}
/**
* A signal emitted when the document is disposed.
*/
get disposed() {
return this._disposed;
}
/**
* Whether the document is disposed or not.
*/
get isDisposed() {
return this._isDisposed;
}
/**
* Document state
*/
get state() {
return JSONExt.deepCopy(this.ystate.toJSON());
}
/**
* Whether the object can undo changes.
*/
canUndo() {
return this.undoManager.undoStack.length > 0;
}
/**
* Whether the object can redo changes.
*/
canRedo() {
return this.undoManager.redoStack.length > 0;
}
/**
* Dispose of the resources.
*/
dispose() {
if (this._isDisposed) {
return;
}
this._isDisposed = true;
this.ystate.unobserve(this.onStateChanged);
this.awareness.destroy();
this.undoManager.destroy();
this.ydoc.destroy();
this._disposed.emit();
Signal.clearData(this);
}
/**
* Get the value for a state attribute
*
* @param key Key to get
*/
getState(key) {
const value = this.ystate.get(key);
return typeof value === 'undefined'
? value
: JSONExt.deepCopy(value);
}
/**
* Set the value of a state attribute
*
* @param key Key to set
* @param value New attribute value
*/
setState(key, value) {
if (!JSONExt.deepEqual(this.ystate.get(key), value)) {
this.ystate.set(key, value);
}
}
/**
* Get the document source
*
* @returns The source
*/
get source() {
return this.getSource();
}
/**
* Set the document source
*
* @param value The source to set
*/
set source(value) {
this.setSource(value);
}
/**
* Undo an operation.
*/
undo() {
this.undoManager.undo();
}
/**
* Redo an operation.
*/
redo() {
this.undoManager.redo();
}
/**
* Clear the change stack.
*/
clearUndoHistory() {
this.undoManager.clear();
}
/**
* Perform a transaction. While the function f is called, all changes to the shared
* document are bundled into a single event.
*/
transact(f, undoable = true, origin = null) {
this.ydoc.transact(f, undoable ? this : origin);
}
}
//# sourceMappingURL=ydocument.js.map