@jupyter-notebook/notebook-extension 7.0.0-alpha.9 → 7.0.0-beta.1
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/lib/index.js +41 -14
- package/lib/trusted.d.ts +18 -0
- package/lib/trusted.js +69 -0
- package/package.json +12 -13
- package/style/base.css +26 -0
package/lib/index.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
// Copyright (c) Jupyter Development Team.
|
|
2
2
|
// Distributed under the terms of the Modified BSD License.
|
|
3
|
-
import { DOMUtils, IToolbarWidgetRegistry } from '@jupyterlab/apputils';
|
|
3
|
+
import { DOMUtils, IToolbarWidgetRegistry, } from '@jupyterlab/apputils';
|
|
4
4
|
import { Text, Time } from '@jupyterlab/coreutils';
|
|
5
5
|
import { IDocumentManager } from '@jupyterlab/docmanager';
|
|
6
|
-
import { NotebookPanel, INotebookTracker, INotebookTools } from '@jupyterlab/notebook';
|
|
6
|
+
import { NotebookPanel, INotebookTracker, INotebookTools, } from '@jupyterlab/notebook';
|
|
7
7
|
import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
8
8
|
import { ITranslator } from '@jupyterlab/translation';
|
|
9
9
|
import { INotebookShell } from '@jupyter-notebook/application';
|
|
10
10
|
import { Poll } from '@lumino/polling';
|
|
11
11
|
import { Widget } from '@lumino/widgets';
|
|
12
|
+
import { TrustedComponent } from './trusted';
|
|
12
13
|
/**
|
|
13
14
|
* The class for kernel status errors.
|
|
14
15
|
*/
|
|
@@ -42,7 +43,7 @@ const checkpoints = {
|
|
|
42
43
|
const trans = translator.load('notebook');
|
|
43
44
|
const node = document.createElement('div');
|
|
44
45
|
if (toolbarRegistry) {
|
|
45
|
-
toolbarRegistry.addFactory('TopBar', 'checkpoint', toolbar => {
|
|
46
|
+
toolbarRegistry.addFactory('TopBar', 'checkpoint', (toolbar) => {
|
|
46
47
|
const widget = new Widget({ node });
|
|
47
48
|
widget.id = DOMUtils.createDomID();
|
|
48
49
|
widget.addClass('jp-NotebookCheckpoint');
|
|
@@ -72,11 +73,11 @@ const checkpoints = {
|
|
|
72
73
|
factory: () => onChange(),
|
|
73
74
|
frequency: {
|
|
74
75
|
interval: 2000,
|
|
75
|
-
backoff: false
|
|
76
|
+
backoff: false,
|
|
76
77
|
},
|
|
77
|
-
standby: 'when-hidden'
|
|
78
|
+
standby: 'when-hidden',
|
|
78
79
|
});
|
|
79
|
-
}
|
|
80
|
+
},
|
|
80
81
|
};
|
|
81
82
|
/**
|
|
82
83
|
* The kernel logo plugin.
|
|
@@ -90,30 +91,34 @@ const kernelLogo = {
|
|
|
90
91
|
const { serviceManager } = app;
|
|
91
92
|
const node = document.createElement('div');
|
|
92
93
|
const img = document.createElement('img');
|
|
93
|
-
node.appendChild(img);
|
|
94
94
|
const onChange = async () => {
|
|
95
95
|
var _a, _b, _c, _d, _e;
|
|
96
96
|
const current = shell.currentWidget;
|
|
97
97
|
if (!(current instanceof NotebookPanel)) {
|
|
98
98
|
return;
|
|
99
99
|
}
|
|
100
|
+
if (!node.hasChildNodes()) {
|
|
101
|
+
node.appendChild(img);
|
|
102
|
+
}
|
|
100
103
|
await current.sessionContext.ready;
|
|
101
104
|
current.sessionContext.kernelChanged.disconnect(onChange);
|
|
102
105
|
current.sessionContext.kernelChanged.connect(onChange);
|
|
103
106
|
const name = (_c = (_b = (_a = current.sessionContext.session) === null || _a === void 0 ? void 0 : _a.kernel) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : '';
|
|
104
107
|
const spec = (_e = (_d = serviceManager.kernelspecs) === null || _d === void 0 ? void 0 : _d.specs) === null || _e === void 0 ? void 0 : _e.kernelspecs[name];
|
|
105
108
|
if (!spec) {
|
|
109
|
+
node.childNodes[0].remove();
|
|
106
110
|
return;
|
|
107
111
|
}
|
|
108
112
|
const kernelIconUrl = spec.resources['logo-64x64'];
|
|
109
113
|
if (!kernelIconUrl) {
|
|
114
|
+
node.childNodes[0].remove();
|
|
110
115
|
return;
|
|
111
116
|
}
|
|
112
117
|
img.src = kernelIconUrl;
|
|
113
118
|
img.title = spec.display_name;
|
|
114
119
|
};
|
|
115
120
|
if (toolbarRegistry) {
|
|
116
|
-
toolbarRegistry.addFactory('TopBar', 'kernelLogo', toolbar => {
|
|
121
|
+
toolbarRegistry.addFactory('TopBar', 'kernelLogo', (toolbar) => {
|
|
117
122
|
const widget = new Widget({ node });
|
|
118
123
|
widget.addClass('jp-NotebookKernelLogo');
|
|
119
124
|
return widget;
|
|
@@ -122,7 +127,7 @@ const kernelLogo = {
|
|
|
122
127
|
app.started.then(() => {
|
|
123
128
|
shell.currentChanged.connect(onChange);
|
|
124
129
|
});
|
|
125
|
-
}
|
|
130
|
+
},
|
|
126
131
|
};
|
|
127
132
|
/**
|
|
128
133
|
* A plugin to display the kernel status;
|
|
@@ -175,7 +180,7 @@ const kernelStatus = {
|
|
|
175
180
|
sessionContext.statusChanged.connect(onStatusChanged);
|
|
176
181
|
};
|
|
177
182
|
shell.currentChanged.connect(onChange);
|
|
178
|
-
}
|
|
183
|
+
},
|
|
179
184
|
};
|
|
180
185
|
/**
|
|
181
186
|
* A plugin to enable scrolling for outputs by default.
|
|
@@ -243,7 +248,7 @@ const scrollOutput = {
|
|
|
243
248
|
Promise.all([loadSettings, app.restored])
|
|
244
249
|
.then(([settings]) => {
|
|
245
250
|
updateSettings(settings);
|
|
246
|
-
settings.changed.connect(settings => {
|
|
251
|
+
settings.changed.connect((settings) => {
|
|
247
252
|
updateSettings(settings);
|
|
248
253
|
});
|
|
249
254
|
})
|
|
@@ -251,7 +256,7 @@ const scrollOutput = {
|
|
|
251
256
|
console.error(reason.message);
|
|
252
257
|
});
|
|
253
258
|
}
|
|
254
|
-
}
|
|
259
|
+
},
|
|
255
260
|
};
|
|
256
261
|
/**
|
|
257
262
|
* A plugin to add the NotebookTools to the side panel;
|
|
@@ -273,7 +278,28 @@ const notebookToolsWidget = {
|
|
|
273
278
|
}
|
|
274
279
|
};
|
|
275
280
|
shell.currentChanged.connect(onChange);
|
|
276
|
-
}
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
/**
|
|
284
|
+
* A plugin that adds a Trusted indicator to the menu area
|
|
285
|
+
*/
|
|
286
|
+
const trusted = {
|
|
287
|
+
id: '@jupyter-notebook/notebook-extension:trusted',
|
|
288
|
+
autoStart: true,
|
|
289
|
+
requires: [INotebookShell, ITranslator],
|
|
290
|
+
activate: (app, notebookShell, translator) => {
|
|
291
|
+
const onChange = async () => {
|
|
292
|
+
const current = notebookShell.currentWidget;
|
|
293
|
+
if (!(current instanceof NotebookPanel)) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
const notebook = current.content;
|
|
297
|
+
await current.context.ready;
|
|
298
|
+
const widget = TrustedComponent.create({ notebook, translator });
|
|
299
|
+
notebookShell.add(widget, 'menu', { rank: 11000 });
|
|
300
|
+
};
|
|
301
|
+
notebookShell.currentChanged.connect(onChange);
|
|
302
|
+
},
|
|
277
303
|
};
|
|
278
304
|
/**
|
|
279
305
|
* Export the plugins as default.
|
|
@@ -283,6 +309,7 @@ const plugins = [
|
|
|
283
309
|
kernelLogo,
|
|
284
310
|
kernelStatus,
|
|
285
311
|
scrollOutput,
|
|
286
|
-
notebookToolsWidget
|
|
312
|
+
notebookToolsWidget,
|
|
313
|
+
trusted,
|
|
287
314
|
];
|
|
288
315
|
export default plugins;
|
package/lib/trusted.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ReactWidget } from '@jupyterlab/apputils';
|
|
2
|
+
import { Notebook } from '@jupyterlab/notebook';
|
|
3
|
+
import { ITranslator } from '@jupyterlab/translation';
|
|
4
|
+
/**
|
|
5
|
+
* A namespace for TrustedComponent statics.
|
|
6
|
+
*/
|
|
7
|
+
export declare namespace TrustedComponent {
|
|
8
|
+
/**
|
|
9
|
+
* Create a new TrustedComponent
|
|
10
|
+
*
|
|
11
|
+
* @param notebook The notebook
|
|
12
|
+
* @param translator The translator
|
|
13
|
+
*/
|
|
14
|
+
const create: ({ notebook, translator, }: {
|
|
15
|
+
notebook: Notebook;
|
|
16
|
+
translator: ITranslator;
|
|
17
|
+
}) => ReactWidget;
|
|
18
|
+
}
|
package/lib/trusted.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { ReactWidget } from '@jupyterlab/apputils';
|
|
2
|
+
import { NotebookActions } from '@jupyterlab/notebook';
|
|
3
|
+
import React, { useEffect, useState } from 'react';
|
|
4
|
+
/**
|
|
5
|
+
* Check if a notebook is trusted
|
|
6
|
+
* @param notebook The notebook to check
|
|
7
|
+
* @returns true if the notebook is trusted, false otherwise
|
|
8
|
+
*/
|
|
9
|
+
const isTrusted = (notebook) => {
|
|
10
|
+
const model = notebook.model;
|
|
11
|
+
if (!model) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
const cells = Array.from(model.cells);
|
|
15
|
+
const trusted = cells.reduce((accum, current) => {
|
|
16
|
+
if (current.trusted) {
|
|
17
|
+
return accum + 1;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
return accum;
|
|
21
|
+
}
|
|
22
|
+
}, 0);
|
|
23
|
+
const total = cells.length;
|
|
24
|
+
return trusted === total;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* A React component to display the Trusted badge in the menu bar.
|
|
28
|
+
* @param notebook The Notebook
|
|
29
|
+
* @param translator The Translation service
|
|
30
|
+
*/
|
|
31
|
+
const TrustedButton = ({ notebook, translator, }) => {
|
|
32
|
+
const trans = translator.load('notebook');
|
|
33
|
+
const [trusted, setTrusted] = useState(isTrusted(notebook));
|
|
34
|
+
const checkTrust = () => {
|
|
35
|
+
const v = isTrusted(notebook);
|
|
36
|
+
setTrusted(v);
|
|
37
|
+
};
|
|
38
|
+
const trust = async () => {
|
|
39
|
+
await NotebookActions.trust(notebook, translator);
|
|
40
|
+
checkTrust();
|
|
41
|
+
};
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
notebook.modelContentChanged.connect(checkTrust);
|
|
44
|
+
notebook.activeCellChanged.connect(checkTrust);
|
|
45
|
+
checkTrust();
|
|
46
|
+
return () => {
|
|
47
|
+
notebook.modelContentChanged.disconnect(checkTrust);
|
|
48
|
+
notebook.activeCellChanged.disconnect(checkTrust);
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
return (React.createElement("button", { className: 'jp-NotebookTrustedStatus', style: !trusted ? { cursor: 'pointer' } : { cursor: 'help' }, onClick: () => !trusted && trust(), title: trusted
|
|
52
|
+
? trans.__('JavaScript enabled for notebook display')
|
|
53
|
+
: trans.__('JavaScript disabled for notebook display') }, trusted ? trans.__('Trusted') : trans.__('Not Trusted')));
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* A namespace for TrustedComponent statics.
|
|
57
|
+
*/
|
|
58
|
+
export var TrustedComponent;
|
|
59
|
+
(function (TrustedComponent) {
|
|
60
|
+
/**
|
|
61
|
+
* Create a new TrustedComponent
|
|
62
|
+
*
|
|
63
|
+
* @param notebook The notebook
|
|
64
|
+
* @param translator The translator
|
|
65
|
+
*/
|
|
66
|
+
TrustedComponent.create = ({ notebook, translator, }) => {
|
|
67
|
+
return ReactWidget.create(React.createElement(TrustedButton, { notebook: notebook, translator: translator }));
|
|
68
|
+
};
|
|
69
|
+
})(TrustedComponent || (TrustedComponent = {}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupyter-notebook/notebook-extension",
|
|
3
|
-
"version": "7.0.0-
|
|
3
|
+
"version": "7.0.0-beta.1",
|
|
4
4
|
"description": "Jupyter Notebook - Notebook Extension",
|
|
5
5
|
"homepage": "https://github.com/jupyter/notebook",
|
|
6
6
|
"bugs": {
|
|
@@ -35,24 +35,23 @@
|
|
|
35
35
|
"build:prod": "tsc -b",
|
|
36
36
|
"clean": "rimraf lib && rimraf tsconfig.tsbuildinfo",
|
|
37
37
|
"docs": "typedoc src",
|
|
38
|
-
"prepublishOnly": "npm run build",
|
|
39
38
|
"watch": "tsc -b --watch"
|
|
40
39
|
},
|
|
41
40
|
"dependencies": {
|
|
42
|
-
"@jupyter-notebook/application": "^7.0.0-
|
|
43
|
-
"@jupyterlab/application": "^4.0.0-
|
|
44
|
-
"@jupyterlab/apputils": "^4.0.0-
|
|
45
|
-
"@jupyterlab/cells": "^4.0.0-
|
|
46
|
-
"@jupyterlab/docmanager": "^4.0.0-
|
|
47
|
-
"@jupyterlab/notebook": "^4.0.0-
|
|
48
|
-
"@jupyterlab/settingregistry": "^4.0.0-
|
|
49
|
-
"@jupyterlab/translation": "^4.0.0-
|
|
50
|
-
"@lumino/polling": "^2.
|
|
51
|
-
"@lumino/widgets": "^2.
|
|
41
|
+
"@jupyter-notebook/application": "^7.0.0-beta.1",
|
|
42
|
+
"@jupyterlab/application": "^4.0.0-rc.0",
|
|
43
|
+
"@jupyterlab/apputils": "^4.0.0-rc.0",
|
|
44
|
+
"@jupyterlab/cells": "^4.0.0-rc.0",
|
|
45
|
+
"@jupyterlab/docmanager": "^4.0.0-rc.0",
|
|
46
|
+
"@jupyterlab/notebook": "^4.0.0-rc.0",
|
|
47
|
+
"@jupyterlab/settingregistry": "^4.0.0-rc.0",
|
|
48
|
+
"@jupyterlab/translation": "^4.0.0-rc.0",
|
|
49
|
+
"@lumino/polling": "^2.1.1",
|
|
50
|
+
"@lumino/widgets": "^2.1.1"
|
|
52
51
|
},
|
|
53
52
|
"devDependencies": {
|
|
54
53
|
"rimraf": "^3.0.2",
|
|
55
|
-
"typescript": "~
|
|
54
|
+
"typescript": "~5.0.2"
|
|
56
55
|
},
|
|
57
56
|
"publishConfig": {
|
|
58
57
|
"access": "public"
|
package/style/base.css
CHANGED
|
@@ -122,6 +122,15 @@ body[data-notebook='notebooks']
|
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
/* Tweak the notebook footer (to add a new cell) */
|
|
126
|
+
body[data-notebook='notebooks'] .jp-Notebook-footer {
|
|
127
|
+
/* TODO: re-enable */
|
|
128
|
+
display: none;
|
|
129
|
+
width: 100%;
|
|
130
|
+
margin-left: unset;
|
|
131
|
+
background: unset;
|
|
132
|
+
}
|
|
133
|
+
|
|
125
134
|
/* Mobile View */
|
|
126
135
|
|
|
127
136
|
body[data-format='mobile'] .jp-NotebookCheckpoint {
|
|
@@ -132,6 +141,10 @@ body[data-format='mobile'] .jp-Notebook > *:first-child {
|
|
|
132
141
|
margin-top: 0;
|
|
133
142
|
}
|
|
134
143
|
|
|
144
|
+
body[data-format='mobile'] .jp-ToolbarButton .jp-DebuggerBugButton {
|
|
145
|
+
display: none;
|
|
146
|
+
}
|
|
147
|
+
|
|
135
148
|
/* Virtual Notebook fixes */
|
|
136
149
|
|
|
137
150
|
body[data-notebook='notebooks'] .jp-WindowedPanel-window {
|
|
@@ -216,6 +229,19 @@ body[data-notebook='notebooks']
|
|
|
216
229
|
animation: 0.5s fade-out forwards;
|
|
217
230
|
}
|
|
218
231
|
|
|
232
|
+
.jp-NotebookTrustedStatus {
|
|
233
|
+
background: var(--jp-layout-color1);
|
|
234
|
+
color: var(--jp-ui-font-color1);
|
|
235
|
+
margin-top: 4px;
|
|
236
|
+
margin-bottom: 4px;
|
|
237
|
+
border: solid 1px var(--jp-border-color2);
|
|
238
|
+
cursor: help;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.jp-NotebookTrustedStatus-not-trusted {
|
|
242
|
+
cursor: pointer;
|
|
243
|
+
}
|
|
244
|
+
|
|
219
245
|
@keyframes fade-out {
|
|
220
246
|
0% {
|
|
221
247
|
opacity: 1;
|