@jupyterlab/notebook-extension 4.6.2 → 4.6.4

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
@@ -6,7 +6,7 @@
6
6
  * @module notebook-extension
7
7
  */
8
8
  import { ILabShell, ILayoutRestorer, IRouter } from '@jupyterlab/application';
9
- import { Clipboard, createToolbarFactory, Dialog, ICommandPalette, IKernelStatusModel, InputDialog, ISanitizer, ISessionContextDialogs, IToolbarWidgetRegistry, MainAreaWidget, Sanitizer, SemanticCommand, SessionContextDialogs, showDialog, Toolbar, WidgetTracker } from '@jupyterlab/apputils';
9
+ import { Clipboard, CommandLinker, createToolbarFactory, Dialog, ICommandPalette, IKernelStatusModel, InputDialog, ISanitizer, ISessionContextDialogs, IToolbarWidgetRegistry, MainAreaWidget, Sanitizer, SemanticCommand, SessionContextDialogs, showDialog, Toolbar, WidgetTracker } from '@jupyterlab/apputils';
10
10
  import { MarkdownCell } from '@jupyterlab/cells';
11
11
  import { IEditorServices, IPositionModel } from '@jupyterlab/codeeditor';
12
12
  import { compareVersions, PageConfig } from '@jupyterlab/coreutils';
@@ -480,6 +480,9 @@ export const exportPlugin = {
480
480
  const formatList = Object.keys(response);
481
481
  formatList.forEach(function (key) {
482
482
  const formattedKey = key[0].toLocaleUpperCase() + key.slice(1);
483
+ // Fallback for export formats the server offers but `formatLabels`
484
+ // does not know about, so there is no literal to extract.
485
+ // eslint-disable-next-line jupyter/no-dynamic-translation
483
486
  const capCaseKey = trans.__(formattedKey);
484
487
  const labelStr = formatLabels[key] ? formatLabels[key] : capCaseKey;
485
488
  let args = {
@@ -748,6 +751,9 @@ const updateRawMimetype = {
748
751
  const mimetypeExists = ((_a = properties.oneOf) === null || _a === void 0 ? void 0 : _a.filter(value => value.const === key).length) > 0;
749
752
  if (!mimetypeExists) {
750
753
  const formattedKey = key[0].toLocaleUpperCase() + key.slice(1);
754
+ // Fallback for export formats the server offers but `formatLabels`
755
+ // does not know about, so there is no literal to extract.
756
+ // eslint-disable-next-line jupyter/no-dynamic-translation
751
757
  const altOption = trans.__(formattedKey);
752
758
  const option = formatLabels[key] ? formatLabels[key] : altOption;
753
759
  const mimeTypeValue = response[key].output_mimetype;
@@ -775,26 +781,32 @@ const customMetadataEditorFields = {
775
781
  optional: [ITranslator],
776
782
  activate: (app, tracker, editorServices, formRegistry, translator) => {
777
783
  const editorFactory = options => editorServices.factoryService.newInlineEditor(options);
778
- // Register the custom fields.
784
+ // Register the custom fields. As with the active cell tool below, the
785
+ // field renderers are used by rjsf as React components, so they run on
786
+ // every rebuild of the metadata form. Each field is created once and
787
+ // reused: constructing one per render abandons an editor, its host node
788
+ // and its listeners on every keystroke that rebuilds the form.
789
+ const cellMetadataField = new CellMetadataField({
790
+ editorFactory,
791
+ tracker,
792
+ label: 'Cell metadata',
793
+ translator: translator
794
+ });
779
795
  const cellComponent = {
780
796
  fieldRenderer: (props) => {
781
- return new CellMetadataField({
782
- editorFactory,
783
- tracker,
784
- label: 'Cell metadata',
785
- translator: translator
786
- }).render(props);
797
+ return cellMetadataField.render(props);
787
798
  }
788
799
  };
789
800
  formRegistry.addRenderer('@jupyterlab/notebook-extension:metadata-editor.cell-metadata', cellComponent);
801
+ const notebookMetadataField = new NotebookMetadataField({
802
+ editorFactory,
803
+ tracker,
804
+ label: 'Notebook metadata',
805
+ translator: translator
806
+ });
790
807
  const notebookComponent = {
791
808
  fieldRenderer: (props) => {
792
- return new NotebookMetadataField({
793
- editorFactory,
794
- tracker,
795
- label: 'Notebook metadata',
796
- translator: translator
797
- }).render(props);
809
+ return notebookMetadataField.render(props);
798
810
  }
799
811
  };
800
812
  formRegistry.addRenderer('@jupyterlab/notebook-extension:metadata-editor.notebook-metadata', notebookComponent);
@@ -811,12 +823,18 @@ const activeCellTool = {
811
823
  activate: (
812
824
  // Register the custom field.
813
825
  app, tracker, formRegistry, languages) => {
826
+ // The field renderer is used by rjsf as a React component, so it runs on
827
+ // every rebuild of the metadata form. The tool is created once and reused:
828
+ // constructing one per render would rebuild the prompt and the preview from
829
+ // scratch (showing them empty until the next update) and would leave a
830
+ // connection to the cell model behind for every abandoned instance.
831
+ const tool = new ActiveCellTool({
832
+ tracker,
833
+ languages
834
+ });
814
835
  const component = {
815
836
  fieldRenderer: (props) => {
816
- return new ActiveCellTool({
817
- tracker,
818
- languages
819
- }).render(props);
837
+ return tool.render(props);
820
838
  }
821
839
  };
822
840
  formRegistry.addRenderer('@jupyterlab/notebook-extension:active-cell-tool.renderer', component);
@@ -2182,8 +2200,12 @@ function addCommands(app, tracker, translator, sessionDialogs, settings, isEnabl
2182
2200
  commands.addCommand(CommandIDs.trust, {
2183
2201
  label: () => trans.__('Trust Notebook'),
2184
2202
  execute: async (args) => {
2185
- const current = getCurrent(tracker, shell, args);
2186
- if (current) {
2203
+ var _a;
2204
+ const trustBoundaryId = args[CommandLinker.TRUST_BOUNDARY_ID_ARG];
2205
+ const current = typeof trustBoundaryId === 'string'
2206
+ ? ((_a = tracker.find(widget => widget.content.node.id === trustBoundaryId)) !== null && _a !== void 0 ? _a : null)
2207
+ : getCurrent(tracker, shell, args);
2208
+ if (current && !current.isDisposed) {
2187
2209
  const { context, content } = current;
2188
2210
  const trustResult = await NotebookActions.trust(content);
2189
2211
  if (trustResult.trusted) {
@@ -2197,7 +2219,12 @@ function addCommands(app, tracker, translator, sessionDialogs, settings, isEnabl
2197
2219
  describedBy: {
2198
2220
  args: {
2199
2221
  type: 'object',
2200
- properties: {}
2222
+ properties: {
2223
+ [CommandLinker.TRUST_BOUNDARY_ID_ARG]: {
2224
+ type: 'string',
2225
+ description: trans.__('The notebook trust boundary ID')
2226
+ }
2227
+ }
2201
2228
  }
2202
2229
  }
2203
2230
  });