@theia/notebook 1.67.0-next.3 → 1.67.0-next.59

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 (103) hide show
  1. package/README.md +1 -1
  2. package/lib/browser/contributions/notebook-actions-contribution.d.ts.map +1 -1
  3. package/lib/browser/contributions/notebook-actions-contribution.js +29 -26
  4. package/lib/browser/contributions/notebook-actions-contribution.js.map +1 -1
  5. package/lib/browser/contributions/notebook-cell-actions-contribution.d.ts.map +1 -1
  6. package/lib/browser/contributions/notebook-cell-actions-contribution.js +23 -9
  7. package/lib/browser/contributions/notebook-cell-actions-contribution.js.map +1 -1
  8. package/lib/browser/contributions/notebook-label-provider-contribution.d.ts.map +1 -1
  9. package/lib/browser/contributions/notebook-label-provider-contribution.js +2 -1
  10. package/lib/browser/contributions/notebook-label-provider-contribution.js.map +1 -1
  11. package/lib/browser/contributions/notebook-outline-contribution.d.ts +3 -2
  12. package/lib/browser/contributions/notebook-outline-contribution.d.ts.map +1 -1
  13. package/lib/browser/contributions/notebook-outline-contribution.js +7 -5
  14. package/lib/browser/contributions/notebook-outline-contribution.js.map +1 -1
  15. package/lib/browser/contributions/notebook-status-bar-contribution.d.ts.map +1 -1
  16. package/lib/browser/contributions/notebook-status-bar-contribution.js +4 -6
  17. package/lib/browser/contributions/notebook-status-bar-contribution.js.map +1 -1
  18. package/lib/browser/index.d.ts +1 -0
  19. package/lib/browser/index.d.ts.map +1 -1
  20. package/lib/browser/index.js +1 -0
  21. package/lib/browser/index.js.map +1 -1
  22. package/lib/browser/notebook-cell-open-handler.js +3 -2
  23. package/lib/browser/notebook-cell-open-handler.js.map +1 -1
  24. package/lib/browser/notebook-editor-split-contribution.d.ts +14 -0
  25. package/lib/browser/notebook-editor-split-contribution.d.ts.map +1 -0
  26. package/lib/browser/notebook-editor-split-contribution.js +51 -0
  27. package/lib/browser/notebook-editor-split-contribution.js.map +1 -0
  28. package/lib/browser/notebook-editor-widget-factory.d.ts +1 -0
  29. package/lib/browser/notebook-editor-widget-factory.d.ts.map +1 -1
  30. package/lib/browser/notebook-editor-widget-factory.js +10 -2
  31. package/lib/browser/notebook-editor-widget-factory.js.map +1 -1
  32. package/lib/browser/notebook-editor-widget.d.ts +3 -0
  33. package/lib/browser/notebook-editor-widget.d.ts.map +1 -1
  34. package/lib/browser/notebook-editor-widget.js +17 -4
  35. package/lib/browser/notebook-editor-widget.js.map +1 -1
  36. package/lib/browser/notebook-frontend-module.d.ts.map +1 -1
  37. package/lib/browser/notebook-frontend-module.js +4 -0
  38. package/lib/browser/notebook-frontend-module.js.map +1 -1
  39. package/lib/browser/notebook-open-handler.d.ts +6 -0
  40. package/lib/browser/notebook-open-handler.d.ts.map +1 -1
  41. package/lib/browser/notebook-open-handler.js +17 -11
  42. package/lib/browser/notebook-open-handler.js.map +1 -1
  43. package/lib/browser/notebook-types.d.ts +1 -0
  44. package/lib/browser/notebook-types.d.ts.map +1 -1
  45. package/lib/browser/notebook-types.js.map +1 -1
  46. package/lib/browser/service/notebook-context-manager.d.ts +2 -0
  47. package/lib/browser/service/notebook-context-manager.d.ts.map +1 -1
  48. package/lib/browser/service/notebook-context-manager.js +14 -10
  49. package/lib/browser/service/notebook-context-manager.js.map +1 -1
  50. package/lib/browser/view/notebook-cell-editor.d.ts +2 -0
  51. package/lib/browser/view/notebook-cell-editor.d.ts.map +1 -1
  52. package/lib/browser/view/notebook-cell-editor.js +9 -5
  53. package/lib/browser/view/notebook-cell-editor.js.map +1 -1
  54. package/lib/browser/view/notebook-cell-list-view.d.ts +2 -0
  55. package/lib/browser/view/notebook-cell-list-view.d.ts.map +1 -1
  56. package/lib/browser/view/notebook-cell-list-view.js +34 -31
  57. package/lib/browser/view/notebook-cell-list-view.js.map +1 -1
  58. package/lib/browser/view/notebook-cell-toolbar-factory.d.ts.map +1 -1
  59. package/lib/browser/view/notebook-cell-toolbar-factory.js +5 -5
  60. package/lib/browser/view/notebook-cell-toolbar-factory.js.map +1 -1
  61. package/lib/browser/view/notebook-code-cell-view.d.ts +2 -0
  62. package/lib/browser/view/notebook-code-cell-view.d.ts.map +1 -1
  63. package/lib/browser/view/notebook-code-cell-view.js +7 -2
  64. package/lib/browser/view/notebook-code-cell-view.js.map +1 -1
  65. package/lib/browser/view/notebook-markdown-cell-view.d.ts +2 -0
  66. package/lib/browser/view/notebook-markdown-cell-view.d.ts.map +1 -1
  67. package/lib/browser/view/notebook-markdown-cell-view.js +27 -9
  68. package/lib/browser/view/notebook-markdown-cell-view.js.map +1 -1
  69. package/lib/browser/view-model/notebook-cell-model.d.ts +2 -14
  70. package/lib/browser/view-model/notebook-cell-model.d.ts.map +1 -1
  71. package/lib/browser/view-model/notebook-cell-model.js +7 -31
  72. package/lib/browser/view-model/notebook-cell-model.js.map +1 -1
  73. package/lib/browser/view-model/notebook-model.d.ts +1 -9
  74. package/lib/browser/view-model/notebook-model.d.ts.map +1 -1
  75. package/lib/browser/view-model/notebook-model.js +2 -24
  76. package/lib/browser/view-model/notebook-model.js.map +1 -1
  77. package/lib/browser/view-model/notebook-view-model.d.ts +40 -0
  78. package/lib/browser/view-model/notebook-view-model.d.ts.map +1 -0
  79. package/lib/browser/view-model/notebook-view-model.js +120 -0
  80. package/lib/browser/view-model/notebook-view-model.js.map +1 -0
  81. package/package.json +7 -7
  82. package/src/browser/contributions/notebook-actions-contribution.ts +25 -22
  83. package/src/browser/contributions/notebook-cell-actions-contribution.ts +20 -9
  84. package/src/browser/contributions/notebook-label-provider-contribution.ts +2 -1
  85. package/src/browser/contributions/notebook-outline-contribution.ts +8 -6
  86. package/src/browser/contributions/notebook-status-bar-contribution.ts +4 -6
  87. package/src/browser/index.ts +1 -0
  88. package/src/browser/notebook-cell-open-handler.ts +3 -3
  89. package/src/browser/notebook-editor-split-contribution.ts +51 -0
  90. package/src/browser/notebook-editor-widget-factory.ts +11 -1
  91. package/src/browser/notebook-editor-widget.tsx +18 -3
  92. package/src/browser/notebook-frontend-module.ts +5 -0
  93. package/src/browser/notebook-open-handler.ts +19 -11
  94. package/src/browser/notebook-types.ts +1 -0
  95. package/src/browser/service/notebook-context-manager.ts +17 -9
  96. package/src/browser/view/notebook-cell-editor.tsx +13 -5
  97. package/src/browser/view/notebook-cell-list-view.tsx +15 -12
  98. package/src/browser/view/notebook-cell-toolbar-factory.tsx +5 -4
  99. package/src/browser/view/notebook-code-cell-view.tsx +6 -1
  100. package/src/browser/view/notebook-markdown-cell-view.tsx +27 -7
  101. package/src/browser/view-model/notebook-cell-model.ts +8 -41
  102. package/src/browser/view-model/notebook-model.ts +2 -33
  103. package/src/browser/view-model/notebook-view-model.ts +138 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notebook-view-model.d.ts","sourceRoot":"","sources":["../../../src/browser/view-model/notebook-view-model.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,WAAW,uBAAuB;IACpC,IAAI,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACpC,cAAc,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;AAErE;;GAEG;AACH,qBACa,iBAAkB,YAAW,UAAU;IAEhD,SAAS,CAAC,QAAQ,CAAC,8BAA8B,mCAA0C;IAC3F,QAAQ,CAAC,uBAAuB,uDAA6C;IAE7E,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,IAAI,qBAAqB,IAAI,aAAa,GAAG,SAAS,CAIrD;IAGD,QAAQ,CAAC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAa;IAEhE,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IA+BzC,eAAe,CAAC,IAAI,EAAE,iBAAiB,EAAE,cAAc,GAAE,OAAc,GAAG,IAAI;IAO9E,OAAO,IAAI,IAAI;CAIlB;AAED,qBAAa,aAAc,YAAW,UAAU;IAgBhC,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,iBAAiB;IAAE,SAAS,CAAC,SAAS,EAAE,MAAM,IAAI;IAdvF,SAAS,CAAC,QAAQ,CAAC,iCAAiC,mBAA0B;IAC9E,QAAQ,CAAC,0BAA0B,uCAAgD;IAEnF,SAAS,CAAC,QAAQ,CAAC,4BAA4B,kCAAyC;IACxF,QAAQ,CAAC,qBAAqB,sDAA2C;IAEzE,SAAS,CAAC,QAAQ,CAAC,2BAA2B,gBAAuB;IACrE,QAAQ,CAAC,oBAAoB,oCAA0C;IAEvE,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAS;IACpC,IAAI,OAAO,IAAI,OAAO,CAErB;gBAE8B,IAAI,EAAE,iBAAiB,EAAY,SAAS,EAAE,MAAM,IAAI;IAIvF,WAAW,IAAI,IAAI;IAOnB,eAAe,IAAI,IAAI;IAKvB,kBAAkB,CAAC,YAAY,CAAC,EAAE,sBAAsB,GAAG,IAAI;IAK/D,iBAAiB,IAAI,IAAI;IAKzB,OAAO,IAAI,IAAI;CAIlB"}
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ // *****************************************************************************
3
+ // Copyright (C) 2025 Typefox and others.
4
+ //
5
+ // This program and the accompanying materials are made available under the
6
+ // terms of the Eclipse Public License v. 2.0 which is available at
7
+ // http://www.eclipse.org/legal/epl-2.0.
8
+ //
9
+ // This Source Code may also be made available under the following Secondary
10
+ // Licenses when the conditions for such availability set forth in the Eclipse
11
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
+ // with the GNU Classpath Exception which is available at
13
+ // https://www.gnu.org/software/classpath/license.html.
14
+ //
15
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
+ // *****************************************************************************
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.CellViewModel = exports.NotebookViewModel = void 0;
19
+ const tslib_1 = require("tslib");
20
+ const inversify_1 = require("@theia/core/shared/inversify");
21
+ const core_1 = require("@theia/core");
22
+ /**
23
+ * Model containing the editor state/view information of a notebook editor. The actual notebook data can be found in the {@link NotebookModel}.
24
+ */
25
+ let NotebookViewModel = class NotebookViewModel {
26
+ constructor() {
27
+ this.onDidChangeSelectedCellEmitter = new core_1.Emitter();
28
+ this.onDidChangeSelectedCell = this.onDidChangeSelectedCellEmitter.event;
29
+ // Cell handle to CellViewModel mapping
30
+ this.cellViewModels = new Map();
31
+ }
32
+ get selectedCellViewModel() {
33
+ if (this.selectedCell) {
34
+ return this.cellViewModels.get(this.selectedCell.handle);
35
+ }
36
+ }
37
+ initDataModel(model) {
38
+ model.onDidAddOrRemoveCell(e => {
39
+ var _a, _b;
40
+ for (const cellId of e.newCellIds || []) {
41
+ const cell = model.getCellByHandle(cellId);
42
+ if (cell) {
43
+ this.cellViewModels.set(cell.handle, new CellViewModel(cell, () => {
44
+ this.cellViewModels.delete(cell.handle);
45
+ }));
46
+ }
47
+ }
48
+ if (e.newCellIds && ((_a = e.newCellIds) === null || _a === void 0 ? void 0 : _a.length) > 0 && e.externalEvent) {
49
+ const lastNewCellHandle = e.newCellIds[e.newCellIds.length - 1];
50
+ const newSelectedCell = model.getCellByHandle(lastNewCellHandle);
51
+ this.setSelectedCell(newSelectedCell, true);
52
+ (_b = this.cellViewModels.get(newSelectedCell.handle)) === null || _b === void 0 ? void 0 : _b.requestEdit();
53
+ }
54
+ else if (this.selectedCell && !model.getCellByHandle(this.selectedCell.handle)) {
55
+ const newSelectedIndex = e.rawEvent.changes[e.rawEvent.changes.length - 1].start;
56
+ const newSelectedCell = model.cells[Math.min(newSelectedIndex, model.cells.length - 1)];
57
+ this.setSelectedCell(newSelectedCell, false);
58
+ }
59
+ });
60
+ for (const cell of model.cells) {
61
+ this.cellViewModels.set(cell.handle, new CellViewModel(cell, () => {
62
+ this.cellViewModels.delete(cell.handle);
63
+ }));
64
+ }
65
+ }
66
+ setSelectedCell(cell, scrollIntoView = true) {
67
+ if (this.selectedCell !== cell) {
68
+ this.selectedCell = cell;
69
+ this.onDidChangeSelectedCellEmitter.fire({ cell, scrollIntoView });
70
+ }
71
+ }
72
+ dispose() {
73
+ this.onDidChangeSelectedCellEmitter.dispose();
74
+ }
75
+ };
76
+ exports.NotebookViewModel = NotebookViewModel;
77
+ exports.NotebookViewModel = NotebookViewModel = tslib_1.__decorate([
78
+ (0, inversify_1.injectable)()
79
+ ], NotebookViewModel);
80
+ class CellViewModel {
81
+ get editing() {
82
+ return this._editing;
83
+ }
84
+ constructor(cell, onDispose) {
85
+ this.cell = cell;
86
+ this.onDispose = onDispose;
87
+ this.onDidRequestCellEditChangeEmitter = new core_1.Emitter();
88
+ this.onDidRequestCellEditChange = this.onDidRequestCellEditChangeEmitter.event;
89
+ this.onWillFocusCellEditorEmitter = new core_1.Emitter();
90
+ this.onWillFocusCellEditor = this.onWillFocusCellEditorEmitter.event;
91
+ this.onWillBlurCellEditorEmitter = new core_1.Emitter();
92
+ this.onWillBlurCellEditor = this.onWillBlurCellEditorEmitter.event;
93
+ this._editing = false;
94
+ cell.toDispose.push(this);
95
+ }
96
+ requestEdit() {
97
+ if (this.cell.isTextModelWritable) {
98
+ this._editing = true;
99
+ this.onDidRequestCellEditChangeEmitter.fire(true);
100
+ }
101
+ }
102
+ requestStopEdit() {
103
+ this._editing = false;
104
+ this.onDidRequestCellEditChangeEmitter.fire(false);
105
+ }
106
+ requestFocusEditor(focusRequest) {
107
+ this.requestEdit();
108
+ this.onWillFocusCellEditorEmitter.fire(focusRequest);
109
+ }
110
+ requestBlurEditor() {
111
+ this.requestStopEdit();
112
+ this.onWillBlurCellEditorEmitter.fire();
113
+ }
114
+ dispose() {
115
+ this.onDispose();
116
+ this.onDidRequestCellEditChangeEmitter.dispose();
117
+ }
118
+ }
119
+ exports.CellViewModel = CellViewModel;
120
+ //# sourceMappingURL=notebook-view-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notebook-view-model.js","sourceRoot":"","sources":["../../../src/browser/view-model/notebook-view-model.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@theia/notebook",
3
- "version": "1.67.0-next.3+7946ca874",
3
+ "version": "1.67.0-next.59+3f14297ea",
4
4
  "description": "Theia - Notebook Extension",
5
5
  "dependencies": {
6
- "@theia/core": "1.67.0-next.3+7946ca874",
7
- "@theia/editor": "1.67.0-next.3+7946ca874",
8
- "@theia/filesystem": "1.67.0-next.3+7946ca874",
9
- "@theia/monaco": "1.67.0-next.3+7946ca874",
6
+ "@theia/core": "1.67.0-next.59+3f14297ea",
7
+ "@theia/editor": "1.67.0-next.59+3f14297ea",
8
+ "@theia/filesystem": "1.67.0-next.59+3f14297ea",
9
+ "@theia/monaco": "1.67.0-next.59+3f14297ea",
10
10
  "@theia/monaco-editor-core": "1.96.302",
11
- "@theia/outline-view": "1.67.0-next.3+7946ca874",
11
+ "@theia/outline-view": "1.67.0-next.59+3f14297ea",
12
12
  "advanced-mark.js": "^2.6.0",
13
13
  "react-perfect-scrollbar": "^1.5.8",
14
14
  "tslib": "^2.6.2"
@@ -54,5 +54,5 @@
54
54
  "nyc": {
55
55
  "extends": "../../configs/nyc.json"
56
56
  },
57
- "gitHead": "7946ca874b04e6249d883e9a586f193194df1365"
57
+ "gitHead": "3f14297ea2edcdb1fffd74afee0613e70b43e125"
58
58
  }
@@ -131,13 +131,14 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
131
131
  commands.registerCommand(NotebookCommands.ADD_NEW_CELL_COMMAND, {
132
132
  execute: (notebookModel: NotebookModel, cellKind: CellKind = CellKind.Markup, index?: number | 'above' | 'below', focusContainer?: boolean) => {
133
133
  notebookModel = notebookModel ?? this.notebookEditorWidgetService.focusedEditor?.model;
134
+ const viewModel = this.notebookEditorWidgetService.focusedEditor?.viewModel;
134
135
 
135
136
  let insertIndex: number = 0;
136
137
  if (typeof index === 'number' && index >= 0) {
137
138
  insertIndex = index;
138
- } else if (notebookModel.selectedCell && typeof index === 'string') {
139
+ } else if (viewModel?.selectedCell && typeof index === 'string') {
139
140
  // if index is -1 insert below otherwise at the index of the selected cell which is above the selected.
140
- insertIndex = notebookModel.cells.indexOf(notebookModel.selectedCell) + (index === 'below' ? 1 : 0);
141
+ insertIndex = notebookModel.cells.indexOf(viewModel.selectedCell) + (index === 'below' ? 1 : 0);
141
142
  }
142
143
 
143
144
  let cellLanguage: string = 'markdown';
@@ -158,7 +159,7 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
158
159
  }]
159
160
  }], true);
160
161
  if (focusContainer) {
161
- notebookModel.selectedCell?.requestBlurEditor();
162
+ viewModel?.cellViewModels.get(viewModel.selectedCell?.handle ?? -1)?.requestBlurEditor();
162
163
  }
163
164
  }
164
165
  });
@@ -191,27 +192,28 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
191
192
  execute: (change: number | CellChangeDirection) => {
192
193
  const focusedEditor = this.notebookEditorWidgetService.focusedEditor;
193
194
  const model = focusedEditor?.model;
195
+ const viewModel = focusedEditor?.viewModel;
194
196
  if (model && typeof change === 'number') {
195
- model.setSelectedCell(model.cells[change]);
196
- } else if (model && model.selectedCell) {
197
- const currentIndex = model.cells.indexOf(model.selectedCell);
197
+ viewModel?.setSelectedCell(model.cells[change]);
198
+ } else if (model && viewModel?.selectedCell) {
199
+ const currentIndex = model.cells.indexOf(viewModel?.selectedCell);
198
200
  const shouldFocusEditor = this.contextKeyService.match('editorTextFocus');
199
201
 
200
202
  if (change === CellChangeDirection.Up && currentIndex > 0) {
201
- model.setSelectedCell(model.cells[currentIndex - 1]);
202
- if ((model.selectedCell?.cellKind === CellKind.Code
203
- || (model.selectedCell?.cellKind === CellKind.Markup && model.selectedCell?.editing)) && shouldFocusEditor) {
204
- model.selectedCell.requestFocusEditor('lastLine');
203
+ viewModel?.setSelectedCell(model.cells[currentIndex - 1]);
204
+ if ((viewModel?.selectedCell?.cellKind === CellKind.Code
205
+ || (viewModel?.selectedCell?.cellKind === CellKind.Markup && viewModel?.selectedCellViewModel?.editing)) && shouldFocusEditor) {
206
+ viewModel?.cellViewModels.get(viewModel.selectedCell.handle)?.requestFocusEditor('lastLine');
205
207
  }
206
208
  } else if (change === CellChangeDirection.Down && currentIndex < model.cells.length - 1) {
207
- model.setSelectedCell(model.cells[currentIndex + 1]);
208
- if ((model.selectedCell?.cellKind === CellKind.Code
209
- || (model.selectedCell?.cellKind === CellKind.Markup && model.selectedCell?.editing)) && shouldFocusEditor) {
210
- model.selectedCell.requestFocusEditor();
209
+ viewModel?.setSelectedCell(model.cells[currentIndex + 1]);
210
+ if ((viewModel?.selectedCell?.cellKind === CellKind.Code
211
+ || (viewModel?.selectedCell?.cellKind === CellKind.Markup && viewModel?.selectedCellViewModel?.editing)) && shouldFocusEditor) {
212
+ viewModel?.cellViewModels.get(viewModel.selectedCell.handle)?.requestFocusEditor();
211
213
  }
212
214
  }
213
215
 
214
- if (model.selectedCell.cellKind === CellKind.Markup) {
216
+ if (viewModel?.selectedCell.cellKind === CellKind.Markup) {
215
217
  // since were losing focus from the cell editor, we need to focus the notebook editor again
216
218
  focusedEditor?.node.focus();
217
219
  }
@@ -229,8 +231,8 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
229
231
  commands.registerCommand(NotebookCommands.CUT_SELECTED_CELL, this.editableCommandHandler(
230
232
  () => {
231
233
  const model = this.notebookEditorWidgetService.focusedEditor?.model;
232
- const selectedCell = model?.selectedCell;
233
- if (selectedCell) {
234
+ const selectedCell = this.notebookEditorWidgetService.focusedEditor?.viewModel?.selectedCell;
235
+ if (selectedCell && model) {
234
236
  model.applyEdits([{ editType: CellEditType.Replace, index: model.cells.indexOf(selectedCell), count: 1, cells: [] }], true);
235
237
  this.notebookClipboardService.copyCell(selectedCell);
236
238
  }
@@ -238,8 +240,8 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
238
240
 
239
241
  commands.registerCommand(NotebookCommands.COPY_SELECTED_CELL, {
240
242
  execute: () => {
241
- const model = this.notebookEditorWidgetService.focusedEditor?.model;
242
- const selectedCell = model?.selectedCell;
243
+ const viewModel = this.notebookEditorWidgetService.focusedEditor?.viewModel;
244
+ const selectedCell = viewModel?.selectedCell;
243
245
  if (selectedCell) {
244
246
  this.notebookClipboardService.copyCell(selectedCell);
245
247
  }
@@ -253,7 +255,8 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
253
255
  const copiedCell = this.notebookClipboardService.getCell();
254
256
  if (copiedCell) {
255
257
  const model = this.notebookEditorWidgetService.focusedEditor?.model;
256
- const insertIndex = model?.selectedCell ? model.cells.indexOf(model.selectedCell) + (position === 'above' ? 0 : 1) : 0;
258
+ const viewModel = this.notebookEditorWidgetService.focusedEditor?.viewModel;
259
+ const insertIndex = viewModel?.selectedCell && model ? model.cells.indexOf(viewModel?.selectedCell) + (position === 'above' ? 0 : 1) : 0;
257
260
  model?.applyEdits([{ editType: CellEditType.Replace, index: insertIndex, count: 0, cells: [copiedCell] }], true);
258
261
  }
259
262
  }
@@ -267,8 +270,8 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
267
270
 
268
271
  commands.registerCommand(NotebookCommands.CENTER_ACTIVE_CELL, {
269
272
  execute: (editor?: NotebookEditorWidget) => {
270
- const model = editor ? editor.model : this.notebookEditorWidgetService.focusedEditor?.model;
271
- model?.selectedCell?.requestCenterEditor();
273
+ const viewModel = editor ? editor.viewModel : this.notebookEditorWidgetService.focusedEditor?.viewModel;
274
+ viewModel?.selectedCell?.requestCenterEditor();
272
275
  }
273
276
  });
274
277
 
@@ -284,8 +284,16 @@ export class NotebookCellActionContribution implements MenuContribution, Command
284
284
  }
285
285
 
286
286
  registerCommands(commands: CommandRegistry): void {
287
- commands.registerCommand(NotebookCellCommands.EDIT_COMMAND, this.editableCellCommandHandler((_, cell) => cell.requestFocusEditor()));
288
- commands.registerCommand(NotebookCellCommands.STOP_EDIT_COMMAND, { execute: (_, cell: NotebookCellModel) => (cell ?? this.getSelectedCell()).requestBlurEditor() });
287
+ commands.registerCommand(NotebookCellCommands.EDIT_COMMAND, this.editableCellCommandHandler((_, cell) => {
288
+ const cellViewModel = this.notebookEditorWidgetService.focusedEditor?.viewModel.cellViewModels.get(cell.handle);
289
+ cellViewModel?.requestFocusEditor();
290
+ }));
291
+ commands.registerCommand(NotebookCellCommands.STOP_EDIT_COMMAND, {
292
+ execute: (_, cell: NotebookCellModel) => {
293
+ const cellViewModel = this.notebookEditorWidgetService.focusedEditor?.viewModel.cellViewModels.get(cell.handle);
294
+ cellViewModel?.requestBlurEditor();
295
+ }
296
+ });
289
297
  commands.registerCommand(NotebookCellCommands.DELETE_COMMAND,
290
298
  this.editableCellCommandHandler((notebookModel, cell) => {
291
299
  notebookModel.applyEdits([{
@@ -346,6 +354,8 @@ export class NotebookCellActionContribution implements MenuContribution, Command
346
354
 
347
355
  commands.registerCommand(NotebookCellCommands.EXECUTE_SINGLE_CELL_AND_FOCUS_NEXT_COMMAND, this.editableCellCommandHandler(
348
356
  (notebookModel, cell) => {
357
+ const viewModel = this.notebookEditorWidgetService.focusedEditor?.viewModel;
358
+
349
359
  if (cell.cellKind === CellKind.Code) {
350
360
  commands.executeCommand(NotebookCellCommands.EXECUTE_SINGLE_CELL_COMMAND.id, notebookModel, cell);
351
361
  } else {
@@ -353,7 +363,7 @@ export class NotebookCellActionContribution implements MenuContribution, Command
353
363
  }
354
364
  const index = notebookModel.cells.indexOf(cell);
355
365
  if (index < notebookModel.cells.length - 1) {
356
- notebookModel.setSelectedCell(notebookModel.cells[index + 1]);
366
+ viewModel?.setSelectedCell(notebookModel.cells[index + 1]);
357
367
  } else if (cell.cellKind === CellKind.Code) {
358
368
  commands.executeCommand(NotebookCellCommands.INSERT_NEW_CELL_BELOW_COMMAND.id);
359
369
  } else {
@@ -375,7 +385,8 @@ export class NotebookCellActionContribution implements MenuContribution, Command
375
385
  }
376
386
 
377
387
  const index = notebookModel.cells.indexOf(cell);
378
- notebookModel.setSelectedCell(notebookModel.cells[index + 1]);
388
+ const viewModel = this.notebookEditorWidgetService.focusedEditor?.viewModel;
389
+ viewModel?.setSelectedCell(notebookModel.cells[index + 1]);
379
390
  })
380
391
  );
381
392
 
@@ -436,7 +447,7 @@ export class NotebookCellActionContribution implements MenuContribution, Command
436
447
 
437
448
  commands.registerCommand(NotebookCellCommands.TOGGLE_CELL_OUTPUT, {
438
449
  execute: () => {
439
- const selectedCell = this.notebookEditorWidgetService.focusedEditor?.model?.selectedCell;
450
+ const selectedCell = this.notebookEditorWidgetService.focusedEditor?.viewModel?.selectedCell;
440
451
  if (selectedCell) {
441
452
  selectedCell.outputVisible = !selectedCell.outputVisible;
442
453
  }
@@ -444,9 +455,9 @@ export class NotebookCellActionContribution implements MenuContribution, Command
444
455
  });
445
456
 
446
457
  commands.registerCommand(NotebookCellCommands.CHANGE_CELL_LANGUAGE, {
447
- isVisible: () => !!this.notebookEditorWidgetService.focusedEditor?.model?.selectedCell,
458
+ isVisible: () => !!this.notebookEditorWidgetService.focusedEditor?.viewModel?.selectedCell,
448
459
  execute: async (notebook?: NotebookModel, cell?: NotebookCellModel) => {
449
- const selectedCell = cell ?? this.notebookEditorWidgetService.focusedEditor?.model?.selectedCell;
460
+ const selectedCell = cell ?? this.notebookEditorWidgetService.focusedEditor?.viewModel?.selectedCell;
450
461
  const activeNotebook = notebook ?? this.notebookEditorWidgetService.focusedEditor?.model;
451
462
  if (!selectedCell || !activeNotebook) {
452
463
  return;
@@ -475,7 +486,7 @@ export class NotebookCellActionContribution implements MenuContribution, Command
475
486
 
476
487
  commands.registerCommand(NotebookCellCommands.TOGGLE_LINE_NUMBERS, {
477
488
  execute: () => {
478
- const selectedCell = this.notebookEditorWidgetService.focusedEditor?.model?.selectedCell;
489
+ const selectedCell = this.notebookEditorWidgetService.focusedEditor?.viewModel?.selectedCell;
479
490
  if (selectedCell) {
480
491
  const currentLineNumber = selectedCell.editorOptions?.lineNumbers;
481
492
  selectedCell.editorOptions = { ...selectedCell.editorOptions, lineNumbers: !currentLineNumber || currentLineNumber === 'off' ? 'on' : 'off' };
@@ -498,7 +509,7 @@ export class NotebookCellActionContribution implements MenuContribution, Command
498
509
  }
499
510
 
500
511
  protected getSelectedCell(): NotebookCellModel | undefined {
501
- return this.notebookEditorWidgetService.focusedEditor?.model?.selectedCell;
512
+ return this.notebookEditorWidgetService.focusedEditor?.viewModel?.selectedCell;
502
513
  }
503
514
 
504
515
  registerKeybindings(keybindings: KeybindingRegistry): void {
@@ -21,6 +21,7 @@ import { NotebookService } from '../service/notebook-service';
21
21
  import { NotebookCellOutlineNode } from './notebook-outline-contribution';
22
22
  import type Token = require('markdown-it/lib/token');
23
23
  import markdownit = require('@theia/core/shared/markdown-it');
24
+ import * as markdownitemoji from '@theia/core/shared/markdown-it-emoji';
24
25
  import { NotebookCellModel } from '../view-model/notebook-cell-model';
25
26
  import { URI } from '@theia/core';
26
27
 
@@ -33,7 +34,7 @@ export class NotebookLabelProviderContribution implements LabelProviderContribut
33
34
  @inject(LabelProvider)
34
35
  protected readonly labelProvider: LabelProvider;
35
36
 
36
- protected markdownIt = markdownit();
37
+ protected markdownIt = markdownit().use(markdownitemoji.full);
37
38
 
38
39
  canHandle(element: object): number {
39
40
  if (NotebookCellOutlineNode.is(element)) {
@@ -24,6 +24,7 @@ import { NotebookEditorWidget } from '../notebook-editor-widget';
24
24
  import { DisposableCollection, isObject, URI } from '@theia/core';
25
25
  import { CellKind, CellUri } from '../../common';
26
26
  import { NotebookService } from '../service/notebook-service';
27
+ import { NotebookViewModel } from '../view-model/notebook-view-model';
27
28
  export interface NotebookCellOutlineNode extends OutlineSymbolInformationNode {
28
29
  uri: URI;
29
30
  }
@@ -77,36 +78,37 @@ export class NotebookOutlineContribution implements FrontendApplicationContribut
77
78
  }));
78
79
  if (editor.model) {
79
80
  this.editorModelListeners.dispose();
80
- this.editorModelListeners.push(editor.model.onDidChangeSelectedCell(() => {
81
+ this.editorModelListeners.push(editor.viewModel.onDidChangeSelectedCell(() => {
81
82
  if (editor === this.currentEditor) {
82
83
  this.updateOutline(editor);
83
84
  }
84
85
  }));
85
- const roots = editor && editor.model && await this.createRoots(editor.model);
86
+ const roots = editor && editor.model && await this.createRoots(editor.model, editor.viewModel);
86
87
  this.outlineViewService.publish(roots || []);
87
88
  }
88
89
  }
89
90
  }
90
91
 
91
- protected async createRoots(model: NotebookModel): Promise<OutlineSymbolInformationNode[] | undefined> {
92
+ protected async createRoots(model: NotebookModel, viewModel: NotebookViewModel): Promise<OutlineSymbolInformationNode[] | undefined> {
92
93
  return model.cells.map(cell => ({
93
94
  id: cell.uri.toString(),
94
95
  iconClass: cell.cellKind === CellKind.Markup ? codicon('markdown') : codicon('code'),
95
96
  parent: undefined,
96
97
  children: [],
97
- selected: model.selectedCell === cell,
98
+ selected: viewModel.selectedCell === cell,
98
99
  expanded: false,
99
100
  uri: cell.uri,
100
101
  } as NotebookCellOutlineNode));
101
102
  }
102
103
 
103
- selectCell(node: object): void {
104
+ protected selectCell(node: object): void {
104
105
  if (NotebookCellOutlineNode.is(node)) {
105
106
  const parsed = CellUri.parse(node.uri);
106
107
  const model = parsed && this.notebookService.getNotebookEditorModel(parsed.notebook);
108
+ const viewModel = this.currentEditor?.viewModel;
107
109
  const cell = model?.cells.find(c => c.handle === parsed?.handle);
108
110
  if (model && cell) {
109
- model.setSelectedCell(cell);
111
+ viewModel?.setSelectedCell(cell);
110
112
  }
111
113
  }
112
114
  }
@@ -33,10 +33,8 @@ export class NotebookStatusBarContribution implements WidgetStatusBarContributio
33
33
  }
34
34
 
35
35
  activate(statusBar: StatusBar, widget: NotebookEditorWidget): void {
36
- widget.ready.then(model => {
37
- this.onDeactivate = model.onDidChangeSelectedCell(() => {
38
- this.updateStatusbar(statusBar, widget);
39
- });
36
+ this.onDeactivate = widget.viewModel.onDidChangeSelectedCell(() => {
37
+ this.updateStatusbar(statusBar, widget);
40
38
  });
41
39
  this.updateStatusbar(statusBar, widget);
42
40
  }
@@ -48,12 +46,12 @@ export class NotebookStatusBarContribution implements WidgetStatusBarContributio
48
46
 
49
47
  protected async updateStatusbar(statusBar: StatusBar, editor?: NotebookEditorWidget): Promise<void> {
50
48
  const model = await editor?.ready;
51
- if (!model || model.cells.length === 0 || !model.selectedCell) {
49
+ if (!model || model.cells.length === 0 || !editor?.viewModel.selectedCell) {
52
50
  statusBar.removeElement(NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID);
53
51
  return;
54
52
  }
55
53
 
56
- const selectedCellIndex = model.cells.indexOf(model.selectedCell) + 1;
54
+ const selectedCellIndex = model.cells.indexOf(editor.viewModel.selectedCell) + 1;
57
55
 
58
56
  statusBar.setElement(NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID, {
59
57
  text: nls.localizeByDefault('Cell {0} of {1}', selectedCellIndex, model.cells.length),
@@ -26,3 +26,4 @@ export * from './service/notebook-renderer-messaging-service';
26
26
  export * from './service/notebook-cell-editor-service';
27
27
  export * from './renderers/cell-output-webview';
28
28
  export * from './notebook-types';
29
+ export * from './notebook-editor-split-contribution';
@@ -44,9 +44,9 @@ export class NotebookCellOpenHandler implements OpenHandler {
44
44
 
45
45
  const executionCount = parseInt(executionCountParam);
46
46
 
47
- this.notebookEditorWidgetService.currentEditor?.model?.cells
48
- .find(c => c.metadata.execution_count === executionCount)
49
- ?.requestFocusEditor(parseInt(lineParam));
47
+ const cell = this.notebookEditorWidgetService.currentEditor?.model?.cells
48
+ .find(c => c.metadata.execution_count === executionCount);
49
+ this.notebookEditorWidgetService.currentEditor?.viewModel.cellViewModels.get(cell?.handle ?? -1)?.requestFocusEditor();
50
50
  }
51
51
 
52
52
  }
@@ -0,0 +1,51 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2025 TypeFox and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { inject, injectable } from '@theia/core/shared/inversify';
18
+ import { Widget, DockLayout } from '@theia/core/lib/browser';
19
+ import { SplitEditorContribution } from '@theia/editor/lib/browser/split-editor-contribution';
20
+ import { NotebookEditorWidget } from './notebook-editor-widget';
21
+ import { NotebookOpenHandler } from './notebook-open-handler';
22
+
23
+ /**
24
+ * Implementation of SplitEditorContribution for notebook editors (NotebookEditorWidget).
25
+ * Delegates to NotebookOpenHandler.openToSide which handles counter management for splits.
26
+ */
27
+ @injectable()
28
+ export class NotebookEditorSplitContribution implements SplitEditorContribution<NotebookEditorWidget> {
29
+
30
+ @inject(NotebookOpenHandler)
31
+ protected readonly notebookOpenHandler: NotebookOpenHandler;
32
+
33
+ canHandle(widget: Widget): number {
34
+ return widget instanceof NotebookEditorWidget ? 100 : 0;
35
+ }
36
+
37
+ async split(widget: NotebookEditorWidget, splitMode: DockLayout.InsertMode): Promise<NotebookEditorWidget | undefined> {
38
+ const uri = widget.getResourceUri();
39
+ if (!uri) {
40
+ return undefined;
41
+ }
42
+
43
+ const newNotebook = await this.notebookOpenHandler.openToSide(uri, {
44
+ notebookType: widget.notebookType,
45
+ widgetOptions: { mode: splitMode, ref: widget }
46
+ });
47
+
48
+ return newNotebook;
49
+ }
50
+ }
51
+
@@ -17,7 +17,7 @@
17
17
  import { nls, URI } from '@theia/core';
18
18
  import { WidgetFactory, NavigatableWidgetOptions, LabelProvider } from '@theia/core/lib/browser';
19
19
  import { inject, injectable } from '@theia/core/shared/inversify';
20
- import { NotebookEditorWidget, NotebookEditorWidgetContainerFactory, NotebookEditorProps } from './notebook-editor-widget';
20
+ import { NotebookEditorWidget, NotebookEditorWidgetContainerFactory, NotebookEditorProps, NOTEBOOK_EDITOR_ID_PREFIX } from './notebook-editor-widget';
21
21
  import { NotebookService } from './service/notebook-service';
22
22
  import { NotebookModelResolverService } from './service/notebook-model-resolver-service';
23
23
  import { Deferred } from '@theia/core/lib/common/promise-util';
@@ -29,6 +29,13 @@ export interface NotebookEditorWidgetOptions extends NavigatableWidgetOptions {
29
29
 
30
30
  @injectable()
31
31
  export class NotebookEditorWidgetFactory implements WidgetFactory {
32
+
33
+ static createID(uri: URI, counter?: number): string {
34
+ return NOTEBOOK_EDITOR_ID_PREFIX
35
+ + uri.toString()
36
+ + (counter !== undefined ? `:${counter}` : '');
37
+ }
38
+
32
39
  readonly id: string = NotebookEditorWidget.ID;
33
40
 
34
41
  @inject(NotebookService)
@@ -53,6 +60,9 @@ export class NotebookEditorWidgetFactory implements WidgetFactory {
53
60
 
54
61
  const editor = await this.createEditor(uri, options.notebookType);
55
62
 
63
+ // Set the widget ID with counter to support multiple instances
64
+ editor.id = NotebookEditorWidgetFactory.createID(uri, options.counter);
65
+
56
66
  this.setLabels(editor, uri);
57
67
  const labelListener = this.labelProvider.onDidChange(event => {
58
68
  if (event.affects(uri)) {
@@ -37,6 +37,7 @@ import { NotebookFindWidget } from './view/notebook-find-widget';
37
37
  import debounce = require('@theia/core/shared/lodash.debounce');
38
38
  import { CellOutputWebview, CellOutputWebviewFactory } from './renderers/cell-output-webview';
39
39
  import { NotebookCellOutputModel } from './view-model/notebook-cell-output-model';
40
+ import { NotebookViewModel } from './view-model/notebook-view-model';
40
41
  const PerfectScrollbar = require('react-perfect-scrollbar');
41
42
 
42
43
  export const NotebookEditorWidgetContainerFactory = Symbol('NotebookEditorWidgetContainerFactory');
@@ -49,6 +50,8 @@ export function createNotebookEditorWidgetContainer(parent: interfaces.Container
49
50
  const cellOutputWebviewFactory: CellOutputWebviewFactory = parent.get(CellOutputWebviewFactory);
50
51
  child.bind(CellOutputWebview).toConstantValue(cellOutputWebviewFactory());
51
52
 
53
+ child.bind(NotebookViewModel).toSelf().inSingletonScope();
54
+
52
55
  child.bind(NotebookContextManager).toSelf().inSingletonScope();
53
56
  child.bind(NotebookMainToolbarRenderer).toSelf().inSingletonScope();
54
57
  child.bind(NotebookCellToolbarFactory).toSelf().inSingletonScope();
@@ -113,6 +116,9 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
113
116
  @inject(CellOutputWebview)
114
117
  protected readonly cellOutputWebview: CellOutputWebview;
115
118
 
119
+ @inject(NotebookViewModel)
120
+ protected readonly _viewModel: NotebookViewModel;
121
+
116
122
  protected readonly onDidChangeModelEmitter = new Emitter<void>();
117
123
  readonly onDidChangeModel = this.onDidChangeModelEmitter.event;
118
124
 
@@ -161,9 +167,16 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
161
167
  return this._model;
162
168
  }
163
169
 
170
+ get viewModel(): NotebookViewModel {
171
+ return this._viewModel;
172
+ }
173
+
164
174
  @postConstruct()
165
175
  protected init(): void {
166
- this.id = NOTEBOOK_EDITOR_ID_PREFIX + this.props.uri.toString();
176
+ // ID is set by NotebookEditorWidgetFactory to include counter for multiple instances
177
+ if (!this.id) {
178
+ this.id = NOTEBOOK_EDITOR_ID_PREFIX + this.props.uri.toString();
179
+ }
167
180
 
168
181
  this.scrollOptions = {
169
182
  suppressScrollY: true
@@ -181,7 +194,7 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
181
194
  this.ready.then(model => {
182
195
  if (model.cells.length === 1 && model.cells[0].source === '') {
183
196
  this.commandRegistry.executeCommand(NotebookCellCommands.EDIT_COMMAND.id, model, model.cells[0]);
184
- model.setSelectedCell(model.cells[0]);
197
+ this.viewModel.setSelectedCell(model.cells[0]);
185
198
  }
186
199
  model.onDidChangeContent(changeEvents => {
187
200
  const cellEvent = changeEvents.filter(event => event.kind === NotebookCellsChangeType.Move || event.kind === NotebookCellsChangeType.ModelChange);
@@ -198,6 +211,7 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
198
211
 
199
212
  protected async waitForData(): Promise<NotebookModel> {
200
213
  this._model = await this.props.notebookData;
214
+ this.viewModel.initDataModel(this._model);
201
215
  this.cellOutputWebview.init(this._model, this);
202
216
  this.saveable.delegate = this._model;
203
217
  this.toDispose.push(this._model);
@@ -225,7 +239,7 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
225
239
  }
226
240
  // Ensure that the model is loaded before adding the editor
227
241
  this.notebookEditorService.addNotebookEditor(this);
228
- this._model.selectedCell = this._model.cells[0];
242
+ this.viewModel.selectedCell = this._model.cells[0];
229
243
  this.update();
230
244
  this.notebookContextManager.init(this);
231
245
  return this._model;
@@ -286,6 +300,7 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
286
300
  {this.cellOutputWebview.render()}
287
301
  <NotebookCellListView renderers={this.renderers}
288
302
  notebookModel={this._model}
303
+ notebookViewModel={this.viewModel}
289
304
  notebookContext={this.notebookContextManager}
290
305
  toolbarRenderer={this.cellToolbarFactory}
291
306
  commandRegistry={this.commandRegistry}