@jupyter-notebook/application-extension 7.0.0-alpha.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.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { JupyterFrontEndPlugin } from '@jupyterlab/application';
2
+ /**
3
+ * Export the plugins as default.
4
+ */
5
+ declare const plugins: JupyterFrontEndPlugin<any>[];
6
+ export default plugins;
package/lib/index.js ADDED
@@ -0,0 +1,604 @@
1
+ // Copyright (c) Jupyter Development Team.
2
+ // Distributed under the terms of the Modified BSD License.
3
+ import { ILabStatus, IRouter, ITreePathUpdater, JupyterFrontEnd, Router } from '@jupyterlab/application';
4
+ import { sessionContextDialogs, ISessionContextDialogs, DOMUtils, ICommandPalette } from '@jupyterlab/apputils';
5
+ import { ConsolePanel } from '@jupyterlab/console';
6
+ import { PageConfig, PathExt, URLExt } from '@jupyterlab/coreutils';
7
+ import { IDocumentManager, renameDialog } from '@jupyterlab/docmanager';
8
+ import { DocumentWidget } from '@jupyterlab/docregistry';
9
+ import { IMainMenu } from '@jupyterlab/mainmenu';
10
+ import { ISettingRegistry } from '@jupyterlab/settingregistry';
11
+ import { ITranslator } from '@jupyterlab/translation';
12
+ import { NotebookApp, NotebookShell, INotebookShell } from '@jupyter-notebook/application';
13
+ import { jupyterIcon } from '@jupyter-notebook/ui-components';
14
+ import { PromiseDelegate } from '@lumino/coreutils';
15
+ import { DisposableDelegate, DisposableSet } from '@lumino/disposable';
16
+ import { Widget } from '@lumino/widgets';
17
+ /**
18
+ * The default notebook factory.
19
+ */
20
+ const NOTEBOOK_FACTORY = 'Notebook';
21
+ /**
22
+ * The editor factory.
23
+ */
24
+ const EDITOR_FACTORY = 'Editor';
25
+ /**
26
+ * A regular expression to match path to notebooks and documents
27
+ */
28
+ const TREE_PATTERN = new RegExp('/(notebooks|edit)/(.*)');
29
+ /**
30
+ * A regular expression to suppress the file extension from display for .ipynb files.
31
+ */
32
+ const STRIP_IPYNB = /\.ipynb$/;
33
+ /**
34
+ * The command IDs used by the application plugin.
35
+ */
36
+ var CommandIDs;
37
+ (function (CommandIDs) {
38
+ /**
39
+ * Toggle Top Bar visibility
40
+ */
41
+ CommandIDs.toggleTop = 'application:toggle-top';
42
+ /**
43
+ * Toggle the Zen mode
44
+ */
45
+ CommandIDs.toggleZen = 'application:toggle-zen';
46
+ /**
47
+ * Open JupyterLab
48
+ */
49
+ CommandIDs.openLab = 'application:open-lab';
50
+ /**
51
+ * Open the tree page.
52
+ */
53
+ CommandIDs.openTree = 'application:open-tree';
54
+ /**
55
+ * Rename the current document
56
+ */
57
+ CommandIDs.rename = 'application:rename';
58
+ /**
59
+ * Resolve tree path
60
+ */
61
+ CommandIDs.resolveTree = 'application:resolve-tree';
62
+ })(CommandIDs || (CommandIDs = {}));
63
+ /**
64
+ * Check if the application is dirty before closing the browser tab.
65
+ */
66
+ const dirty = {
67
+ id: '@jupyter-notebook/application-extension:dirty',
68
+ autoStart: true,
69
+ requires: [ILabStatus, ITranslator],
70
+ activate: (app, status, translator) => {
71
+ if (!(app instanceof NotebookApp)) {
72
+ throw new Error(`${dirty.id} must be activated in Jupyter Notebook.`);
73
+ }
74
+ const trans = translator.load('notebook');
75
+ const message = trans.__('Are you sure you want to exit Jupyter Notebook?\n\nAny unsaved changes will be lost.');
76
+ window.addEventListener('beforeunload', event => {
77
+ if (app.status.isDirty) {
78
+ return (event.returnValue = message);
79
+ }
80
+ });
81
+ }
82
+ };
83
+ /**
84
+ * The logo plugin.
85
+ */
86
+ const logo = {
87
+ id: '@jupyter-notebook/application-extension:logo',
88
+ autoStart: true,
89
+ activate: (app) => {
90
+ const baseUrl = PageConfig.getBaseUrl();
91
+ const node = document.createElement('a');
92
+ node.href = `${baseUrl}tree`;
93
+ node.target = '_blank';
94
+ node.rel = 'noopener noreferrer';
95
+ const logo = new Widget({ node });
96
+ jupyterIcon.element({
97
+ container: node,
98
+ elementPosition: 'center',
99
+ padding: '2px 2px 2px 8px',
100
+ height: '28px',
101
+ width: 'auto'
102
+ });
103
+ logo.id = 'jp-NotebookLogo';
104
+ app.shell.add(logo, 'top', { rank: 0 });
105
+ }
106
+ };
107
+ /**
108
+ * A plugin to open documents in the main area.
109
+ */
110
+ const opener = {
111
+ id: '@jupyter-notebook/application-extension:opener',
112
+ autoStart: true,
113
+ requires: [IRouter, IDocumentManager],
114
+ activate: (app, router, docManager) => {
115
+ const { commands } = app;
116
+ const command = 'router:tree';
117
+ commands.addCommand(command, {
118
+ execute: (args) => {
119
+ var _a;
120
+ const parsed = args;
121
+ const matches = (_a = parsed.path.match(TREE_PATTERN)) !== null && _a !== void 0 ? _a : [];
122
+ const [, , path] = matches;
123
+ if (!path) {
124
+ return;
125
+ }
126
+ const file = decodeURIComponent(path);
127
+ const ext = PathExt.extname(file);
128
+ app.restored.then(async () => {
129
+ // TODO: get factory from file type instead?
130
+ if (ext === '.ipynb') {
131
+ docManager.open(file, NOTEBOOK_FACTORY, undefined, {
132
+ ref: '_noref'
133
+ });
134
+ }
135
+ else {
136
+ docManager.open(file, EDITOR_FACTORY, undefined, {
137
+ ref: '_noref'
138
+ });
139
+ }
140
+ });
141
+ }
142
+ });
143
+ router.register({ command, pattern: TREE_PATTERN });
144
+ }
145
+ };
146
+ /**
147
+ * A plugin to customize menus
148
+ *
149
+ * TODO: use this plugin to customize the menu items and their order
150
+ */
151
+ const menus = {
152
+ id: '@jupyter-notebook/application-extension:menus',
153
+ requires: [IMainMenu],
154
+ autoStart: true,
155
+ activate: (app, menu) => {
156
+ // always disable the Tabs menu
157
+ menu.tabsMenu.dispose();
158
+ const page = PageConfig.getOption('notebookPage');
159
+ switch (page) {
160
+ case 'consoles':
161
+ case 'terminals':
162
+ case 'tree':
163
+ menu.editMenu.dispose();
164
+ menu.kernelMenu.dispose();
165
+ menu.runMenu.dispose();
166
+ break;
167
+ case 'edit':
168
+ menu.kernelMenu.dispose();
169
+ menu.runMenu.dispose();
170
+ break;
171
+ default:
172
+ break;
173
+ }
174
+ }
175
+ };
176
+ /**
177
+ * Add commands to open the tree and running pages.
178
+ */
179
+ const pages = {
180
+ id: '@jupyter-notebook/application-extension:pages',
181
+ autoStart: true,
182
+ requires: [ITranslator],
183
+ optional: [ICommandPalette, IMainMenu],
184
+ activate: (app, translator, palette, menu) => {
185
+ const trans = translator.load('notebook');
186
+ const baseUrl = PageConfig.getBaseUrl();
187
+ app.commands.addCommand(CommandIDs.openLab, {
188
+ label: trans.__('Open JupyterLab'),
189
+ execute: () => {
190
+ window.open(`${baseUrl}lab`);
191
+ }
192
+ });
193
+ app.commands.addCommand(CommandIDs.openTree, {
194
+ label: trans.__('Open Files'),
195
+ execute: () => {
196
+ window.open(`${baseUrl}tree`);
197
+ }
198
+ });
199
+ if (palette) {
200
+ [CommandIDs.openLab, CommandIDs.openTree].forEach(command => {
201
+ palette.addItem({ command, category: 'View' });
202
+ });
203
+ }
204
+ if (menu) {
205
+ menu.viewMenu.addGroup([{ command: CommandIDs.openLab }, { command: CommandIDs.openTree }], 0);
206
+ }
207
+ }
208
+ };
209
+ /**
210
+ * The default paths for a Jupyter Notebook app.
211
+ */
212
+ const paths = {
213
+ id: '@jupyter-notebook/application-extension:paths',
214
+ autoStart: true,
215
+ provides: JupyterFrontEnd.IPaths,
216
+ activate: (app) => {
217
+ if (!(app instanceof NotebookApp)) {
218
+ throw new Error(`${paths.id} must be activated in Jupyter Notebook.`);
219
+ }
220
+ return app.paths;
221
+ }
222
+ };
223
+ /**
224
+ * The default URL router provider.
225
+ */
226
+ const router = {
227
+ id: '@jupyter-notebook/application-extension:router',
228
+ autoStart: true,
229
+ provides: IRouter,
230
+ requires: [JupyterFrontEnd.IPaths],
231
+ activate: (app, paths) => {
232
+ const { commands } = app;
233
+ const base = paths.urls.base;
234
+ const router = new Router({ base, commands });
235
+ void app.started.then(() => {
236
+ // Route the very first request on load.
237
+ void router.route();
238
+ // Route all pop state events.
239
+ window.addEventListener('popstate', () => {
240
+ void router.route();
241
+ });
242
+ });
243
+ return router;
244
+ }
245
+ };
246
+ /**
247
+ * The default session dialogs plugin
248
+ */
249
+ const sessionDialogs = {
250
+ id: '@jupyter-notebook/application-extension:session-dialogs',
251
+ provides: ISessionContextDialogs,
252
+ autoStart: true,
253
+ activate: () => sessionContextDialogs
254
+ };
255
+ /**
256
+ * The default Jupyter Notebook application shell.
257
+ */
258
+ const shell = {
259
+ id: '@jupyter-notebook/application-extension:shell',
260
+ activate: (app) => {
261
+ if (!(app.shell instanceof NotebookShell)) {
262
+ throw new Error(`${shell.id} did not find a NotebookShell instance.`);
263
+ }
264
+ return app.shell;
265
+ },
266
+ autoStart: true,
267
+ provides: INotebookShell
268
+ };
269
+ /**
270
+ * A plugin to provide a spacer at rank 900 for flex panels
271
+ * TODO: reuse upstream @jupyterlab/application-extension:top-spacer plugin when fixed
272
+ * in https://github.com/jupyterlab/jupyterlab/pull/11900
273
+ */
274
+ const spacer = {
275
+ id: '@jupyter-notebook/application-extension:spacer',
276
+ autoStart: true,
277
+ activate: (app) => {
278
+ const top = new Widget();
279
+ top.id = DOMUtils.createDomID();
280
+ top.addClass('jp-NotebookSpacer');
281
+ app.shell.add(top, 'top', { rank: 900 });
282
+ const menu = new Widget();
283
+ menu.id = DOMUtils.createDomID();
284
+ menu.addClass('jp-NotebookSpacer');
285
+ app.shell.add(menu, 'menu', { rank: 900 });
286
+ }
287
+ };
288
+ /**
289
+ * The default JupyterLab application status provider.
290
+ */
291
+ const status = {
292
+ id: '@jupyter-notebook/application-extension:status',
293
+ autoStart: true,
294
+ provides: ILabStatus,
295
+ activate: (app) => {
296
+ if (!(app instanceof NotebookApp)) {
297
+ throw new Error(`${status.id} must be activated in Jupyter Notebook.`);
298
+ }
299
+ return app.status;
300
+ }
301
+ };
302
+ /**
303
+ * A plugin to display the document title in the browser tab title
304
+ */
305
+ const tabTitle = {
306
+ id: '@jupyter-notebook/application-extension:tab-title',
307
+ autoStart: true,
308
+ requires: [INotebookShell],
309
+ activate: (app, shell) => {
310
+ const setTabTitle = () => {
311
+ const current = shell.currentWidget;
312
+ if (current instanceof ConsolePanel) {
313
+ const update = () => {
314
+ const title = current.sessionContext.path || current.sessionContext.name;
315
+ const basename = PathExt.basename(title);
316
+ // Strip the ".ipynb" suffix from filenames for display in tab titles.
317
+ document.title = basename.replace(STRIP_IPYNB, '');
318
+ };
319
+ current.sessionContext.sessionChanged.connect(update);
320
+ update();
321
+ return;
322
+ }
323
+ else if (current instanceof DocumentWidget) {
324
+ const update = () => {
325
+ const basename = PathExt.basename(current.context.path);
326
+ document.title = basename.replace(STRIP_IPYNB, '');
327
+ };
328
+ current.context.pathChanged.connect(update);
329
+ update();
330
+ }
331
+ };
332
+ shell.currentChanged.connect(setTabTitle);
333
+ setTabTitle();
334
+ }
335
+ };
336
+ /**
337
+ * A plugin to display and rename the title of a file
338
+ */
339
+ const title = {
340
+ id: '@jupyter-notebook/application-extension:title',
341
+ autoStart: true,
342
+ requires: [INotebookShell, ITranslator],
343
+ optional: [IDocumentManager, IRouter],
344
+ activate: (app, shell, translator, docManager, router) => {
345
+ const { commands } = app;
346
+ const trans = translator.load('notebook');
347
+ const widget = new Widget();
348
+ widget.id = 'jp-title';
349
+ app.shell.add(widget, 'top', { rank: 10 });
350
+ const addTitle = async () => {
351
+ const current = shell.currentWidget;
352
+ if (!current || !(current instanceof DocumentWidget)) {
353
+ return;
354
+ }
355
+ if (widget.node.children.length > 0) {
356
+ return;
357
+ }
358
+ const h = document.createElement('h1');
359
+ h.textContent = current.title.label.replace(STRIP_IPYNB, '');
360
+ widget.node.appendChild(h);
361
+ widget.node.style.marginLeft = '10px';
362
+ if (!docManager) {
363
+ return;
364
+ }
365
+ const isEnabled = () => {
366
+ const { currentWidget } = shell;
367
+ return !!(currentWidget && docManager.contextForWidget(currentWidget));
368
+ };
369
+ commands.addCommand(CommandIDs.rename, {
370
+ label: () => trans.__('Rename…'),
371
+ isEnabled,
372
+ execute: async () => {
373
+ var _a, _b;
374
+ if (!isEnabled()) {
375
+ return;
376
+ }
377
+ const result = await renameDialog(docManager, current.context.path);
378
+ // activate the current widget to bring the focus
379
+ if (current) {
380
+ current.activate();
381
+ }
382
+ if (result === null) {
383
+ return;
384
+ }
385
+ const newPath = (_a = current.context.path) !== null && _a !== void 0 ? _a : result.path;
386
+ const basename = PathExt.basename(newPath);
387
+ h.textContent = basename.replace(STRIP_IPYNB, '');
388
+ if (!router) {
389
+ return;
390
+ }
391
+ const matches = (_b = router.current.path.match(TREE_PATTERN)) !== null && _b !== void 0 ? _b : [];
392
+ const [, route, path] = matches;
393
+ if (!route || !path) {
394
+ return;
395
+ }
396
+ const encoded = encodeURIComponent(newPath);
397
+ router.navigate(`/${route}/${encoded}`, {
398
+ skipRouting: true
399
+ });
400
+ }
401
+ });
402
+ widget.node.onclick = async () => {
403
+ void commands.execute(CommandIDs.rename);
404
+ };
405
+ };
406
+ shell.currentChanged.connect(addTitle);
407
+ void addTitle();
408
+ }
409
+ };
410
+ /**
411
+ * Plugin to toggle the top header visibility.
412
+ */
413
+ const topVisibility = {
414
+ id: '@jupyter-notebook/application-extension:top',
415
+ requires: [INotebookShell, ITranslator],
416
+ optional: [IMainMenu, ISettingRegistry],
417
+ activate: (app, notebookShell, translator, menu, settingRegistry) => {
418
+ const trans = translator.load('notebook');
419
+ const top = notebookShell.top;
420
+ const pluginId = topVisibility.id;
421
+ app.commands.addCommand(CommandIDs.toggleTop, {
422
+ label: trans.__('Show Header'),
423
+ execute: () => {
424
+ top.setHidden(top.isVisible);
425
+ if (settingRegistry) {
426
+ void settingRegistry.set(pluginId, 'visible', top.isVisible);
427
+ }
428
+ },
429
+ isToggled: () => top.isVisible
430
+ });
431
+ if (menu) {
432
+ menu.viewMenu.addGroup([{ command: CommandIDs.toggleTop }], 2);
433
+ }
434
+ let settingsOverride = false;
435
+ if (settingRegistry) {
436
+ const loadSettings = settingRegistry.load(pluginId);
437
+ const updateSettings = (settings) => {
438
+ const visible = settings.get('visible').composite;
439
+ if (settings.user.visible !== undefined) {
440
+ settingsOverride = true;
441
+ top.setHidden(!visible);
442
+ }
443
+ };
444
+ Promise.all([loadSettings, app.restored])
445
+ .then(([settings]) => {
446
+ updateSettings(settings);
447
+ settings.changed.connect(settings => {
448
+ updateSettings(settings);
449
+ });
450
+ })
451
+ .catch((reason) => {
452
+ console.error(reason.message);
453
+ });
454
+ }
455
+ const onChanged = () => {
456
+ if (settingsOverride) {
457
+ return;
458
+ }
459
+ if (app.format === 'desktop') {
460
+ notebookShell.expandTop();
461
+ }
462
+ else {
463
+ notebookShell.collapseTop();
464
+ }
465
+ };
466
+ // listen on format change (mobile and desktop) to make the view more compact
467
+ app.formatChanged.connect(onChanged);
468
+ },
469
+ autoStart: true
470
+ };
471
+ /**
472
+ * The default tree route resolver plugin.
473
+ */
474
+ const tree = {
475
+ id: '@jupyter-notebook/application-extension:tree-resolver',
476
+ autoStart: true,
477
+ requires: [IRouter],
478
+ provides: JupyterFrontEnd.ITreeResolver,
479
+ activate: (app, router) => {
480
+ const { commands } = app;
481
+ const set = new DisposableSet();
482
+ const delegate = new PromiseDelegate();
483
+ const treePattern = new RegExp('/(/tree/.*)?');
484
+ set.add(commands.addCommand(CommandIDs.resolveTree, {
485
+ execute: (async (args) => {
486
+ var _a;
487
+ if (set.isDisposed) {
488
+ return;
489
+ }
490
+ const query = URLExt.queryStringToObject((_a = args.search) !== null && _a !== void 0 ? _a : '');
491
+ const browser = query['file-browser-path'] || '';
492
+ // Remove the file browser path from the query string.
493
+ delete query['file-browser-path'];
494
+ // Clean up artifacts immediately upon routing.
495
+ set.dispose();
496
+ delegate.resolve({ browser, file: PageConfig.getOption('treePath') });
497
+ })
498
+ }));
499
+ set.add(router.register({ command: CommandIDs.resolveTree, pattern: treePattern }));
500
+ // If a route is handled by the router without the tree command being
501
+ // invoked, resolve to `null` and clean up artifacts.
502
+ const listener = () => {
503
+ if (set.isDisposed) {
504
+ return;
505
+ }
506
+ set.dispose();
507
+ delegate.resolve(null);
508
+ };
509
+ router.routed.connect(listener);
510
+ set.add(new DisposableDelegate(() => {
511
+ router.routed.disconnect(listener);
512
+ }));
513
+ return { paths: delegate.promise };
514
+ }
515
+ };
516
+ const treePathUpdater = {
517
+ id: '@jupyter-notebook/application-extension:tree-updater',
518
+ requires: [IRouter],
519
+ provides: ITreePathUpdater,
520
+ activate: (app, router) => {
521
+ function updateTreePath(treePath) {
522
+ if (treePath !== PageConfig.getOption('treePath')) {
523
+ const path = URLExt.join(PageConfig.getOption('baseUrl') || '/', 'tree', URLExt.encodeParts(treePath));
524
+ router.navigate(path, { skipRouting: true });
525
+ // Persist the new tree path to PageConfig as it is used elsewhere at runtime.
526
+ PageConfig.setOption('treePath', treePath);
527
+ }
528
+ }
529
+ return updateTreePath;
530
+ },
531
+ autoStart: true
532
+ };
533
+ /**
534
+ * Zen mode plugin
535
+ */
536
+ const zen = {
537
+ id: '@jupyter-notebook/application-extension:zen',
538
+ autoStart: true,
539
+ requires: [ITranslator],
540
+ optional: [ICommandPalette, INotebookShell, IMainMenu],
541
+ activate: (app, translator, palette, notebookShell, menu) => {
542
+ const { commands } = app;
543
+ const elem = document.documentElement;
544
+ const trans = translator.load('notebook');
545
+ const toggleOn = () => {
546
+ notebookShell === null || notebookShell === void 0 ? void 0 : notebookShell.collapseTop();
547
+ notebookShell === null || notebookShell === void 0 ? void 0 : notebookShell.menu.setHidden(true);
548
+ zenModeEnabled = true;
549
+ };
550
+ const toggleOff = () => {
551
+ notebookShell === null || notebookShell === void 0 ? void 0 : notebookShell.expandTop();
552
+ notebookShell === null || notebookShell === void 0 ? void 0 : notebookShell.menu.setHidden(false);
553
+ zenModeEnabled = false;
554
+ };
555
+ let zenModeEnabled = false;
556
+ commands.addCommand(CommandIDs.toggleZen, {
557
+ label: trans.__('Toggle Zen Mode'),
558
+ execute: () => {
559
+ if (!zenModeEnabled) {
560
+ elem.requestFullscreen();
561
+ toggleOn();
562
+ }
563
+ else {
564
+ document.exitFullscreen();
565
+ toggleOff();
566
+ }
567
+ }
568
+ });
569
+ document.addEventListener('fullscreenchange', () => {
570
+ if (!document.fullscreenElement) {
571
+ toggleOff();
572
+ }
573
+ });
574
+ if (palette) {
575
+ palette.addItem({ command: CommandIDs.toggleZen, category: 'Mode' });
576
+ }
577
+ if (menu) {
578
+ menu.viewMenu.addGroup([{ command: CommandIDs.toggleZen }], 3);
579
+ }
580
+ }
581
+ };
582
+ /**
583
+ * Export the plugins as default.
584
+ */
585
+ const plugins = [
586
+ dirty,
587
+ logo,
588
+ menus,
589
+ opener,
590
+ pages,
591
+ paths,
592
+ router,
593
+ sessionDialogs,
594
+ shell,
595
+ spacer,
596
+ status,
597
+ tabTitle,
598
+ title,
599
+ topVisibility,
600
+ tree,
601
+ treePathUpdater,
602
+ zen
603
+ ];
604
+ export default plugins;
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@jupyter-notebook/application-extension",
3
+ "version": "7.0.0-alpha.1",
4
+ "description": "Jupyter Notebook - Application Extension",
5
+ "homepage": "https://github.com/jupyter/notebook",
6
+ "bugs": {
7
+ "url": "https://github.com/jupyter/notebook/issues"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/jupyter/notebook.git"
12
+ },
13
+ "license": "BSD-3-Clause",
14
+ "author": "Project Jupyter",
15
+ "sideEffects": [
16
+ "style/**/*.css",
17
+ "style/index.js"
18
+ ],
19
+ "main": "lib/index.js",
20
+ "types": "lib/index.d.ts",
21
+ "style": "style/index.css",
22
+ "directories": {
23
+ "lib": "lib/"
24
+ },
25
+ "files": [
26
+ "lib/*.d.ts",
27
+ "lib/*.js.map",
28
+ "lib/*.js",
29
+ "schema/*.json",
30
+ "style/**/*.css",
31
+ "style/index.js"
32
+ ],
33
+ "scripts": {
34
+ "build": "tsc -b",
35
+ "build:prod": "tsc -b",
36
+ "clean": "rimraf lib && rimraf tsconfig.tsbuildinfo",
37
+ "docs": "typedoc src",
38
+ "prepublishOnly": "npm run build",
39
+ "watch": "tsc -b --watch"
40
+ },
41
+ "dependencies": {
42
+ "@jupyter-notebook/application": "^7.0.0-alpha.1",
43
+ "@jupyter-notebook/ui-components": "^7.0.0-alpha.1",
44
+ "@jupyterlab/application": "^4.0.0-alpha.5",
45
+ "@jupyterlab/apputils": "^4.0.0-alpha.5",
46
+ "@jupyterlab/celltags": "^4.0.0-alpha.5",
47
+ "@jupyterlab/codeeditor": "^4.0.0-alpha.5",
48
+ "@jupyterlab/codemirror": "^4.0.0-alpha.5",
49
+ "@jupyterlab/console": "^4.0.0-alpha.5",
50
+ "@jupyterlab/coreutils": "^6.0.0-alpha.5",
51
+ "@jupyterlab/docmanager": "^4.0.0-alpha.5",
52
+ "@jupyterlab/docregistry": "^4.0.0-alpha.5",
53
+ "@jupyterlab/mainmenu": "^4.0.0-alpha.5",
54
+ "@jupyterlab/settingregistry": "^4.0.0-alpha.5",
55
+ "@jupyterlab/translation": "^4.0.0-alpha.4",
56
+ "@lumino/coreutils": "^1.12.0",
57
+ "@lumino/disposable": "^1.10.1",
58
+ "@lumino/widgets": "^1.31.1"
59
+ },
60
+ "devDependencies": {
61
+ "rimraf": "~3.0.0",
62
+ "typescript": "~4.1.3"
63
+ },
64
+ "publishConfig": {
65
+ "access": "public"
66
+ },
67
+ "jupyterlab": {
68
+ "extension": true,
69
+ "schemaDir": "schema"
70
+ },
71
+ "styleModule": "style/index.js"
72
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "title": "Jupyter Notebook Menu Entries",
3
+ "description": "Jupyter Notebook Menu Entries",
4
+ "jupyter.lab.menus": {
5
+ "main": [
6
+ {
7
+ "id": "jp-mainmenu-file",
8
+ "items": [
9
+ {
10
+ "command": "application:rename",
11
+ "rank": 4
12
+ },
13
+ {
14
+ "command": "notebook:trust",
15
+ "rank": 20
16
+ }
17
+ ]
18
+ }
19
+ ]
20
+ },
21
+ "properties": {},
22
+ "additionalProperties": false,
23
+ "type": "object"
24
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "jupyter.lab.setting-icon": "notebook-ui-components:jupyter",
3
+ "jupyter.lab.setting-icon-label": "Jupyter Notebook Top Area",
4
+ "title": "Jupyter Notebook Top Area",
5
+ "description": "Jupyter Notebook Top Area settings",
6
+ "properties": {
7
+ "visible": {
8
+ "type": "boolean",
9
+ "title": "Top Bar Visibility",
10
+ "description": "Whether to show the top bar or not",
11
+ "default": true
12
+ }
13
+ },
14
+ "additionalProperties": false,
15
+ "type": "object"
16
+ }
package/style/base.css ADDED
@@ -0,0 +1,14 @@
1
+ /*-----------------------------------------------------------------------------
2
+ | Copyright (c) Jupyter Development Team.
3
+ |
4
+ | Distributed under the terms of the Modified BSD License.
5
+ |----------------------------------------------------------------------------*/
6
+
7
+ .jp-NotebookSpacer {
8
+ flex-grow: 1;
9
+ flex-shrink: 1;
10
+ }
11
+
12
+ .jp-MainAreaWidget {
13
+ height: 100%;
14
+ }
@@ -0,0 +1,4 @@
1
+ @import url('~@jupyter-notebook/application/style/index.css');
2
+ @import url('~@lumino/widgets/style/index.css');
3
+
4
+ @import url('./base.css');
package/style/index.js ADDED
@@ -0,0 +1,4 @@
1
+ import '@jupyter-notebook/application/style/index.js';
2
+ import '@lumino/widgets/style/index.js';
3
+
4
+ import './base.css';