@jupyterlab/notebook-extension 4.6.1 → 4.6.3

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.
@@ -22,14 +22,52 @@ declare namespace Private {
22
22
  *
23
23
  * ## Note
24
24
  * This field does not work as other metadata form fields, as it does not update metadata.
25
+ *
26
+ * A single instance is meant to be shared by every render of the field. The
27
+ * displayed cell follows the notebook tracker rather than the render calls, so
28
+ * that the field keeps working when the metadata form is not being rebuilt, and
29
+ * so that it does not hold on to a cell model of a closed notebook.
30
+ *
31
+ * One instance owns one node, so the field can only be mounted in one place at
32
+ * a time: `render` moves the node to the most recent mount point and leaves any
33
+ * earlier one empty. Nothing renders this field twice today.
25
34
  */
26
35
  export declare class ActiveCellTool extends NotebookTools.Tool {
27
36
  constructor(options: Private.IOptions);
37
+ dispose(): void;
28
38
  render(props: FieldProps): JSX.Element;
29
- private refresh;
39
+ /**
40
+ * Follow the active cell of the tracker, which is null once the last
41
+ * notebook is closed.
42
+ */
43
+ private _onActiveCellChanged;
44
+ /**
45
+ * Handle a change to the current cell source, mime type or execution count.
46
+ */
47
+ private _onCellContentChanged;
48
+ /**
49
+ * Stop listening to the cell model the tool is currently displaying.
50
+ */
51
+ private _disconnectCellModel;
52
+ /**
53
+ * Reflect the execution count of the current cell.
54
+ */
55
+ private _updatePrompt;
56
+ /**
57
+ * Refresh the preview, writing an outdated prompt along with it.
58
+ *
59
+ * The prompt is written in the same task as the preview it belongs with, so
60
+ * that the field never shows the prompt of one cell above the source line of
61
+ * another while a language mode is being loaded.
62
+ */
63
+ private _update;
30
64
  private _tracker;
65
+ private _languages;
31
66
  private _cellModel;
32
- private _refreshDebouncer;
67
+ private _previewDebouncer;
68
+ private _updateId;
69
+ private _pendingUpdate;
70
+ private _promptOutdated;
33
71
  private _editorEl;
34
72
  private _inputPrompt;
35
73
  }
@@ -5,7 +5,7 @@
5
5
  import React from 'react';
6
6
  import { NotebookTools } from '@jupyterlab/notebook';
7
7
  import { PanelLayout, Widget } from '@lumino/widgets';
8
- import { InputPrompt } from '@jupyterlab/cells';
8
+ import { InputPrompt, isCodeCellModel } from '@jupyterlab/cells';
9
9
  import { Debouncer } from '@lumino/polling';
10
10
  /**
11
11
  * The class name added to the ActiveCellTool.
@@ -24,12 +24,25 @@ const ACTIVE_CELL_TOOL_CELL_CONTENT_CLASS = 'jp-ActiveCellTool-CellContent';
24
24
  *
25
25
  * ## Note
26
26
  * This field does not work as other metadata form fields, as it does not update metadata.
27
+ *
28
+ * A single instance is meant to be shared by every render of the field. The
29
+ * displayed cell follows the notebook tracker rather than the render calls, so
30
+ * that the field keeps working when the metadata form is not being rebuilt, and
31
+ * so that it does not hold on to a cell model of a closed notebook.
32
+ *
33
+ * One instance owns one node, so the field can only be mounted in one place at
34
+ * a time: `render` moves the node to the most recent mount point and leaves any
35
+ * earlier one empty. Nothing renders this field twice today.
27
36
  */
28
37
  export class ActiveCellTool extends NotebookTools.Tool {
29
38
  constructor(options) {
30
39
  super();
31
- const { languages } = options;
40
+ this._cellModel = null;
41
+ this._updateId = 0;
42
+ this._pendingUpdate = false;
43
+ this._promptOutdated = false;
32
44
  this._tracker = options.tracker;
45
+ this._languages = options.languages;
33
46
  this.addClass(ACTIVE_CELL_TOOL_CLASS);
34
47
  this.layout = new PanelLayout();
35
48
  this._inputPrompt = new InputPrompt();
@@ -42,37 +55,155 @@ export class ActiveCellTool extends NotebookTools.Tool {
42
55
  container.className = ACTIVE_CELL_TOOL_CELL_CONTENT_CLASS;
43
56
  this._editorEl = editor;
44
57
  this.layout.addWidget(new Widget({ node }));
45
- const update = async () => {
46
- var _a, _b;
47
- this._editorEl.innerHTML = '';
48
- if (((_a = this._cellModel) === null || _a === void 0 ? void 0 : _a.type) === 'code') {
49
- this._inputPrompt.executionCount = `${(_b = this._cellModel.executionCount) !== null && _b !== void 0 ? _b : ''}`;
50
- this._inputPrompt.show();
51
- }
52
- else {
53
- this._inputPrompt.executionCount = null;
54
- this._inputPrompt.hide();
55
- }
56
- if (this._cellModel) {
57
- await languages.highlight(this._cellModel.sharedModel.getSource().split('\n')[0], languages.findByMIME(this._cellModel.mimeType), this._editorEl);
58
- }
59
- };
60
- this._refreshDebouncer = new Debouncer(update, 150);
58
+ // Only edits to the current cell are rate-limited; switching cells updates
59
+ // the display immediately, see `_onActiveCellChanged`.
60
+ this._previewDebouncer = new Debouncer(() => this._update(), 150);
61
+ this._tracker.activeCellChanged.connect(this._onActiveCellChanged, this);
62
+ // `activeCellChanged` is not emitted when the last notebook is closed:
63
+ // NotebookTracker.onCurrentChanged returns early on a null widget. Without
64
+ // this second connection the field would keep the cell model of a closed
65
+ // notebook, and its shared model, alive for the rest of the session.
66
+ this._tracker.currentChanged.connect(this._onActiveCellChanged, this);
67
+ this._onActiveCellChanged();
68
+ }
69
+ dispose() {
70
+ if (this.isDisposed) {
71
+ return;
72
+ }
73
+ this._tracker.activeCellChanged.disconnect(this._onActiveCellChanged, this);
74
+ this._tracker.currentChanged.disconnect(this._onActiveCellChanged, this);
75
+ this._disconnectCellModel();
76
+ this._previewDebouncer.dispose();
77
+ super.dispose();
61
78
  }
62
79
  render(props) {
80
+ // The content is driven by the tracker; React only supplies the mount
81
+ // point, which is a different element on every rebuild of the form.
82
+ return (React.createElement("div", { ref: ref => {
83
+ if (!ref || this.node.parentElement === ref) {
84
+ return;
85
+ }
86
+ ref.appendChild(this.node);
87
+ if (this._pendingUpdate) {
88
+ this._update().catch(console.warn);
89
+ }
90
+ } }));
91
+ }
92
+ /**
93
+ * Follow the active cell of the tracker, which is null once the last
94
+ * notebook is closed.
95
+ */
96
+ _onActiveCellChanged() {
63
97
  var _a, _b;
64
- const activeCell = this._tracker.activeCell;
65
- if (activeCell)
66
- this._cellModel = (activeCell === null || activeCell === void 0 ? void 0 : activeCell.model) || null;
67
- ((_a = this._cellModel) === null || _a === void 0 ? void 0 : _a.sharedModel).changed.connect(this.refresh, this);
68
- (_b = this._cellModel) === null || _b === void 0 ? void 0 : _b.mimeTypeChanged.connect(this.refresh, this);
69
- this.refresh()
70
- .then(() => undefined)
71
- .catch(console.warn);
72
- return React.createElement("div", { ref: ref => ref === null || ref === void 0 ? void 0 : ref.appendChild(this.node) });
98
+ const cellModel = (_b = (_a = this._tracker.activeCell) === null || _a === void 0 ? void 0 : _a.model) !== null && _b !== void 0 ? _b : null;
99
+ if (cellModel === this._cellModel) {
100
+ return;
101
+ }
102
+ this._disconnectCellModel();
103
+ this._cellModel = cellModel;
104
+ if (cellModel) {
105
+ cellModel.sharedModel.changed.connect(this._onCellContentChanged, this);
106
+ cellModel.mimeTypeChanged.connect(this._onCellContentChanged, this);
107
+ }
108
+ // The prompt now belongs to a cell whose source line is not on screen yet,
109
+ // so leave it to `_update` to write both together.
110
+ this._promptOutdated = true;
111
+ this._update().catch(console.warn);
112
+ }
113
+ /**
114
+ * Handle a change to the current cell source, mime type or execution count.
115
+ */
116
+ _onCellContentChanged() {
117
+ if (!this.node.isConnected) {
118
+ this._pendingUpdate = true;
119
+ this._promptOutdated = true;
120
+ return;
121
+ }
122
+ if (!this._promptOutdated) {
123
+ // The cell is unchanged and no switch is in flight, so writing the prompt
124
+ // now cannot pair it with the source line of a different cell.
125
+ this._updatePrompt();
126
+ }
127
+ this._previewDebouncer.invoke().catch(console.warn);
128
+ }
129
+ /**
130
+ * Stop listening to the cell model the tool is currently displaying.
131
+ */
132
+ _disconnectCellModel() {
133
+ const cellModel = this._cellModel;
134
+ if (!cellModel) {
135
+ return;
136
+ }
137
+ cellModel.sharedModel.changed.disconnect(this._onCellContentChanged, this);
138
+ cellModel.mimeTypeChanged.disconnect(this._onCellContentChanged, this);
139
+ this._cellModel = null;
140
+ }
141
+ /**
142
+ * Reflect the execution count of the current cell.
143
+ */
144
+ _updatePrompt() {
145
+ var _a;
146
+ const cellModel = this._cellModel;
147
+ if (cellModel && isCodeCellModel(cellModel)) {
148
+ this._inputPrompt.executionCount = `${(_a = cellModel.executionCount) !== null && _a !== void 0 ? _a : ''}`;
149
+ this._inputPrompt.show();
150
+ }
151
+ else {
152
+ this._inputPrompt.executionCount = null;
153
+ this._inputPrompt.hide();
154
+ }
73
155
  }
74
- async refresh() {
75
- await this._refreshDebouncer.invoke();
156
+ /**
157
+ * Refresh the preview, writing an outdated prompt along with it.
158
+ *
159
+ * The prompt is written in the same task as the preview it belongs with, so
160
+ * that the field never shows the prompt of one cell above the source line of
161
+ * another while a language mode is being loaded.
162
+ */
163
+ async _update() {
164
+ if (!this.node.isConnected) {
165
+ // Nothing is on screen; catch up when the field is mounted again.
166
+ this._pendingUpdate = true;
167
+ return;
168
+ }
169
+ this._pendingUpdate = false;
170
+ const cellModel = this._cellModel;
171
+ const pending = ++this._updateId;
172
+ if (!cellModel) {
173
+ this._promptOutdated = false;
174
+ this._updatePrompt();
175
+ this._editorEl.replaceChildren();
176
+ return;
177
+ }
178
+ const source = cellModel.sharedModel.getSource();
179
+ const lineEnd = source.indexOf('\n');
180
+ const firstLine = lineEnd === -1 ? source : source.slice(0, lineEnd);
181
+ // Highlight into a detached node, so that the preview is never cleared
182
+ // while waiting for a language mode to load.
183
+ const staging = document.createElement('pre');
184
+ try {
185
+ await this._languages.highlight(firstLine, this._languages.findByMIME(cellModel.mimeType), staging);
186
+ }
187
+ catch (error) {
188
+ // Fall back to unhighlighted source rather than keeping the previous
189
+ // cell's line on screen.
190
+ console.warn(error);
191
+ staging.replaceChildren(document.createTextNode(firstLine));
192
+ }
193
+ if (pending !== this._updateId) {
194
+ // A newer update started while this one was highlighting; it still owes
195
+ // the prompt write, so `_promptOutdated` is deliberately left set.
196
+ return;
197
+ }
198
+ if (this._promptOutdated) {
199
+ this._updatePrompt();
200
+ this._promptOutdated = false;
201
+ }
202
+ const fragment = document.createDocumentFragment();
203
+ while (staging.firstChild) {
204
+ fragment.appendChild(staging.firstChild);
205
+ }
206
+ this._editorEl.replaceChildren(fragment);
76
207
  }
77
208
  }
78
209
  //# sourceMappingURL=activeCellToolWidget.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"activeCellToolWidget.js","sourceRoot":"","sources":["../../src/tool-widgets/activeCellToolWidget.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"activeCellToolWidget.js","sourceRoot":"","sources":["../../src/tool-widgets/activeCellToolWidget.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jupyterlab/notebook-extension",
3
- "version": "4.6.1",
3
+ "version": "4.6.3",
4
4
  "description": "JupyterLab - Notebook Extension",
5
5
  "homepage": "https://github.com/jupyterlab/jupyterlab",
6
6
  "bugs": {
@@ -37,36 +37,36 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "@jupyter/ydoc": "^4.0.0",
40
- "@jupyterlab/application": "^4.6.1",
41
- "@jupyterlab/apputils": "^4.7.1",
42
- "@jupyterlab/cell-toolbar": "^4.6.1",
43
- "@jupyterlab/cells": "^4.6.1",
44
- "@jupyterlab/codeeditor": "^4.6.1",
45
- "@jupyterlab/codemirror": "^4.6.1",
46
- "@jupyterlab/completer": "^4.6.1",
47
- "@jupyterlab/coreutils": "^6.6.1",
48
- "@jupyterlab/docmanager": "^4.6.1",
49
- "@jupyterlab/docmanager-extension": "^4.6.1",
50
- "@jupyterlab/docregistry": "^4.6.1",
51
- "@jupyterlab/documentsearch": "^4.6.1",
52
- "@jupyterlab/filebrowser": "^4.6.1",
53
- "@jupyterlab/launcher": "^4.6.1",
54
- "@jupyterlab/logconsole": "^4.6.1",
55
- "@jupyterlab/lsp": "^4.6.1",
56
- "@jupyterlab/mainmenu": "^4.6.1",
57
- "@jupyterlab/metadataform": "^4.6.1",
58
- "@jupyterlab/nbformat": "^4.6.1",
59
- "@jupyterlab/notebook": "^4.6.1",
60
- "@jupyterlab/observables": "^5.6.1",
61
- "@jupyterlab/property-inspector": "^4.6.1",
62
- "@jupyterlab/rendermime": "^4.6.1",
63
- "@jupyterlab/services": "^7.6.1",
64
- "@jupyterlab/settingregistry": "^4.6.1",
65
- "@jupyterlab/statedb": "^4.6.1",
66
- "@jupyterlab/statusbar": "^4.6.1",
67
- "@jupyterlab/toc": "^6.6.1",
68
- "@jupyterlab/translation": "^4.6.1",
69
- "@jupyterlab/ui-components": "^4.6.1",
40
+ "@jupyterlab/application": "^4.6.3",
41
+ "@jupyterlab/apputils": "^4.7.3",
42
+ "@jupyterlab/cell-toolbar": "^4.6.3",
43
+ "@jupyterlab/cells": "^4.6.3",
44
+ "@jupyterlab/codeeditor": "^4.6.3",
45
+ "@jupyterlab/codemirror": "^4.6.3",
46
+ "@jupyterlab/completer": "^4.6.3",
47
+ "@jupyterlab/coreutils": "^6.6.3",
48
+ "@jupyterlab/docmanager": "^4.6.3",
49
+ "@jupyterlab/docmanager-extension": "^4.6.3",
50
+ "@jupyterlab/docregistry": "^4.6.3",
51
+ "@jupyterlab/documentsearch": "^4.6.3",
52
+ "@jupyterlab/filebrowser": "^4.6.3",
53
+ "@jupyterlab/launcher": "^4.6.3",
54
+ "@jupyterlab/logconsole": "^4.6.3",
55
+ "@jupyterlab/lsp": "^4.6.3",
56
+ "@jupyterlab/mainmenu": "^4.6.3",
57
+ "@jupyterlab/metadataform": "^4.6.3",
58
+ "@jupyterlab/nbformat": "^4.6.3",
59
+ "@jupyterlab/notebook": "^4.6.3",
60
+ "@jupyterlab/observables": "^5.6.3",
61
+ "@jupyterlab/property-inspector": "^4.6.3",
62
+ "@jupyterlab/rendermime": "^4.6.3",
63
+ "@jupyterlab/services": "^7.6.3",
64
+ "@jupyterlab/settingregistry": "^4.6.3",
65
+ "@jupyterlab/statedb": "^4.6.3",
66
+ "@jupyterlab/statusbar": "^4.6.3",
67
+ "@jupyterlab/toc": "^6.6.3",
68
+ "@jupyterlab/translation": "^4.6.3",
69
+ "@jupyterlab/ui-components": "^4.6.3",
70
70
  "@lumino/algorithm": "^2.0.4",
71
71
  "@lumino/commands": "^2.3.3",
72
72
  "@lumino/coreutils": "^2.2.2",
@@ -841,12 +841,14 @@
841
841
  "title": "Side-by-side left margin override",
842
842
  "description": "Side-by-side left margin override.",
843
843
  "type": "string",
844
+ "pattern": "^-?(?:0|(?:[0-9]+|[0-9]*\\.[0-9]+)(?:px|em|rem|%|vw|vh|vmin|vmax|ch|ex|cm|mm|in|pt|pc))$",
844
845
  "default": "10px"
845
846
  },
846
847
  "sideBySideRightMarginOverride": {
847
848
  "title": "Side-by-side right margin override",
848
849
  "description": "Side-by-side right margin override.",
849
850
  "type": "string",
851
+ "pattern": "^-?(?:0|(?:[0-9]+|[0-9]*\\.[0-9]+)(?:px|em|rem|%|vw|vh|vmin|vmax|ch|ex|cm|mm|in|pt|pc))$",
850
852
  "default": "10px"
851
853
  },
852
854
  "sideBySideOutputRatio": {
package/src/index.ts CHANGED
@@ -1199,12 +1199,18 @@ const activeCellTool: JupyterFrontEndPlugin<void> = {
1199
1199
  formRegistry: IFormRendererRegistry,
1200
1200
  languages: IEditorLanguageRegistry
1201
1201
  ) => {
1202
+ // The field renderer is used by rjsf as a React component, so it runs on
1203
+ // every rebuild of the metadata form. The tool is created once and reused:
1204
+ // constructing one per render would rebuild the prompt and the preview from
1205
+ // scratch (showing them empty until the next update) and would leave a
1206
+ // connection to the cell model behind for every abandoned instance.
1207
+ const tool = new ActiveCellTool({
1208
+ tracker,
1209
+ languages
1210
+ });
1202
1211
  const component: IFormRenderer = {
1203
1212
  fieldRenderer: (props: FieldProps) => {
1204
- return new ActiveCellTool({
1205
- tracker,
1206
- languages
1207
- }).render(props);
1213
+ return tool.render(props);
1208
1214
  }
1209
1215
  };
1210
1216
  formRegistry.addRenderer(
@@ -2197,15 +2203,16 @@ function activateNotebookHandler(
2197
2203
  setSideBySideOutputRatio(factory.notebookConfig.sideBySideOutputRatio);
2198
2204
  const sideBySideMarginStyle = `.jp-mod-sideBySide.jp-Notebook .jp-Notebook-cell {
2199
2205
  margin-left: ${factory.notebookConfig.sideBySideLeftMarginOverride} !important;
2200
- margin-right: ${factory.notebookConfig.sideBySideRightMarginOverride} !important;`;
2206
+ margin-right: ${factory.notebookConfig.sideBySideRightMarginOverride} !important;
2207
+ }`;
2201
2208
  const sideBySideMarginTag = document.getElementById(SIDE_BY_SIDE_STYLE_ID);
2202
2209
  if (sideBySideMarginTag) {
2203
- sideBySideMarginTag.innerText = sideBySideMarginStyle;
2210
+ sideBySideMarginTag.textContent = sideBySideMarginStyle;
2204
2211
  } else {
2205
- document.head.insertAdjacentHTML(
2206
- 'beforeend',
2207
- `<style id="${SIDE_BY_SIDE_STYLE_ID}">${sideBySideMarginStyle}}</style>`
2208
- );
2212
+ const style = document.createElement('style');
2213
+ style.id = SIDE_BY_SIDE_STYLE_ID;
2214
+ style.textContent = sideBySideMarginStyle;
2215
+ document.head.appendChild(style);
2209
2216
  }
2210
2217
  factory.autoStartDefault = settings.get('autoStartDefaultKernel')
2211
2218
  .composite as boolean;