You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3081 lines
88 KiB
JavaScript

"use strict";
(self["webpackChunk_JUPYTERLAB_CORE_OUTPUT"] = self["webpackChunk_JUPYTERLAB_CORE_OUTPUT"] || []).push([[35],{
/***/ 50035:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
// ESM COMPAT FLAG
__webpack_require__.r(__webpack_exports__);
// EXPORTS
__webpack_require__.d(__webpack_exports__, {
YBaseCell: () => (/* reexport */ YBaseCell),
YCodeCell: () => (/* reexport */ YCodeCell),
YDocument: () => (/* reexport */ YDocument),
YFile: () => (/* reexport */ YFile),
YMarkdownCell: () => (/* reexport */ YMarkdownCell),
YNotebook: () => (/* reexport */ YNotebook),
YRawCell: () => (/* reexport */ YRawCell),
convertYMapEventToMapChange: () => (/* reexport */ convertYMapEventToMapChange),
createMutex: () => (/* reexport */ createMutex),
createStandaloneCell: () => (/* reexport */ createStandaloneCell)
});
;// CONCATENATED MODULE: ../node_modules/@jupyter/ydoc/lib/utils.js
/* -----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
function convertYMapEventToMapChange(event) {
let changes = new Map();
event.changes.keys.forEach((event, key) => {
changes.set(key, {
action: event.action,
oldValue: event.oldValue,
newValue: this.ymeta.get(key)
});
});
return changes;
}
/**
* Creates a mutual exclude function with the following property:
*
* ```js
* const mutex = createMutex()
* mutex(() => {
* // This function is immediately executed
* mutex(() => {
* // This function is not executed, as the mutex is already active.
* })
* })
* ```
*/
const createMutex = () => {
let token = true;
return (f) => {
if (token) {
token = false;
try {
f();
}
finally {
token = true;
}
}
};
};
//# sourceMappingURL=utils.js.map
// EXTERNAL MODULE: consume shared module (default) @lumino/coreutils@~2.2.1 (singleton) (fallback: ../node_modules/@lumino/coreutils/dist/index.js)
var index_js_ = __webpack_require__(5406);
// EXTERNAL MODULE: consume shared module (default) @lumino/signaling@~2.1.4 (singleton) (fallback: ../node_modules/@lumino/signaling/dist/index.es6.js)
var index_es6_js_ = __webpack_require__(2536);
// EXTERNAL MODULE: ../node_modules/lib0/time.js
var lib0_time = __webpack_require__(2431);
// EXTERNAL MODULE: ../node_modules/lib0/math.js
var math = __webpack_require__(11182);
// EXTERNAL MODULE: ../node_modules/lib0/observable.js
var observable = __webpack_require__(12330);
// EXTERNAL MODULE: ../node_modules/lib0/function.js
var lib0_function = __webpack_require__(38828);
// EXTERNAL MODULE: consume shared module (default) yjs@~13.6.8 (singleton) (fallback: ../node_modules/yjs/dist/yjs.mjs)
var yjs_mjs_ = __webpack_require__(17843);
;// CONCATENATED MODULE: ../node_modules/y-protocols/awareness.js
/**
* @module awareness-protocol
*/
// eslint-disable-line
const outdatedTimeout = 30000
/**
* @typedef {Object} MetaClientState
* @property {number} MetaClientState.clock
* @property {number} MetaClientState.lastUpdated unix timestamp
*/
/**
* The Awareness class implements a simple shared state protocol that can be used for non-persistent data like awareness information
* (cursor, username, status, ..). Each client can update its own local state and listen to state changes of
* remote clients. Every client may set a state of a remote peer to `null` to mark the client as offline.
*
* Each client is identified by a unique client id (something we borrow from `doc.clientID`). A client can override
* its own state by propagating a message with an increasing timestamp (`clock`). If such a message is received, it is
* applied if the known state of that client is older than the new state (`clock < newClock`). If a client thinks that
* a remote client is offline, it may propagate a message with
* `{ clock: currentClientClock, state: null, client: remoteClient }`. If such a
* message is received, and the known clock of that client equals the received clock, it will override the state with `null`.
*
* Before a client disconnects, it should propagate a `null` state with an updated clock.
*
* Awareness states must be updated every 30 seconds. Otherwise the Awareness instance will delete the client state.
*
* @extends {Observable<string>}
*/
class Awareness extends observable/* Observable */.y {
/**
* @param {Y.Doc} doc
*/
constructor (doc) {
super()
this.doc = doc
/**
* @type {number}
*/
this.clientID = doc.clientID
/**
* Maps from client id to client state
* @type {Map<number, Object<string, any>>}
*/
this.states = new Map()
/**
* @type {Map<number, MetaClientState>}
*/
this.meta = new Map()
this._checkInterval = /** @type {any} */ (setInterval(() => {
const now = lib0_time/* getUnixTime */.ZG()
if (this.getLocalState() !== null && (outdatedTimeout / 2 <= now - /** @type {{lastUpdated:number}} */ (this.meta.get(this.clientID)).lastUpdated)) {
// renew local clock
this.setLocalState(this.getLocalState())
}
/**
* @type {Array<number>}
*/
const remove = []
this.meta.forEach((meta, clientid) => {
if (clientid !== this.clientID && outdatedTimeout <= now - meta.lastUpdated && this.states.has(clientid)) {
remove.push(clientid)
}
})
if (remove.length > 0) {
removeAwarenessStates(this, remove, 'timeout')
}
}, math/* floor */.GW(outdatedTimeout / 10)))
doc.on('destroy', () => {
this.destroy()
})
this.setLocalState({})
}
destroy () {
this.emit('destroy', [this])
this.setLocalState(null)
super.destroy()
clearInterval(this._checkInterval)
}
/**
* @return {Object<string,any>|null}
*/
getLocalState () {
return this.states.get(this.clientID) || null
}
/**
* @param {Object<string,any>|null} state
*/
setLocalState (state) {
const clientID = this.clientID
const currLocalMeta = this.meta.get(clientID)
const clock = currLocalMeta === undefined ? 0 : currLocalMeta.clock + 1
const prevState = this.states.get(clientID)
if (state === null) {
this.states.delete(clientID)
} else {
this.states.set(clientID, state)
}
this.meta.set(clientID, {
clock,
lastUpdated: lib0_time/* getUnixTime */.ZG()
})
const added = []
const updated = []
const filteredUpdated = []
const removed = []
if (state === null) {
removed.push(clientID)
} else if (prevState == null) {
if (state != null) {
added.push(clientID)
}
} else {
updated.push(clientID)
if (!lib0_function/* equalityDeep */.Hi(prevState, state)) {
filteredUpdated.push(clientID)
}
}
if (added.length > 0 || filteredUpdated.length > 0 || removed.length > 0) {
this.emit('change', [{ added, updated: filteredUpdated, removed }, 'local'])
}
this.emit('update', [{ added, updated, removed }, 'local'])
}
/**
* @param {string} field
* @param {any} value
*/
setLocalStateField (field, value) {
const state = this.getLocalState()
if (state !== null) {
this.setLocalState({
...state,
[field]: value
})
}
}
/**
* @return {Map<number,Object<string,any>>}
*/
getStates () {
return this.states
}
}
/**
* Mark (remote) clients as inactive and remove them from the list of active peers.
* This change will be propagated to remote clients.
*
* @param {Awareness} awareness
* @param {Array<number>} clients
* @param {any} origin
*/
const removeAwarenessStates = (awareness, clients, origin) => {
const removed = []
for (let i = 0; i < clients.length; i++) {
const clientID = clients[i]
if (awareness.states.has(clientID)) {
awareness.states.delete(clientID)
if (clientID === awareness.clientID) {
const curMeta = /** @type {MetaClientState} */ (awareness.meta.get(clientID))
awareness.meta.set(clientID, {
clock: curMeta.clock + 1,
lastUpdated: lib0_time/* getUnixTime */.ZG()
})
}
removed.push(clientID)
}
}
if (removed.length > 0) {
awareness.emit('change', [{ added: [], updated: [], removed }, origin])
awareness.emit('update', [{ added: [], updated: [], removed }, origin])
}
}
/**
* @param {Awareness} awareness
* @param {Array<number>} clients
* @return {Uint8Array}
*/
const encodeAwarenessUpdate = (awareness, clients, states = awareness.states) => {
const len = clients.length
const encoder = encoding.createEncoder()
encoding.writeVarUint(encoder, len)
for (let i = 0; i < len; i++) {
const clientID = clients[i]
const state = states.get(clientID) || null
const clock = /** @type {MetaClientState} */ (awareness.meta.get(clientID)).clock
encoding.writeVarUint(encoder, clientID)
encoding.writeVarUint(encoder, clock)
encoding.writeVarString(encoder, JSON.stringify(state))
}
return encoding.toUint8Array(encoder)
}
/**
* Modify the content of an awareness update before re-encoding it to an awareness update.
*
* This might be useful when you have a central server that wants to ensure that clients
* cant hijack somebody elses identity.
*
* @param {Uint8Array} update
* @param {function(any):any} modify
* @return {Uint8Array}
*/
const modifyAwarenessUpdate = (update, modify) => {
const decoder = decoding.createDecoder(update)
const encoder = encoding.createEncoder()
const len = decoding.readVarUint(decoder)
encoding.writeVarUint(encoder, len)
for (let i = 0; i < len; i++) {
const clientID = decoding.readVarUint(decoder)
const clock = decoding.readVarUint(decoder)
const state = JSON.parse(decoding.readVarString(decoder))
const modifiedState = modify(state)
encoding.writeVarUint(encoder, clientID)
encoding.writeVarUint(encoder, clock)
encoding.writeVarString(encoder, JSON.stringify(modifiedState))
}
return encoding.toUint8Array(encoder)
}
/**
* @param {Awareness} awareness
* @param {Uint8Array} update
* @param {any} origin This will be added to the emitted change event
*/
const applyAwarenessUpdate = (awareness, update, origin) => {
const decoder = decoding.createDecoder(update)
const timestamp = time.getUnixTime()
const added = []
const updated = []
const filteredUpdated = []
const removed = []
const len = decoding.readVarUint(decoder)
for (let i = 0; i < len; i++) {
const clientID = decoding.readVarUint(decoder)
let clock = decoding.readVarUint(decoder)
const state = JSON.parse(decoding.readVarString(decoder))
const clientMeta = awareness.meta.get(clientID)
const prevState = awareness.states.get(clientID)
const currClock = clientMeta === undefined ? 0 : clientMeta.clock
if (currClock < clock || (currClock === clock && state === null && awareness.states.has(clientID))) {
if (state === null) {
// never let a remote client remove this local state
if (clientID === awareness.clientID && awareness.getLocalState() != null) {
// remote client removed the local state. Do not remote state. Broadcast a message indicating
// that this client still exists by increasing the clock
clock++
} else {
awareness.states.delete(clientID)
}
} else {
awareness.states.set(clientID, state)
}
awareness.meta.set(clientID, {
clock,
lastUpdated: timestamp
})
if (clientMeta === undefined && state !== null) {
added.push(clientID)
} else if (clientMeta !== undefined && state === null) {
removed.push(clientID)
} else if (state !== null) {
if (!f.equalityDeep(state, prevState)) {
filteredUpdated.push(clientID)
}
updated.push(clientID)
}
}
}
if (added.length > 0 || filteredUpdated.length > 0 || removed.length > 0) {
awareness.emit('change', [{
added, updated: filteredUpdated, removed
}, origin])
}
if (added.length > 0 || updated.length > 0 || removed.length > 0) {
awareness.emit('update', [{
added, updated, removed
}, origin])
}
}
;// CONCATENATED MODULE: ../node_modules/@jupyter/ydoc/lib/ydocument.js
/* -----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/**
* Generic shareable document.
*/
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 index_es6_js_.Signal(this);
this._isDisposed = false;
this._disposed = new index_es6_js_.Signal(this);
this._ydoc = (_a = options === null || options === void 0 ? void 0 : options.ydoc) !== null && _a !== void 0 ? _a : new yjs_mjs_.Doc();
this._ystate = this._ydoc.getMap('state');
this._undoManager = new yjs_mjs_.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 index_js_.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();
index_es6_js_.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
: index_js_.JSONExt.deepCopy(value);
}
/**
* Set the value of a state attribute
*
* @param key Key to set
* @param value New attribute value
*/
setState(key, value) {
if (!index_js_.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
;// CONCATENATED MODULE: ../node_modules/@jupyter/ydoc/lib/yfile.js
/* -----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/**
* Shareable text file.
*/
class YFile extends YDocument {
/**
* Create a new file
*
* #### Notes
* The document is empty and must be populated
*/
constructor() {
super();
/**
* Document version
*/
this.version = '1.0.0';
/**
* YJS file text.
*/
this.ysource = this.ydoc.getText('source');
/**
* Handle a change to the ymodel.
*/
this._modelObserver = (event) => {
this._changed.emit({ sourceChange: event.changes.delta });
};
this.undoManager.addToScope(this.ysource);
this.ysource.observe(this._modelObserver);
}
/**
* Creates a standalone YFile
*/
static create() {
return new YFile();
}
/**
* File text
*/
get source() {
return this.getSource();
}
set source(v) {
this.setSource(v);
}
/**
* Dispose of the resources.
*/
dispose() {
if (this.isDisposed) {
return;
}
this.ysource.unobserve(this._modelObserver);
super.dispose();
}
/**
* Get the file text.
*
* @returns File text.
*/
getSource() {
return this.ysource.toString();
}
/**
* Set the file text.
*
* @param value New text
*/
setSource(value) {
this.transact(() => {
const ytext = this.ysource;
ytext.delete(0, ytext.length);
ytext.insert(0, value);
});
}
/**
* 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, end, value = '') {
this.transact(() => {
const ysource = this.ysource;
// insert and then delete.
// This ensures that the cursor position is adjusted after the replaced content.
ysource.insert(start, value);
ysource.delete(start + value.length, end - start);
});
}
}
//# sourceMappingURL=yfile.js.map
;// CONCATENATED MODULE: ../node_modules/@jupyter/ydoc/lib/ycell.js
/* -----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/**
* Create a new shared cell model given the YJS shared type.
*/
const createCellModelFromSharedType = (type, options = {}) => {
switch (type.get('cell_type')) {
case 'code':
return new YCodeCell(type, type.get('source'), type.get('outputs'), options);
case 'markdown':
return new YMarkdownCell(type, type.get('source'), options);
case 'raw':
return new YRawCell(type, type.get('source'), options);
default:
throw new Error('Found unknown cell type');
}
};
/**
* Create a new cell that can be inserted in an existing shared model.
*
* If no notebook is specified the cell will be standalone.
*
* @param cell Cell JSON representation
* @param notebook Notebook to which the cell will be added
*/
const createCell = (cell, notebook) => {
var _a, _b;
const ymodel = new yjs_mjs_.Map();
const ysource = new yjs_mjs_.Text();
const ymetadata = new yjs_mjs_.Map();
ymodel.set('source', ysource);
ymodel.set('metadata', ymetadata);
ymodel.set('cell_type', cell.cell_type);
ymodel.set('id', (_a = cell.id) !== null && _a !== void 0 ? _a : index_js_.UUID.uuid4());
let ycell;
switch (cell.cell_type) {
case 'markdown': {
ycell = new YMarkdownCell(ymodel, ysource, { notebook }, ymetadata);
if (cell.attachments != null) {
ycell.setAttachments(cell.attachments);
}
break;
}
case 'code': {
const youtputs = new yjs_mjs_.Array();
ymodel.set('outputs', youtputs);
ycell = new YCodeCell(ymodel, ysource, youtputs, {
notebook
}, ymetadata);
const cCell = cell;
ycell.execution_count = (_b = cCell.execution_count) !== null && _b !== void 0 ? _b : null;
if (cCell.outputs) {
ycell.setOutputs(cCell.outputs);
}
break;
}
default: {
// raw
ycell = new YRawCell(ymodel, ysource, { notebook }, ymetadata);
if (cell.attachments) {
ycell.setAttachments(cell.attachments);
}
break;
}
}
if (cell.metadata != null) {
ycell.setMetadata(cell.metadata);
}
if (cell.source != null) {
ycell.setSource(typeof cell.source === 'string' ? cell.source : cell.source.join(''));
}
return ycell;
};
/**
* Create a new cell that cannot be inserted in an existing shared model.
*
* @param cell Cell JSON representation
*/
const createStandaloneCell = (cell) => createCell(cell);
class YBaseCell {
/**
* Create a new YCell that works standalone. It cannot be
* inserted into a YNotebook because the Yjs model is already
* attached to an anonymous Y.Doc instance.
*/
static create(id) {
return createCell({ id, cell_type: this.prototype.cell_type });
}
/**
* Base cell constructor
*
* ### Notes
* Don't use the constructor directly - prefer using ``YNotebook.insertCell``
*
* The ``ysource`` is needed because ``ymodel.get('source')`` will
* not return the real source if the model is not yet attached to
* a document. Requesting it explicitly allows to introspect a non-empty
* source before the cell is attached to the document.
*
* @param ymodel Cell map
* @param ysource Cell source
* @param options \{ notebook?: The notebook the cell is attached to \}
* @param ymetadata Cell metadata
*/
constructor(ymodel, ysource, options = {}, ymetadata) {
/**
* Handle a change to the ymodel.
*/
this._modelObserver = (events, transaction) => {
if (transaction.origin !== 'silent-change') {
this._changed.emit(this.getChanges(events));
}
};
this._metadataChanged = new index_es6_js_.Signal(this);
/**
* The notebook that this cell belongs to.
*/
this._notebook = null;
this._changed = new index_es6_js_.Signal(this);
this._disposed = new index_es6_js_.Signal(this);
this._isDisposed = false;
this._undoManager = null;
this.ymodel = ymodel;
this._ysource = ysource;
this._ymetadata = ymetadata !== null && ymetadata !== void 0 ? ymetadata : this.ymodel.get('metadata');
this._prevSourceLength = ysource ? ysource.length : 0;
this._notebook = null;
this._awareness = null;
this._undoManager = null;
if (options.notebook) {
this._notebook = options.notebook;
if (this._notebook.disableDocumentWideUndoRedo) {
this._undoManager = new yjs_mjs_.UndoManager([this.ymodel], {
trackedOrigins: new Set([this]),
doc: this._notebook.ydoc
});
}
}
else {
// Standalone cell
const doc = new yjs_mjs_.Doc();
doc.getArray().insert(0, [this.ymodel]);
this._awareness = new Awareness(doc);
this._undoManager = new yjs_mjs_.UndoManager([this.ymodel], {
trackedOrigins: new Set([this])
});
}
this.ymodel.observeDeep(this._modelObserver);
}
/**
* Cell notebook awareness or null.
*/
get awareness() {
var _a, _b, _c;
return (_c = (_a = this._awareness) !== null && _a !== void 0 ? _a : (_b = this.notebook) === null || _b === void 0 ? void 0 : _b.awareness) !== null && _c !== void 0 ? _c : null;
}
/**
* The type of the cell.
*/
get cell_type() {
throw new Error('A YBaseCell must not be constructed');
}
/**
* The changed signal.
*/
get changed() {
return this._changed;
}
/**
* Signal emitted when the cell is disposed.
*/
get disposed() {
return this._disposed;
}
/**
* Cell id
*/
get id() {
return this.getId();
}
/**
* Whether the model has been disposed or not.
*/
get isDisposed() {
return this._isDisposed;
}
/**
* 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.
*/
get isStandalone() {
return this._notebook !== null;
}
/**
* Cell metadata.
*
* #### Notes
* You should prefer to access and modify the specific key of interest.
*/
get metadata() {
return this.getMetadata();
}
set metadata(v) {
this.setMetadata(v);
}
/**
* Signal triggered when the cell metadata changes.
*/
get metadataChanged() {
return this._metadataChanged;
}
/**
* The notebook that this cell belongs to.
*/
get notebook() {
return this._notebook;
}
/**
* Cell input content.
*/
get source() {
return this.getSource();
}
set source(v) {
this.setSource(v);
}
/**
* The cell undo manager.
*/
get undoManager() {
var _a;
if (!this.notebook) {
return this._undoManager;
}
return ((_a = this.notebook) === null || _a === void 0 ? void 0 : _a.disableDocumentWideUndoRedo)
? this._undoManager
: this.notebook.undoManager;
}
get ysource() {
return this._ysource;
}
/**
* Whether the object can undo changes.
*/
canUndo() {
return !!this.undoManager && this.undoManager.undoStack.length > 0;
}
/**
* Whether the object can redo changes.
*/
canRedo() {
return !!this.undoManager && this.undoManager.redoStack.length > 0;
}
/**
* Clear the change stack.
*/
clearUndoHistory() {
var _a;
(_a = this.undoManager) === null || _a === void 0 ? void 0 : _a.clear();
}
/**
* Undo an operation.
*/
undo() {
var _a;
(_a = this.undoManager) === null || _a === void 0 ? void 0 : _a.undo();
}
/**
* Redo an operation.
*/
redo() {
var _a;
(_a = this.undoManager) === null || _a === void 0 ? void 0 : _a.redo();
}
/**
* Dispose of the resources.
*/
dispose() {
var _a;
if (this._isDisposed)
return;
this._isDisposed = true;
this.ymodel.unobserveDeep(this._modelObserver);
if (this._awareness) {
// A new document is created for standalone cell.
const doc = this._awareness.doc;
this._awareness.destroy();
doc.destroy();
}
if (this._undoManager) {
// Be sure to not destroy the document undo manager.
if (this._undoManager === ((_a = this.notebook) === null || _a === void 0 ? void 0 : _a.undoManager)) {
this._undoManager = null;
}
else {
this._undoManager.destroy();
}
}
this._disposed.emit();
index_es6_js_.Signal.clearData(this);
}
/**
* Get cell id.
*
* @returns Cell id
*/
getId() {
return this.ymodel.get('id');
}
/**
* Gets cell's source.
*
* @returns Cell's source.
*/
getSource() {
return this.ysource.toString();
}
/**
* Sets cell's source.
*
* @param value: New source.
*/
setSource(value) {
this.transact(() => {
this.ysource.delete(0, this.ysource.length);
this.ysource.insert(0, value);
});
// @todo Do we need proper replace semantic? This leads to issues in editor bindings because they don't switch source.
// this.ymodel.set('source', new Y.Text(value));
}
/**
* 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, end, value = '') {
this.transact(() => {
const ysource = this.ysource;
// insert and then delete.
// This ensures that the cursor position is adjusted after the replaced content.
ysource.insert(start, value);
ysource.delete(start + value.length, end - start);
});
}
/**
* Delete a metadata cell.
*
* @param key The key to delete
*/
deleteMetadata(key) {
if (typeof this.getMetadata(key) === 'undefined') {
return;
}
this.transact(() => {
this._ymetadata.delete(key);
const jupyter = this.getMetadata('jupyter');
if (key === 'collapsed' && jupyter) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { outputs_hidden, ...others } = jupyter;
if (Object.keys(others).length === 0) {
this._ymetadata.delete('jupyter');
}
else {
this._ymetadata.set('jupyter', others);
}
}
else if (key === 'jupyter') {
this._ymetadata.delete('collapsed');
}
}, false);
}
getMetadata(key) {
const metadata = this._ymetadata;
// Transiently the metadata can be missing - like during destruction
if (metadata === undefined) {
return undefined;
}
if (typeof key === 'string') {
const value = metadata.get(key);
return typeof value === 'undefined'
? undefined // undefined is converted to `{}` by `JSONExt.deepCopy`
: index_js_.JSONExt.deepCopy(metadata.get(key));
}
else {
return index_js_.JSONExt.deepCopy(metadata.toJSON());
}
}
setMetadata(metadata, value) {
var _a, _b;
if (typeof metadata === 'string') {
if (typeof value === 'undefined') {
throw new TypeError(`Metadata value for ${metadata} cannot be 'undefined'; use deleteMetadata.`);
}
const key = metadata;
// Only set metadata if we change something to avoid infinite
// loop of signal changes.
if (index_js_.JSONExt.deepEqual((_a = this.getMetadata(key)) !== null && _a !== void 0 ? _a : null, value)) {
return;
}
this.transact(() => {
var _a;
this._ymetadata.set(key, value);
if (key === 'collapsed') {
const jupyter = ((_a = this.getMetadata('jupyter')) !== null && _a !== void 0 ? _a : {});
if (jupyter.outputs_hidden !== value) {
this.setMetadata('jupyter', {
...jupyter,
outputs_hidden: value
});
}
}
else if (key === 'jupyter') {
const isHidden = value['outputs_hidden'];
if (typeof isHidden !== 'undefined') {
if (this.getMetadata('collapsed') !== isHidden) {
this.setMetadata('collapsed', isHidden);
}
}
else {
this.deleteMetadata('collapsed');
}
}
}, false);
}
else {
const clone = index_js_.JSONExt.deepCopy(metadata);
if (clone.collapsed != null) {
clone.jupyter = clone.jupyter || {};
clone.jupyter.outputs_hidden = clone.collapsed;
}
else if (((_b = clone === null || clone === void 0 ? void 0 : clone.jupyter) === null || _b === void 0 ? void 0 : _b.outputs_hidden) != null) {
clone.collapsed = clone.jupyter.outputs_hidden;
}
if (!index_js_.JSONExt.deepEqual(clone, this.getMetadata())) {
this.transact(() => {
for (const [key, value] of Object.entries(clone)) {
this._ymetadata.set(key, value);
}
}, false);
}
}
}
/**
* Serialize the model to JSON.
*/
toJSON() {
return {
id: this.getId(),
cell_type: this.cell_type,
source: this.getSource(),
metadata: this.getMetadata()
};
}
/**
* 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, undoable = true, origin = null) {
!this.notebook || this.notebook.disableDocumentWideUndoRedo
? this.ymodel.doc == null
? f()
: this.ymodel.doc.transact(f, undoable ? this : origin)
: this.notebook.transact(f, undoable);
}
/**
* Extract changes from YJS events
*
* @param events YJS events
* @returns Cell changes
*/
getChanges(events) {
const changes = {};
const sourceEvent = events.find(event => event.target === this.ymodel.get('source'));
if (sourceEvent) {
changes.sourceChange = sourceEvent.changes.delta;
}
const metadataEvents = events.find(event => event.target === this._ymetadata);
if (metadataEvents) {
changes.metadataChange = metadataEvents.changes.keys;
metadataEvents.changes.keys.forEach((change, key) => {
switch (change.action) {
case 'add':
this._metadataChanged.emit({
key,
newValue: this._ymetadata.get(key),
type: 'add'
});
break;
case 'delete':
this._metadataChanged.emit({
key,
oldValue: change.oldValue,
type: 'remove'
});
break;
case 'update':
{
const newValue = this._ymetadata.get(key);
const oldValue = change.oldValue;
let equal = true;
if (typeof oldValue == 'object' && typeof newValue == 'object') {
equal = index_js_.JSONExt.deepEqual(oldValue, newValue);
}
else {
equal = oldValue === newValue;
}
if (!equal) {
this._metadataChanged.emit({
key,
type: 'change',
oldValue,
newValue
});
}
}
break;
}
});
}
const modelEvent = events.find(event => event.target === this.ymodel);
// The model allows us to replace the complete source with a new string. We express this in the Delta format
// as a replace of the complete string.
const ysource = this.ymodel.get('source');
if (modelEvent && modelEvent.keysChanged.has('source')) {
changes.sourceChange = [
{ delete: this._prevSourceLength },
{ insert: ysource.toString() }
];
}
this._prevSourceLength = ysource.length;
return changes;
}
}
/**
* Shareable code cell.
*/
class YCodeCell extends YBaseCell {
/**
* Create a new YCodeCell that works standalone. It cannot be
* inserted into a YNotebook because the Yjs model is already
* attached to an anonymous Y.Doc instance.
*/
static create(id) {
return super.create(id);
}
/**
* Code cell constructor
*
* ### Notes
* Don't use the constructor directly - prefer using ``YNotebook.insertCell``
*
* The ``ysource`` is needed because ``ymodel.get('source')`` will
* not return the real source if the model is not yet attached to
* a document. Requesting it explicitly allows to introspect a non-empty
* source before the cell is attached to the document.
*
* @param ymodel Cell map
* @param ysource Cell source
* @param youtputs Code cell outputs
* @param options \{ notebook?: The notebook the cell is attached to \}
* @param ymetadata Cell metadata
*/
constructor(ymodel, ysource, youtputs, options = {}, ymetadata) {
super(ymodel, ysource, options, ymetadata);
this._youtputs = youtputs;
}
/**
* The type of the cell.
*/
get cell_type() {
return 'code';
}
/**
* The code cell's prompt number. Will be null if the cell has not been run.
*/
get execution_count() {
return this.ymodel.get('execution_count') || null;
}
set execution_count(count) {
// Do not use `this.execution_count`. When initializing the
// cell, we need to set execution_count to `null` if we compare
// using `this.execution_count` it will return `null` and we will
// never initialize it
if (this.ymodel.get('execution_count') !== count) {
this.transact(() => {
this.ymodel.set('execution_count', count);
}, false);
}
}
/**
* The code cell's execution state.
*/
get executionState() {
var _a;
return (_a = this.ymodel.get('execution_state')) !== null && _a !== void 0 ? _a : 'idle';
}
set executionState(state) {
if (this.ymodel.get('execution_state') !== state) {
this.transact(() => {
this.ymodel.set('execution_state', state);
}, false);
}
}
/**
* Cell outputs.
*/
get outputs() {
return this.getOutputs();
}
set outputs(v) {
this.setOutputs(v);
}
get youtputs() {
return this._youtputs;
}
/**
* Execution, display, or stream outputs.
*/
getOutputs() {
return index_js_.JSONExt.deepCopy(this._youtputs.toJSON());
}
createOutputs(outputs) {
const newOutputs = [];
for (const output of index_js_.JSONExt.deepCopy(outputs)) {
let _newOutput1;
if (output.output_type === 'stream') {
// Set the text field as a Y.Text
const { text, ...outputWithoutText } = output;
_newOutput1 = outputWithoutText;
const newText = new yjs_mjs_.Text();
let _text = text instanceof Array ? text.join() : text;
newText.insert(0, _text);
_newOutput1['text'] = newText;
}
else {
_newOutput1 = output;
}
const _newOutput2 = [];
for (const [key, value] of Object.entries(_newOutput1)) {
_newOutput2.push([key, value]);
}
const newOutput = new yjs_mjs_.Map(_newOutput2);
newOutputs.push(newOutput);
}
return newOutputs;
}
/**
* Replace all outputs.
*/
setOutputs(outputs) {
this.transact(() => {
this._youtputs.delete(0, this._youtputs.length);
const newOutputs = this.createOutputs(outputs);
this._youtputs.insert(0, newOutputs);
}, false);
}
/**
* Remove text from a stream output.
*/
removeStreamOutput(index, start, origin = null) {
this.transact(() => {
const output = this._youtputs.get(index);
const prevText = output.get('text');
const length = prevText.length - start;
prevText.delete(start, length);
}, false, origin);
}
/**
* Append text to a stream output.
*/
appendStreamOutput(index, text, origin = null) {
this.transact(() => {
const output = this._youtputs.get(index);
const prevText = output.get('text');
prevText.insert(prevText.length, text);
}, false, origin);
}
/**
* 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, end, outputs = [], origin = null) {
const fin = end < this._youtputs.length ? end - start : this._youtputs.length - start;
this.transact(() => {
this._youtputs.delete(start, fin);
const newOutputs = this.createOutputs(outputs);
this._youtputs.insert(start, newOutputs);
}, false, origin);
}
/**
* Clear all outputs from the cell.
*/
clearOutputs(origin = null) {
this.transact(() => {
this._youtputs.delete(0, this._youtputs.length);
}, false, origin);
}
/**
* Serialize the model to JSON.
*/
toJSON() {
return {
...super.toJSON(),
outputs: this.getOutputs(),
execution_count: this.execution_count
};
}
/**
* Extract changes from YJS events
*
* @param events YJS events
* @returns Cell changes
*/
getChanges(events) {
const changes = super.getChanges(events);
const streamOutputEvent = events.find(
// Changes to the 'text' of a cell's stream output can be accessed like so:
// ycell['outputs'][output_idx]['text']
// This translates to an event path of: ['outputs', output_idx, 'text]
event => event.path.length === 3 &&
event.path[0] === 'outputs' &&
event.path[2] === 'text');
if (streamOutputEvent) {
changes.streamOutputChange = streamOutputEvent.changes.delta;
}
const outputEvent = events.find(event => event.target === this.ymodel.get('outputs'));
if (outputEvent) {
changes.outputsChange = outputEvent.changes.delta;
}
const modelEvent = events.find(event => event.target === this.ymodel);
if (modelEvent && modelEvent.keysChanged.has('execution_count')) {
const change = modelEvent.changes.keys.get('execution_count');
changes.executionCountChange = {
oldValue: change.oldValue,
newValue: this.ymodel.get('execution_count')
};
}
if (modelEvent && modelEvent.keysChanged.has('execution_state')) {
const change = modelEvent.changes.keys.get('execution_state');
changes.executionStateChange = {
oldValue: change.oldValue,
newValue: this.ymodel.get('execution_state')
};
}
return changes;
}
}
class YAttachmentCell extends YBaseCell {
/**
* Cell attachments
*/
get attachments() {
return this.getAttachments();
}
set attachments(v) {
this.setAttachments(v);
}
/**
* Gets the cell attachments.
*
* @returns The cell attachments.
*/
getAttachments() {
return this.ymodel.get('attachments');
}
/**
* Sets the cell attachments
*
* @param attachments: The cell attachments.
*/
setAttachments(attachments) {
this.transact(() => {
if (attachments == null) {
this.ymodel.delete('attachments');
}
else {
this.ymodel.set('attachments', attachments);
}
}, false);
}
/**
* Extract changes from YJS events
*
* @param events YJS events
* @returns Cell changes
*/
getChanges(events) {
const changes = super.getChanges(events);
const modelEvent = events.find(event => event.target === this.ymodel);
if (modelEvent && modelEvent.keysChanged.has('attachments')) {
const change = modelEvent.changes.keys.get('attachments');
changes.attachmentsChange = {
oldValue: change.oldValue,
newValue: this.ymodel.get('attachments')
};
}
return changes;
}
}
/**
* Shareable raw cell.
*/
class YRawCell extends YAttachmentCell {
/**
* Create a new YRawCell that works standalone. It cannot be
* inserted into a YNotebook because the Yjs model is already
* attached to an anonymous Y.Doc instance.
*/
static create(id) {
return super.create(id);
}
/**
* String identifying the type of cell.
*/
get cell_type() {
return 'raw';
}
/**
* Serialize the model to JSON.
*/
toJSON() {
return {
id: this.getId(),
cell_type: 'raw',
source: this.getSource(),
metadata: this.getMetadata(),
attachments: this.getAttachments()
};
}
}
/**
* Shareable markdown cell.
*/
class YMarkdownCell extends YAttachmentCell {
/**
* Create a new YMarkdownCell that works standalone. It cannot be
* inserted into a YNotebook because the Yjs model is already
* attached to an anonymous Y.Doc instance.
*/
static create(id) {
return super.create(id);
}
/**
* String identifying the type of cell.
*/
get cell_type() {
return 'markdown';
}
/**
* Serialize the model to JSON.
*/
toJSON() {
return {
id: this.getId(),
cell_type: 'markdown',
source: this.getSource(),
metadata: this.getMetadata(),
attachments: this.getAttachments()
};
}
}
//# sourceMappingURL=ycell.js.map
;// CONCATENATED MODULE: ../node_modules/@jupyter/ydoc/lib/ynotebook.js
/* -----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/**
* Shared implementation of the Shared Document types.
*
* Shared cells can be inserted into a SharedNotebook.
* Shared cells only start emitting events when they are connected to a SharedNotebook.
*
* "Standalone" cells must not be inserted into a (Shared)Notebook.
* Standalone cells emit events immediately after they have been created, but they must not
* be included into a (Shared)Notebook.
*/
class YNotebook extends YDocument {
/**
* Create a new notebook
*
* #### Notes
* The document is empty and must be populated
*
* @param options
*/
constructor(options = {}) {
var _a;
super();
/**
* Document version
*/
this.version = '2.0.0';
/**
* YJS map for the notebook metadata
*/
this.ymeta = this.ydoc.getMap('meta');
/**
* Handle a change to the ystate.
*/
this._onMetaChanged = (events) => {
const metadataEvents = events.find(event => event.target === this.ymeta.get('metadata'));
if (metadataEvents) {
const metadataChange = metadataEvents.changes.keys;
const ymetadata = this.ymeta.get('metadata');
metadataEvents.changes.keys.forEach((change, key) => {
switch (change.action) {
case 'add':
this._metadataChanged.emit({
key,
type: 'add',
newValue: ymetadata.get(key)
});
break;
case 'delete':
this._metadataChanged.emit({
key,
type: 'remove',
oldValue: change.oldValue
});
break;
case 'update':
{
const newValue = ymetadata.get(key);
const oldValue = change.oldValue;
let equal = true;
if (typeof oldValue == 'object' && typeof newValue == 'object') {
equal = index_js_.JSONExt.deepEqual(oldValue, newValue);
}
else {
equal = oldValue === newValue;
}
if (!equal) {
this._metadataChanged.emit({
key,
type: 'change',
oldValue,
newValue
});
}
}
break;
}
});
this._changed.emit({ metadataChange });
}
const metaEvent = events.find(event => event.target === this.ymeta);
if (!metaEvent) {
return;
}
if (metaEvent.keysChanged.has('metadata')) {
// Handle metadata change when adding/removing the YMap
const change = metaEvent.changes.keys.get('metadata');
if ((change === null || change === void 0 ? void 0 : change.action) === 'add' && !change.oldValue) {
const metadataChange = new Map();
for (const key of Object.keys(this.metadata)) {
metadataChange.set(key, {
action: 'add',
oldValue: undefined
});
this._metadataChanged.emit({
key,
type: 'add',
newValue: this.getMetadata(key)
});
}
this._changed.emit({ metadataChange });
}
}
if (metaEvent.keysChanged.has('nbformat')) {
const change = metaEvent.changes.keys.get('nbformat');
const nbformatChanged = {
key: 'nbformat',
oldValue: (change === null || change === void 0 ? void 0 : change.oldValue) ? change.oldValue : undefined,
newValue: this.nbformat
};
this._changed.emit({ nbformatChanged });
}
if (metaEvent.keysChanged.has('nbformat_minor')) {
const change = metaEvent.changes.keys.get('nbformat_minor');
const nbformatChanged = {
key: 'nbformat_minor',
oldValue: (change === null || change === void 0 ? void 0 : change.oldValue) ? change.oldValue : undefined,
newValue: this.nbformat_minor
};
this._changed.emit({ nbformatChanged });
}
};
/**
* Handle a change to the list of cells.
*/
this._onYCellsChanged = (event) => {
// update the type cell mapping by iterating through the added/removed types
event.changes.added.forEach(item => {
const type = item.content.type;
if (!this._ycellMapping.has(type)) {
const c = createCellModelFromSharedType(type, { notebook: this });
this._ycellMapping.set(type, c);
}
});
event.changes.deleted.forEach(item => {
const type = item.content.type;
const model = this._ycellMapping.get(type);
if (model) {
model.dispose();
this._ycellMapping.delete(type);
}
});
let index = 0;
// this reflects the event.changes.delta, but replaces the content of delta.insert with ycells
const cellsChange = [];
event.changes.delta.forEach((d) => {
if (d.insert != null) {
const insertedCells = d.insert.map((ycell) => this._ycellMapping.get(ycell));
cellsChange.push({ insert: insertedCells });
this.cells.splice(index, 0, ...insertedCells);
index += d.insert.length;
}
else if (d.delete != null) {
cellsChange.push(d);
this.cells.splice(index, d.delete);
}
else if (d.retain != null) {
cellsChange.push(d);
index += d.retain;
}
});
this._changed.emit({
cellsChange: cellsChange
});
};
this._metadataChanged = new index_es6_js_.Signal(this);
/**
* Internal Yjs cells list
*/
this._ycells = this.ydoc.getArray('cells');
this._ycellMapping = new WeakMap();
this._disableDocumentWideUndoRedo =
(_a = options.disableDocumentWideUndoRedo) !== null && _a !== void 0 ? _a : false;
this.cells = this._ycells.toArray().map(ycell => {
if (!this._ycellMapping.has(ycell)) {
this._ycellMapping.set(ycell, createCellModelFromSharedType(ycell, { notebook: this }));
}
return this._ycellMapping.get(ycell);
});
this.undoManager.addToScope(this._ycells);
this._ycells.observe(this._onYCellsChanged);
this.ymeta.observeDeep(this._onMetaChanged);
}
/**
* Creates a standalone YNotebook
*
* Note: This method is useful when we need to initialize
* the YNotebook from the JavaScript side.
*/
static create(options = {}) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
const ynotebook = new YNotebook({
disableDocumentWideUndoRedo: (_a = options.disableDocumentWideUndoRedo) !== null && _a !== void 0 ? _a : false
});
const data = {
cells: (_c = (_b = options.data) === null || _b === void 0 ? void 0 : _b.cells) !== null && _c !== void 0 ? _c : [],
nbformat: (_e = (_d = options.data) === null || _d === void 0 ? void 0 : _d.nbformat) !== null && _e !== void 0 ? _e : 4,
nbformat_minor: (_g = (_f = options.data) === null || _f === void 0 ? void 0 : _f.nbformat_minor) !== null && _g !== void 0 ? _g : 5,
metadata: (_j = (_h = options.data) === null || _h === void 0 ? void 0 : _h.metadata) !== null && _j !== void 0 ? _j : {}
};
ynotebook.fromJSON(data);
return ynotebook;
}
/**
* Wether the undo/redo logic should be
* considered on the full document across all cells.
*
* Default: false
*/
get disableDocumentWideUndoRedo() {
return this._disableDocumentWideUndoRedo;
}
/**
* Notebook metadata
*/
get metadata() {
return this.getMetadata();
}
set metadata(v) {
this.setMetadata(v);
}
/**
* Signal triggered when a metadata changes.
*/
get metadataChanged() {
return this._metadataChanged;
}
/**
* nbformat major version
*/
get nbformat() {
return this.ymeta.get('nbformat');
}
set nbformat(value) {
this.transact(() => {
this.ymeta.set('nbformat', value);
}, false);
}
/**
* nbformat minor version
*/
get nbformat_minor() {
return this.ymeta.get('nbformat_minor');
}
set nbformat_minor(value) {
this.transact(() => {
this.ymeta.set('nbformat_minor', value);
}, false);
}
/**
* Dispose of the resources.
*/
dispose() {
if (this.isDisposed) {
return;
}
this._ycells.unobserve(this._onYCellsChanged);
this.ymeta.unobserveDeep(this._onMetaChanged);
super.dispose();
}
/**
* Get a shared cell by index.
*
* @param index: Cell's position.
*
* @returns The requested shared cell.
*/
getCell(index) {
return this.cells[index];
}
/**
* Add a shared cell at the notebook bottom.
*
* @param cell Cell to add.
*
* @returns The added cell.
*/
addCell(cell) {
return this.insertCell(this._ycells.length, cell);
}
/**
* Insert a shared cell into a specific position.
*
* @param index: Cell's position.
* @param cell: Cell to insert.
*
* @returns The inserted cell.
*/
insertCell(index, cell) {
return this.insertCells(index, [cell])[0];
}
/**
* 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, cells) {
const yCells = cells.map(c => {
const cell = createCell(c, this);
this._ycellMapping.set(cell.ymodel, cell);
return cell;
});
this.transact(() => {
this._ycells.insert(index, yCells.map(cell => cell.ymodel));
});
return yCells;
}
/**
* Move a cell.
*
* @param fromIndex: Index of the cell to move.
* @param toIndex: New position of the cell.
*/
moveCell(fromIndex, toIndex) {
this.moveCells(fromIndex, toIndex);
}
/**
* 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, toIndex, n = 1) {
// FIXME we need to use yjs move feature to preserve undo history
const clones = new Array(n)
.fill(true)
.map((_, idx) => this.getCell(fromIndex + idx).toJSON());
this.transact(() => {
this._ycells.delete(fromIndex, n);
this._ycells.insert(fromIndex > toIndex ? toIndex : toIndex - n + 1, clones.map(clone => createCell(clone, this).ymodel));
});
}
/**
* Remove a cell.
*
* @param index: Index of the cell to remove.
*/
deleteCell(index) {
this.deleteCellRange(index, index + 1);
}
/**
* 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, to) {
// Cells will be removed from the mapping in the model event listener.
this.transact(() => {
this._ycells.delete(from, to - from);
});
}
/**
* Delete a metadata notebook.
*
* @param key The key to delete
*/
deleteMetadata(key) {
if (typeof this.getMetadata(key) === 'undefined') {
return;
}
const allMetadata = this.metadata;
delete allMetadata[key];
this.setMetadata(allMetadata);
}
getMetadata(key) {
const ymetadata = this.ymeta.get('metadata');
// Transiently the metadata can be missing - like during destruction
if (ymetadata === undefined) {
return undefined;
}
if (typeof key === 'string') {
const value = ymetadata.get(key);
return typeof value === 'undefined'
? undefined // undefined is converted to `{}` by `JSONExt.deepCopy`
: index_js_.JSONExt.deepCopy(value);
}
else {
return index_js_.JSONExt.deepCopy(ymetadata.toJSON());
}
}
setMetadata(metadata, value) {
var _a;
if (typeof metadata === 'string') {
if (typeof value === 'undefined') {
throw new TypeError(`Metadata value for ${metadata} cannot be 'undefined'; use deleteMetadata.`);
}
if (index_js_.JSONExt.deepEqual((_a = this.getMetadata(metadata)) !== null && _a !== void 0 ? _a : null, value)) {
return;
}
const update = {};
update[metadata] = value;
this.updateMetadata(update);
}
else {
if (!this.metadata || !index_js_.JSONExt.deepEqual(this.metadata, metadata)) {
const clone = index_js_.JSONExt.deepCopy(metadata);
const ymetadata = this.ymeta.get('metadata');
// Transiently the metadata can be missing - like during destruction
if (ymetadata === undefined) {
return undefined;
}
this.transact(() => {
ymetadata.clear();
for (const [key, value] of Object.entries(clone)) {
ymetadata.set(key, value);
}
});
}
}
}
/**
* Updates the metadata associated with the notebook.
*
* @param value: Metadata's attribute to update.
*/
updateMetadata(value) {
// TODO: Maybe modify only attributes instead of replacing the whole metadata?
const clone = index_js_.JSONExt.deepCopy(value);
const ymetadata = this.ymeta.get('metadata');
// Transiently the metadata can be missing - like during destruction
if (ymetadata === undefined) {
return undefined;
}
this.transact(() => {
for (const [key, value] of Object.entries(clone)) {
ymetadata.set(key, value);
}
});
}
/**
* Get the notebook source
*
* @returns The notebook
*/
getSource() {
return this.toJSON();
}
/**
* Set the notebook source
*
* @param value The notebook
*/
setSource(value) {
this.fromJSON(value);
}
/**
* Override the notebook with a JSON-serialized document.
*
* @param value The notebook
*/
fromJSON(value) {
this.transact(() => {
this.nbformat = value.nbformat;
this.nbformat_minor = value.nbformat_minor;
const metadata = value.metadata;
if (metadata['orig_nbformat'] !== undefined) {
delete metadata['orig_nbformat'];
}
if (!this.metadata) {
const ymetadata = new yjs_mjs_.Map();
for (const [key, value] of Object.entries(metadata)) {
ymetadata.set(key, value);
}
this.ymeta.set('metadata', ymetadata);
}
else {
this.metadata = metadata;
}
const useId = value.nbformat === 4 && value.nbformat_minor >= 5;
const ycells = value.cells.map(cell => {
if (!useId) {
delete cell.id;
}
return cell;
});
this.insertCells(this.cells.length, ycells);
this.deleteCellRange(0, this.cells.length);
});
}
/**
* Serialize the model to JSON.
*/
toJSON() {
// strip cell ids if we have notebook format 4.0-4.4
const pruneCellId = this.nbformat === 4 && this.nbformat_minor <= 4;
return {
metadata: this.metadata,
nbformat_minor: this.nbformat_minor,
nbformat: this.nbformat,
cells: this.cells.map(c => {
const raw = c.toJSON();
if (pruneCellId) {
delete raw.id;
}
return raw;
})
};
}
}
//# sourceMappingURL=ynotebook.js.map
;// CONCATENATED MODULE: ../node_modules/@jupyter/ydoc/lib/index.js
/* -----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/**
* @packageDocumentation
* @module ydoc
*/
//# sourceMappingURL=index.js.map
/***/ }),
/***/ 79504:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ Dp: () => (/* binding */ from),
/* harmony export */ G: () => (/* binding */ some),
/* harmony export */ JJ: () => (/* binding */ unfold),
/* harmony export */ Z$: () => (/* binding */ last),
/* harmony export */ kJ: () => (/* binding */ isArray),
/* harmony export */ s7: () => (/* binding */ appendTo)
/* harmony export */ });
/* unused harmony exports create, copy, every, equalFlat, flatten, fold, unique, uniqueBy, map */
/**
* Utility module to work with Arrays.
*
* @module array
*/
/**
* Return the last element of an array. The element must exist
*
* @template L
* @param {ArrayLike<L>} arr
* @return {L}
*/
const last = arr => arr[arr.length - 1]
/**
* @template C
* @return {Array<C>}
*/
const create = () => /** @type {Array<C>} */ ([])
/**
* @template D
* @param {Array<D>} a
* @return {Array<D>}
*/
const copy = a => /** @type {Array<D>} */ (a.slice())
/**
* Append elements from src to dest
*
* @template M
* @param {Array<M>} dest
* @param {Array<M>} src
*/
const appendTo = (dest, src) => {
for (let i = 0; i < src.length; i++) {
dest.push(src[i])
}
}
/**
* Transforms something array-like to an actual Array.
*
* @function
* @template T
* @param {ArrayLike<T>|Iterable<T>} arraylike
* @return {T}
*/
const from = Array.from
/**
* True iff condition holds on every element in the Array.
*
* @function
* @template ITEM
* @template {ArrayLike<ITEM>} ARR
*
* @param {ARR} arr
* @param {function(ITEM, number, ARR):boolean} f
* @return {boolean}
*/
const every = (arr, f) => {
for (let i = 0; i < arr.length; i++) {
if (!f(arr[i], i, arr)) {
return false
}
}
return true
}
/**
* True iff condition holds on some element in the Array.
*
* @function
* @template S
* @template {ArrayLike<S>} ARR
* @param {ARR} arr
* @param {function(S, number, ARR):boolean} f
* @return {boolean}
*/
const some = (arr, f) => {
for (let i = 0; i < arr.length; i++) {
if (f(arr[i], i, arr)) {
return true
}
}
return false
}
/**
* @template ELEM
*
* @param {ArrayLike<ELEM>} a
* @param {ArrayLike<ELEM>} b
* @return {boolean}
*/
const equalFlat = (a, b) => a.length === b.length && every(a, (item, index) => item === b[index])
/**
* @template ELEM
* @param {Array<Array<ELEM>>} arr
* @return {Array<ELEM>}
*/
const flatten = arr => fold(arr, /** @type {Array<ELEM>} */ ([]), (acc, val) => acc.concat(val))
/**
* @template T
* @param {number} len
* @param {function(number, Array<T>):T} f
* @return {Array<T>}
*/
const unfold = (len, f) => {
const array = new Array(len)
for (let i = 0; i < len; i++) {
array[i] = f(i, array)
}
return array
}
/**
* @template T
* @template RESULT
* @param {Array<T>} arr
* @param {RESULT} seed
* @param {function(RESULT, T, number):RESULT} folder
*/
const fold = (arr, seed, folder) => arr.reduce(folder, seed)
const isArray = Array.isArray
/**
* @template T
* @param {Array<T>} arr
* @return {Array<T>}
*/
const unique = arr => from(set.from(arr))
/**
* @template T
* @template M
* @param {ArrayLike<T>} arr
* @param {function(T):M} mapper
* @return {Array<T>}
*/
const uniqueBy = (arr, mapper) => {
/**
* @type {Set<M>}
*/
const happened = set.create()
/**
* @type {Array<T>}
*/
const result = []
for (let i = 0; i < arr.length; i++) {
const el = arr[i]
const mapped = mapper(el)
if (!happened.has(mapped)) {
happened.add(mapped)
result.push(el)
}
}
return result
}
/**
* @template {ArrayLike<any>} ARR
* @template {function(ARR extends ArrayLike<infer T> ? T : never, number, ARR):any} MAPPER
* @param {ARR} arr
* @param {MAPPER} mapper
* @return {Array<MAPPER extends function(...any): infer M ? M : never>}
*/
const map = (arr, mapper) => {
/**
* @type {Array<any>}
*/
const res = Array(arr.length)
for (let i = 0; i < arr.length; i++) {
res[i] = mapper(/** @type {any} */ (arr[i]), i, /** @type {any} */ (arr))
}
return /** @type {any} */ (res)
}
/***/ }),
/***/ 38828:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ Hi: () => (/* binding */ equalityDeep),
/* harmony export */ PP: () => (/* binding */ callAll),
/* harmony export */ gB: () => (/* binding */ isOneOf),
/* harmony export */ id: () => (/* binding */ id)
/* harmony export */ });
/* unused harmony exports nop, apply, equalityStrict, equalityFlat, isArray, isString, isNumber, is, isTemplate */
/* harmony import */ var _array_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(79504);
/* harmony import */ var _object_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(36498);
/**
* Common functions and function call helpers.
*
* @module function
*/
/**
* Calls all functions in `fs` with args. Only throws after all functions were called.
*
* @param {Array<function>} fs
* @param {Array<any>} args
*/
const callAll = (fs, args, i = 0) => {
try {
for (; i < fs.length; i++) {
fs[i](...args)
}
} finally {
if (i < fs.length) {
callAll(fs, args, i + 1)
}
}
}
const nop = () => {}
/**
* @template T
* @param {function():T} f
* @return {T}
*/
const apply = f => f()
/**
* @template A
*
* @param {A} a
* @return {A}
*/
const id = a => a
/**
* @template T
*
* @param {T} a
* @param {T} b
* @return {boolean}
*/
const equalityStrict = (a, b) => a === b
/**
* @template T
*
* @param {Array<T>|object} a
* @param {Array<T>|object} b
* @return {boolean}
*/
const equalityFlat = (a, b) => a === b || (a != null && b != null && a.constructor === b.constructor && ((array.isArray(a) && array.equalFlat(a, /** @type {Array<T>} */ (b))) || (typeof a === 'object' && object.equalFlat(a, b))))
/* c8 ignore start */
/**
* @param {any} a
* @param {any} b
* @return {boolean}
*/
const equalityDeep = (a, b) => {
if (a == null || b == null) {
return equalityStrict(a, b)
}
if (a.constructor !== b.constructor) {
return false
}
if (a === b) {
return true
}
switch (a.constructor) {
case ArrayBuffer:
a = new Uint8Array(a)
b = new Uint8Array(b)
// eslint-disable-next-line no-fallthrough
case Uint8Array: {
if (a.byteLength !== b.byteLength) {
return false
}
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) {
return false
}
}
break
}
case Set: {
if (a.size !== b.size) {
return false
}
for (const value of a) {
if (!b.has(value)) {
return false
}
}
break
}
case Map: {
if (a.size !== b.size) {
return false
}
for (const key of a.keys()) {
if (!b.has(key) || !equalityDeep(a.get(key), b.get(key))) {
return false
}
}
break
}
case Object:
if (_object_js__WEBPACK_IMPORTED_MODULE_0__/* .length */ .kE(a) !== _object_js__WEBPACK_IMPORTED_MODULE_0__/* .length */ .kE(b)) {
return false
}
for (const key in a) {
if (!_object_js__WEBPACK_IMPORTED_MODULE_0__/* .hasProperty */ .l$(a, key) || !equalityDeep(a[key], b[key])) {
return false
}
}
break
case Array:
if (a.length !== b.length) {
return false
}
for (let i = 0; i < a.length; i++) {
if (!equalityDeep(a[i], b[i])) {
return false
}
}
break
default:
return false
}
return true
}
/**
* @template V
* @template {V} OPTS
*
* @param {V} value
* @param {Array<OPTS>} options
*/
// @ts-ignore
const isOneOf = (value, options) => options.includes(value)
/* c8 ignore stop */
const isArray = _array_js__WEBPACK_IMPORTED_MODULE_1__/* .isArray */ .kJ
/**
* @param {any} s
* @return {s is String}
*/
const isString = (s) => s && s.constructor === String
/**
* @param {any} n
* @return {n is Number}
*/
const isNumber = n => n != null && n.constructor === Number
/**
* @template {abstract new (...args: any) => any} TYPE
* @param {any} n
* @param {TYPE} T
* @return {n is InstanceType<TYPE>}
*/
const is = (n, T) => n && n.constructor === T
/**
* @template {abstract new (...args: any) => any} TYPE
* @param {TYPE} T
*/
const isTemplate = (T) =>
/**
* @param {any} n
* @return {n is InstanceType<TYPE>}
**/
n => n && n.constructor === T
/***/ }),
/***/ 22592:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ JG: () => (/* binding */ copy),
/* harmony export */ UI: () => (/* binding */ map),
/* harmony export */ Ue: () => (/* binding */ create),
/* harmony export */ Yj: () => (/* binding */ any),
/* harmony export */ Yu: () => (/* binding */ setIfUndefined)
/* harmony export */ });
/* unused harmony export all */
/**
* Utility module to work with key-value stores.
*
* @module map
*/
/**
* Creates a new Map instance.
*
* @function
* @return {Map<any, any>}
*
* @function
*/
const create = () => new Map()
/**
* Copy a Map object into a fresh Map object.
*
* @function
* @template X,Y
* @param {Map<X,Y>} m
* @return {Map<X,Y>}
*/
const copy = m => {
const r = create()
m.forEach((v, k) => { r.set(k, v) })
return r
}
/**
* Get map property. Create T if property is undefined and set T on map.
*
* ```js
* const listeners = map.setIfUndefined(events, 'eventName', set.create)
* listeners.add(listener)
* ```
*
* @function
* @template V,K
* @template {Map<K,V>} MAP
* @param {MAP} map
* @param {K} key
* @param {function():V} createT
* @return {V}
*/
const setIfUndefined = (map, key, createT) => {
let set = map.get(key)
if (set === undefined) {
map.set(key, set = createT())
}
return set
}
/**
* Creates an Array and populates it with the content of all key-value pairs using the `f(value, key)` function.
*
* @function
* @template K
* @template V
* @template R
* @param {Map<K,V>} m
* @param {function(V,K):R} f
* @return {Array<R>}
*/
const map = (m, f) => {
const res = []
for (const [key, value] of m) {
res.push(f(value, key))
}
return res
}
/**
* Tests whether any key-value pairs pass the test implemented by `f(value, key)`.
*
* @todo should rename to some - similarly to Array.some
*
* @function
* @template K
* @template V
* @param {Map<K,V>} m
* @param {function(V,K):boolean} f
* @return {boolean}
*/
const any = (m, f) => {
for (const [key, value] of m) {
if (f(value, key)) {
return true
}
}
return false
}
/**
* Tests whether all key-value pairs pass the test implemented by `f(value, key)`.
*
* @function
* @template K
* @template V
* @param {Map<K,V>} m
* @param {function(V,K):boolean} f
* @return {boolean}
*/
const all = (m, f) => {
for (const [key, value] of m) {
if (!f(value, key)) {
return false
}
}
return true
}
/***/ }),
/***/ 11182:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ Fp: () => (/* binding */ max),
/* harmony export */ GR: () => (/* binding */ isNegativeZero),
/* harmony export */ GW: () => (/* binding */ floor),
/* harmony export */ VV: () => (/* binding */ min),
/* harmony export */ Wn: () => (/* binding */ abs)
/* harmony export */ });
/* unused harmony exports ceil, imul, round, log10, log2, log, sqrt, add, isNaN, pow, exp10, sign */
/**
* Common Math expressions.
*
* @module math
*/
const floor = Math.floor
const ceil = Math.ceil
const abs = Math.abs
const imul = Math.imul
const round = Math.round
const log10 = Math.log10
const log2 = Math.log2
const log = Math.log
const sqrt = Math.sqrt
/**
* @function
* @param {number} a
* @param {number} b
* @return {number} The sum of a and b
*/
const add = (a, b) => a + b
/**
* @function
* @param {number} a
* @param {number} b
* @return {number} The smaller element of a and b
*/
const min = (a, b) => a < b ? a : b
/**
* @function
* @param {number} a
* @param {number} b
* @return {number} The bigger element of a and b
*/
const max = (a, b) => a > b ? a : b
const isNaN = Number.isNaN
const pow = Math.pow
/**
* Base 10 exponential function. Returns the value of 10 raised to the power of pow.
*
* @param {number} exp
* @return {number}
*/
const exp10 = exp => Math.pow(10, exp)
const sign = Math.sign
/**
* @param {number} n
* @return {boolean} Wether n is negative. This function also differentiates between -0 and +0
*/
const isNegativeZero = n => n !== 0 ? n < 0 : 1 / n < 0
/***/ }),
/***/ 36498:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ $m: () => (/* binding */ equalFlat),
/* harmony export */ Ed: () => (/* binding */ forEach),
/* harmony export */ f0: () => (/* binding */ assign),
/* harmony export */ kE: () => (/* binding */ length),
/* harmony export */ l$: () => (/* binding */ hasProperty),
/* harmony export */ xb: () => (/* binding */ isEmpty)
/* harmony export */ });
/* unused harmony exports create, keys, map, some, every */
/**
* Utility functions for working with EcmaScript objects.
*
* @module object
*/
/**
* @return {Object<string,any>} obj
*/
const create = () => Object.create(null)
/**
* Object.assign
*/
const assign = Object.assign
/**
* @param {Object<string,any>} obj
*/
const keys = Object.keys
/**
* @template V
* @param {{[k:string]:V}} obj
* @param {function(V,string):any} f
*/
const forEach = (obj, f) => {
for (const key in obj) {
f(obj[key], key)
}
}
/**
* @todo implement mapToArray & map
*
* @template R
* @param {Object<string,any>} obj
* @param {function(any,string):R} f
* @return {Array<R>}
*/
const map = (obj, f) => {
const results = []
for (const key in obj) {
results.push(f(obj[key], key))
}
return results
}
/**
* @param {Object<string,any>} obj
* @return {number}
*/
const length = obj => keys(obj).length
/**
* @param {Object<string,any>} obj
* @param {function(any,string):boolean} f
* @return {boolean}
*/
const some = (obj, f) => {
for (const key in obj) {
if (f(obj[key], key)) {
return true
}
}
return false
}
/**
* @param {Object|undefined} obj
*/
const isEmpty = obj => {
// eslint-disable-next-line
for (const _k in obj) {
return false
}
return true
}
/**
* @param {Object<string,any>} obj
* @param {function(any,string):boolean} f
* @return {boolean}
*/
const every = (obj, f) => {
for (const key in obj) {
if (!f(obj[key], key)) {
return false
}
}
return true
}
/**
* Calls `Object.prototype.hasOwnProperty`.
*
* @param {any} obj
* @param {string|symbol} key
* @return {boolean}
*/
const hasProperty = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key)
/**
* @param {Object<string,any>} a
* @param {Object<string,any>} b
* @return {boolean}
*/
const equalFlat = (a, b) => a === b || (length(a) === length(b) && every(a, (val, key) => (val !== undefined || hasProperty(b, key)) && b[key] === val))
/***/ }),
/***/ 12330:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ y: () => (/* binding */ Observable)
/* harmony export */ });
/* unused harmony export ObservableV2 */
/* harmony import */ var _map_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(22592);
/* harmony import */ var _set_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(79287);
/* harmony import */ var _array_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(79504);
/**
* Observable class prototype.
*
* @module observable
*/
/**
* Handles named events.
* @experimental
*
* This is basically a (better typed) duplicate of Observable, which will replace Observable in the
* next release.
*
* @template {{[key: string]: function(...any):void}} EVENTS
*/
class ObservableV2 {
constructor () {
/**
* Some desc.
* @type {Map<string, Set<any>>}
*/
this._observers = map.create()
}
/**
* @template {string} NAME
* @param {NAME} name
* @param {EVENTS[NAME]} f
*/
on (name, f) {
map.setIfUndefined(this._observers, /** @type {string} */ (name), set.create).add(f)
return f
}
/**
* @template {string} NAME
* @param {NAME} name
* @param {EVENTS[NAME]} f
*/
once (name, f) {
/**
* @param {...any} args
*/
const _f = (...args) => {
this.off(name, /** @type {any} */ (_f))
f(...args)
}
this.on(name, /** @type {any} */ (_f))
}
/**
* @template {string} NAME
* @param {NAME} name
* @param {EVENTS[NAME]} f
*/
off (name, f) {
const observers = this._observers.get(name)
if (observers !== undefined) {
observers.delete(f)
if (observers.size === 0) {
this._observers.delete(name)
}
}
}
/**
* Emit a named event. All registered event listeners that listen to the
* specified name will receive the event.
*
* @todo This should catch exceptions
*
* @template {string} NAME
* @param {NAME} name The event name.
* @param {Parameters<EVENTS[NAME]>} args The arguments that are applied to the event listener.
*/
emit (name, args) {
// copy all listeners to an array first to make sure that no event is emitted to listeners that are subscribed while the event handler is called.
return array.from((this._observers.get(name) || map.create()).values()).forEach(f => f(...args))
}
destroy () {
this._observers = map.create()
}
}
/* c8 ignore start */
/**
* Handles named events.
*
* @deprecated
* @template N
*/
class Observable {
constructor () {
/**
* Some desc.
* @type {Map<N, any>}
*/
this._observers = _map_js__WEBPACK_IMPORTED_MODULE_0__/* .create */ .Ue()
}
/**
* @param {N} name
* @param {function} f
*/
on (name, f) {
_map_js__WEBPACK_IMPORTED_MODULE_0__/* .setIfUndefined */ .Yu(this._observers, name, _set_js__WEBPACK_IMPORTED_MODULE_1__/* .create */ .Ue).add(f)
}
/**
* @param {N} name
* @param {function} f
*/
once (name, f) {
/**
* @param {...any} args
*/
const _f = (...args) => {
this.off(name, _f)
f(...args)
}
this.on(name, _f)
}
/**
* @param {N} name
* @param {function} f
*/
off (name, f) {
const observers = this._observers.get(name)
if (observers !== undefined) {
observers.delete(f)
if (observers.size === 0) {
this._observers.delete(name)
}
}
}
/**
* Emit a named event. All registered event listeners that listen to the
* specified name will receive the event.
*
* @todo This should catch exceptions
*
* @param {N} name The event name.
* @param {Array<any>} args The arguments that are applied to the event listener.
*/
emit (name, args) {
// copy all listeners to an array first to make sure that no event is emitted to listeners that are subscribed while the event handler is called.
return _array_js__WEBPACK_IMPORTED_MODULE_2__/* .from */ .Dp((this._observers.get(name) || _map_js__WEBPACK_IMPORTED_MODULE_0__/* .create */ .Ue()).values()).forEach(f => f(...args))
}
destroy () {
this._observers = _map_js__WEBPACK_IMPORTED_MODULE_0__/* .create */ .Ue()
}
}
/* c8 ignore end */
/***/ }),
/***/ 79287:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ Ue: () => (/* binding */ create)
/* harmony export */ });
/* unused harmony exports toArray, first, from */
/**
* Utility module to work with sets.
*
* @module set
*/
const create = () => new Set()
/**
* @template T
* @param {Set<T>} set
* @return {Array<T>}
*/
const toArray = set => Array.from(set)
/**
* @template T
* @param {Set<T>} set
* @return {T}
*/
const first = set =>
set.values().next().value || undefined
/**
* @template T
* @param {Iterable<T>} entries
* @return {Set<T>}
*/
const from = entries => new Set(entries)
/***/ }),
/***/ 2431:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ ZG: () => (/* binding */ getUnixTime)
/* harmony export */ });
/* unused harmony exports getDate, humanizeDuration */
/**
* Utility module to work with time.
*
* @module time
*/
/**
* Return current time.
*
* @return {Date}
*/
const getDate = () => new Date()
/**
* Return current unix time.
*
* @return {number}
*/
const getUnixTime = Date.now
/**
* Transform time (in ms) to a human readable format. E.g. 1100 => 1.1s. 60s => 1min. .001 => 10μs.
*
* @param {number} d duration in milliseconds
* @return {string} humanized approximation of time
*/
const humanizeDuration = d => {
if (d < 60000) {
const p = metric.prefix(d, -1)
return math.round(p.n * 100) / 100 + p.prefix + 's'
}
d = math.floor(d / 1000)
const seconds = d % 60
const minutes = math.floor(d / 60) % 60
const hours = math.floor(d / 3600) % 24
const days = math.floor(d / 86400)
if (days > 0) {
return days + 'd' + ((hours > 0 || minutes > 30) ? ' ' + (minutes > 30 ? hours + 1 : hours) + 'h' : '')
}
if (hours > 0) {
/* c8 ignore next */
return hours + 'h' + ((minutes > 0 || seconds > 30) ? ' ' + (seconds > 30 ? minutes + 1 : minutes) + 'min' : '')
}
return minutes + 'min' + (seconds > 0 ? ' ' + seconds + 's' : '')
}
/***/ })
}]);
//# sourceMappingURL=35.20ba31d4f65b5da8ab98.js.map?v=20ba31d4f65b5da8ab98