@jupyterlab/toc-extension 6.0.0-alpha.19 → 6.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/lib/index.d.ts +2 -2
- package/package.json +10 -9
- package/src/index.ts +340 -0
package/lib/index.d.ts
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* @packageDocumentation
|
|
3
3
|
* @module toc-extension
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
5
|
+
import { JupyterFrontEndPlugin } from '@jupyterlab/application';
|
|
6
6
|
import { ITableOfContentsRegistry, ITableOfContentsTracker } from '@jupyterlab/toc';
|
|
7
7
|
/**
|
|
8
8
|
* Exports.
|
|
9
9
|
*/
|
|
10
|
-
declare const _default: (JupyterFrontEndPlugin<ITableOfContentsRegistry
|
|
10
|
+
declare const _default: (JupyterFrontEndPlugin<ITableOfContentsRegistry> | JupyterFrontEndPlugin<ITableOfContentsTracker>)[];
|
|
11
11
|
export default _default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupyterlab/toc-extension",
|
|
3
|
-
"version": "6.0.0-alpha.
|
|
3
|
+
"version": "6.0.0-alpha.20",
|
|
4
4
|
"description": "JupyterLab - Table of Contents widget extension",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jupyter",
|
|
@@ -31,7 +31,8 @@
|
|
|
31
31
|
"lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
|
|
32
32
|
"schema/*.json",
|
|
33
33
|
"style/**/*.{css,eot,gif,html,jpg,json,png,svg,woff2,ttf}",
|
|
34
|
-
"style/index.js"
|
|
34
|
+
"style/index.js",
|
|
35
|
+
"src/**/*.{ts,tsx}"
|
|
35
36
|
],
|
|
36
37
|
"scripts": {
|
|
37
38
|
"build": "tsc -b",
|
|
@@ -40,16 +41,16 @@
|
|
|
40
41
|
"watch": "tsc -b --watch"
|
|
41
42
|
},
|
|
42
43
|
"dependencies": {
|
|
43
|
-
"@jupyterlab/application": "^4.0.0-alpha.
|
|
44
|
-
"@jupyterlab/settingregistry": "^4.0.0-alpha.
|
|
45
|
-
"@jupyterlab/toc": "^6.0.0-alpha.
|
|
46
|
-
"@jupyterlab/translation": "^4.0.0-alpha.
|
|
47
|
-
"@jupyterlab/ui-components": "^4.0.0-alpha.
|
|
44
|
+
"@jupyterlab/application": "^4.0.0-alpha.20",
|
|
45
|
+
"@jupyterlab/settingregistry": "^4.0.0-alpha.20",
|
|
46
|
+
"@jupyterlab/toc": "^6.0.0-alpha.20",
|
|
47
|
+
"@jupyterlab/translation": "^4.0.0-alpha.20",
|
|
48
|
+
"@jupyterlab/ui-components": "^4.0.0-alpha.35"
|
|
48
49
|
},
|
|
49
50
|
"devDependencies": {
|
|
50
51
|
"rimraf": "~3.0.0",
|
|
51
|
-
"typedoc": "~0.
|
|
52
|
-
"typescript": "~
|
|
52
|
+
"typedoc": "~0.23.25",
|
|
53
|
+
"typescript": "~5.0.0-beta"
|
|
53
54
|
},
|
|
54
55
|
"publishConfig": {
|
|
55
56
|
"access": "public"
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
// Copyright (c) Jupyter Development Team.
|
|
2
|
+
// Distributed under the terms of the Modified BSD License.
|
|
3
|
+
/**
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
* @module toc-extension
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
ILabShell,
|
|
10
|
+
ILayoutRestorer,
|
|
11
|
+
JupyterFrontEnd,
|
|
12
|
+
JupyterFrontEndPlugin
|
|
13
|
+
} from '@jupyterlab/application';
|
|
14
|
+
import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
15
|
+
import {
|
|
16
|
+
ITableOfContentsRegistry,
|
|
17
|
+
ITableOfContentsTracker,
|
|
18
|
+
TableOfContents,
|
|
19
|
+
TableOfContentsPanel,
|
|
20
|
+
TableOfContentsRegistry,
|
|
21
|
+
TableOfContentsTracker
|
|
22
|
+
} from '@jupyterlab/toc';
|
|
23
|
+
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
|
|
24
|
+
import {
|
|
25
|
+
collapseAllIcon,
|
|
26
|
+
CommandToolbarButton,
|
|
27
|
+
ellipsesIcon,
|
|
28
|
+
expandAllIcon,
|
|
29
|
+
MenuSvg,
|
|
30
|
+
numberingIcon,
|
|
31
|
+
tocIcon,
|
|
32
|
+
Toolbar,
|
|
33
|
+
ToolbarButton
|
|
34
|
+
} from '@jupyterlab/ui-components';
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A namespace for command IDs of table of contents plugin.
|
|
38
|
+
*/
|
|
39
|
+
namespace CommandIDs {
|
|
40
|
+
export const displayNumbering = 'toc:display-numbering';
|
|
41
|
+
|
|
42
|
+
export const displayH1Numbering = 'toc:display-h1-numbering';
|
|
43
|
+
|
|
44
|
+
export const displayOutputNumbering = 'toc:display-outputs-numbering';
|
|
45
|
+
|
|
46
|
+
export const showPanel = 'toc:show-panel';
|
|
47
|
+
|
|
48
|
+
export const toggleCollapse = 'toc:toggle-collapse';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Activates the ToC extension.
|
|
53
|
+
*
|
|
54
|
+
* @private
|
|
55
|
+
* @param app - Jupyter application
|
|
56
|
+
* @param tocRegistry - Table of contents registry
|
|
57
|
+
* @param translator - translator
|
|
58
|
+
* @param restorer - application layout restorer
|
|
59
|
+
* @param labShell - Jupyter lab shell
|
|
60
|
+
* @param settingRegistry - setting registry
|
|
61
|
+
* @returns table of contents registry
|
|
62
|
+
*/
|
|
63
|
+
async function activateTOC(
|
|
64
|
+
app: JupyterFrontEnd,
|
|
65
|
+
tocRegistry: ITableOfContentsRegistry,
|
|
66
|
+
translator?: ITranslator | null,
|
|
67
|
+
restorer?: ILayoutRestorer | null,
|
|
68
|
+
labShell?: ILabShell | null,
|
|
69
|
+
settingRegistry?: ISettingRegistry | null
|
|
70
|
+
): Promise<ITableOfContentsTracker> {
|
|
71
|
+
const trans = (translator ?? nullTranslator).load('jupyterlab');
|
|
72
|
+
let configuration = { ...TableOfContents.defaultConfig };
|
|
73
|
+
|
|
74
|
+
// Create the ToC widget:
|
|
75
|
+
const toc = new TableOfContentsPanel(translator ?? undefined);
|
|
76
|
+
toc.title.icon = tocIcon;
|
|
77
|
+
toc.title.caption = trans.__('Table of Contents');
|
|
78
|
+
toc.id = 'table-of-contents';
|
|
79
|
+
toc.node.setAttribute('role', 'region');
|
|
80
|
+
toc.node.setAttribute('aria-label', trans.__('Table of Contents section'));
|
|
81
|
+
|
|
82
|
+
app.commands.addCommand(CommandIDs.displayH1Numbering, {
|
|
83
|
+
label: trans.__('Show first-level heading number'),
|
|
84
|
+
execute: () => {
|
|
85
|
+
if (toc.model) {
|
|
86
|
+
toc.model.setConfiguration({
|
|
87
|
+
numberingH1: !toc.model.configuration.numberingH1
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
isEnabled: () =>
|
|
92
|
+
toc.model?.supportedOptions.includes('numberingH1') ?? false,
|
|
93
|
+
isToggled: () => toc.model?.configuration.numberingH1 ?? false
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
app.commands.addCommand(CommandIDs.displayNumbering, {
|
|
97
|
+
label: trans.__('Show heading number in the document'),
|
|
98
|
+
icon: args => (args.toolbar ? numberingIcon : undefined),
|
|
99
|
+
execute: () => {
|
|
100
|
+
if (toc.model) {
|
|
101
|
+
toc.model.setConfiguration({
|
|
102
|
+
numberHeaders: !toc.model.configuration.numberHeaders
|
|
103
|
+
});
|
|
104
|
+
app.commands.notifyCommandChanged(CommandIDs.displayNumbering);
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
isEnabled: () =>
|
|
108
|
+
toc.model?.supportedOptions.includes('numberHeaders') ?? false,
|
|
109
|
+
isToggled: () => toc.model?.configuration.numberHeaders ?? false
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
app.commands.addCommand(CommandIDs.displayOutputNumbering, {
|
|
113
|
+
label: trans.__('Show output headings'),
|
|
114
|
+
execute: () => {
|
|
115
|
+
if (toc.model) {
|
|
116
|
+
toc.model.setConfiguration({
|
|
117
|
+
includeOutput: !toc.model.configuration.includeOutput
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
isEnabled: () =>
|
|
122
|
+
toc.model?.supportedOptions.includes('includeOutput') ?? false,
|
|
123
|
+
isToggled: () => toc.model?.configuration.includeOutput ?? false
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
app.commands.addCommand(CommandIDs.showPanel, {
|
|
127
|
+
label: trans.__('Table of Contents'),
|
|
128
|
+
execute: () => {
|
|
129
|
+
app.shell.activateById(toc.id);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
function someExpanded(model: TableOfContents.Model): boolean {
|
|
134
|
+
return model.headings.some(h => !(h.collapsed ?? false));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
app.commands.addCommand(CommandIDs.toggleCollapse, {
|
|
138
|
+
label: () =>
|
|
139
|
+
toc.model && !someExpanded(toc.model)
|
|
140
|
+
? trans.__('Expand All Headings')
|
|
141
|
+
: trans.__('Collapse All Headings'),
|
|
142
|
+
icon: args =>
|
|
143
|
+
args.toolbar
|
|
144
|
+
? toc.model && !someExpanded(toc.model)
|
|
145
|
+
? expandAllIcon
|
|
146
|
+
: collapseAllIcon
|
|
147
|
+
: undefined,
|
|
148
|
+
execute: () => {
|
|
149
|
+
if (toc.model) {
|
|
150
|
+
if (someExpanded(toc.model)) {
|
|
151
|
+
toc.model.toggleCollapse({ collapsed: true });
|
|
152
|
+
} else {
|
|
153
|
+
toc.model.toggleCollapse({ collapsed: false });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
isEnabled: () => toc.model !== null
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const tracker = new TableOfContentsTracker();
|
|
161
|
+
|
|
162
|
+
if (restorer) {
|
|
163
|
+
// Add the ToC widget to the application restorer:
|
|
164
|
+
restorer.add(toc, '@jupyterlab/toc:plugin');
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Attempt to load plugin settings:
|
|
168
|
+
let settings: ISettingRegistry.ISettings | undefined;
|
|
169
|
+
if (settingRegistry) {
|
|
170
|
+
try {
|
|
171
|
+
settings = await settingRegistry.load(registry.id);
|
|
172
|
+
const updateSettings = (plugin: ISettingRegistry.ISettings) => {
|
|
173
|
+
const composite = plugin.composite;
|
|
174
|
+
for (const key of [...Object.keys(configuration)]) {
|
|
175
|
+
const value = composite[key] as any;
|
|
176
|
+
if (value !== undefined) {
|
|
177
|
+
configuration[key] = value;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (labShell) {
|
|
182
|
+
for (const widget of labShell.widgets('main')) {
|
|
183
|
+
const model = tracker.get(widget);
|
|
184
|
+
if (model) {
|
|
185
|
+
model.setConfiguration(configuration);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
} else {
|
|
189
|
+
if (app.shell.currentWidget) {
|
|
190
|
+
const model = tracker.get(app.shell.currentWidget);
|
|
191
|
+
if (model) {
|
|
192
|
+
model.setConfiguration(configuration);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
if (settings) {
|
|
198
|
+
settings.changed.connect(updateSettings);
|
|
199
|
+
updateSettings(settings);
|
|
200
|
+
}
|
|
201
|
+
} catch (error) {
|
|
202
|
+
console.error(
|
|
203
|
+
`Failed to load settings for the Table of Contents extension.\n\n${error}`
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Set up the panel toolbar
|
|
209
|
+
const numbering = new CommandToolbarButton({
|
|
210
|
+
commands: app.commands,
|
|
211
|
+
id: CommandIDs.displayNumbering,
|
|
212
|
+
args: {
|
|
213
|
+
toolbar: true
|
|
214
|
+
},
|
|
215
|
+
label: ''
|
|
216
|
+
});
|
|
217
|
+
numbering.addClass('jp-toc-numberingButton');
|
|
218
|
+
toc.toolbar.addItem('display-numbering', numbering);
|
|
219
|
+
|
|
220
|
+
toc.toolbar.addItem('spacer', Toolbar.createSpacerItem());
|
|
221
|
+
|
|
222
|
+
toc.toolbar.addItem(
|
|
223
|
+
'collapse-all',
|
|
224
|
+
new CommandToolbarButton({
|
|
225
|
+
commands: app.commands,
|
|
226
|
+
id: CommandIDs.toggleCollapse,
|
|
227
|
+
args: {
|
|
228
|
+
toolbar: true
|
|
229
|
+
},
|
|
230
|
+
label: ''
|
|
231
|
+
})
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
const toolbarMenu = new MenuSvg({ commands: app.commands });
|
|
235
|
+
toolbarMenu.addItem({
|
|
236
|
+
command: CommandIDs.displayH1Numbering
|
|
237
|
+
});
|
|
238
|
+
toolbarMenu.addItem({
|
|
239
|
+
command: CommandIDs.displayOutputNumbering
|
|
240
|
+
});
|
|
241
|
+
const menuButton = new ToolbarButton({
|
|
242
|
+
tooltip: trans.__('More actions…'),
|
|
243
|
+
icon: ellipsesIcon,
|
|
244
|
+
actualOnClick: true,
|
|
245
|
+
onClick: () => {
|
|
246
|
+
const bbox = menuButton.node.getBoundingClientRect();
|
|
247
|
+
toolbarMenu.open(bbox.x, bbox.bottom);
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
toc.toolbar.addItem('submenu', menuButton);
|
|
251
|
+
|
|
252
|
+
// Add the ToC to the left area:
|
|
253
|
+
app.shell.add(toc, 'left', { rank: 400, type: 'Table of Contents' });
|
|
254
|
+
|
|
255
|
+
// Update the ToC when the active widget changes:
|
|
256
|
+
if (labShell) {
|
|
257
|
+
labShell.currentChanged.connect(onConnect);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Connect to current widget
|
|
261
|
+
void app.restored.then(() => {
|
|
262
|
+
onConnect();
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
return tracker;
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Callback invoked when the active widget changes.
|
|
269
|
+
*
|
|
270
|
+
* @private
|
|
271
|
+
*/
|
|
272
|
+
function onConnect() {
|
|
273
|
+
let widget = app.shell.currentWidget;
|
|
274
|
+
if (!widget) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
let model = tracker.get(widget);
|
|
278
|
+
if (!model) {
|
|
279
|
+
model = tocRegistry.getModel(widget, configuration) ?? null;
|
|
280
|
+
if (model) {
|
|
281
|
+
tracker.add(widget, model);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
widget.disposed.connect(() => {
|
|
285
|
+
model?.dispose();
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (toc.model) {
|
|
290
|
+
toc.model.headingsChanged.disconnect(onCollapseChange);
|
|
291
|
+
toc.model.collapseChanged.disconnect(onCollapseChange);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
toc.model = model;
|
|
295
|
+
if (toc.model) {
|
|
296
|
+
toc.model.headingsChanged.connect(onCollapseChange);
|
|
297
|
+
toc.model.collapseChanged.connect(onCollapseChange);
|
|
298
|
+
}
|
|
299
|
+
setToolbarButtonsState();
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function setToolbarButtonsState() {
|
|
303
|
+
app.commands.notifyCommandChanged(CommandIDs.displayNumbering);
|
|
304
|
+
app.commands.notifyCommandChanged(CommandIDs.toggleCollapse);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function onCollapseChange() {
|
|
308
|
+
app.commands.notifyCommandChanged(CommandIDs.toggleCollapse);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Table of contents registry plugin.
|
|
314
|
+
*/
|
|
315
|
+
const registry: JupyterFrontEndPlugin<ITableOfContentsRegistry> = {
|
|
316
|
+
id: '@jupyterlab/toc-extension:registry',
|
|
317
|
+
autoStart: true,
|
|
318
|
+
provides: ITableOfContentsRegistry,
|
|
319
|
+
activate: (): ITableOfContentsRegistry => {
|
|
320
|
+
// Create the ToC registry
|
|
321
|
+
return new TableOfContentsRegistry();
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Table of contents tracker plugin.
|
|
327
|
+
*/
|
|
328
|
+
const tracker: JupyterFrontEndPlugin<ITableOfContentsTracker> = {
|
|
329
|
+
id: '@jupyterlab/toc-extension:tracker',
|
|
330
|
+
autoStart: true,
|
|
331
|
+
provides: ITableOfContentsTracker,
|
|
332
|
+
requires: [ITableOfContentsRegistry],
|
|
333
|
+
optional: [ITranslator, ILayoutRestorer, ILabShell, ISettingRegistry],
|
|
334
|
+
activate: activateTOC
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Exports.
|
|
339
|
+
*/
|
|
340
|
+
export default [registry, tracker];
|