@jupyterlab/notebook-extension 4.6.0-alpha.5 → 4.6.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 +238 -9
- package/lib/index.js.map +1 -1
- package/package.json +33 -33
- package/schema/panel.json +4 -1
- package/schema/tracker.json +34 -9
- package/src/index.ts +264 -6
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
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
4
|
/**
|
|
4
5
|
* @packageDocumentation
|
|
5
6
|
* @module notebook-extension
|
|
6
7
|
*/
|
|
7
8
|
import { ILabShell, ILayoutRestorer, IRouter } from '@jupyterlab/application';
|
|
8
|
-
import { createToolbarFactory, Dialog, ICommandPalette, IKernelStatusModel, InputDialog, ISanitizer, ISessionContextDialogs, IToolbarWidgetRegistry, MainAreaWidget, Sanitizer, SemanticCommand, SessionContextDialogs, showDialog, Toolbar, WidgetTracker } from '@jupyterlab/apputils';
|
|
9
|
+
import { Clipboard, createToolbarFactory, Dialog, ICommandPalette, IKernelStatusModel, InputDialog, ISanitizer, ISessionContextDialogs, IToolbarWidgetRegistry, MainAreaWidget, Sanitizer, SemanticCommand, SessionContextDialogs, showDialog, Toolbar, WidgetTracker } from '@jupyterlab/apputils';
|
|
9
10
|
import { MarkdownCell } from '@jupyterlab/cells';
|
|
10
11
|
import { IEditorServices, IPositionModel } from '@jupyterlab/codeeditor';
|
|
11
|
-
import { PageConfig } from '@jupyterlab/coreutils';
|
|
12
|
+
import { compareVersions, PageConfig } from '@jupyterlab/coreutils';
|
|
12
13
|
import { IEditorExtensionRegistry, IEditorLanguageRegistry } from '@jupyterlab/codemirror';
|
|
13
14
|
import { ICompletionProviderManager } from '@jupyterlab/completer';
|
|
14
15
|
import { IDocumentManager } from '@jupyterlab/docmanager';
|
|
@@ -127,6 +128,8 @@ var CommandIDs;
|
|
|
127
128
|
CommandIDs.disableOutputScrolling = 'notebook:disable-output-scrolling';
|
|
128
129
|
CommandIDs.toggleOutputScrolling = 'notebook:toggle-output-scrolling';
|
|
129
130
|
CommandIDs.selectLastRunCell = 'notebook:select-last-run-cell';
|
|
131
|
+
CommandIDs.selectLastModifiedCell = 'notebook:select-last-modified-cell';
|
|
132
|
+
CommandIDs.selectNextModifiedCell = 'notebook:select-next-modified-cell';
|
|
130
133
|
CommandIDs.replaceSelection = 'notebook:replace-selection';
|
|
131
134
|
CommandIDs.autoClosingBrackets = 'notebook:toggle-autoclosing-brackets';
|
|
132
135
|
CommandIDs.toggleCollapseCmd = 'notebook:toggle-heading-collapse';
|
|
@@ -139,6 +142,9 @@ var CommandIDs;
|
|
|
139
142
|
CommandIDs.accessPreviousHistory = 'notebook:access-previous-history-entry';
|
|
140
143
|
CommandIDs.accessNextHistory = 'notebook:access-next-history-entry';
|
|
141
144
|
CommandIDs.virtualScrollbar = 'notebook:toggle-virtual-scrollbar';
|
|
145
|
+
CommandIDs.copySelectedtext = 'notebook:copy-selected-text';
|
|
146
|
+
CommandIDs.pasteText = 'notebook:paste-text';
|
|
147
|
+
CommandIDs.cutSelectedtext = 'notebook:cut-selected-text';
|
|
142
148
|
})(CommandIDs || (CommandIDs = {}));
|
|
143
149
|
/**
|
|
144
150
|
* The name of the factory that creates notebooks.
|
|
@@ -391,23 +397,40 @@ export const exportPlugin = {
|
|
|
391
397
|
: formatLabel;
|
|
392
398
|
},
|
|
393
399
|
execute: async (args) => {
|
|
394
|
-
var _a, _b;
|
|
400
|
+
var _a, _b, _c;
|
|
395
401
|
const current = getCurrent(tracker, shell, args);
|
|
396
402
|
if (!current) {
|
|
397
403
|
return;
|
|
398
404
|
}
|
|
399
405
|
const { context } = current;
|
|
406
|
+
const serverVersion = PageConfig.getNotebookVersion();
|
|
407
|
+
const supportsHTMLSanitizationOption = compareVersions(serverVersion, [4, 0, 0]) <
|
|
408
|
+
0 /* Jupyter Server only */ &&
|
|
409
|
+
compareVersions(serverVersion, [2, 18, 0]) >= 0;
|
|
410
|
+
let sanitizeHtml = false;
|
|
411
|
+
if (args['format'] === 'html' && supportsHTMLSanitizationOption) {
|
|
412
|
+
const result = await InputDialog.getBoolean({
|
|
413
|
+
title: trans.__('Export as HTML'),
|
|
414
|
+
label: trans.__('Sanitize HTML output'),
|
|
415
|
+
value: true
|
|
416
|
+
});
|
|
417
|
+
if (!result.button.accept) {
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
sanitizeHtml = (_a = result.value) !== null && _a !== void 0 ? _a : false;
|
|
421
|
+
}
|
|
400
422
|
const exportOptions = {
|
|
401
423
|
format: args['format'],
|
|
402
424
|
path: current.context.path,
|
|
403
425
|
exporterOptions: {
|
|
404
|
-
download: true
|
|
426
|
+
download: true,
|
|
427
|
+
sanitizeHtml
|
|
405
428
|
}
|
|
406
429
|
};
|
|
407
430
|
if (context.model.dirty && !context.model.readOnly) {
|
|
408
431
|
await context.save();
|
|
409
432
|
}
|
|
410
|
-
return (
|
|
433
|
+
return (_c = (_b = services.nbconvert).exportAs) === null || _c === void 0 ? void 0 : _c.call(_b, exportOptions);
|
|
411
434
|
},
|
|
412
435
|
isEnabled,
|
|
413
436
|
describedBy: {
|
|
@@ -654,7 +677,7 @@ const tocPlugin = {
|
|
|
654
677
|
optional: [IMarkdownParser, ISettingRegistry],
|
|
655
678
|
autoStart: true,
|
|
656
679
|
activate: (app, tracker, tocRegistry, sanitizer, mdParser, settingRegistry) => {
|
|
657
|
-
const nbTocFactory = new NotebookToCFactory(tracker, mdParser, sanitizer);
|
|
680
|
+
const nbTocFactory = new NotebookToCFactory(tracker, mdParser, sanitizer, app.commands);
|
|
658
681
|
tocRegistry.add(nbTocFactory);
|
|
659
682
|
if (settingRegistry) {
|
|
660
683
|
Promise.all([app.restored, settingRegistry.load(trackerPlugin.id)])
|
|
@@ -842,7 +865,8 @@ const openWithNoKernelPlugin = {
|
|
|
842
865
|
label: trans.__('Notebook (no kernel)'),
|
|
843
866
|
factory: FACTORY,
|
|
844
867
|
kernelPreference: {
|
|
845
|
-
shouldStart: false
|
|
868
|
+
shouldStart: false,
|
|
869
|
+
shouldReuse: false
|
|
846
870
|
}
|
|
847
871
|
}
|
|
848
872
|
}));
|
|
@@ -904,6 +928,10 @@ function activateNotebookTools(app, tracker, editorServices, languages, state, t
|
|
|
904
928
|
return true;
|
|
905
929
|
};
|
|
906
930
|
notebookTools.title.icon = buildIcon;
|
|
931
|
+
notebookTools.title.dataset = {
|
|
932
|
+
...notebookTools.title.dataset,
|
|
933
|
+
jpTabLabel: trans.__('Notebook Tools')
|
|
934
|
+
};
|
|
907
935
|
notebookTools.title.caption = trans.__('Notebook Tools');
|
|
908
936
|
notebookTools.id = id;
|
|
909
937
|
MessageLoop.installMessageHook(notebookTools, hook);
|
|
@@ -1878,6 +1906,9 @@ function addCommands(app, tracker, translator, sessionDialogs, settings, isEnabl
|
|
|
1878
1906
|
tracker.selectionChanged.connect(() => {
|
|
1879
1907
|
commands.notifyCommandChanged(CommandIDs.duplicateBelow);
|
|
1880
1908
|
commands.notifyCommandChanged(CommandIDs.deleteCell);
|
|
1909
|
+
commands.notifyCommandChanged(CommandIDs.copySelectedtext);
|
|
1910
|
+
commands.notifyCommandChanged(CommandIDs.pasteText);
|
|
1911
|
+
commands.notifyCommandChanged(CommandIDs.cutSelectedtext);
|
|
1881
1912
|
commands.notifyCommandChanged(CommandIDs.copy);
|
|
1882
1913
|
commands.notifyCommandChanged(CommandIDs.cut);
|
|
1883
1914
|
commands.notifyCommandChanged(CommandIDs.pasteBelow);
|
|
@@ -1894,6 +1925,16 @@ function addCommands(app, tracker, translator, sessionDialogs, settings, isEnabl
|
|
|
1894
1925
|
commands.notifyCommandChanged(CommandIDs.deleteCell);
|
|
1895
1926
|
commands.notifyCommandChanged(CommandIDs.moveUp);
|
|
1896
1927
|
commands.notifyCommandChanged(CommandIDs.moveDown);
|
|
1928
|
+
commands.notifyCommandChanged(CommandIDs.selectLastModifiedCell);
|
|
1929
|
+
commands.notifyCommandChanged(CommandIDs.selectNextModifiedCell);
|
|
1930
|
+
});
|
|
1931
|
+
tracker.widgetAdded.connect((_, panel) => {
|
|
1932
|
+
panel.content.stateChanged.connect((_, args) => {
|
|
1933
|
+
if (args.name === 'lastModifiedCellStack') {
|
|
1934
|
+
commands.notifyCommandChanged(CommandIDs.selectLastModifiedCell);
|
|
1935
|
+
commands.notifyCommandChanged(CommandIDs.selectNextModifiedCell);
|
|
1936
|
+
}
|
|
1937
|
+
});
|
|
1897
1938
|
});
|
|
1898
1939
|
commands.addCommand(CommandIDs.runAndAdvance, {
|
|
1899
1940
|
label: args => {
|
|
@@ -2589,6 +2630,143 @@ function addCommands(app, tracker, translator, sessionDialogs, settings, isEnabl
|
|
|
2589
2630
|
}
|
|
2590
2631
|
}
|
|
2591
2632
|
});
|
|
2633
|
+
commands.addCommand(CommandIDs.copySelectedtext, {
|
|
2634
|
+
label: trans.__('Copy Selected Text'),
|
|
2635
|
+
caption: trans.__('Copy selected text from the active cell or output area'),
|
|
2636
|
+
execute: async (args) => {
|
|
2637
|
+
var _a;
|
|
2638
|
+
const current = getCurrent(tracker, shell, args);
|
|
2639
|
+
if (!current) {
|
|
2640
|
+
return;
|
|
2641
|
+
}
|
|
2642
|
+
// copying from the editor (input area)
|
|
2643
|
+
const editor = (_a = current.content.activeCell) === null || _a === void 0 ? void 0 : _a.editor;
|
|
2644
|
+
if (editor) {
|
|
2645
|
+
const selection = editor.getSelection();
|
|
2646
|
+
const start = editor.getOffsetAt(selection.start);
|
|
2647
|
+
const end = editor.getOffsetAt(selection.end);
|
|
2648
|
+
const text = editor.model.sharedModel.getSource().slice(start, end);
|
|
2649
|
+
if (text) {
|
|
2650
|
+
await navigator.clipboard.writeText(text);
|
|
2651
|
+
return;
|
|
2652
|
+
}
|
|
2653
|
+
}
|
|
2654
|
+
// fallback to DOM selection (output)
|
|
2655
|
+
const domSelection = window.getSelection();
|
|
2656
|
+
const selectedText = domSelection === null || domSelection === void 0 ? void 0 : domSelection.toString();
|
|
2657
|
+
if (selectedText && selectedText.trim().length > 0) {
|
|
2658
|
+
await navigator.clipboard.writeText(selectedText);
|
|
2659
|
+
}
|
|
2660
|
+
},
|
|
2661
|
+
isEnabled: args => {
|
|
2662
|
+
var _a;
|
|
2663
|
+
const current = getCurrent(tracker, shell, { ...args, activate: false });
|
|
2664
|
+
if (!current) {
|
|
2665
|
+
return false;
|
|
2666
|
+
}
|
|
2667
|
+
const editor = (_a = current.content.activeCell) === null || _a === void 0 ? void 0 : _a.editor;
|
|
2668
|
+
if (editor) {
|
|
2669
|
+
const selection = editor.getSelection();
|
|
2670
|
+
const hasEditorSelection = selection.start.line !== selection.end.line ||
|
|
2671
|
+
selection.start.column !== selection.end.column;
|
|
2672
|
+
if (hasEditorSelection) {
|
|
2673
|
+
return true;
|
|
2674
|
+
}
|
|
2675
|
+
}
|
|
2676
|
+
// Check for text selection in output area
|
|
2677
|
+
const domSelection = window.getSelection();
|
|
2678
|
+
return !!domSelection && domSelection.toString().trim().length > 0;
|
|
2679
|
+
},
|
|
2680
|
+
describedBy: {
|
|
2681
|
+
args: {
|
|
2682
|
+
type: 'object',
|
|
2683
|
+
properties: {}
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
});
|
|
2687
|
+
commands.addCommand(CommandIDs.cutSelectedtext, {
|
|
2688
|
+
label: trans.__('Cut Selected Text'),
|
|
2689
|
+
caption: trans.__('Cut selected text from the active cell or output area'),
|
|
2690
|
+
execute: async (args) => {
|
|
2691
|
+
var _a, _b;
|
|
2692
|
+
const current = getCurrent(tracker, shell, args);
|
|
2693
|
+
if (!current) {
|
|
2694
|
+
return;
|
|
2695
|
+
}
|
|
2696
|
+
const editor = (_a = current.content.activeCell) === null || _a === void 0 ? void 0 : _a.editor;
|
|
2697
|
+
if (editor) {
|
|
2698
|
+
const selection = editor.getSelection();
|
|
2699
|
+
const start = editor.getOffsetAt(selection.start);
|
|
2700
|
+
const end = editor.getOffsetAt(selection.end);
|
|
2701
|
+
const text = editor.model.sharedModel.getSource().slice(start, end);
|
|
2702
|
+
if (text) {
|
|
2703
|
+
await navigator.clipboard.writeText(text);
|
|
2704
|
+
(_b = editor.replaceSelection) === null || _b === void 0 ? void 0 : _b.call(editor, '');
|
|
2705
|
+
return;
|
|
2706
|
+
}
|
|
2707
|
+
}
|
|
2708
|
+
},
|
|
2709
|
+
isEnabled: args => {
|
|
2710
|
+
var _a;
|
|
2711
|
+
const current = getCurrent(tracker, shell, { ...args, activate: false });
|
|
2712
|
+
if (!current) {
|
|
2713
|
+
return false;
|
|
2714
|
+
}
|
|
2715
|
+
const editor = (_a = current.content.activeCell) === null || _a === void 0 ? void 0 : _a.editor;
|
|
2716
|
+
if (!editor) {
|
|
2717
|
+
return false;
|
|
2718
|
+
}
|
|
2719
|
+
const selection = editor.getSelection();
|
|
2720
|
+
const hasEditorSelection = selection.start.line !== selection.end.line ||
|
|
2721
|
+
selection.start.column !== selection.end.column;
|
|
2722
|
+
return hasEditorSelection;
|
|
2723
|
+
},
|
|
2724
|
+
describedBy: {
|
|
2725
|
+
args: {
|
|
2726
|
+
type: 'object',
|
|
2727
|
+
properties: {}
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
});
|
|
2731
|
+
commands.addCommand(CommandIDs.pasteText, {
|
|
2732
|
+
label: trans.__('Paste Text'),
|
|
2733
|
+
caption: trans.__('Paste text from the clipboard into the active cell editor'),
|
|
2734
|
+
execute: async (args) => {
|
|
2735
|
+
var _a, _b;
|
|
2736
|
+
const current = getCurrent(tracker, shell, args);
|
|
2737
|
+
if (!current) {
|
|
2738
|
+
return;
|
|
2739
|
+
}
|
|
2740
|
+
const editor = (_a = current.content.activeCell) === null || _a === void 0 ? void 0 : _a.editor;
|
|
2741
|
+
if (!editor) {
|
|
2742
|
+
return;
|
|
2743
|
+
}
|
|
2744
|
+
try {
|
|
2745
|
+
const text = await navigator.clipboard.readText();
|
|
2746
|
+
if (text) {
|
|
2747
|
+
(_b = editor.replaceSelection) === null || _b === void 0 ? void 0 : _b.call(editor, text);
|
|
2748
|
+
}
|
|
2749
|
+
}
|
|
2750
|
+
catch (err) {
|
|
2751
|
+
// browser limitation fallback (e.g Firefox)
|
|
2752
|
+
Clipboard.showPasteUnavailableDialog(trans);
|
|
2753
|
+
}
|
|
2754
|
+
},
|
|
2755
|
+
isEnabled: args => {
|
|
2756
|
+
var _a;
|
|
2757
|
+
const current = getCurrent(tracker, shell, { ...args, activate: false });
|
|
2758
|
+
if (!current) {
|
|
2759
|
+
return false;
|
|
2760
|
+
}
|
|
2761
|
+
return !!((_a = current.content.activeCell) === null || _a === void 0 ? void 0 : _a.editor);
|
|
2762
|
+
},
|
|
2763
|
+
describedBy: {
|
|
2764
|
+
args: {
|
|
2765
|
+
type: 'object',
|
|
2766
|
+
properties: {}
|
|
2767
|
+
}
|
|
2768
|
+
}
|
|
2769
|
+
});
|
|
2592
2770
|
commands.addCommand(CommandIDs.split, {
|
|
2593
2771
|
label: trans.__('Split Cell'),
|
|
2594
2772
|
execute: args => {
|
|
@@ -2615,7 +2793,15 @@ function addCommands(app, tracker, translator, sessionDialogs, settings, isEnabl
|
|
|
2615
2793
|
return NotebookActions.mergeCells(current.content, false, addExtraLine, translator);
|
|
2616
2794
|
}
|
|
2617
2795
|
},
|
|
2618
|
-
|
|
2796
|
+
isVisible: args => {
|
|
2797
|
+
const current = getCurrent(tracker, shell, { ...args, activate: false });
|
|
2798
|
+
if (!current) {
|
|
2799
|
+
return false;
|
|
2800
|
+
}
|
|
2801
|
+
// Enable only if more than one cell is selected
|
|
2802
|
+
const notebook = current.content;
|
|
2803
|
+
return notebook && notebook.selectedCells.length > 1;
|
|
2804
|
+
},
|
|
2619
2805
|
describedBy: {
|
|
2620
2806
|
args: {
|
|
2621
2807
|
type: 'object',
|
|
@@ -3534,6 +3720,44 @@ function addCommands(app, tracker, translator, sessionDialogs, settings, isEnabl
|
|
|
3534
3720
|
}
|
|
3535
3721
|
}
|
|
3536
3722
|
});
|
|
3723
|
+
commands.addCommand(CommandIDs.selectLastModifiedCell, {
|
|
3724
|
+
label: trans.__('Select Last Modified Cell'),
|
|
3725
|
+
execute: async (args) => {
|
|
3726
|
+
const current = getCurrent(tracker, shell, args);
|
|
3727
|
+
if (current) {
|
|
3728
|
+
await NotebookActions.selectLastModifiedCell(current.content);
|
|
3729
|
+
}
|
|
3730
|
+
},
|
|
3731
|
+
isEnabled: args => {
|
|
3732
|
+
const current = getCurrent(tracker, shell, { ...args, activate: false });
|
|
3733
|
+
return !!current && current.content.hasNavigableModifiedCellBack();
|
|
3734
|
+
},
|
|
3735
|
+
describedBy: {
|
|
3736
|
+
args: {
|
|
3737
|
+
type: 'object',
|
|
3738
|
+
properties: {}
|
|
3739
|
+
}
|
|
3740
|
+
}
|
|
3741
|
+
});
|
|
3742
|
+
commands.addCommand(CommandIDs.selectNextModifiedCell, {
|
|
3743
|
+
label: trans.__('Select Next Modified Cell'),
|
|
3744
|
+
execute: async (args) => {
|
|
3745
|
+
const current = getCurrent(tracker, shell, args);
|
|
3746
|
+
if (current) {
|
|
3747
|
+
await NotebookActions.selectNextModifiedCell(current.content);
|
|
3748
|
+
}
|
|
3749
|
+
},
|
|
3750
|
+
isEnabled: args => {
|
|
3751
|
+
const current = getCurrent(tracker, shell, { ...args, activate: false });
|
|
3752
|
+
return !!current && current.content.hasNavigableModifiedCellForward();
|
|
3753
|
+
},
|
|
3754
|
+
describedBy: {
|
|
3755
|
+
args: {
|
|
3756
|
+
type: 'object',
|
|
3757
|
+
properties: {}
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3760
|
+
});
|
|
3537
3761
|
commands.addCommand(CommandIDs.replaceSelection, {
|
|
3538
3762
|
label: trans.__('Replace Selection in Notebook Cell'),
|
|
3539
3763
|
execute: args => {
|
|
@@ -3764,6 +3988,9 @@ function populatePalette(palette, translator) {
|
|
|
3764
3988
|
CommandIDs.pasteAbove,
|
|
3765
3989
|
CommandIDs.pasteAndReplace,
|
|
3766
3990
|
CommandIDs.deleteCell,
|
|
3991
|
+
CommandIDs.copySelectedtext,
|
|
3992
|
+
CommandIDs.pasteText,
|
|
3993
|
+
CommandIDs.cutSelectedtext,
|
|
3767
3994
|
CommandIDs.split,
|
|
3768
3995
|
CommandIDs.merge,
|
|
3769
3996
|
CommandIDs.mergeAbove,
|
|
@@ -3802,7 +4029,9 @@ function populatePalette(palette, translator) {
|
|
|
3802
4029
|
CommandIDs.toggleRenderSideBySideCurrentNotebook,
|
|
3803
4030
|
CommandIDs.setSideBySideRatio,
|
|
3804
4031
|
CommandIDs.enableOutputScrolling,
|
|
3805
|
-
CommandIDs.disableOutputScrolling
|
|
4032
|
+
CommandIDs.disableOutputScrolling,
|
|
4033
|
+
CommandIDs.selectLastModifiedCell,
|
|
4034
|
+
CommandIDs.selectNextModifiedCell
|
|
3806
4035
|
].forEach(command => {
|
|
3807
4036
|
palette.addItem({ command, category });
|
|
3808
4037
|
});
|