@jupyter-notebook/application-extension 7.7.0-alpha.1 → 7.7.0-beta.0

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 CHANGED
@@ -17,9 +17,9 @@ import { PromiseDelegate } from '@lumino/coreutils';
17
17
  import { DisposableDelegate, DisposableSet, } from '@lumino/disposable';
18
18
  import { Menu, Widget } from '@lumino/widgets';
19
19
  /**
20
- * A regular expression to match path to notebooks and documents
20
+ * A regular expression to match the notebook and editor routes
21
21
  */
22
- const TREE_PATTERN = new RegExp('/(notebooks|edit)/(.*)');
22
+ const DOCUMENT_PATTERN = new RegExp('^/(notebooks|edit)/(.*)$');
23
23
  /**
24
24
  * A regular expression to suppress the file extension from display for .ipynb files.
25
25
  */
@@ -114,7 +114,7 @@ const logo = {
114
114
  description: 'The logo plugin.',
115
115
  autoStart: true,
116
116
  activate: (app) => {
117
- const baseUrl = PageConfig.getBaseUrl();
117
+ const baseUrl = app.serviceManager.serverSettings.baseUrl;
118
118
  const node = document.createElement('a');
119
119
  node.href = `${baseUrl}tree`;
120
120
  node.target = '_blank';
@@ -149,7 +149,7 @@ const opener = {
149
149
  execute: (args) => {
150
150
  var _a;
151
151
  const parsed = args;
152
- const matches = (_a = parsed.path.match(TREE_PATTERN)) !== null && _a !== void 0 ? _a : [];
152
+ const matches = (_a = parsed.path.match(DOCUMENT_PATTERN)) !== null && _a !== void 0 ? _a : [];
153
153
  const [, , path] = matches;
154
154
  if (!path) {
155
155
  return;
@@ -178,9 +178,31 @@ const opener = {
178
178
  });
179
179
  }
180
180
  const factory = (_a = urlParams.get('factory')) !== null && _a !== void 0 ? _a : defaultFactory;
181
- docManager.open(file, factory, undefined, {
181
+ const kernelPreference = urlParams.get('kernel') === 'none'
182
+ ? { shouldStart: false, shouldReuse: false }
183
+ : undefined;
184
+ const widget = docManager.openOrReveal(file, factory, undefined, {
182
185
  ref: '_noref',
183
- });
186
+ }, kernelPreference);
187
+ if (kernelPreference && widget) {
188
+ const { sessionContext } = widget.context;
189
+ /**
190
+ * `kernel=none` only describes how to open the notebook. Drop it
191
+ * as soon as a kernel runs, so a reload reconnects to that session.
192
+ */
193
+ const clearNoKernelQuery = () => {
194
+ var _a;
195
+ if (!((_a = sessionContext.session) === null || _a === void 0 ? void 0 : _a.kernel)) {
196
+ return;
197
+ }
198
+ const url = new URL(window.location.href);
199
+ url.searchParams.delete('kernel');
200
+ window.history.replaceState(window.history.state, '', url.toString());
201
+ sessionContext.kernelChanged.disconnect(clearNoKernelQuery);
202
+ };
203
+ sessionContext.kernelChanged.connect(clearNoKernelQuery);
204
+ clearNoKernelQuery();
205
+ }
184
206
  });
185
207
  },
186
208
  describedBy: {
@@ -200,7 +222,7 @@ const opener = {
200
222
  },
201
223
  },
202
224
  });
203
- router.register({ command, pattern: TREE_PATTERN });
225
+ router.register({ command, pattern: DOCUMENT_PATTERN });
204
226
  },
205
227
  };
206
228
  /**
@@ -257,7 +279,7 @@ const pages = {
257
279
  optional: [ICommandPalette],
258
280
  activate: (app, translator, palette) => {
259
281
  const trans = translator.load('notebook');
260
- const baseUrl = PageConfig.getBaseUrl();
282
+ const baseUrl = app.serviceManager.serverSettings.baseUrl;
261
283
  app.commands.addCommand(CommandIDs.openLab, {
262
284
  label: trans.__('Open JupyterLab'),
263
285
  execute: () => {
@@ -289,8 +311,14 @@ const pages = {
289
311
  },
290
312
  });
291
313
  if (palette) {
292
- palette.addItem({ command: CommandIDs.openLab, category: 'View' });
293
- palette.addItem({ command: CommandIDs.openTree, category: 'View' });
314
+ palette.addItem({
315
+ command: CommandIDs.openLab,
316
+ category: trans.__('View'),
317
+ });
318
+ palette.addItem({
319
+ command: CommandIDs.openTree,
320
+ category: trans.__('View'),
321
+ });
294
322
  }
295
323
  },
296
324
  };
@@ -351,7 +379,7 @@ const rendermime = {
351
379
  return docManager.services.contents
352
380
  .get(path, { content: false })
353
381
  .then((model) => {
354
- const baseUrl = PageConfig.getBaseUrl();
382
+ const baseUrl = app.serviceManager.serverSettings.baseUrl;
355
383
  opener.open({
356
384
  prefix: URLExt.join(baseUrl, 'tree'),
357
385
  path: model.path,
@@ -602,7 +630,7 @@ const title = {
602
630
  if (!router) {
603
631
  return;
604
632
  }
605
- const matches = (_a = router.current.path.match(TREE_PATTERN)) !== null && _a !== void 0 ? _a : [];
633
+ const matches = (_a = router.current.path.match(DOCUMENT_PATTERN)) !== null && _a !== void 0 ? _a : [];
606
634
  const [, route, path] = matches;
607
635
  if (!route || !path) {
608
636
  return;
@@ -680,7 +708,10 @@ const topVisibility = {
680
708
  });
681
709
  }
682
710
  if (palette) {
683
- palette.addItem({ command: CommandIDs.toggleTop, category: 'View' });
711
+ palette.addItem({
712
+ command: CommandIDs.toggleTop,
713
+ category: trans.__('View'),
714
+ });
684
715
  }
685
716
  const onChanged = () => {
686
717
  if (!adjustToScreen) {
@@ -715,7 +746,7 @@ const sidePanelVisibility = {
715
746
  * id, widget ID to activate in the side panel
716
747
  */
717
748
  app.commands.addCommand(CommandIDs.togglePanel, {
718
- label: (args) => args['title'],
749
+ label: (args) => trans.__('Show %1', args['title']),
719
750
  caption: (args) => {
720
751
  // We do not substitute the parameter into the string because the parameter is not
721
752
  // localized (e.g., it is always 'left') even though the string is localized.
@@ -796,7 +827,7 @@ const sidePanelVisibility = {
796
827
  },
797
828
  title: {
798
829
  type: 'string',
799
- description: 'The title shown for the side panel entry.',
830
+ description: 'The title of the side panel widget.',
800
831
  },
801
832
  id: {
802
833
  type: 'string',
@@ -816,38 +847,38 @@ const sidePanelVisibility = {
816
847
  *
817
848
  * @param area - 'left' or 'right', the area of the side panel.
818
849
  * @param entryLabel - the name of the main entry in the View menu for that side panel.
819
- * @returns - The disposable menu added to the View menu or null.
820
850
  */
821
851
  const updateMenu = (area, entryLabel) => {
822
852
  var _a;
823
853
  if (menu === null) {
824
- return null;
854
+ return;
825
855
  }
826
856
  // Remove the previous menu entry for this side panel.
827
857
  (_a = sidePanelMenu[area]) === null || _a === void 0 ? void 0 : _a.dispose();
858
+ sidePanelMenu[area] = null;
859
+ // Nothing to add to the View menu if the side panel has no widget.
860
+ const widgets = Array.from(notebookShell.widgets(area));
861
+ if (widgets.length === 0) {
862
+ return;
863
+ }
828
864
  // Creates a new menu entry and populates it with side panel widgets.
829
865
  const newMenu = new Menu({ commands: app.commands });
830
866
  newMenu.title.label = entryLabel;
831
- const widgets = notebookShell.widgets(area);
832
- let menuToAdd = false;
833
867
  for (const widget of widgets) {
834
868
  newMenu.addItem({
835
869
  command: CommandIDs.togglePanel,
836
870
  args: {
837
871
  side: area,
838
- title: `Show ${widget.title.caption}`,
872
+ title: widget.title.caption,
839
873
  id: widget.id,
840
874
  },
841
875
  });
842
- menuToAdd = true;
843
- }
844
- // If there are widgets, add the menu to the main menu entry.
845
- if (menuToAdd) {
846
- sidePanelMenu[area] = menu.viewMenu.addItem({
847
- type: 'submenu',
848
- submenu: newMenu,
849
- });
850
876
  }
877
+ // Add the menu to the main menu entry.
878
+ sidePanelMenu[area] = menu.viewMenu.addItem({
879
+ type: 'submenu',
880
+ submenu: newMenu,
881
+ });
851
882
  };
852
883
  app.restored.then(() => {
853
884
  // Create menu entries for the left and right panel.
@@ -880,6 +911,7 @@ const sidePanelVisibility = {
880
911
  const sidePanelPalette = new SidePanelPalette({
881
912
  commandPalette: palette,
882
913
  command: CommandIDs.togglePanel,
914
+ translator,
883
915
  });
884
916
  notebookShell.leftHandler.widgets.forEach((widget) => {
885
917
  sidePanelPalette.addItem(widget, notebookShell.leftHandler.area);
@@ -1055,7 +1087,10 @@ const zen = {
1055
1087
  }
1056
1088
  });
1057
1089
  if (palette) {
1058
- palette.addItem({ command: CommandIDs.toggleZen, category: 'Mode' });
1090
+ palette.addItem({
1091
+ command: CommandIDs.toggleZen,
1092
+ category: trans.__('Mode'),
1093
+ });
1059
1094
  }
1060
1095
  },
1061
1096
  };
@@ -1,21 +1,15 @@
1
- import type { ISettingConnector, ISettingRegistry } from '@jupyterlab/settingregistry';
2
- import type { IDataConnector } from '@jupyterlab/statedb';
3
- import { DataConnector } from '@jupyterlab/statedb';
1
+ import { ISettingRegistry, SettingConnector as BaseSettingConnector } from '@jupyterlab/settingregistry';
4
2
  /**
5
3
  * A data connector for fetching settings.
6
4
  *
7
5
  * #### Notes
8
- * This connector is based on the default JupyterLab setting connector,
9
- * and additionally overrides the default values of some settings.
6
+ * This connector extends the default JupyterLab setting connector with
7
+ * Jupyter Notebook-specific overrides.
10
8
  */
11
- export declare class SettingConnector extends DataConnector<ISettingRegistry.IPlugin, string> implements ISettingConnector {
12
- constructor(connector: IDataConnector<ISettingRegistry.IPlugin, string>);
9
+ export declare class SettingConnector extends BaseSettingConnector {
13
10
  /**
14
11
  * Fetch settings for a plugin.
15
12
  * @param id - The plugin ID
16
- *
17
- * #### Notes
18
- * The REST API requests are throttled at one request per plugin per 100ms.
19
13
  */
20
14
  fetch(id: string): Promise<ISettingRegistry.IPlugin | undefined>;
21
15
  list(query: 'ids'): Promise<{
@@ -25,7 +19,4 @@ export declare class SettingConnector extends DataConnector<ISettingRegistry.IPl
25
19
  ids: string[];
26
20
  values: ISettingRegistry.IPlugin[];
27
21
  }>;
28
- save(id: string, raw: string): Promise<void>;
29
- private _connector;
30
- private _throttlers;
31
22
  }
@@ -1,8 +1,7 @@
1
1
  // Copyright (c) Jupyter Development Team.
2
2
  // Distributed under the terms of the Modified BSD License.
3
3
  import { PageConfig } from '@jupyterlab/coreutils';
4
- import { DataConnector } from '@jupyterlab/statedb';
5
- import { Throttler } from '@lumino/polling';
4
+ import { SettingConnector as BaseSettingConnector, } from '@jupyterlab/settingregistry';
6
5
  /**
7
6
  * The default setting values overridden in Jupyter Notebook, mapping
8
7
  * a plugin identifier to the overridden properties.
@@ -21,54 +20,30 @@ const SETTING_OVERRIDES = {
21
20
  helpInBottomPanel: true,
22
21
  },
23
22
  };
23
+ const FILE_EDITOR_PLUGIN_ID = '@jupyterlab/fileeditor-extension:plugin';
24
+ const SYNTAX_HIGHLIGHTING_SUBMENU_ID = 'jp-mainmenu-view-codemirror-language';
24
25
  /**
25
26
  * A data connector for fetching settings.
26
27
  *
27
28
  * #### Notes
28
- * This connector is based on the default JupyterLab setting connector,
29
- * and additionally overrides the default values of some settings.
29
+ * This connector extends the default JupyterLab setting connector with
30
+ * Jupyter Notebook-specific overrides.
30
31
  */
31
- export class SettingConnector extends DataConnector {
32
- constructor(connector) {
33
- super();
34
- this._throttlers = Object.create(null);
35
- this._connector = connector;
36
- }
32
+ export class SettingConnector extends BaseSettingConnector {
37
33
  /**
38
34
  * Fetch settings for a plugin.
39
35
  * @param id - The plugin ID
40
- *
41
- * #### Notes
42
- * The REST API requests are throttled at one request per plugin per 100ms.
43
36
  */
44
- fetch(id) {
45
- const throttlers = this._throttlers;
46
- if (!(id in throttlers)) {
47
- throttlers[id] = new Throttler(async () => {
48
- const plugin = await this._connector.fetch(id);
49
- return plugin && Private.overrideDefaults(plugin);
50
- }, 100);
51
- }
52
- return throttlers[id].invoke();
37
+ async fetch(id) {
38
+ const plugin = await super.fetch(id);
39
+ return plugin && Private.applyOverrides(plugin);
53
40
  }
54
41
  async list(query = 'all') {
55
- const { isDisabled } = PageConfig.Extension;
56
- const { ids, values } = await this._connector.list(query === 'ids' ? 'ids' : undefined);
57
42
  if (query === 'ids') {
58
- return { ids };
59
- }
60
- if (query === 'all') {
61
- return { ids, values: values.map(Private.overrideDefaults) };
43
+ return super.list(query);
62
44
  }
63
- return {
64
- ids: ids.filter((id) => !isDisabled(id)),
65
- values: values
66
- .filter(({ id }) => !isDisabled(id))
67
- .map(Private.overrideDefaults),
68
- };
69
- }
70
- async save(id, raw) {
71
- await this._connector.save(id, raw);
45
+ const { ids, values } = await super.list(query);
46
+ return { ids, values: values.map(Private.applyOverrides) };
72
47
  }
73
48
  }
74
49
  /**
@@ -76,6 +51,10 @@ export class SettingConnector extends DataConnector {
76
51
  */
77
52
  var Private;
78
53
  (function (Private) {
54
+ function applyOverrides(plugin) {
55
+ return hideSyntaxHighlightingMenu(overrideDefaults(plugin));
56
+ }
57
+ Private.applyOverrides = applyOverrides;
79
58
  /**
80
59
  * Override the default values of the plugin settings listed
81
60
  * in `SETTING_OVERRIDES`.
@@ -93,5 +72,21 @@ var Private;
93
72
  }
94
73
  return plugin;
95
74
  }
96
- Private.overrideDefaults = overrideDefaults;
75
+ function hideSyntaxHighlightingMenu(plugin) {
76
+ var _a, _b, _c, _d;
77
+ const page = PageConfig.getOption('notebookPage');
78
+ if (plugin.id !== FILE_EDITOR_PLUGIN_ID || page === 'edit') {
79
+ return plugin;
80
+ }
81
+ const menus = (_b = (_a = plugin.schema['jupyter.lab.menus']) === null || _a === void 0 ? void 0 : _a.main) !== null && _b !== void 0 ? _b : [];
82
+ for (const menu of menus) {
83
+ for (const item of (_c = menu.items) !== null && _c !== void 0 ? _c : []) {
84
+ if (item.type === 'submenu' &&
85
+ ((_d = item.submenu) === null || _d === void 0 ? void 0 : _d.id) === SYNTAX_HIGHLIGHTING_SUBMENU_ID) {
86
+ item.disabled = true;
87
+ }
88
+ }
89
+ }
90
+ return plugin;
91
+ }
97
92
  })(Private || (Private = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jupyter-notebook/application-extension",
3
- "version": "7.7.0-alpha.1",
3
+ "version": "7.7.0-beta.0",
4
4
  "description": "Jupyter Notebook - Application Extension",
5
5
  "homepage": "https://github.com/jupyter/notebook",
6
6
  "bugs": {
@@ -38,23 +38,21 @@
38
38
  "watch": "tsc -b --watch"
39
39
  },
40
40
  "dependencies": {
41
- "@jupyter-notebook/application": "^7.7.0-alpha.1",
42
- "@jupyter-notebook/ui-components": "^7.7.0-alpha.1",
43
- "@jupyterlab/application": "~4.7.0-alpha.1",
44
- "@jupyterlab/apputils": "~4.8.0-alpha.1",
45
- "@jupyterlab/codeeditor": "~4.7.0-alpha.1",
46
- "@jupyterlab/console": "~4.7.0-alpha.1",
47
- "@jupyterlab/coreutils": "~6.7.0-alpha.1",
48
- "@jupyterlab/docmanager": "~4.7.0-alpha.1",
49
- "@jupyterlab/docregistry": "~4.7.0-alpha.1",
50
- "@jupyterlab/mainmenu": "~4.7.0-alpha.1",
51
- "@jupyterlab/rendermime": "~4.7.0-alpha.1",
52
- "@jupyterlab/settingregistry": "~4.7.0-alpha.1",
53
- "@jupyterlab/statedb": "~4.7.0-alpha.1",
54
- "@jupyterlab/translation": "~4.7.0-alpha.1",
41
+ "@jupyter-notebook/application": "^7.7.0-beta.0",
42
+ "@jupyter-notebook/ui-components": "^7.7.0-beta.0",
43
+ "@jupyterlab/application": "~4.7.0-beta.0",
44
+ "@jupyterlab/apputils": "~4.8.0-beta.0",
45
+ "@jupyterlab/codeeditor": "~4.7.0-beta.0",
46
+ "@jupyterlab/console": "~4.7.0-beta.0",
47
+ "@jupyterlab/coreutils": "~6.7.0-beta.0",
48
+ "@jupyterlab/docmanager": "~4.7.0-beta.0",
49
+ "@jupyterlab/docregistry": "~4.7.0-beta.0",
50
+ "@jupyterlab/mainmenu": "~4.7.0-beta.0",
51
+ "@jupyterlab/rendermime": "~4.7.0-beta.0",
52
+ "@jupyterlab/settingregistry": "~4.7.0-beta.0",
53
+ "@jupyterlab/translation": "~4.7.0-beta.0",
55
54
  "@lumino/coreutils": "^2.2.2",
56
55
  "@lumino/disposable": "^2.1.5",
57
- "@lumino/polling": "^2.1.5",
58
56
  "@lumino/widgets": "^2.7.2"
59
57
  },
60
58
  "devDependencies": {
package/schema/shell.json CHANGED
@@ -20,20 +20,34 @@
20
20
  "definitions": {
21
21
  "layout": {
22
22
  "type": "object",
23
- "properties": {
23
+ "patternProperties": {
24
24
  "[\\w-]+": {
25
25
  "type": "object",
26
26
  "properties": {
27
27
  "area": {
28
+ "type": "string",
28
29
  "oneOf": [
30
+ { "const": "main", "title": "Main" },
31
+ { "const": "top", "title": "Top" },
32
+ { "const": "menu", "title": "Menu" },
29
33
  { "const": "left", "title": "Left" },
30
- { "const": "right", "title": "Right" }
34
+ { "const": "right", "title": "Right" },
35
+ { "const": "down", "title": "Down" }
31
36
  ]
37
+ },
38
+ "options": {
39
+ "$ref": "#/definitions/options"
32
40
  }
33
41
  },
34
42
  "additionalProperties": false
35
43
  }
36
44
  }
45
+ },
46
+ "options": {
47
+ "type": "object",
48
+ "properties": {
49
+ "rank": { "type": "number", "minimum": 0 }
50
+ }
37
51
  }
38
52
  }
39
53
  }
package/schema/top.json CHANGED
@@ -21,6 +21,7 @@
21
21
  "title": "Top Bar Visibility",
22
22
  "description": "Whether to show the top bar or not, yes for always showing, no for always not showing, automatic for adjusting to screen size",
23
23
  "default": "automatic",
24
+ "type": "string",
24
25
  "oneOf": [
25
26
  { "const": "yes", "title": "Yes" },
26
27
  { "const": "no", "title": "No" },