@difizen/libro-shared-model 0.0.2-alpha.0

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/es/ymodels.js ADDED
@@ -0,0 +1,1778 @@
1
+ function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
2
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
3
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
4
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
5
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
6
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
7
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
8
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
9
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
10
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
11
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
12
+ function _get() { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get.bind(); } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(arguments.length < 3 ? target : receiver); } return desc.value; }; } return _get.apply(this, arguments); }
13
+ function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }
14
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
15
+ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
16
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
17
+ function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
18
+ function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
19
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
20
+ function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
21
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
22
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
23
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
24
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
25
+ function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
26
+ import { deepCopy, deepEqual } from '@difizen/libro-common';
27
+ import { Emitter } from '@difizen/mana-common';
28
+ import { v4 } from 'uuid';
29
+ import { Awareness } from 'y-protocols/awareness';
30
+ import * as Y from 'yjs';
31
+
32
+ /**
33
+ * Abstract interface to define Shared Models that can be bound to a text editor using any existing
34
+ * Yjs-based editor binding.
35
+ */
36
+
37
+ /**
38
+ * Generic shareable document.
39
+ */
40
+ export var YDocument = /*#__PURE__*/function () {
41
+ function YDocument() {
42
+ var _this = this;
43
+ _classCallCheck(this, YDocument);
44
+ /**
45
+ * YJS document
46
+ */
47
+ this.ydoc = new Y.Doc();
48
+ /**
49
+ * Shared state
50
+ */
51
+ this.ystate = this.ydoc.getMap('state');
52
+ /**
53
+ * YJS document undo manager
54
+ */
55
+ this.undoManager = new Y.UndoManager([], {
56
+ trackedOrigins: new Set([this]),
57
+ doc: this.ydoc
58
+ });
59
+ /**
60
+ * Shared awareness
61
+ */
62
+ this.awareness = new Awareness(this.ydoc);
63
+ /**
64
+ * Handle a change to the ystate.
65
+ */
66
+ this.onStateChanged = function (event) {
67
+ var stateChange = new Array();
68
+ event.keysChanged.forEach(function (key) {
69
+ var change = event.changes.keys.get(key);
70
+ if (change) {
71
+ stateChange.push({
72
+ name: key,
73
+ oldValue: change.oldValue,
74
+ newValue: _this.ystate.get(key)
75
+ });
76
+ }
77
+ });
78
+ _this._changedEmitter.fire({
79
+ stateChange: stateChange
80
+ });
81
+ };
82
+ this._changedEmitter = new Emitter();
83
+ this._changed = this._changedEmitter.event;
84
+ this._isDisposed = false;
85
+ this.ystate.observe(this.onStateChanged);
86
+ }
87
+ _createClass(YDocument, [{
88
+ key: "changed",
89
+ get:
90
+ /**
91
+ * The changed signal.
92
+ */
93
+ function get() {
94
+ return this._changed;
95
+ }
96
+
97
+ /**
98
+ * Whether the document is disposed or not.
99
+ */
100
+ }, {
101
+ key: "isDisposed",
102
+ get: function get() {
103
+ return this._isDisposed;
104
+ }
105
+
106
+ /**
107
+ * Whether the object can undo changes.
108
+ */
109
+ }, {
110
+ key: "canUndo",
111
+ value: function canUndo() {
112
+ return this.undoManager.undoStack.length > 0;
113
+ }
114
+
115
+ /**
116
+ * Whether the object can redo changes.
117
+ */
118
+ }, {
119
+ key: "canRedo",
120
+ value: function canRedo() {
121
+ return this.undoManager.redoStack.length > 0;
122
+ }
123
+
124
+ /**
125
+ * Dispose of the resources.
126
+ */
127
+ }, {
128
+ key: "dispose",
129
+ value: function dispose() {
130
+ if (this._isDisposed) {
131
+ return;
132
+ }
133
+ this._isDisposed = true;
134
+ this.ystate.unobserve(this.onStateChanged);
135
+ this.awareness.destroy();
136
+ this.undoManager.destroy();
137
+ this.ydoc.destroy();
138
+ }
139
+
140
+ /**
141
+ * Undo an operation.
142
+ */
143
+ }, {
144
+ key: "undo",
145
+ value: function undo() {
146
+ this.undoManager.undo();
147
+ }
148
+
149
+ /**
150
+ * Redo an operation.
151
+ */
152
+ }, {
153
+ key: "redo",
154
+ value: function redo() {
155
+ this.undoManager.redo();
156
+ }
157
+
158
+ /**
159
+ * Clear the change stack.
160
+ */
161
+ }, {
162
+ key: "clearUndoHistory",
163
+ value: function clearUndoHistory() {
164
+ this.undoManager.clear();
165
+ }
166
+
167
+ /**
168
+ * Perform a transaction. While the function f is called, all changes to the shared
169
+ * document are bundled into a single event.
170
+ */
171
+ }, {
172
+ key: "transact",
173
+ value: function transact(f) {
174
+ var undoable = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
175
+ this.ydoc.transact(f, undoable ? this : null);
176
+ }
177
+ }]);
178
+ return YDocument;
179
+ }();
180
+
181
+ /**
182
+ * Shareable text file.
183
+ */
184
+ export var YFile = /*#__PURE__*/function (_ref) {
185
+ _inherits(YFile, _ref);
186
+ var _super = _createSuper(YFile);
187
+ function YFile() {
188
+ var _this2;
189
+ _classCallCheck(this, YFile);
190
+ _this2 = _super.call(this);
191
+ /**
192
+ * YJS file text.
193
+ */
194
+ _this2.ysource = _this2.ydoc.getText('source');
195
+ /**
196
+ * Handle a change to the ymodel.
197
+ */
198
+ _this2._modelObserver = function (event) {
199
+ _this2._changedEmitter.fire({
200
+ sourceChange: event.changes.delta
201
+ });
202
+ };
203
+ _this2.undoManager.addToScope(_this2.ysource);
204
+ _this2.ysource.observe(_this2._modelObserver);
205
+ return _this2;
206
+ }
207
+ _createClass(YFile, [{
208
+ key: "source",
209
+ get:
210
+ /**
211
+ * File text
212
+ */
213
+ function get() {
214
+ return this.getSource();
215
+ },
216
+ set: function set(v) {
217
+ this.setSource(v);
218
+ }
219
+
220
+ /**
221
+ * Dispose of the resources.
222
+ */
223
+ }, {
224
+ key: "dispose",
225
+ value: function dispose() {
226
+ if (this.isDisposed) {
227
+ return;
228
+ }
229
+ this.ysource.unobserve(this._modelObserver);
230
+ _get(_getPrototypeOf(YFile.prototype), "dispose", this).call(this);
231
+ }
232
+
233
+ /**
234
+ * Get the file text.
235
+ *
236
+ * @returns File text.
237
+ */
238
+ }, {
239
+ key: "getSource",
240
+ value: function getSource() {
241
+ return this.ysource.toString();
242
+ }
243
+
244
+ /**
245
+ * Set the file text.
246
+ *
247
+ * @param value New text
248
+ */
249
+ }, {
250
+ key: "setSource",
251
+ value: function setSource(value) {
252
+ var _this3 = this;
253
+ this.transact(function () {
254
+ var ytext = _this3.ysource;
255
+ ytext.delete(0, ytext.length);
256
+ ytext.insert(0, value);
257
+ });
258
+ }
259
+
260
+ /**
261
+ * Replace content from `start' to `end` with `value`.
262
+ *
263
+ * @param start: The start index of the range to replace (inclusive).
264
+ * @param end: The end index of the range to replace (exclusive).
265
+ * @param value: New source (optional).
266
+ */
267
+ }, {
268
+ key: "updateSource",
269
+ value: function updateSource(start, end) {
270
+ var _this4 = this;
271
+ var value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
272
+ this.transact(function () {
273
+ var ysource = _this4.ysource;
274
+ // insert and then delete.
275
+ // This ensures that the cursor position is adjusted after the replaced content.
276
+ ysource.insert(start, value);
277
+ ysource.delete(start + value.length, end - start);
278
+ });
279
+ }
280
+ }], [{
281
+ key: "create",
282
+ value:
283
+ /**
284
+ * Instantiate a new shareable file.
285
+ *
286
+ * @param source The initial file content
287
+ *
288
+ * @returns The file model
289
+ */
290
+ function create(source) {
291
+ var model = new YFile();
292
+ if (source) {
293
+ model.source = source;
294
+ }
295
+ return model;
296
+ }
297
+ }]);
298
+ return YFile;
299
+ }(YDocument);
300
+ export var defaultCellTypeAdaptor = function defaultCellTypeAdaptor(cell_Type) {
301
+ return cell_Type;
302
+ };
303
+
304
+ /**
305
+ * Create a new shared cell model given the YJS shared type.
306
+ */
307
+ var createCellModelFromSharedType = function createCellModelFromSharedType(type) {
308
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
309
+ var cellTypeAdaptor = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultCellTypeAdaptor;
310
+ switch (cellTypeAdaptor(type.get('cell_type'))) {
311
+ case 'code':
312
+ return new YCodeCell(type, type.get('source'), type.get('outputs'), options);
313
+ case 'markdown':
314
+ return new YMarkdownCell(type, type.get('source'), options);
315
+ case 'raw':
316
+ return new YRawCell(type, type.get('source'), options);
317
+ default:
318
+ throw new Error('Found unknown cell type');
319
+ }
320
+ };
321
+
322
+ /**
323
+ * Create a new cell that can be inserted in an existing shared model.
324
+ *
325
+ * If no notebook is specified the cell will be standalone.
326
+ *
327
+ * @param cell Cell JSON representation
328
+ * @param notebook Notebook to which the cell will be added
329
+ */
330
+ var createCell = function createCell(cell, notebook) {
331
+ var _cell$id;
332
+ var cellTypeAdaptor = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultCellTypeAdaptor;
333
+ var ymodel = new Y.Map();
334
+ var ysource = new Y.Text();
335
+ ymodel.set('source', ysource);
336
+ ymodel.set('metadata', {});
337
+ ymodel.set('cell_type', cell.cell_type);
338
+ ymodel.set('id', (_cell$id = cell.id) !== null && _cell$id !== void 0 ? _cell$id : v4());
339
+ var ycell;
340
+ switch (cellTypeAdaptor(cell.cell_type)) {
341
+ case 'markdown':
342
+ {
343
+ ycell = new YMarkdownCell(ymodel, ysource, {
344
+ notebook: notebook
345
+ });
346
+ if (cell.attachments !== null) {
347
+ ycell.setAttachments(cell.attachments);
348
+ }
349
+ break;
350
+ }
351
+ case 'code':
352
+ {
353
+ var _cCell$execution_coun;
354
+ var youtputs = new Y.Array();
355
+ ymodel.set('outputs', youtputs);
356
+ ycell = new YCodeCell(ymodel, ysource, youtputs, {
357
+ notebook: notebook
358
+ });
359
+ var cCell = cell;
360
+ ycell.execution_count = (_cCell$execution_coun = cCell.execution_count) !== null && _cCell$execution_coun !== void 0 ? _cCell$execution_coun : null;
361
+ if (cCell.outputs) {
362
+ ycell.setOutputs(cCell.outputs);
363
+ }
364
+ break;
365
+ }
366
+ default:
367
+ {
368
+ // raw
369
+ ycell = new YRawCell(ymodel, ysource, {
370
+ notebook: notebook
371
+ });
372
+ if (cell.attachments) {
373
+ ycell.setAttachments(cell.attachments);
374
+ }
375
+ break;
376
+ }
377
+ }
378
+ if (cell.metadata !== null) {
379
+ ycell.setMetadata(cell.metadata);
380
+ }
381
+ if (cell.source !== null) {
382
+ ycell.setSource(typeof cell.source === 'string' ? cell.source : cell.source.join('\n'));
383
+ }
384
+ return ycell;
385
+ };
386
+
387
+ /**
388
+ * Create a new cell that cannot be inserted in an existing shared model.
389
+ *
390
+ * @param cell Cell JSON representation
391
+ */
392
+ export var createStandaloneCell = function createStandaloneCell(cell, cellTypeAdaptor) {
393
+ return createCell(cell, undefined, cellTypeAdaptor);
394
+ };
395
+ export var YBaseCell = /*#__PURE__*/function () {
396
+ /**
397
+ * Base cell constructor
398
+ *
399
+ * ### Notes
400
+ * Don't use the constructor directly - prefer using ``YNotebook.insertCell``
401
+ *
402
+ * The ``ysource`` is needed because ``ymodel.get('source')`` will
403
+ * not return the real source if the model is not yet attached to
404
+ * a document. Requesting it explicitly allows to introspect a non-empty
405
+ * source before the cell is attached to the document.
406
+ *
407
+ * @param ymodel Cell map
408
+ * @param ysource Cell source
409
+ * @param options { notebook?: The notebook the cell is attached to }
410
+ */
411
+ function YBaseCell(ymodel, ysource) {
412
+ var _this5 = this;
413
+ var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
414
+ _classCallCheck(this, YBaseCell);
415
+ /**
416
+ * Handle a change to the ymodel.
417
+ */
418
+ this._modelObserver = function (events) {
419
+ _this5._changedEmitter.fire(_this5.getChanges(events));
420
+ };
421
+ this._metadataChangedEmitter = new Emitter();
422
+ this._metadataChanged = this._metadataChangedEmitter.event;
423
+ /**
424
+ * The notebook that this cell belongs to.
425
+ */
426
+ this._notebook = null;
427
+ this._changedEmitter = new Emitter();
428
+ this._changed = this._changedEmitter.event;
429
+ this._isDisposed = false;
430
+ this._undoManager = null;
431
+ this.ymodel = ymodel;
432
+ this._ysource = ysource;
433
+ this._prevSourceLength = ysource ? ysource.length : 0;
434
+ this._notebook = null;
435
+ this._awareness = null;
436
+ this._undoManager = null;
437
+ if (options.notebook) {
438
+ this._notebook = options.notebook;
439
+ // We cannot create a undo manager with the cell not yet attached in the notebook
440
+ // so we defer that to the notebook insertCell method
441
+ } else {
442
+ // Standalone cell
443
+ var doc = new Y.Doc();
444
+ doc.getArray().insert(0, [this.ymodel]);
445
+ this._awareness = new Awareness(doc);
446
+ this._undoManager = new Y.UndoManager([this.ymodel], {
447
+ trackedOrigins: new Set([this])
448
+ });
449
+ }
450
+ this.ymodel.observeDeep(this._modelObserver);
451
+ }
452
+
453
+ /**
454
+ * Cell notebook awareness or null if the cell is standalone.
455
+ */
456
+ _createClass(YBaseCell, [{
457
+ key: "awareness",
458
+ get: function get() {
459
+ var _ref2, _this$_awareness, _this$notebook;
460
+ return (_ref2 = (_this$_awareness = this._awareness) !== null && _this$_awareness !== void 0 ? _this$_awareness : (_this$notebook = this.notebook) === null || _this$notebook === void 0 ? void 0 : _this$notebook.awareness) !== null && _ref2 !== void 0 ? _ref2 : null;
461
+ }
462
+
463
+ /**
464
+ * The type of the cell.
465
+ */
466
+ }, {
467
+ key: "cell_type",
468
+ get: function get() {
469
+ throw new Error('A YBaseCell must not be constructed');
470
+ }
471
+
472
+ /**
473
+ * The changed signal.
474
+ */
475
+ }, {
476
+ key: "changed",
477
+ get: function get() {
478
+ return this._changed;
479
+ }
480
+
481
+ /**
482
+ * Cell id
483
+ */
484
+ }, {
485
+ key: "id",
486
+ get: function get() {
487
+ return this.getId();
488
+ }
489
+
490
+ /**
491
+ * Whether the model has been disposed or not.
492
+ */
493
+ }, {
494
+ key: "isDisposed",
495
+ get: function get() {
496
+ return this._isDisposed;
497
+ }
498
+
499
+ /**
500
+ * Whether the cell is standalone or not.
501
+ *
502
+ * If the cell is standalone. It cannot be
503
+ * inserted into a YNotebook because the Yjs model is already
504
+ * attached to an anonymous Y.Doc instance.
505
+ */
506
+ }, {
507
+ key: "isStandalone",
508
+ get: function get() {
509
+ return this._notebook !== null;
510
+ }
511
+
512
+ /**
513
+ * Cell metadata.
514
+ */
515
+ }, {
516
+ key: "metadata",
517
+ get: function get() {
518
+ return this.getMetadata();
519
+ },
520
+ set: function set(v) {
521
+ this.setMetadata(v);
522
+ }
523
+
524
+ /**
525
+ * Signal triggered when the cell metadata changes.
526
+ */
527
+ }, {
528
+ key: "metadataChanged",
529
+ get: function get() {
530
+ return this._metadataChanged;
531
+ }
532
+
533
+ /**
534
+ * The notebook that this cell belongs to.
535
+ */
536
+ }, {
537
+ key: "notebook",
538
+ get: function get() {
539
+ return this._notebook;
540
+ }
541
+
542
+ /**
543
+ * Cell input content.
544
+ */
545
+ }, {
546
+ key: "source",
547
+ get: function get() {
548
+ return this.getSource();
549
+ },
550
+ set: function set(v) {
551
+ this.setSource(v);
552
+ }
553
+
554
+ /**
555
+ * The cell undo manager.
556
+ */
557
+ }, {
558
+ key: "undoManager",
559
+ get: function get() {
560
+ var _this$notebook2;
561
+ if (!this.notebook) {
562
+ return this._undoManager;
563
+ }
564
+ return (_this$notebook2 = this.notebook) !== null && _this$notebook2 !== void 0 && _this$notebook2.disableDocumentWideUndoRedo ? this._undoManager : this.notebook.undoManager;
565
+ }
566
+
567
+ /**
568
+ * Defer setting the undo manager as it requires the
569
+ * cell to be attached to the notebook Y document.
570
+ */
571
+ }, {
572
+ key: "setUndoManager",
573
+ value: function setUndoManager() {
574
+ if (this._undoManager) {
575
+ throw new Error('The cell undo manager is already set.');
576
+ }
577
+ if (this._notebook && this._notebook.disableDocumentWideUndoRedo) {
578
+ this._undoManager = new Y.UndoManager([this.ymodel], {
579
+ trackedOrigins: new Set([this])
580
+ });
581
+ }
582
+ }
583
+ }, {
584
+ key: "ysource",
585
+ get: function get() {
586
+ return this._ysource;
587
+ }
588
+
589
+ /**
590
+ * Whether the object can undo changes.
591
+ */
592
+ }, {
593
+ key: "canUndo",
594
+ value: function canUndo() {
595
+ return !!this.undoManager && this.undoManager.undoStack.length > 0;
596
+ }
597
+
598
+ /**
599
+ * Whether the object can redo changes.
600
+ */
601
+ }, {
602
+ key: "canRedo",
603
+ value: function canRedo() {
604
+ return !!this.undoManager && this.undoManager.redoStack.length > 0;
605
+ }
606
+
607
+ /**
608
+ * Clear the change stack.
609
+ */
610
+ }, {
611
+ key: "clearUndoHistory",
612
+ value: function clearUndoHistory() {
613
+ var _this$undoManager;
614
+ (_this$undoManager = this.undoManager) === null || _this$undoManager === void 0 ? void 0 : _this$undoManager.clear();
615
+ }
616
+
617
+ /**
618
+ * Undo an operation.
619
+ */
620
+ }, {
621
+ key: "undo",
622
+ value: function undo() {
623
+ var _this$undoManager2;
624
+ (_this$undoManager2 = this.undoManager) === null || _this$undoManager2 === void 0 ? void 0 : _this$undoManager2.undo();
625
+ }
626
+
627
+ /**
628
+ * Redo an operation.
629
+ */
630
+ }, {
631
+ key: "redo",
632
+ value: function redo() {
633
+ var _this$undoManager3;
634
+ (_this$undoManager3 = this.undoManager) === null || _this$undoManager3 === void 0 ? void 0 : _this$undoManager3.redo();
635
+ }
636
+
637
+ /**
638
+ * Dispose of the resources.
639
+ */
640
+ }, {
641
+ key: "dispose",
642
+ value: function dispose() {
643
+ if (this._isDisposed) {
644
+ return;
645
+ }
646
+ this._isDisposed = true;
647
+ this.ymodel.unobserveDeep(this._modelObserver);
648
+ if (this._awareness) {
649
+ // A new document is created for standalone cell.
650
+ var doc = this._awareness.doc;
651
+ this._awareness.destroy();
652
+ doc.destroy();
653
+ }
654
+ if (this._undoManager) {
655
+ var _this$notebook3;
656
+ // Be sure to not destroy the document undo manager.
657
+ if (this._undoManager === ((_this$notebook3 = this.notebook) === null || _this$notebook3 === void 0 ? void 0 : _this$notebook3.undoManager)) {
658
+ this._undoManager = null;
659
+ } else {
660
+ this._undoManager.destroy();
661
+ }
662
+ }
663
+ }
664
+
665
+ /**
666
+ * Get cell id.
667
+ *
668
+ * @returns Cell id
669
+ */
670
+ }, {
671
+ key: "getId",
672
+ value: function getId() {
673
+ return this.ymodel.get('id');
674
+ }
675
+
676
+ /**
677
+ * Gets cell's source.
678
+ *
679
+ * @returns Cell's source.
680
+ */
681
+ }, {
682
+ key: "getSource",
683
+ value: function getSource() {
684
+ return this.ysource.toString();
685
+ }
686
+
687
+ /**
688
+ * Sets cell's source.
689
+ *
690
+ * @param value: New source.
691
+ */
692
+ }, {
693
+ key: "setSource",
694
+ value: function setSource(value) {
695
+ var _this6 = this;
696
+ this.transact(function () {
697
+ _this6.ysource.delete(0, _this6.ysource.length);
698
+ _this6.ysource.insert(0, value);
699
+ });
700
+ // @todo Do we need proper replace semantic? This leads to issues in editor bindings because they don't switch source.
701
+ // this.ymodel.set('source', new Y.Text(value));
702
+ }
703
+
704
+ /**
705
+ * Replace content from `start' to `end` with `value`.
706
+ *
707
+ * @param start: The start index of the range to replace (inclusive).
708
+ *
709
+ * @param end: The end index of the range to replace (exclusive).
710
+ *
711
+ * @param value: New source (optional).
712
+ */
713
+ }, {
714
+ key: "updateSource",
715
+ value: function updateSource(start, end) {
716
+ var _this7 = this;
717
+ var value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
718
+ this.transact(function () {
719
+ var ysource = _this7.ysource;
720
+ // insert and then delete.
721
+ // This ensures that the cursor position is adjusted after the replaced content.
722
+ ysource.insert(start, value);
723
+ ysource.delete(start + value.length, end - start);
724
+ });
725
+ }
726
+
727
+ /**
728
+ * Delete a metadata cell.
729
+ *
730
+ * @param key The key to delete
731
+ */
732
+ }, {
733
+ key: "deleteMetadata",
734
+ value: function deleteMetadata(key) {
735
+ var allMetadata = deepCopy(this.ymodel.get('metadata'));
736
+ delete allMetadata[key];
737
+ this.setMetadata(allMetadata);
738
+ }
739
+
740
+ /**
741
+ * Returns the metadata associated with the cell.
742
+ *
743
+ * @param key
744
+ * @returns Cell metadata.
745
+ */
746
+ }, {
747
+ key: "getMetadata",
748
+ value: function getMetadata(key) {
749
+ var metadata = this.ymodel.get('metadata');
750
+ if (typeof key === 'string') {
751
+ return deepCopy(metadata[key]);
752
+ } else {
753
+ return deepCopy(metadata);
754
+ }
755
+ }
756
+
757
+ /**
758
+ * Sets some cell metadata.
759
+ *
760
+ * If only one argument is provided, it will override all cell metadata.
761
+ * Otherwise a single key will be set to a new value.
762
+ *
763
+ * @param metadata Cell's metadata or key.
764
+ * @param value Metadata value
765
+ */
766
+ }, {
767
+ key: "setMetadata",
768
+ value: function setMetadata(metadata, value) {
769
+ var _clone$jupyter,
770
+ _this8 = this;
771
+ if (typeof metadata === 'string') {
772
+ if (typeof value === 'undefined') {
773
+ throw new TypeError("Metadata value for ".concat(metadata, " cannot be 'undefined'; use deleteMetadata."));
774
+ }
775
+ var key = metadata;
776
+ // eslint-disable-next-line no-param-reassign
777
+ metadata = this.getMetadata();
778
+ // @ts-expect-error metadata type is changed at runtime.
779
+ metadata[key] = value;
780
+ }
781
+ var clone = deepCopy(metadata);
782
+ if (clone.collapsed !== null) {
783
+ clone.jupyter = clone.jupyter || {};
784
+ clone.jupyter.outputs_hidden = clone.collapsed;
785
+ } else if ((clone === null || clone === void 0 ? void 0 : (_clone$jupyter = clone.jupyter) === null || _clone$jupyter === void 0 ? void 0 : _clone$jupyter.outputs_hidden) !== null) {
786
+ clone.collapsed = clone.jupyter.outputs_hidden;
787
+ }
788
+ if (this.ymodel.doc === null || !deepEqual(clone, this.getMetadata())) {
789
+ this.transact(function () {
790
+ _this8.ymodel.set('metadata', clone);
791
+ });
792
+ }
793
+ }
794
+
795
+ /**
796
+ * Serialize the model to JSON.
797
+ */
798
+ }, {
799
+ key: "toJSON",
800
+ value: function toJSON() {
801
+ return {
802
+ id: this.getId(),
803
+ cell_type: this.cell_type,
804
+ source: this.getSource(),
805
+ metadata: this.getMetadata()
806
+ };
807
+ }
808
+
809
+ /**
810
+ * Perform a transaction. While the function f is called, all changes to the shared
811
+ * document are bundled into a single event.
812
+ */
813
+ }, {
814
+ key: "transact",
815
+ value: function transact(f) {
816
+ var undoable = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
817
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
818
+ this.notebook && undoable ? this.notebook.transact(f) : this.ymodel.doc === null ? f() : this.ymodel.doc.transact(f, this);
819
+ }
820
+
821
+ /**
822
+ * Extract changes from YJS events
823
+ *
824
+ * @param events YJS events
825
+ * @returns Cell changes
826
+ */
827
+ }, {
828
+ key: "getChanges",
829
+ value: function getChanges(events) {
830
+ var _this9 = this;
831
+ var changes = {};
832
+ var sourceEvent = events.find(function (event) {
833
+ return event.target === _this9.ymodel.get('source');
834
+ });
835
+ if (sourceEvent) {
836
+ changes.sourceChange = sourceEvent.changes.delta;
837
+ }
838
+ var modelEvent = events.find(function (event) {
839
+ return event.target === _this9.ymodel;
840
+ });
841
+ if (modelEvent && modelEvent.keysChanged.has('metadata')) {
842
+ var _metadataChange$oldVa;
843
+ var change = modelEvent.changes.keys.get('metadata');
844
+ var metadataChange = changes.metadataChange = {
845
+ oldValue: change !== null && change !== void 0 && change.oldValue ? change.oldValue : undefined,
846
+ newValue: this.getMetadata()
847
+ };
848
+ var oldValue = (_metadataChange$oldVa = metadataChange.oldValue) !== null && _metadataChange$oldVa !== void 0 ? _metadataChange$oldVa : {};
849
+ var oldKeys = Object.keys(oldValue);
850
+ var newKeys = Object.keys(metadataChange.newValue);
851
+ var _iterator = _createForOfIteratorHelper(new Set(oldKeys.concat(newKeys))),
852
+ _step;
853
+ try {
854
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
855
+ var key = _step.value;
856
+ if (!oldKeys.includes(key)) {
857
+ this._metadataChangedEmitter.fire({
858
+ key: key,
859
+ newValue: metadataChange.newValue[key],
860
+ type: 'add'
861
+ });
862
+ } else if (!newKeys.includes(key)) {
863
+ this._metadataChangedEmitter.fire({
864
+ key: key,
865
+ oldValue: metadataChange.oldValue[key],
866
+ type: 'remove'
867
+ });
868
+ } else if (!deepEqual(oldValue[key], metadataChange.newValue[key])) {
869
+ this._metadataChangedEmitter.fire({
870
+ key: key,
871
+ newValue: metadataChange.newValue[key],
872
+ oldValue: metadataChange.oldValue[key],
873
+ type: 'change'
874
+ });
875
+ }
876
+ }
877
+ } catch (err) {
878
+ _iterator.e(err);
879
+ } finally {
880
+ _iterator.f();
881
+ }
882
+ }
883
+
884
+ // The model allows us to replace the complete source with a new string. We express this in the Delta format
885
+ // as a replace of the complete string.
886
+ var ysource = this.ymodel.get('source');
887
+ if (modelEvent && modelEvent.keysChanged.has('source')) {
888
+ changes.sourceChange = [{
889
+ delete: this._prevSourceLength
890
+ }, {
891
+ insert: ysource.toString()
892
+ }];
893
+ }
894
+ this._prevSourceLength = ysource.length;
895
+ return changes;
896
+ }
897
+ }], [{
898
+ key: "createStandalone",
899
+ value:
900
+ /**
901
+ * Create a new YCell that works standalone. It cannot be
902
+ * inserted into a YNotebook because the Yjs model is already
903
+ * attached to an anonymous Y.Doc instance.
904
+ */
905
+ function createStandalone(id) {
906
+ var cell = createCell({
907
+ id: id,
908
+ cell_type: this.prototype.cell_type,
909
+ source: '',
910
+ metadata: {}
911
+ });
912
+ return cell;
913
+ }
914
+ }]);
915
+ return YBaseCell;
916
+ }();
917
+
918
+ /**
919
+ * Shareable code cell.
920
+ */
921
+ export var YCodeCell = /*#__PURE__*/function (_YBaseCell) {
922
+ _inherits(YCodeCell, _YBaseCell);
923
+ var _super2 = _createSuper(YCodeCell);
924
+ /**
925
+ * Code cell constructor
926
+ *
927
+ * ### Notes
928
+ * Don't use the constructor directly - prefer using ``YNotebook.insertCell``
929
+ *
930
+ * The ``ysource`` is needed because ``ymodel.get('source')`` will
931
+ * not return the real source if the model is not yet attached to
932
+ * a document. Requesting it explicitly allows to introspect a non-empty
933
+ * source before the cell is attached to the document.
934
+ *
935
+ * @param ymodel Cell map
936
+ * @param ysource Cell source
937
+ * @param youtputs Code cell outputs
938
+ * @param options { notebook?: The notebook the cell is attached to }
939
+ */
940
+ function YCodeCell(ymodel, ysource, youtputs) {
941
+ var _this10;
942
+ var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
943
+ _classCallCheck(this, YCodeCell);
944
+ _this10 = _super2.call(this, ymodel, ysource, options);
945
+ _this10._youtputs = youtputs;
946
+ return _this10;
947
+ }
948
+
949
+ /**
950
+ * The type of the cell.
951
+ */
952
+ _createClass(YCodeCell, [{
953
+ key: "cell_type",
954
+ get: function get() {
955
+ return this.ymodel.get('cell_type');
956
+ }
957
+
958
+ /**
959
+ * The code cell's prompt number. Will be null if the cell has not been run.
960
+ */
961
+ }, {
962
+ key: "execution_count",
963
+ get: function get() {
964
+ return this.ymodel.get('execution_count') || null;
965
+ },
966
+ set: function set(count) {
967
+ var _this11 = this;
968
+ // Do not use `this.execution_count`. When initializing the
969
+ // cell, we need to set execution_count to `null` if we compare
970
+ // using `this.execution_count` it will return `null` and we will
971
+ // never initialize it
972
+ if (this.ymodel.get('execution_count') !== count) {
973
+ this.transact(function () {
974
+ _this11.ymodel.set('execution_count', count);
975
+ });
976
+ }
977
+ }
978
+
979
+ /**
980
+ * Cell outputs.
981
+ */
982
+ }, {
983
+ key: "outputs",
984
+ get: function get() {
985
+ return this.getOutputs();
986
+ },
987
+ set: function set(v) {
988
+ this.setOutputs(v);
989
+ }
990
+
991
+ /**
992
+ * Execution, display, or stream outputs.
993
+ */
994
+ }, {
995
+ key: "getOutputs",
996
+ value: function getOutputs() {
997
+ return deepCopy(this._youtputs.toArray());
998
+ }
999
+
1000
+ /**
1001
+ * Replace all outputs.
1002
+ */
1003
+ }, {
1004
+ key: "setOutputs",
1005
+ value: function setOutputs(outputs) {
1006
+ var _this12 = this;
1007
+ this.transact(function () {
1008
+ _this12._youtputs.delete(0, _this12._youtputs.length);
1009
+ _this12._youtputs.insert(0, outputs);
1010
+ }, false);
1011
+ }
1012
+
1013
+ /**
1014
+ * Replace content from `start' to `end` with `outputs`.
1015
+ *
1016
+ * @param start: The start index of the range to replace (inclusive).
1017
+ *
1018
+ * @param end: The end index of the range to replace (exclusive).
1019
+ *
1020
+ * @param outputs: New outputs (optional).
1021
+ */
1022
+ }, {
1023
+ key: "updateOutputs",
1024
+ value: function updateOutputs(start, end) {
1025
+ var _this13 = this;
1026
+ var outputs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
1027
+ var fin = end < this._youtputs.length ? end - start : this._youtputs.length - start;
1028
+ this.transact(function () {
1029
+ _this13._youtputs.delete(start, fin);
1030
+ _this13._youtputs.insert(start, outputs);
1031
+ }, false);
1032
+ }
1033
+
1034
+ /**
1035
+ * Serialize the model to JSON.
1036
+ */
1037
+ }, {
1038
+ key: "toJSON",
1039
+ value: function toJSON() {
1040
+ return _objectSpread(_objectSpread({}, _get(_getPrototypeOf(YCodeCell.prototype), "toJSON", this).call(this)), {}, {
1041
+ outputs: this.getOutputs(),
1042
+ execution_count: this.execution_count
1043
+ });
1044
+ }
1045
+
1046
+ /**
1047
+ * Extract changes from YJS events
1048
+ *
1049
+ * @param events YJS events
1050
+ * @returns Cell changes
1051
+ */
1052
+ }, {
1053
+ key: "getChanges",
1054
+ value: function getChanges(events) {
1055
+ var _this14 = this;
1056
+ var changes = _get(_getPrototypeOf(YCodeCell.prototype), "getChanges", this).call(this, events);
1057
+ var outputEvent = events.find(function (event) {
1058
+ return event.target === _this14.ymodel.get('outputs');
1059
+ });
1060
+ if (outputEvent) {
1061
+ changes.outputsChange = outputEvent.changes.delta;
1062
+ }
1063
+ var modelEvent = events.find(function (event) {
1064
+ return event.target === _this14.ymodel;
1065
+ });
1066
+ if (modelEvent && modelEvent.keysChanged.has('execution_count')) {
1067
+ var change = modelEvent.changes.keys.get('execution_count');
1068
+ changes.executionCountChange = {
1069
+ oldValue: change.oldValue,
1070
+ newValue: this.ymodel.get('execution_count')
1071
+ };
1072
+ }
1073
+ return changes;
1074
+ }
1075
+ }], [{
1076
+ key: "createStandalone",
1077
+ value:
1078
+ /**
1079
+ * Create a new YCodeCell that works standalone. It cannot be
1080
+ * inserted into a YNotebook because the Yjs model is already
1081
+ * attached to an anonymous Y.Doc instance.
1082
+ */
1083
+ function createStandalone(id) {
1084
+ return _get(_getPrototypeOf(YCodeCell), "createStandalone", this).call(this, id);
1085
+ }
1086
+ }]);
1087
+ return YCodeCell;
1088
+ }(YBaseCell);
1089
+ var YAttachmentCell = /*#__PURE__*/function (_ref3) {
1090
+ _inherits(YAttachmentCell, _ref3);
1091
+ var _super3 = _createSuper(YAttachmentCell);
1092
+ function YAttachmentCell() {
1093
+ _classCallCheck(this, YAttachmentCell);
1094
+ return _super3.apply(this, arguments);
1095
+ }
1096
+ _createClass(YAttachmentCell, [{
1097
+ key: "attachments",
1098
+ get:
1099
+ /**
1100
+ * Cell attachments
1101
+ */
1102
+ function get() {
1103
+ return this.getAttachments();
1104
+ },
1105
+ set: function set(v) {
1106
+ this.setAttachments(v);
1107
+ }
1108
+
1109
+ /**
1110
+ * Gets the cell attachments.
1111
+ *
1112
+ * @returns The cell attachments.
1113
+ */
1114
+ }, {
1115
+ key: "getAttachments",
1116
+ value: function getAttachments() {
1117
+ return this.ymodel.get('attachments');
1118
+ }
1119
+
1120
+ /**
1121
+ * Sets the cell attachments
1122
+ *
1123
+ * @param attachments: The cell attachments.
1124
+ */
1125
+ }, {
1126
+ key: "setAttachments",
1127
+ value: function setAttachments(attachments) {
1128
+ var _this15 = this;
1129
+ this.transact(function () {
1130
+ if (attachments === null) {
1131
+ _this15.ymodel.delete('attachments');
1132
+ } else {
1133
+ _this15.ymodel.set('attachments', attachments);
1134
+ }
1135
+ });
1136
+ }
1137
+
1138
+ /**
1139
+ * Extract changes from YJS events
1140
+ *
1141
+ * @param events YJS events
1142
+ * @returns Cell changes
1143
+ */
1144
+ }, {
1145
+ key: "getChanges",
1146
+ value: function getChanges(events) {
1147
+ var _this16 = this;
1148
+ var changes = _get(_getPrototypeOf(YAttachmentCell.prototype), "getChanges", this).call(this, events);
1149
+ var modelEvent = events.find(function (event) {
1150
+ return event.target === _this16.ymodel;
1151
+ });
1152
+ if (modelEvent && modelEvent.keysChanged.has('attachments')) {
1153
+ var change = modelEvent.changes.keys.get('attachments');
1154
+ changes.executionCountChange = {
1155
+ oldValue: change.oldValue,
1156
+ newValue: this.ymodel.get('attachments')
1157
+ };
1158
+ }
1159
+ return changes;
1160
+ }
1161
+ }]);
1162
+ return YAttachmentCell;
1163
+ }(YBaseCell);
1164
+ /**
1165
+ * Shareable raw cell.
1166
+ */
1167
+ export var YRawCell = /*#__PURE__*/function (_YAttachmentCell) {
1168
+ _inherits(YRawCell, _YAttachmentCell);
1169
+ var _super4 = _createSuper(YRawCell);
1170
+ function YRawCell() {
1171
+ _classCallCheck(this, YRawCell);
1172
+ return _super4.apply(this, arguments);
1173
+ }
1174
+ _createClass(YRawCell, [{
1175
+ key: "cell_type",
1176
+ get:
1177
+ /**
1178
+ * String identifying the type of cell.
1179
+ */
1180
+ function get() {
1181
+ return 'raw';
1182
+ }
1183
+
1184
+ /**
1185
+ * Serialize the model to JSON.
1186
+ */
1187
+ }, {
1188
+ key: "toJSON",
1189
+ value: function toJSON() {
1190
+ return {
1191
+ id: this.getId(),
1192
+ cell_type: 'raw',
1193
+ source: this.getSource(),
1194
+ metadata: this.getMetadata(),
1195
+ attachments: this.getAttachments()
1196
+ };
1197
+ }
1198
+ }], [{
1199
+ key: "createStandalone",
1200
+ value:
1201
+ /**
1202
+ * Create a new YRawCell that works standalone. It cannot be
1203
+ * inserted into a YNotebook because the Yjs model is already
1204
+ * attached to an anonymous Y.Doc instance.
1205
+ */
1206
+ function createStandalone(id) {
1207
+ return _get(_getPrototypeOf(YRawCell), "createStandalone", this).call(this, id);
1208
+ }
1209
+ }]);
1210
+ return YRawCell;
1211
+ }(YAttachmentCell);
1212
+
1213
+ /**
1214
+ * Shareable markdown cell.
1215
+ */
1216
+ export var YMarkdownCell = /*#__PURE__*/function (_YAttachmentCell2) {
1217
+ _inherits(YMarkdownCell, _YAttachmentCell2);
1218
+ var _super5 = _createSuper(YMarkdownCell);
1219
+ function YMarkdownCell() {
1220
+ _classCallCheck(this, YMarkdownCell);
1221
+ return _super5.apply(this, arguments);
1222
+ }
1223
+ _createClass(YMarkdownCell, [{
1224
+ key: "cell_type",
1225
+ get:
1226
+ /**
1227
+ * String identifying the type of cell.
1228
+ */
1229
+ function get() {
1230
+ return 'markdown';
1231
+ }
1232
+
1233
+ /**
1234
+ * Serialize the model to JSON.
1235
+ */
1236
+ }, {
1237
+ key: "toJSON",
1238
+ value: function toJSON() {
1239
+ return {
1240
+ id: this.getId(),
1241
+ cell_type: 'markdown',
1242
+ source: this.getSource(),
1243
+ metadata: this.getMetadata(),
1244
+ attachments: this.getAttachments()
1245
+ };
1246
+ }
1247
+ }], [{
1248
+ key: "createStandalone",
1249
+ value:
1250
+ /**
1251
+ * Create a new YMarkdownCell that works standalone. It cannot be
1252
+ * inserted into a YNotebook because the Yjs model is already
1253
+ * attached to an anonymous Y.Doc instance.
1254
+ */
1255
+ function createStandalone(id) {
1256
+ return _get(_getPrototypeOf(YMarkdownCell), "createStandalone", this).call(this, id);
1257
+ }
1258
+ }]);
1259
+ return YMarkdownCell;
1260
+ }(YAttachmentCell);
1261
+
1262
+ /**
1263
+ * Cell type.
1264
+ */
1265
+
1266
+ /**
1267
+ * Shared implementation of the Shared Document types.
1268
+ *
1269
+ * Shared cells can be inserted into a SharedNotebook.
1270
+ * Shared cells only start emitting events when they are connected to a SharedNotebook.
1271
+ *
1272
+ * "Standalone" cells must not be inserted into a (Shared)Notebook.
1273
+ * Standalone cells emit events immediately after they have been created, but they must not
1274
+ * be included into a (Shared)Notebook.
1275
+ */
1276
+ export var YNotebook = /*#__PURE__*/function (_YDocument) {
1277
+ _inherits(YNotebook, _YDocument);
1278
+ var _super6 = _createSuper(YNotebook);
1279
+ function YNotebook() {
1280
+ var _options$disableDocum, _options$cellTypeAdap;
1281
+ var _this17;
1282
+ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1283
+ _classCallCheck(this, YNotebook);
1284
+ _this17 = _super6.call(this);
1285
+ _this17._undoChangedEmitter = new Emitter();
1286
+ _this17._redoChangedEmitter = new Emitter();
1287
+ _this17._canRedo = false;
1288
+ _this17._canUndo = false;
1289
+ _this17.handleUndoChanged = function () {
1290
+ var canRedo = _this17.undoManager.canRedo();
1291
+ if (_this17._canRedo !== canRedo) {
1292
+ _this17._canRedo = canRedo;
1293
+ _this17._redoChangedEmitter.fire(canRedo);
1294
+ }
1295
+ var canUndo = _this17.undoManager.canUndo();
1296
+ if (_this17._canUndo !== canUndo) {
1297
+ _this17._canUndo = canUndo;
1298
+ _this17._undoChangedEmitter.fire(canUndo);
1299
+ }
1300
+ };
1301
+ _this17.cellTypeAdaptor = defaultCellTypeAdaptor;
1302
+ /**
1303
+ * YJS map for the notebook metadata
1304
+ */
1305
+ _this17.ymeta = _this17.ydoc.getMap('meta');
1306
+ /**
1307
+ * Handle a change to the ystate.
1308
+ */
1309
+ _this17._onMetaChanged = function (event) {
1310
+ if (event.keysChanged.has('metadata')) {
1311
+ var _metadataChange$oldVa2;
1312
+ var change = event.changes.keys.get('metadata');
1313
+ var metadataChange = {
1314
+ oldValue: change !== null && change !== void 0 && change.oldValue ? change.oldValue : undefined,
1315
+ newValue: _this17.getMetadata()
1316
+ };
1317
+ var oldValue = (_metadataChange$oldVa2 = metadataChange.oldValue) !== null && _metadataChange$oldVa2 !== void 0 ? _metadataChange$oldVa2 : {};
1318
+ var oldKeys = Object.keys(oldValue);
1319
+ var newKeys = Object.keys(metadataChange.newValue);
1320
+ var _iterator2 = _createForOfIteratorHelper(new Set(oldKeys.concat(newKeys))),
1321
+ _step2;
1322
+ try {
1323
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
1324
+ var key = _step2.value;
1325
+ if (!oldKeys.includes(key)) {
1326
+ _this17._metadataChangedEmitter.fire({
1327
+ key: key,
1328
+ newValue: metadataChange.newValue[key],
1329
+ type: 'add'
1330
+ });
1331
+ } else if (!newKeys.includes(key)) {
1332
+ _this17._metadataChangedEmitter.fire({
1333
+ key: key,
1334
+ oldValue: metadataChange.oldValue[key],
1335
+ type: 'remove'
1336
+ });
1337
+ } else if (!deepEqual(oldValue[key], metadataChange.newValue[key])) {
1338
+ _this17._metadataChangedEmitter.fire({
1339
+ key: key,
1340
+ newValue: metadataChange.newValue[key],
1341
+ oldValue: metadataChange.oldValue[key],
1342
+ type: 'change'
1343
+ });
1344
+ }
1345
+ }
1346
+ } catch (err) {
1347
+ _iterator2.e(err);
1348
+ } finally {
1349
+ _iterator2.f();
1350
+ }
1351
+ _this17._changedEmitter.fire({
1352
+ metadataChange: metadataChange
1353
+ });
1354
+ }
1355
+ if (event.keysChanged.has('nbformat')) {
1356
+ var _change = event.changes.keys.get('nbformat');
1357
+ var nbformatChanged = {
1358
+ key: 'nbformat',
1359
+ oldValue: _change !== null && _change !== void 0 && _change.oldValue ? _change.oldValue : undefined,
1360
+ newValue: _this17.nbformat
1361
+ };
1362
+ _this17._changedEmitter.fire({
1363
+ nbformatChanged: nbformatChanged
1364
+ });
1365
+ }
1366
+ if (event.keysChanged.has('nbformat_minor')) {
1367
+ var _change2 = event.changes.keys.get('nbformat_minor');
1368
+ var _nbformatChanged = {
1369
+ key: 'nbformat_minor',
1370
+ oldValue: _change2 !== null && _change2 !== void 0 && _change2.oldValue ? _change2.oldValue : undefined,
1371
+ newValue: _this17.nbformat_minor
1372
+ };
1373
+ _this17._changedEmitter.fire({
1374
+ nbformatChanged: _nbformatChanged
1375
+ });
1376
+ }
1377
+ };
1378
+ /**
1379
+ * Handle a change to the list of cells.
1380
+ */
1381
+ _this17._onYCellsChanged = function (event) {
1382
+ // update the type cell mapping by iterating through the added/removed types
1383
+ event.changes.added.forEach(function (item) {
1384
+ var type = item.content.type;
1385
+ if (!_this17._ycellMapping.has(type)) {
1386
+ var c = createCellModelFromSharedType(type, {
1387
+ notebook: _assertThisInitialized(_this17)
1388
+ }, _this17.cellTypeAdaptor);
1389
+ c.setUndoManager();
1390
+ _this17._ycellMapping.set(type, c);
1391
+ }
1392
+ });
1393
+ event.changes.deleted.forEach(function (item) {
1394
+ var type = item.content.type;
1395
+ var model = _this17._ycellMapping.get(type);
1396
+ if (model) {
1397
+ model.dispose();
1398
+ _this17._ycellMapping.delete(type);
1399
+ }
1400
+ });
1401
+ var index = 0;
1402
+
1403
+ // this reflects the event.changes.delta, but replaces the content of delta.insert with ycells
1404
+ var cellsChange = [];
1405
+ event.changes.delta.forEach(function (d) {
1406
+ if (d.insert !== null) {
1407
+ var _this17$cells;
1408
+ var insertedCells = d.insert.map(function (ycell) {
1409
+ return _this17._ycellMapping.get(ycell);
1410
+ });
1411
+ cellsChange.push({
1412
+ insert: insertedCells
1413
+ });
1414
+ (_this17$cells = _this17.cells).splice.apply(_this17$cells, [index, 0].concat(_toConsumableArray(insertedCells)));
1415
+ _this17._cellsChangedEmitter.fire({
1416
+ type: 'add',
1417
+ newIndex: index,
1418
+ newValues: insertedCells,
1419
+ oldIndex: -2,
1420
+ oldValues: []
1421
+ });
1422
+ index += d.insert.length;
1423
+ } else if (d.delete !== null) {
1424
+ cellsChange.push(d);
1425
+ var oldValues = _this17.cells.splice(index, d.delete);
1426
+ _this17._cellsChangedEmitter.fire({
1427
+ type: 'remove',
1428
+ newIndex: -1,
1429
+ newValues: [],
1430
+ oldIndex: index,
1431
+ oldValues: oldValues
1432
+ });
1433
+ } else if (d.retain !== null) {
1434
+ cellsChange.push(d);
1435
+ index += d.retain;
1436
+ }
1437
+ });
1438
+ _this17._changedEmitter.fire({
1439
+ cellsChange: cellsChange
1440
+ });
1441
+ };
1442
+ _this17._cellsChangedEmitter = new Emitter();
1443
+ _this17._cellsChanged = _this17._cellsChangedEmitter.event;
1444
+ _this17._metadataChangedEmitter = new Emitter();
1445
+ _this17._metadataChanged = _this17._metadataChangedEmitter.event;
1446
+ /**
1447
+ * Internal Yjs cells list
1448
+ */
1449
+ _this17._ycells = _this17.ydoc.getArray('cells');
1450
+ _this17._ycellMapping = new WeakMap();
1451
+ _this17._disableDocumentWideUndoRedo = (_options$disableDocum = options.disableDocumentWideUndoRedo) !== null && _options$disableDocum !== void 0 ? _options$disableDocum : false;
1452
+ _this17.cellTypeAdaptor = (_options$cellTypeAdap = options.cellTypeAdaptor) !== null && _options$cellTypeAdap !== void 0 ? _options$cellTypeAdap : defaultCellTypeAdaptor;
1453
+ _this17.cells = _this17._ycells.toArray().map(function (ycell) {
1454
+ if (!_this17._ycellMapping.has(ycell)) {
1455
+ _this17._ycellMapping.set(ycell, createCellModelFromSharedType(ycell, {
1456
+ notebook: _assertThisInitialized(_this17)
1457
+ }, _this17.cellTypeAdaptor));
1458
+ }
1459
+ return _this17._ycellMapping.get(ycell);
1460
+ });
1461
+ _this17.undoManager.addToScope(_this17._ycells);
1462
+ _this17._ycells.observe(_this17._onYCellsChanged);
1463
+ _this17.ymeta.observe(_this17._onMetaChanged);
1464
+ _this17.undoManager.on('stack-item-updated', _this17.handleUndoChanged);
1465
+ _this17.undoManager.on('stack-item-added', _this17.handleUndoChanged);
1466
+ _this17.undoManager.on('stack-item-popped', _this17.handleUndoChanged);
1467
+ _this17.undoManager.on('stack-cleared', _this17.handleUndoChanged);
1468
+ _this17._canRedo = _this17.undoManager.canRedo();
1469
+ _this17._canUndo = _this17.undoManager.canUndo();
1470
+ return _this17;
1471
+ }
1472
+ _createClass(YNotebook, [{
1473
+ key: "undoChanged",
1474
+ get:
1475
+ /**
1476
+ * Signal triggered when a undo stack changed.
1477
+ */
1478
+ function get() {
1479
+ return this._undoChangedEmitter.event;
1480
+ }
1481
+ }, {
1482
+ key: "redoChanged",
1483
+ get:
1484
+ /**
1485
+ * Signal triggered when a undo stack changed.
1486
+ */
1487
+ function get() {
1488
+ return this._redoChangedEmitter.event;
1489
+ }
1490
+
1491
+ /**
1492
+ * Create a new YNotebook.
1493
+ */
1494
+ }, {
1495
+ key: "cellsChanged",
1496
+ get:
1497
+ /**
1498
+ * Cells list
1499
+ */
1500
+
1501
+ /**
1502
+ * Signal triggered when the cells list changes.
1503
+ */
1504
+ function get() {
1505
+ return this._cellsChanged;
1506
+ }
1507
+
1508
+ /**
1509
+ * Wether the undo/redo logic should be
1510
+ * considered on the full document across all cells.
1511
+ *
1512
+ * Default: false
1513
+ */
1514
+ }, {
1515
+ key: "disableDocumentWideUndoRedo",
1516
+ get: function get() {
1517
+ return this._disableDocumentWideUndoRedo;
1518
+ }
1519
+
1520
+ /**
1521
+ * Notebook metadata
1522
+ */
1523
+ }, {
1524
+ key: "metadata",
1525
+ get: function get() {
1526
+ return this.getMetadata();
1527
+ },
1528
+ set: function set(v) {
1529
+ this.setMetadata(v);
1530
+ }
1531
+
1532
+ /**
1533
+ * Signal triggered when a metadata changes.
1534
+ */
1535
+ }, {
1536
+ key: "metadataChanged",
1537
+ get: function get() {
1538
+ return this._metadataChanged;
1539
+ }
1540
+
1541
+ /**
1542
+ * nbformat major version
1543
+ */
1544
+ }, {
1545
+ key: "nbformat",
1546
+ get: function get() {
1547
+ return this.ymeta.get('nbformat');
1548
+ },
1549
+ set: function set(value) {
1550
+ var _this18 = this;
1551
+ this.transact(function () {
1552
+ _this18.ymeta.set('nbformat', value);
1553
+ }, false);
1554
+ }
1555
+
1556
+ /**
1557
+ * nbformat minor version
1558
+ */
1559
+ }, {
1560
+ key: "nbformat_minor",
1561
+ get: function get() {
1562
+ return this.ymeta.get('nbformat_minor');
1563
+ },
1564
+ set: function set(value) {
1565
+ var _this19 = this;
1566
+ this.transact(function () {
1567
+ _this19.ymeta.set('nbformat_minor', value);
1568
+ }, false);
1569
+ }
1570
+
1571
+ /**
1572
+ * Dispose of the resources.
1573
+ */
1574
+ }, {
1575
+ key: "dispose",
1576
+ value: function dispose() {
1577
+ if (this.isDisposed) {
1578
+ return;
1579
+ }
1580
+ this._ycells.unobserve(this._onYCellsChanged);
1581
+ this.ymeta.unobserve(this._onMetaChanged);
1582
+ this.undoManager.off('stack-item-updated', this.handleUndoChanged);
1583
+ this.undoManager.off('stack-item-added', this.handleUndoChanged);
1584
+ this.undoManager.off('stack-item-popped', this.handleUndoChanged);
1585
+ this.undoManager.off('stack-cleared', this.handleUndoChanged);
1586
+ _get(_getPrototypeOf(YNotebook.prototype), "dispose", this).call(this);
1587
+ }
1588
+
1589
+ /**
1590
+ * Get a shared cell by index.
1591
+ *
1592
+ * @param index: Cell's position.
1593
+ *
1594
+ * @returns The requested shared cell.
1595
+ */
1596
+ }, {
1597
+ key: "getCell",
1598
+ value: function getCell(index) {
1599
+ return this.cells[index];
1600
+ }
1601
+
1602
+ /**
1603
+ * Add a shared cell at the notebook bottom.
1604
+ *
1605
+ * @param cell Cell to add.
1606
+ *
1607
+ * @returns The added cell.
1608
+ */
1609
+ }, {
1610
+ key: "addCell",
1611
+ value: function addCell(cell) {
1612
+ return this.insertCell(this._ycells.length, cell);
1613
+ }
1614
+
1615
+ /**
1616
+ * Insert a shared cell into a specific position.
1617
+ *
1618
+ * @param index: Cell's position.
1619
+ * @param cell: Cell to insert.
1620
+ *
1621
+ * @returns The inserted cell.
1622
+ */
1623
+ }, {
1624
+ key: "insertCell",
1625
+ value: function insertCell(index, cell) {
1626
+ return this.insertCells(index, [cell])[0];
1627
+ }
1628
+
1629
+ /**
1630
+ * Insert a list of shared cells into a specific position.
1631
+ *
1632
+ * @param index: Position to insert the cells.
1633
+ * @param cells: Array of shared cells to insert.
1634
+ *
1635
+ * @returns The inserted cells.
1636
+ */
1637
+ }, {
1638
+ key: "insertCells",
1639
+ value: function insertCells(index, cells) {
1640
+ var _this20 = this;
1641
+ var yCells = cells.map(function (c) {
1642
+ var cell = createCell(c, _this20);
1643
+ _this20._ycellMapping.set(cell.ymodel, cell);
1644
+ return cell;
1645
+ });
1646
+ this.transact(function () {
1647
+ _this20._ycells.insert(index, yCells.map(function (cell) {
1648
+ return cell.ymodel;
1649
+ }));
1650
+ });
1651
+ yCells.forEach(function (c) {
1652
+ c.setUndoManager();
1653
+ });
1654
+ return yCells;
1655
+ }
1656
+
1657
+ /**
1658
+ * Move a cell.
1659
+ *
1660
+ * @param fromIndex: Index of the cell to move.
1661
+ * @param toIndex: New position of the cell.
1662
+ */
1663
+ }, {
1664
+ key: "moveCell",
1665
+ value: function moveCell(fromIndex, toIndex) {
1666
+ var _this21 = this;
1667
+ this.transact(function () {
1668
+ // FIXME we need to use yjs move feature to preserve undo history
1669
+ var clone = createCell(_this21.getCell(fromIndex).toJSON(), _this21);
1670
+ _this21._ycells.delete(fromIndex, 1);
1671
+ _this21._ycells.insert(toIndex, [clone.ymodel]);
1672
+ });
1673
+ }
1674
+
1675
+ /**
1676
+ * Remove a cell.
1677
+ *
1678
+ * @param index: Index of the cell to remove.
1679
+ */
1680
+ }, {
1681
+ key: "deleteCell",
1682
+ value: function deleteCell(index) {
1683
+ this.deleteCellRange(index, index + 1);
1684
+ }
1685
+
1686
+ /**
1687
+ * Remove a range of cells.
1688
+ *
1689
+ * @param from: The start index of the range to remove (inclusive).
1690
+ * @param to: The end index of the range to remove (exclusive).
1691
+ */
1692
+ }, {
1693
+ key: "deleteCellRange",
1694
+ value: function deleteCellRange(from, to) {
1695
+ var _this22 = this;
1696
+ // Cells will be removed from the mapping in the model event listener.
1697
+ this.transact(function () {
1698
+ _this22._ycells.delete(from, to - from);
1699
+ });
1700
+ }
1701
+
1702
+ /**
1703
+ * Delete a metadata notebook.
1704
+ *
1705
+ * @param key The key to delete
1706
+ */
1707
+ }, {
1708
+ key: "deleteMetadata",
1709
+ value: function deleteMetadata(key) {
1710
+ var allMetadata = deepCopy(this.ymeta.get('metadata'));
1711
+ delete allMetadata[key];
1712
+ this.setMetadata(allMetadata);
1713
+ }
1714
+
1715
+ /**
1716
+ * Returns some metadata associated with the notebook.
1717
+ *
1718
+ * If no `key` is provided, it will return all metadata.
1719
+ * Else it will return the value for that key.
1720
+ *
1721
+ * @param key Key to get from the metadata
1722
+ * @returns Notebook's metadata.
1723
+ */
1724
+ }, {
1725
+ key: "getMetadata",
1726
+ value: function getMetadata(key) {
1727
+ var meta = this.ymeta.get('metadata');
1728
+ if (typeof key === 'string') {
1729
+ return deepCopy(meta[key]);
1730
+ } else {
1731
+ return deepCopy(meta !== null && meta !== void 0 ? meta : {});
1732
+ }
1733
+ }
1734
+
1735
+ /**
1736
+ * Sets some metadata associated with the notebook.
1737
+ *
1738
+ * If only one argument is provided, it will override all notebook metadata.
1739
+ * Otherwise a single key will be set to a new value.
1740
+ *
1741
+ * @param metadata All Notebook's metadata or the key to set.
1742
+ * @param value New metadata value
1743
+ */
1744
+ }, {
1745
+ key: "setMetadata",
1746
+ value: function setMetadata(metadata, value) {
1747
+ if (typeof metadata === 'string') {
1748
+ if (typeof value === 'undefined') {
1749
+ throw new TypeError("Metadata value for ".concat(metadata, " cannot be 'undefined'; use deleteMetadata."));
1750
+ }
1751
+ var update = {};
1752
+ update[metadata] = value;
1753
+ this.updateMetadata(update);
1754
+ } else {
1755
+ this.ymeta.set('metadata', deepCopy(metadata));
1756
+ }
1757
+ }
1758
+
1759
+ /**
1760
+ * Updates the metadata associated with the notebook.
1761
+ *
1762
+ * @param value: Metadata's attribute to update.
1763
+ */
1764
+ }, {
1765
+ key: "updateMetadata",
1766
+ value: function updateMetadata(value) {
1767
+ // TODO: Maybe modify only attributes instead of replacing the whole metadata?
1768
+ this.ymeta.set('metadata', _objectSpread(_objectSpread({}, this.getMetadata()), value));
1769
+ }
1770
+ }], [{
1771
+ key: "create",
1772
+ value: function create() {
1773
+ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1774
+ return new YNotebook(options);
1775
+ }
1776
+ }]);
1777
+ return YNotebook;
1778
+ }(YDocument);