@theia/notebook 1.51.0 → 1.53.0-next.18

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.
Files changed (91) hide show
  1. package/lib/browser/contributions/cell-operations.d.ts +1 -1
  2. package/lib/browser/contributions/cell-operations.d.ts.map +1 -1
  3. package/lib/browser/contributions/cell-operations.js +10 -2
  4. package/lib/browser/contributions/cell-operations.js.map +1 -1
  5. package/lib/browser/contributions/notebook-actions-contribution.d.ts +2 -0
  6. package/lib/browser/contributions/notebook-actions-contribution.d.ts.map +1 -1
  7. package/lib/browser/contributions/notebook-actions-contribution.js +43 -24
  8. package/lib/browser/contributions/notebook-actions-contribution.js.map +1 -1
  9. package/lib/browser/contributions/notebook-cell-actions-contribution.d.ts +4 -0
  10. package/lib/browser/contributions/notebook-cell-actions-contribution.d.ts.map +1 -1
  11. package/lib/browser/contributions/notebook-cell-actions-contribution.js +63 -10
  12. package/lib/browser/contributions/notebook-cell-actions-contribution.js.map +1 -1
  13. package/lib/browser/contributions/notebook-preferences.d.ts +3 -0
  14. package/lib/browser/contributions/notebook-preferences.d.ts.map +1 -1
  15. package/lib/browser/contributions/notebook-preferences.js +9 -1
  16. package/lib/browser/contributions/notebook-preferences.js.map +1 -1
  17. package/lib/browser/contributions/notebook-status-bar-contribution.d.ts +14 -0
  18. package/lib/browser/contributions/notebook-status-bar-contribution.d.ts.map +1 -0
  19. package/lib/browser/contributions/notebook-status-bar-contribution.js +75 -0
  20. package/lib/browser/contributions/notebook-status-bar-contribution.js.map +1 -0
  21. package/lib/browser/contributions/notebook-undo-redo-handler.d.ts +10 -0
  22. package/lib/browser/contributions/notebook-undo-redo-handler.d.ts.map +1 -0
  23. package/lib/browser/contributions/notebook-undo-redo-handler.js +49 -0
  24. package/lib/browser/contributions/notebook-undo-redo-handler.js.map +1 -0
  25. package/lib/browser/notebook-editor-widget.d.ts +6 -0
  26. package/lib/browser/notebook-editor-widget.d.ts.map +1 -1
  27. package/lib/browser/notebook-editor-widget.js +40 -4
  28. package/lib/browser/notebook-editor-widget.js.map +1 -1
  29. package/lib/browser/notebook-frontend-module.d.ts.map +1 -1
  30. package/lib/browser/notebook-frontend-module.js +7 -1
  31. package/lib/browser/notebook-frontend-module.js.map +1 -1
  32. package/lib/browser/service/notebook-context-manager.d.ts +2 -1
  33. package/lib/browser/service/notebook-context-manager.d.ts.map +1 -1
  34. package/lib/browser/service/notebook-context-manager.js +6 -3
  35. package/lib/browser/service/notebook-context-manager.js.map +1 -1
  36. package/lib/browser/service/notebook-options.d.ts +1 -0
  37. package/lib/browser/service/notebook-options.d.ts.map +1 -1
  38. package/lib/browser/service/notebook-options.js +1 -0
  39. package/lib/browser/service/notebook-options.js.map +1 -1
  40. package/lib/browser/service/notebook-service.d.ts +1 -0
  41. package/lib/browser/service/notebook-service.d.ts.map +1 -1
  42. package/lib/browser/service/notebook-service.js +7 -0
  43. package/lib/browser/service/notebook-service.js.map +1 -1
  44. package/lib/browser/view/notebook-cell-editor.d.ts +8 -1
  45. package/lib/browser/view/notebook-cell-editor.d.ts.map +1 -1
  46. package/lib/browser/view/notebook-cell-editor.js +89 -5
  47. package/lib/browser/view/notebook-cell-editor.js.map +1 -1
  48. package/lib/browser/view/notebook-cell-list-view.d.ts +3 -0
  49. package/lib/browser/view/notebook-cell-list-view.d.ts.map +1 -1
  50. package/lib/browser/view/notebook-cell-list-view.js +33 -2
  51. package/lib/browser/view/notebook-cell-list-view.js.map +1 -1
  52. package/lib/browser/view/notebook-code-cell-view.d.ts +1 -1
  53. package/lib/browser/view/notebook-code-cell-view.d.ts.map +1 -1
  54. package/lib/browser/view/notebook-code-cell-view.js +19 -17
  55. package/lib/browser/view/notebook-code-cell-view.js.map +1 -1
  56. package/lib/browser/view/notebook-find-widget.d.ts +63 -0
  57. package/lib/browser/view/notebook-find-widget.d.ts.map +1 -0
  58. package/lib/browser/view/notebook-find-widget.js +225 -0
  59. package/lib/browser/view/notebook-find-widget.js.map +1 -0
  60. package/lib/browser/view/notebook-markdown-cell-view.d.ts +4 -0
  61. package/lib/browser/view/notebook-markdown-cell-view.d.ts.map +1 -1
  62. package/lib/browser/view/notebook-markdown-cell-view.js +105 -8
  63. package/lib/browser/view/notebook-markdown-cell-view.js.map +1 -1
  64. package/lib/browser/view-model/notebook-cell-model.d.ts +27 -1
  65. package/lib/browser/view-model/notebook-cell-model.d.ts.map +1 -1
  66. package/lib/browser/view-model/notebook-cell-model.js +76 -1
  67. package/lib/browser/view-model/notebook-cell-model.js.map +1 -1
  68. package/lib/browser/view-model/notebook-model.d.ts +8 -1
  69. package/lib/browser/view-model/notebook-model.d.ts.map +1 -1
  70. package/lib/browser/view-model/notebook-model.js +66 -14
  71. package/lib/browser/view-model/notebook-model.js.map +1 -1
  72. package/package.json +9 -8
  73. package/src/browser/contributions/cell-operations.ts +8 -2
  74. package/src/browser/contributions/notebook-actions-contribution.ts +47 -22
  75. package/src/browser/contributions/notebook-cell-actions-contribution.ts +66 -11
  76. package/src/browser/contributions/notebook-preferences.ts +10 -1
  77. package/src/browser/contributions/notebook-status-bar-contribution.ts +77 -0
  78. package/src/browser/contributions/notebook-undo-redo-handler.ts +41 -0
  79. package/src/browser/notebook-editor-widget.tsx +50 -5
  80. package/src/browser/notebook-frontend-module.ts +11 -3
  81. package/src/browser/service/notebook-context-manager.ts +8 -4
  82. package/src/browser/service/notebook-options.ts +2 -1
  83. package/src/browser/service/notebook-service.ts +7 -1
  84. package/src/browser/style/index.css +178 -7
  85. package/src/browser/view/notebook-cell-editor.tsx +94 -5
  86. package/src/browser/view/notebook-cell-list-view.tsx +40 -4
  87. package/src/browser/view/notebook-code-cell-view.tsx +19 -17
  88. package/src/browser/view/notebook-find-widget.tsx +335 -0
  89. package/src/browser/view/notebook-markdown-cell-view.tsx +134 -17
  90. package/src/browser/view-model/notebook-cell-model.ts +101 -8
  91. package/src/browser/view-model/notebook-model.ts +77 -20
@@ -32,6 +32,8 @@ import { NotebookCellOutputModel } from './notebook-cell-output-model';
32
32
  import { PreferenceService } from '@theia/core/lib/browser';
33
33
  import { NotebookPreferences } from '../contributions/notebook-preferences';
34
34
  import { LanguageService } from '@theia/core/lib/browser/language-service';
35
+ import { NotebookEditorFindMatch, NotebookEditorFindMatchOptions } from '../view/notebook-find-widget';
36
+ import { Range } from '@theia/core/shared/vscode-languageserver-protocol';
35
37
 
36
38
  export const NotebookCellModelFactory = Symbol('NotebookModelFactory');
37
39
  export type NotebookCellModelFactory = (props: NotebookCellModelProps) => NotebookCellModel;
@@ -86,22 +88,22 @@ export interface NotebookCellModelProps {
86
88
  export class NotebookCellModel implements NotebookCell, Disposable {
87
89
 
88
90
  protected readonly onDidChangeOutputsEmitter = new Emitter<NotebookCellOutputsSplice>();
89
- readonly onDidChangeOutputs: Event<NotebookCellOutputsSplice> = this.onDidChangeOutputsEmitter.event;
91
+ readonly onDidChangeOutputs = this.onDidChangeOutputsEmitter.event;
90
92
 
91
93
  protected readonly onDidChangeOutputItemsEmitter = new Emitter<CellOutput>();
92
- readonly onDidChangeOutputItems: Event<CellOutput> = this.onDidChangeOutputItemsEmitter.event;
94
+ readonly onDidChangeOutputItems = this.onDidChangeOutputItemsEmitter.event;
93
95
 
94
96
  protected readonly onDidChangeContentEmitter = new Emitter<'content' | 'language' | 'mime'>();
95
- readonly onDidChangeContent: Event<'content' | 'language' | 'mime'> = this.onDidChangeContentEmitter.event;
97
+ readonly onDidChangeContent = this.onDidChangeContentEmitter.event;
96
98
 
97
99
  protected readonly onDidChangeMetadataEmitter = new Emitter<void>();
98
- readonly onDidChangeMetadata: Event<void> = this.onDidChangeMetadataEmitter.event;
100
+ readonly onDidChangeMetadata = this.onDidChangeMetadataEmitter.event;
99
101
 
100
102
  protected readonly onDidChangeInternalMetadataEmitter = new Emitter<CellInternalMetadataChangedEvent>();
101
- readonly onDidChangeInternalMetadata: Event<CellInternalMetadataChangedEvent> = this.onDidChangeInternalMetadataEmitter.event;
103
+ readonly onDidChangeInternalMetadata = this.onDidChangeInternalMetadataEmitter.event;
102
104
 
103
105
  protected readonly onDidChangeLanguageEmitter = new Emitter<string>();
104
- readonly onDidChangeLanguage: Event<string> = this.onDidChangeLanguageEmitter.event;
106
+ readonly onDidChangeLanguage = this.onDidChangeLanguageEmitter.event;
105
107
 
106
108
  protected readonly onDidRequestCellEditChangeEmitter = new Emitter<boolean>();
107
109
  readonly onDidRequestCellEditChange = this.onDidRequestCellEditChangeEmitter.event;
@@ -113,10 +115,19 @@ export class NotebookCellModel implements NotebookCell, Disposable {
113
115
  readonly onWillBlurCellEditor = this.onWillBlurCellEditorEmitter.event;
114
116
 
115
117
  protected readonly onDidChangeEditorOptionsEmitter = new Emitter<MonacoEditor.IOptions>();
116
- readonly onDidChangeEditorOptions: Event<MonacoEditor.IOptions> = this.onDidChangeEditorOptionsEmitter.event;
118
+ readonly onDidChangeEditorOptions = this.onDidChangeEditorOptionsEmitter.event;
117
119
 
118
120
  protected readonly outputVisibilityChangeEmitter = new Emitter<boolean>();
119
- readonly onDidChangeOutputVisibility: Event<boolean> = this.outputVisibilityChangeEmitter.event;
121
+ readonly onDidChangeOutputVisibility = this.outputVisibilityChangeEmitter.event;
122
+
123
+ protected readonly onDidFindMatchesEmitter = new Emitter<NotebookCodeEditorFindMatch[]>();
124
+ readonly onDidFindMatches: Event<NotebookCodeEditorFindMatch[]> = this.onDidFindMatchesEmitter.event;
125
+
126
+ protected readonly onDidSelectFindMatchEmitter = new Emitter<NotebookCodeEditorFindMatch>();
127
+ readonly onDidSelectFindMatch: Event<NotebookCodeEditorFindMatch> = this.onDidSelectFindMatchEmitter.event;
128
+
129
+ protected onDidRequestCenterEditorEmitter = new Emitter<void>();
130
+ readonly onDidRequestCenterEditor = this.onDidRequestCenterEditorEmitter.event;
120
131
 
121
132
  @inject(NotebookCellModelProps)
122
133
  protected readonly props: NotebookCellModelProps;
@@ -175,10 +186,12 @@ export class NotebookCellModel implements NotebookCell, Disposable {
175
186
  get source(): string {
176
187
  return this.props.source;
177
188
  }
189
+
178
190
  set source(source: string) {
179
191
  this.props.source = source;
180
192
  this.textModel?.textEditorModel.setValue(source);
181
193
  }
194
+
182
195
  get language(): string {
183
196
  return this.props.language;
184
197
  }
@@ -289,6 +302,10 @@ export class NotebookCellModel implements NotebookCell, Disposable {
289
302
  this.onWillBlurCellEditorEmitter.fire();
290
303
  }
291
304
 
305
+ requestCenterEditor(): void {
306
+ this.onDidRequestCenterEditorEmitter.fire();
307
+ }
308
+
292
309
  spliceNotebookCellOutputs(splice: NotebookCellOutputsSplice): void {
293
310
  if (splice.deleteCount > 0 && splice.newOutputs.length > 0) {
294
311
  const commonLen = Math.min(splice.deleteCount, splice.newOutputs.length);
@@ -368,6 +385,82 @@ export class NotebookCellModel implements NotebookCell, Disposable {
368
385
  this.onDidChangeOutputItemsEmitter.fire(output);
369
386
  }
370
387
  }
388
+
389
+ onMarkdownFind: ((options: NotebookEditorFindMatchOptions) => NotebookEditorFindMatch[]) | undefined;
390
+
391
+ showMatch(selected: NotebookCodeEditorFindMatch): void {
392
+ this.onDidSelectFindMatchEmitter.fire(selected);
393
+ }
394
+
395
+ findMatches(options: NotebookEditorFindMatchOptions): NotebookEditorFindMatch[] {
396
+ if (this.cellKind === CellKind.Markup && !this.editing) {
397
+ return this.onMarkdownFind?.(options) ?? [];
398
+ }
399
+ if (!this.textModel) {
400
+ return [];
401
+ }
402
+ const matches = options.search ? this.textModel.findMatches({
403
+ searchString: options.search,
404
+ isRegex: options.regex,
405
+ matchCase: options.matchCase,
406
+ matchWholeWord: options.wholeWord
407
+ }) : [];
408
+ const editorFindMatches = matches.map(match => new NotebookCodeEditorFindMatch(this, match.range, this.textModel!));
409
+ this.onDidFindMatchesEmitter.fire(editorFindMatches);
410
+ return editorFindMatches;
411
+ }
412
+
413
+ replaceAll(matches: NotebookCodeEditorFindMatch[], value: string): void {
414
+ const editOperations = matches.map(match => ({
415
+ range: {
416
+ startColumn: match.range.start.character,
417
+ startLineNumber: match.range.start.line,
418
+ endColumn: match.range.end.character,
419
+ endLineNumber: match.range.end.line
420
+ },
421
+ text: value
422
+ }));
423
+ this.textModel?.textEditorModel.pushEditOperations(
424
+ // eslint-disable-next-line no-null/no-null
425
+ null,
426
+ editOperations,
427
+ // eslint-disable-next-line no-null/no-null
428
+ () => null);
429
+ }
430
+ }
431
+
432
+ export interface NotebookCellFindMatches {
433
+ matches: NotebookEditorFindMatch[];
434
+ selected: NotebookEditorFindMatch;
435
+ }
436
+
437
+ export class NotebookCodeEditorFindMatch implements NotebookEditorFindMatch {
438
+
439
+ selected = false;
440
+
441
+ constructor(readonly cell: NotebookCellModel, readonly range: Range, readonly textModel: MonacoEditorModel) {
442
+ }
443
+
444
+ show(): void {
445
+ this.cell.showMatch(this);
446
+ }
447
+ replace(value: string): void {
448
+ this.textModel.textEditorModel.pushEditOperations(
449
+ // eslint-disable-next-line no-null/no-null
450
+ null,
451
+ [{
452
+ range: {
453
+ startColumn: this.range.start.character,
454
+ startLineNumber: this.range.start.line,
455
+ endColumn: this.range.end.character,
456
+ endLineNumber: this.range.end.line
457
+ },
458
+ text: value
459
+ }],
460
+ // eslint-disable-next-line no-null/no-null
461
+ () => null);
462
+ }
463
+
371
464
  }
372
465
 
373
466
  function computeRunStartTimeAdjustment(oldMetadata: NotebookCellInternalMetadata, newMetadata: NotebookCellInternalMetadata): number | undefined {
@@ -29,12 +29,13 @@ import {
29
29
  } from '../notebook-types';
30
30
  import { NotebookSerializer } from '../service/notebook-service';
31
31
  import { FileService } from '@theia/filesystem/lib/browser/file-service';
32
- import { NotebookCellModel, NotebookCellModelFactory } from './notebook-cell-model';
32
+ import { NotebookCellModel, NotebookCellModelFactory, NotebookCodeEditorFindMatch } from './notebook-cell-model';
33
33
  import { inject, injectable, interfaces, postConstruct } from '@theia/core/shared/inversify';
34
34
  import { UndoRedoService } from '@theia/editor/lib/browser/undo-redo-service';
35
35
  import { MarkdownString } from '@theia/core/lib/common/markdown-rendering';
36
36
  import type { NotebookModelResolverService } from '../service/notebook-model-resolver-service';
37
37
  import { BinaryBuffer } from '@theia/core/lib/common/buffer';
38
+ import { NotebookEditorFindMatch, NotebookEditorFindMatchOptions } from '../view/notebook-find-widget';
38
39
 
39
40
  export const NotebookModelFactory = Symbol('NotebookModelFactory');
40
41
 
@@ -125,6 +126,16 @@ export class NotebookModel implements Saveable, Disposable {
125
126
  return this.props.resource.readOnly ?? false;
126
127
  }
127
128
 
129
+ protected _selectedText = '';
130
+
131
+ set selectedText(value: string) {
132
+ this._selectedText = value;
133
+ }
134
+
135
+ get selectedText(): string {
136
+ return this._selectedText;
137
+ }
138
+
128
139
  selectedCell?: NotebookCellModel;
129
140
  protected dirtyCells: NotebookCellModel[] = [];
130
141
 
@@ -227,12 +238,15 @@ export class NotebookModel implements Saveable, Disposable {
227
238
  }
228
239
 
229
240
  this.dirty = this.dirtyCells.length > 0;
241
+ // Only fire `onContentChangedEmitter` here, because `onDidChangeContentEmitter` is used for model level changes only
242
+ // However, this event indicates that the content of a cell has changed
243
+ this.onContentChangedEmitter.fire();
230
244
  }
231
245
 
232
246
  setData(data: NotebookData, markDirty = true): void {
233
247
  // Replace all cells in the model
234
248
  this.dirtyCells = [];
235
- this.replaceCells(0, this.cells.length, data.cells, false);
249
+ this.replaceCells(0, this.cells.length, data.cells, false, false);
236
250
  this.metadata = data.metadata;
237
251
  this.dirty = markDirty;
238
252
  this.onDidChangeContentEmitter.fire();
@@ -246,13 +260,15 @@ export class NotebookModel implements Saveable, Disposable {
246
260
  }
247
261
 
248
262
  undo(): void {
249
- // TODO we probably need to check if a monaco editor is focused and if so, not undo
250
- this.undoRedoService.undo(this.uri);
263
+ if (!this.readOnly) {
264
+ this.undoRedoService.undo(this.uri);
265
+ }
251
266
  }
252
267
 
253
268
  redo(): void {
254
- // TODO see undo
255
- this.undoRedoService.redo(this.uri);
269
+ if (!this.readOnly) {
270
+ this.undoRedoService.redo(this.uri);
271
+ }
256
272
  }
257
273
 
258
274
  setSelectedCell(cell: NotebookCellModel, scrollIntoView?: boolean): void {
@@ -267,6 +283,9 @@ export class NotebookModel implements Saveable, Disposable {
267
283
  cell.onDidChangeOutputs(() => {
268
284
  this.dirty = true;
269
285
  });
286
+ cell.onDidRequestCellEditChange(() => {
287
+ this.onContentChangedEmitter.fire();
288
+ });
270
289
  }
271
290
  }
272
291
 
@@ -298,7 +317,7 @@ export class NotebookModel implements Saveable, Disposable {
298
317
  let scrollIntoView = true;
299
318
  switch (edit.editType) {
300
319
  case CellEditType.Replace:
301
- this.replaceCells(edit.index, edit.count, edit.cells, computeUndoRedo);
320
+ this.replaceCells(edit.index, edit.count, edit.cells, computeUndoRedo, true);
302
321
  scrollIntoView = edit.cells.length > 0;
303
322
  break;
304
323
  case CellEditType.Output: {
@@ -321,10 +340,10 @@ export class NotebookModel implements Saveable, Disposable {
321
340
 
322
341
  break;
323
342
  case CellEditType.Metadata:
324
- this.changeCellMetadata(this.cells[cellIndex], edit.metadata, computeUndoRedo);
343
+ this.changeCellMetadata(this.cells[cellIndex], edit.metadata, false);
325
344
  break;
326
345
  case CellEditType.PartialMetadata:
327
- this.changeCellMetadataPartial(this.cells[cellIndex], edit.metadata, computeUndoRedo);
346
+ this.changeCellMetadataPartial(this.cells[cellIndex], edit.metadata, false);
328
347
  break;
329
348
  case CellEditType.PartialInternalMetadata:
330
349
  this.changeCellInternalMetadataPartial(this.cells[cellIndex], edit.internalMetadata);
@@ -333,7 +352,7 @@ export class NotebookModel implements Saveable, Disposable {
333
352
  this.changeCellLanguage(this.cells[cellIndex], edit.language, computeUndoRedo);
334
353
  break;
335
354
  case CellEditType.DocumentMetadata:
336
- this.updateNotebookMetadata(edit.metadata, computeUndoRedo);
355
+ this.updateNotebookMetadata(edit.metadata, false);
337
356
  break;
338
357
  case CellEditType.Move:
339
358
  this.moveCellToIndex(cellIndex, edit.length, edit.newIdx, computeUndoRedo);
@@ -346,11 +365,15 @@ export class NotebookModel implements Saveable, Disposable {
346
365
  }
347
366
  }
348
367
 
368
+ this.fireContentChange();
369
+ }
370
+
371
+ protected fireContentChange(): void {
349
372
  this.onDidChangeContentEmitter.fire();
350
373
  this.onContentChangedEmitter.fire();
351
374
  }
352
375
 
353
- protected replaceCells(start: number, deleteCount: number, newCells: CellData[], computeUndoRedo: boolean): void {
376
+ protected replaceCells(start: number, deleteCount: number, newCells: CellData[], computeUndoRedo: boolean, requestEdit: boolean): void {
354
377
  const cells = newCells.map(cell => {
355
378
  const handle = this.nextHandle++;
356
379
  return this.cellModelFactory({
@@ -377,13 +400,20 @@ export class NotebookModel implements Saveable, Disposable {
377
400
 
378
401
  if (computeUndoRedo) {
379
402
  this.undoRedoService.pushElement(this.uri,
380
- async () => this.replaceCells(start, newCells.length, deletedCells.map(cell => cell.getData()), false),
381
- async () => this.replaceCells(start, deleteCount, newCells, false));
403
+ async () => {
404
+ this.replaceCells(start, newCells.length, deletedCells.map(cell => cell.getData()), false, false);
405
+ this.fireContentChange();
406
+ },
407
+ async () => {
408
+ this.replaceCells(start, deleteCount, newCells, false, false);
409
+ this.fireContentChange();
410
+ }
411
+ );
382
412
  }
383
413
 
384
414
  this.onDidAddOrRemoveCellEmitter.fire({ rawEvent: { kind: NotebookCellsChangeType.ModelChange, changes }, newCellIds: cells.map(cell => cell.handle) });
385
415
  this.onDidChangeContentEmitter.queue({ kind: NotebookCellsChangeType.ModelChange, changes });
386
- if (cells.length > 0) {
416
+ if (cells.length > 0 && requestEdit) {
387
417
  this.setSelectedCell(cells[cells.length - 1]);
388
418
  cells[cells.length - 1].requestEdit();
389
419
  }
@@ -461,8 +491,14 @@ export class NotebookModel implements Saveable, Disposable {
461
491
  protected moveCellToIndex(fromIndex: number, length: number, toIndex: number, computeUndoRedo: boolean): boolean {
462
492
  if (computeUndoRedo) {
463
493
  this.undoRedoService.pushElement(this.uri,
464
- async () => { this.moveCellToIndex(toIndex, length, fromIndex, false); },
465
- async () => { this.moveCellToIndex(fromIndex, length, toIndex, false); }
494
+ async () => {
495
+ this.moveCellToIndex(toIndex, length, fromIndex, false);
496
+ this.fireContentChange();
497
+ },
498
+ async () => {
499
+ this.moveCellToIndex(fromIndex, length, toIndex, false);
500
+ this.fireContentChange();
501
+ }
466
502
  );
467
503
  }
468
504
 
@@ -478,11 +514,9 @@ export class NotebookModel implements Saveable, Disposable {
478
514
  }
479
515
 
480
516
  protected isCellMetadataChanged(a: NotebookCellMetadata, b: NotebookCellMetadata): boolean {
481
- const keys = new Set([...Object.keys(a || {}), ...Object.keys(b || {})]);
517
+ const keys = new Set<keyof NotebookCellMetadata>([...Object.keys(a || {}), ...Object.keys(b || {})]);
482
518
  for (const key of keys) {
483
- if (
484
- (a[key as keyof NotebookCellMetadata] !== b[key as keyof NotebookCellMetadata])
485
- ) {
519
+ if (a[key] !== b[key]) {
486
520
  return true;
487
521
  }
488
522
  }
@@ -490,4 +524,27 @@ export class NotebookModel implements Saveable, Disposable {
490
524
  return false;
491
525
  }
492
526
 
527
+ findMatches(options: NotebookEditorFindMatchOptions): NotebookEditorFindMatch[] {
528
+ const matches: NotebookEditorFindMatch[] = [];
529
+ for (const cell of this.cells) {
530
+ matches.push(...cell.findMatches(options));
531
+ }
532
+ return matches;
533
+ }
534
+
535
+ replaceAll(matches: NotebookEditorFindMatch[], text: string): void {
536
+ const matchMap = new Map<NotebookCellModel, NotebookCodeEditorFindMatch[]>();
537
+ for (const match of matches) {
538
+ if (match instanceof NotebookCodeEditorFindMatch) {
539
+ if (!matchMap.has(match.cell)) {
540
+ matchMap.set(match.cell, []);
541
+ }
542
+ matchMap.get(match.cell)?.push(match);
543
+ }
544
+ }
545
+ for (const [cell, cellMatches] of matchMap) {
546
+ cell.replaceAll(cellMatches, text);
547
+ }
548
+ }
549
+
493
550
  }