@jupyter/ydoc
Version:
Jupyter document structures for collaborative editing using YJS
798 lines (699 loc) • 16.4 kB
text/typescript
/* -----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/**
* This file defines the shared shared-models types.
*
* - Notebook Type.
* - Notebook Metadata Types.
* - Cell Types.
* - Cell Metadata Types.
*
* It also defines the shared changes to be used in the events.
*/
import type * as nbformat from '@jupyterlab/nbformat';
import type {
JSONObject,
JSONValue,
PartialJSONValue
} from '@lumino/coreutils';
import type { IObservableDisposable } from '@lumino/disposable';
import type { ISignal } from '@lumino/signaling';
import * as Y from 'yjs';
import { IAwareness } from './awareness.js';
/**
* Changes on Sequence-like data are expressed as Quill-inspired deltas.
*
* @source https://quilljs.com/docs/delta/
*/
export type Delta<T> = Array<{ insert?: T; delete?: number; retain?: number }>;
/**
* Changes on a map-like data.
*/
export type MapChanges = Map<
string,
{
action: 'add' | 'update' | 'delete';
oldValue: any;
}
>;
/**
* ISharedBase defines common operations that can be performed on any shared object.
*/
export interface ISharedBase extends IObservableDisposable {
/**
* Undo an operation.
*/
undo(): void;
/**
* Redo an operation.
*/
redo(): void;
/**
* Whether the object can redo changes.
*/
canUndo(): boolean;
/**
* Whether the object can undo changes.
*/
canRedo(): boolean;
/**
* Clear the change stack.
*/
clearUndoHistory(): void;
/**
* Perform a transaction. While the function f is called, all changes to the shared
* document are bundled into a single event.
*
* @param f Transaction to execute
* @param undoable Whether to track the change in the action history or not (default `true`)
*/
transact(f: () => void, undoable?: boolean, origin?: any): void;
}
/**
* Implement an API for Context information on the shared information.
* This is used by, for example, docregistry to share the file-path of the edited content.
*/
interface ISharedDocumentNoSource extends ISharedBase {
/**
* Document version
*/
readonly version: string;
/**
* Document state
*/
readonly state: JSONObject;
/**
* Document awareness
*/
readonly awareness: IAwareness;
/**
* Get the value for a state attribute
*
* @param key Key to get
*/
getState(key: string): JSONValue | undefined;
/**
* Set the value of a state attribute
*
* @param key Key to set
* @param value New attribute value
*/
setState(key: string, value: JSONValue): void;
/**
* The changed signal.
*/
readonly changed: ISignal<this, DocumentChange>;
}
/**
* Implement an API for Context information on the shared information.
* This is used by, for example, docregistry to share the file-path of the edited content.
*/
export interface ISharedDocument extends ISharedDocumentNoSource {
/**
* Get the document source.
*
* @returns Source.
*/
getSource(): string | JSONValue;
/**
* Set the document source.
*
* @param value New source.
*/
setSource(value: string | JSONValue): void;
}
/**
* The ISharedText interface defines models that can be bound to a text editor like CodeMirror.
*/
export interface ISharedText extends ISharedBase {
/**
* The changed signal.
*/
readonly changed: ISignal<this, SourceChange>;
/**
* Text
*/
source: string;
/**
* Get text.
*
* @returns Text.
*/
getSource(): string;
/**
* Set text.
*
* @param value New text.
*/
setSource(value: string): void;
/**
* Replace content from `start` to `end` with `value`.
*
* @param start: The start index of the range to replace (inclusive).
* @param end: The end index of the range to replace (exclusive).
* @param value: New source (optional).
*/
updateSource(start: number, end: number, value?: string): void;
}
/**
* Text/Markdown/Code files are represented as ISharedFile
*/
export interface ISharedFile extends ISharedDocumentNoSource, ISharedText {
/**
* The changed signal.
*/
readonly changed: ISignal<this, FileChange>;
}
/**
* Implements an API for nbformat.INotebookContent
*/
export interface ISharedNotebook extends ISharedDocument {
/**
* The changed signal.
*/
readonly changed: ISignal<this, NotebookChange>;
/**
* Signal triggered when a metadata changes.
*/
readonly metadataChanged: ISignal<this, IMapChange>;
/**
* The list of shared cells in the notebook.
*/
readonly cells: ISharedCell[];
/**
* Wether the undo/redo logic should be
* considered on the full document across all cells.
*/
readonly disableDocumentWideUndoRedo?: boolean;
/**
* Notebook metadata.
*/
metadata: nbformat.INotebookMetadata;
/**
* The minor version number of the nbformat.
*/
readonly nbformat_minor: number;
/**
* The major version number of the nbformat.
*/
readonly nbformat: number;
/**
* Delete a metadata notebook.
*
* @param key The key to delete
*/
deleteMetadata(key: string): void;
/**
* Returns all metadata associated with the notebook.
*
* @returns Notebook's metadata.
*/
getMetadata(): nbformat.INotebookMetadata;
/**
* Returns a metadata associated with the notebook.
*
* @param key Key to get from the metadata
* @returns Notebook's metadata.
*/
getMetadata(key: string): PartialJSONValue | undefined;
/**
* Sets all metadata associated with the notebook.
*
* @param metadata All Notebook's metadata.
*/
setMetadata(metadata: nbformat.INotebookMetadata): void;
/**
* Sets a metadata associated with the notebook.
*
* @param metadata The key to set.
* @param value New metadata value
*/
setMetadata(metadata: string, value: PartialJSONValue): void;
/**
* Updates the metadata associated with the notebook.
*
* @param value: Metadata's attribute to update.
*/
updateMetadata(value: Partial<nbformat.INotebookMetadata>): void;
/**
* Add a shared cell at the notebook bottom.
*
* @param cell Cell to add.
*
* @returns The added cell.
*/
addCell(cell: SharedCell.Cell): ISharedCell;
/**
* Get a shared cell by index.
*
* @param index: Cell's position.
*
* @returns The requested shared cell.
*/
getCell(index: number): ISharedCell;
/**
* Insert a shared cell into a specific position.
*
* @param index Cell's position.
* @param cell Cell to insert.
*
* @returns The inserted cell.
*/
insertCell(index: number, cell: SharedCell.Cell): ISharedCell;
/**
* Insert a list of shared cells into a specific position.
*
* @param index Position to insert the cells.
* @param cells Array of shared cells to insert.
*
* @returns The inserted cells.
*/
insertCells(index: number, cells: Array<SharedCell.Cell>): ISharedCell[];
/**
* Move a cell.
*
* @param fromIndex: Index of the cell to move.
* @param toIndex: New position of the cell.
*/
moveCell(fromIndex: number, toIndex: number): void;
/**
* Move cells.
*
* @param fromIndex: Index of the first cells to move.
* @param toIndex: New position of the first cell (in the current array).
* @param n: Number of cells to move (default 1)
*/
moveCells(fromIndex: number, toIndex: number, n?: number): void;
/**
* Remove a cell.
*
* @param index: Index of the cell to remove.
*/
deleteCell(index: number): void;
/**
* Remove a range of cells.
*
* @param from: The start index of the range to remove (inclusive).
*
* @param to: The end index of the range to remove (exclusive).
*/
deleteCellRange(from: number, to: number): void;
/**
* Override the notebook with a JSON-serialized document.
*
* @param value The notebook
*/
fromJSON(value: nbformat.INotebookContent): void;
/**
* Serialize the model to JSON.
*/
toJSON(): nbformat.INotebookContent;
}
/**
* Definition of the map changes for yjs.
*/
export type MapChange = Map<
string,
{ action: 'add' | 'update' | 'delete'; oldValue: any; newValue: any }
>;
/**
* The namespace for `ISharedNotebook` class statics.
*/
export namespace ISharedNotebook {
/**
* The options used to initialize a a ISharedNotebook
*/
export interface IOptions {
/**
* Wether the the undo/redo logic should be
* considered on the full document across all cells.
*/
disableDocumentWideUndoRedo?: boolean;
/**
* The content of the notebook.
*/
data?: Partial<nbformat.INotebookContent>;
}
}
/** Cell Types. */
export type ISharedCell =
| ISharedCodeCell
| ISharedRawCell
| ISharedMarkdownCell
| ISharedUnrecognizedCell;
/**
* Shared cell namespace
*/
export namespace SharedCell {
/**
* Cell data
*/
export type Cell = (
| Partial<nbformat.IRawCell>
| Partial<nbformat.ICodeCell>
| Partial<nbformat.IMarkdownCell>
| Partial<nbformat.IBaseCell>
) & { cell_type: string };
/**
* Shared cell constructor options.
*/
export interface IOptions {
/**
* Optional notebook to which this cell belongs.
*
* If not provided the cell will be standalone.
*/
notebook?: ISharedNotebook;
}
}
/**
* Implements an API for nbformat.IBaseCell.
*/
export interface ISharedBaseCell<
Metadata extends nbformat.IBaseCellMetadata = nbformat.IBaseCellMetadata
> extends ISharedText {
/**
* The type of the cell.
*/
readonly cell_type: nbformat.CellType | string;
/**
* The changed signal.
*/
readonly changed: ISignal<this, CellChange>;
/**
* Cell id.
*/
readonly id: string;
/**
* Whether the cell is standalone or not.
*
* If the cell is standalone. It cannot be
* inserted into a YNotebook because the Yjs model is already
* attached to an anonymous Y.Doc instance.
*/
readonly isStandalone: boolean;
/**
* Cell metadata.
*
* #### Notes
* You should prefer to access and modify the specific key of interest.
*/
metadata: Partial<Metadata>;
/**
* Signal triggered when the cell metadata changes.
*/
readonly metadataChanged: ISignal<this, IMapChange>;
/**
* The notebook that this cell belongs to.
*/
readonly notebook: ISharedNotebook | null;
/**
* Get Cell id.
*
* @returns Cell id.
*/
getId(): string;
/**
* Delete a metadata cell.
*
* @param key The key to delete
*/
deleteMetadata(key: string): void;
/**
* Returns all metadata associated with the cell.
*
* @returns Cell's metadata.
*/
getMetadata(): Partial<Metadata>;
/**
* Returns a metadata associated with the cell.
*
* @param key Metadata key to get
* @returns Cell's metadata.
*/
getMetadata(key: string): PartialJSONValue | undefined;
/**
* Sets some cell metadata.
*
* @param metadata Cell's metadata.
*/
setMetadata(metadata: Partial<Metadata>): void;
/**
* Sets a cell metadata.
*
* @param metadata Cell's metadata key.
* @param value Metadata value
*/
setMetadata(metadata: string, value: PartialJSONValue): void;
/**
* Serialize the model to JSON.
*/
toJSON(): nbformat.IBaseCell;
}
export type IExecutionState = 'running' | 'idle';
/**
* Implements an API for nbformat.ICodeCell.
*/
export interface ISharedCodeCell
extends ISharedBaseCell<nbformat.IBaseCellMetadata> {
/**
* The type of the cell.
*/
cell_type: 'code';
/**
* The code cell's prompt number. Will be null if the cell has not been run.
*/
execution_count: nbformat.ExecutionCount;
/**
* The code cell's execution state.
*/
executionState: IExecutionState;
/**
* Cell outputs
*/
outputs: Array<nbformat.IOutput>;
/**
* Execution, display, or stream outputs.
*/
getOutputs(): Array<nbformat.IOutput>;
/**
* Add/Update output.
*/
setOutputs(outputs: Array<nbformat.IOutput>): void;
/**
* Replace content from `start' to `end` with `outputs`.
*
* @param start: The start index of the range to replace (inclusive).
*
* @param end: The end index of the range to replace (exclusive).
*
* @param outputs: New outputs (optional).
*/
updateOutputs(
start: number,
end: number,
outputs: Array<nbformat.IOutput>
): void;
/**
* Serialize the model to JSON.
*/
toJSON(): nbformat.IBaseCell;
}
/**
* Cell with attachment interface.
*/
export interface ISharedAttachmentsCell
extends ISharedBaseCell<nbformat.IBaseCellMetadata> {
/**
* Cell attachments
*/
attachments?: nbformat.IAttachments;
/**
* Gets the cell attachments.
*
* @returns The cell attachments.
*/
getAttachments(): nbformat.IAttachments | undefined;
/**
* Sets the cell attachments
*
* @param attachments: The cell attachments.
*/
setAttachments(attachments: nbformat.IAttachments | undefined): void;
}
/**
* Implements an API for nbformat.IMarkdownCell.
*/
export interface ISharedMarkdownCell extends ISharedAttachmentsCell {
/**
* String identifying the type of cell.
*/
cell_type: 'markdown';
/**
* Serialize the model to JSON.
*/
toJSON(): nbformat.IMarkdownCell;
}
/**
* Implements an API for nbformat.IRawCell.
*/
export interface ISharedRawCell extends ISharedAttachmentsCell {
/**
* String identifying the type of cell.
*/
cell_type: 'raw';
/**
* Serialize the model to JSON.
*/
toJSON(): nbformat.IRawCell;
}
/**
* Implements an API for nbformat.IUnrecognizedCell.
*/
export interface ISharedUnrecognizedCell
extends ISharedBaseCell<nbformat.IBaseCellMetadata> {
/**
* The type of the cell.
*
* The notebook format specified the type will not be 'markdown' | 'raw' | 'code'
*/
cell_type: string;
/**
* Serialize the model to JSON.
*/
toJSON(): nbformat.IUnrecognizedCell;
}
export type StateChange<T> = {
/**
* Key changed
*/
name: string;
/**
* Old value
*/
oldValue?: T;
/**
* New value
*/
newValue?: T;
};
/**
* Generic document change
*/
export type DocumentChange = {
/**
* Change occurring in the document state.
*/
stateChange?: StateChange<any>[];
};
/**
* The change types which occur on an observable map.
*/
export type MapChangeType =
/**
* An entry was added.
*/
| 'add'
/**
* An entry was removed.
*/
| 'remove'
/**
* An entry was changed.
*/
| 'change';
/**
* The changed args object which is emitted by an observable map.
*/
export interface IMapChange<T = any> {
/**
* The type of change undergone by the map.
*/
type: MapChangeType;
/**
* The key of the change.
*/
key: string;
/**
* The old value of the change.
*/
oldValue?: T;
/**
* The new value of the change.
*/
newValue?: T;
}
/**
* Text source change
*/
export type SourceChange = {
/**
* Text source change
*/
sourceChange?: Delta<string>;
};
/**
* Definition of the shared Notebook changes.
*/
export type NotebookChange = DocumentChange & {
/**
* Cell changes
*/
cellsChange?: Delta<ISharedCell[]>;
/**
* Notebook metadata changes
*/
metadataChange?: MapChanges;
/**
* nbformat version change
*/
nbformatChanged?: {
key: string;
oldValue?: number;
newValue?: number;
};
};
/**
* File change
*/
export type FileChange = DocumentChange & SourceChange;
/**
* Definition of the shared Cell changes.
*/
export type CellChange = SourceChange & {
/**
* Cell attachment change
*/
attachmentsChange?: {
oldValue?: nbformat.IAttachments;
newValue?: nbformat.IAttachments;
};
/**
* Cell output changes
*/
outputsChange?: Delta<Y.Map<any>>;
/**
* Cell stream output text changes
*/
streamOutputChange?: Delta<Y.Text>;
/**
* Cell execution count change
*/
executionCountChange?: {
oldValue?: number;
newValue?: number;
};
/**
* Cell execution state change
*/
executionStateChange?: {
oldValue?: IExecutionState;
newValue?: IExecutionState;
};
/**
* Cell metadata change
*/
metadataChange?: MapChanges;
};