@jupyterlab/extensionmanager-extension 4.0.0-alpha.19 → 4.0.0-alpha.20
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/package.json +11 -10
- package/src/index.ts +191 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupyterlab/extensionmanager-extension",
|
|
3
|
-
"version": "4.0.0-alpha.
|
|
3
|
+
"version": "4.0.0-alpha.20",
|
|
4
4
|
"description": "JupyterLab - Extension Manager Extension",
|
|
5
5
|
"homepage": "https://github.com/jupyterlab/jupyterlab",
|
|
6
6
|
"bugs": {
|
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
"schema/*.json",
|
|
30
30
|
"listing/*.json",
|
|
31
31
|
"style/*.css",
|
|
32
|
-
"style/index.js"
|
|
32
|
+
"style/index.js",
|
|
33
|
+
"src/**/*.{ts,tsx}"
|
|
33
34
|
],
|
|
34
35
|
"scripts": {
|
|
35
36
|
"build": "tsc -b",
|
|
@@ -38,17 +39,17 @@
|
|
|
38
39
|
"watch": "tsc -b --watch"
|
|
39
40
|
},
|
|
40
41
|
"dependencies": {
|
|
41
|
-
"@jupyterlab/application": "^4.0.0-alpha.
|
|
42
|
-
"@jupyterlab/apputils": "^4.0.0-alpha.
|
|
43
|
-
"@jupyterlab/extensionmanager": "^4.0.0-alpha.
|
|
44
|
-
"@jupyterlab/settingregistry": "^4.0.0-alpha.
|
|
45
|
-
"@jupyterlab/translation": "^4.0.0-alpha.
|
|
46
|
-
"@jupyterlab/ui-components": "^4.0.0-alpha.
|
|
42
|
+
"@jupyterlab/application": "^4.0.0-alpha.20",
|
|
43
|
+
"@jupyterlab/apputils": "^4.0.0-alpha.20",
|
|
44
|
+
"@jupyterlab/extensionmanager": "^4.0.0-alpha.20",
|
|
45
|
+
"@jupyterlab/settingregistry": "^4.0.0-alpha.20",
|
|
46
|
+
"@jupyterlab/translation": "^4.0.0-alpha.20",
|
|
47
|
+
"@jupyterlab/ui-components": "^4.0.0-alpha.35"
|
|
47
48
|
},
|
|
48
49
|
"devDependencies": {
|
|
49
50
|
"rimraf": "~3.0.0",
|
|
50
|
-
"typedoc": "~0.
|
|
51
|
-
"typescript": "~
|
|
51
|
+
"typedoc": "~0.23.25",
|
|
52
|
+
"typescript": "~5.0.0-beta"
|
|
52
53
|
},
|
|
53
54
|
"publishConfig": {
|
|
54
55
|
"access": "public"
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
// Copyright (c) Jupyter Development Team.
|
|
2
|
+
// Distributed under the terms of the Modified BSD License.
|
|
3
|
+
/**
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
* @module extensionmanager-extension
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
ILayoutRestorer,
|
|
10
|
+
JupyterFrontEnd,
|
|
11
|
+
JupyterFrontEndPlugin
|
|
12
|
+
} from '@jupyterlab/application';
|
|
13
|
+
import { Dialog, ICommandPalette, showDialog } from '@jupyterlab/apputils';
|
|
14
|
+
import { ExtensionsPanel, ListModel } from '@jupyterlab/extensionmanager';
|
|
15
|
+
import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
16
|
+
import {
|
|
17
|
+
ITranslator,
|
|
18
|
+
nullTranslator,
|
|
19
|
+
TranslationBundle
|
|
20
|
+
} from '@jupyterlab/translation';
|
|
21
|
+
import { extensionIcon } from '@jupyterlab/ui-components';
|
|
22
|
+
|
|
23
|
+
const PLUGIN_ID = '@jupyterlab/extensionmanager-extension:plugin';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* IDs of the commands added by this extension.
|
|
27
|
+
*/
|
|
28
|
+
namespace CommandIDs {
|
|
29
|
+
export const showPanel = 'extensionmanager:show-panel';
|
|
30
|
+
export const toggle = 'extensionmanager:toggle';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The extension manager plugin.
|
|
35
|
+
*/
|
|
36
|
+
const plugin: JupyterFrontEndPlugin<void> = {
|
|
37
|
+
id: PLUGIN_ID,
|
|
38
|
+
autoStart: true,
|
|
39
|
+
requires: [ISettingRegistry],
|
|
40
|
+
optional: [ITranslator, ILayoutRestorer, ICommandPalette],
|
|
41
|
+
activate: async (
|
|
42
|
+
app: JupyterFrontEnd,
|
|
43
|
+
registry: ISettingRegistry,
|
|
44
|
+
translator: ITranslator | null,
|
|
45
|
+
restorer: ILayoutRestorer | null,
|
|
46
|
+
palette: ICommandPalette | null
|
|
47
|
+
) => {
|
|
48
|
+
const { commands, shell, serviceManager } = app;
|
|
49
|
+
translator = translator ?? nullTranslator;
|
|
50
|
+
const trans = translator.load('jupyterlab');
|
|
51
|
+
|
|
52
|
+
const model = new ListModel(serviceManager, translator);
|
|
53
|
+
|
|
54
|
+
const createView = () => {
|
|
55
|
+
const v = new ExtensionsPanel({ model, translator: translator! });
|
|
56
|
+
v.id = 'extensionmanager.main-view';
|
|
57
|
+
v.title.icon = extensionIcon;
|
|
58
|
+
v.title.caption = trans.__('Extension Manager');
|
|
59
|
+
v.node.setAttribute('role', 'region');
|
|
60
|
+
v.node.setAttribute('aria-label', trans.__('Extension Manager section'));
|
|
61
|
+
if (restorer) {
|
|
62
|
+
restorer.add(v, v.id);
|
|
63
|
+
}
|
|
64
|
+
shell.add(v, 'left', { rank: 1000 });
|
|
65
|
+
|
|
66
|
+
return v;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Create a view by default, so it can be restored when loading the workspace.
|
|
70
|
+
let view: ExtensionsPanel | null = createView();
|
|
71
|
+
|
|
72
|
+
// If the extension is enabled or disabled,
|
|
73
|
+
// add or remove it from the left area.
|
|
74
|
+
Promise.all([app.restored, registry.load(PLUGIN_ID)])
|
|
75
|
+
.then(([, settings]) => {
|
|
76
|
+
model.isDisclaimed = settings.get('disclaimed').composite as boolean;
|
|
77
|
+
model.isEnabled = settings.get('enabled').composite as boolean;
|
|
78
|
+
model.stateChanged.connect(() => {
|
|
79
|
+
if (
|
|
80
|
+
model.isDisclaimed !==
|
|
81
|
+
(settings.get('disclaimed').composite as boolean)
|
|
82
|
+
) {
|
|
83
|
+
settings.set('disclaimed', model.isDisclaimed).catch(reason => {
|
|
84
|
+
console.error(`Failed to set setting 'disclaimed'.\n${reason}`);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
if (
|
|
88
|
+
model.isEnabled !== (settings.get('enabled').composite as boolean)
|
|
89
|
+
) {
|
|
90
|
+
settings.set('enabled', model.isEnabled).catch(reason => {
|
|
91
|
+
console.error(`Failed to set setting 'enabled'.\n${reason}`);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (model.isEnabled) {
|
|
97
|
+
view = view ?? createView();
|
|
98
|
+
} else {
|
|
99
|
+
view?.dispose();
|
|
100
|
+
view = null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
settings.changed.connect(async () => {
|
|
104
|
+
model.isDisclaimed = settings.get('disclaimed').composite as boolean;
|
|
105
|
+
model.isEnabled = settings.get('enabled').composite as boolean;
|
|
106
|
+
app.commands.notifyCommandChanged(CommandIDs.toggle);
|
|
107
|
+
|
|
108
|
+
if (model.isEnabled) {
|
|
109
|
+
if (view === null || !view.isAttached) {
|
|
110
|
+
const accepted = await Private.showWarning(trans);
|
|
111
|
+
if (!accepted) {
|
|
112
|
+
void settings.set('enabled', false);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
view = view ?? createView();
|
|
117
|
+
} else {
|
|
118
|
+
view?.dispose();
|
|
119
|
+
view = null;
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
})
|
|
123
|
+
.catch(reason => {
|
|
124
|
+
console.error(
|
|
125
|
+
`Something went wrong when reading the settings.\n${reason}`
|
|
126
|
+
);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
commands.addCommand(CommandIDs.showPanel, {
|
|
130
|
+
label: trans.__('Extension Manager'),
|
|
131
|
+
execute: () => {
|
|
132
|
+
if (view) {
|
|
133
|
+
shell.activateById(view.id);
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
isVisible: () => model.isEnabled
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
commands.addCommand(CommandIDs.toggle, {
|
|
140
|
+
label: trans.__('Enable Extension Manager'),
|
|
141
|
+
execute: () => {
|
|
142
|
+
if (registry) {
|
|
143
|
+
void registry.set(plugin.id, 'enabled', !model.isEnabled);
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
isToggled: () => model.isEnabled
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
if (palette) {
|
|
150
|
+
palette.addItem({
|
|
151
|
+
command: CommandIDs.toggle,
|
|
152
|
+
category: trans.__('Extension Manager')
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Export the plugin as the default.
|
|
160
|
+
*/
|
|
161
|
+
export default plugin;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* A namespace for module-private functions.
|
|
165
|
+
*/
|
|
166
|
+
namespace Private {
|
|
167
|
+
/**
|
|
168
|
+
* Show a warning dialog about extension security.
|
|
169
|
+
*
|
|
170
|
+
* @returns whether the user accepted the dialog.
|
|
171
|
+
*/
|
|
172
|
+
export async function showWarning(
|
|
173
|
+
trans: TranslationBundle
|
|
174
|
+
): Promise<boolean> {
|
|
175
|
+
const result = await showDialog({
|
|
176
|
+
title: trans.__('Enable Extension Manager?'),
|
|
177
|
+
body: trans.__(`Thanks for trying out JupyterLab's extension manager.
|
|
178
|
+
The JupyterLab development team is excited to have a robust
|
|
179
|
+
third-party extension community.
|
|
180
|
+
However, we cannot vouch for every extension,
|
|
181
|
+
and some may introduce security risks.
|
|
182
|
+
Do you want to continue?`),
|
|
183
|
+
buttons: [
|
|
184
|
+
Dialog.cancelButton({ label: trans.__('Disable') }),
|
|
185
|
+
Dialog.warnButton({ label: trans.__('Enable') })
|
|
186
|
+
]
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
return result.button.accept;
|
|
190
|
+
}
|
|
191
|
+
}
|