jupyter-specta 0.3.5 → 0.4.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/README.md +2 -0
- package/lib/document/plugin.d.ts +2 -1
- package/lib/document/plugin.js +28 -5
- package/lib/extension_plugins.d.ts +1 -1
- package/lib/extension_plugins.js +3 -2
- package/lib/token.d.ts +2 -0
- package/lib/token.js +1 -0
- package/lib/tool.d.ts +3 -2
- package/lib/tool.js +41 -24
- package/lib/topbar/widget.js +0 -1
- package/package.json +2 -2
- package/style/base.css +1 -1
package/README.md
CHANGED
|
@@ -52,6 +52,8 @@ jupyter lite build
|
|
|
52
52
|
|
|
53
53
|
Then serve the contents of the output directory (by default `./_output`) using any static file server. You can access the `Specta` app at the `/specta/` path.
|
|
54
54
|
|
|
55
|
+
If you want to disable specta loading spinner, you can set the environment variable `SPECTA_NO_LOADING_SCREEN` to `1`before calling jupyterlite build command
|
|
56
|
+
|
|
55
57
|
## Specta Configuration
|
|
56
58
|
|
|
57
59
|
### Available layouts
|
package/lib/document/plugin.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ILabShell, JupyterFrontEndPlugin } from '@jupyterlab/application';
|
|
2
2
|
import { IWidgetTracker } from '@jupyterlab/apputils';
|
|
3
|
-
import { ISpectaShell } from '../token';
|
|
3
|
+
import { ISpectaShell, ISpectaUrlFactory } from '../token';
|
|
4
4
|
export declare const spectaDocument: JupyterFrontEndPlugin<IWidgetTracker, ISpectaShell>;
|
|
5
|
+
export declare const spectaUrlFactory: JupyterFrontEndPlugin<ISpectaUrlFactory>;
|
|
5
6
|
export declare const spectaOpener: JupyterFrontEndPlugin<void, ILabShell>;
|
package/lib/document/plugin.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { IThemeManager, WidgetTracker } from '@jupyterlab/apputils';
|
|
2
2
|
import { IEditorServices } from '@jupyterlab/codeeditor';
|
|
3
|
-
import { PathExt } from '@jupyterlab/coreutils';
|
|
3
|
+
import { PageConfig, PathExt, URLExt } from '@jupyterlab/coreutils';
|
|
4
4
|
import { IDocumentManager } from '@jupyterlab/docmanager';
|
|
5
5
|
import { IDefaultFileBrowser } from '@jupyterlab/filebrowser';
|
|
6
6
|
import { INotebookTracker, NotebookPanel } from '@jupyterlab/notebook';
|
|
7
7
|
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
|
|
8
8
|
import { IKernelSpecManager } from '@jupyterlab/services';
|
|
9
9
|
import { Widget } from '@lumino/widgets';
|
|
10
|
-
import { ISpectaDocTracker, ISpectaLayoutRegistry } from '../token';
|
|
10
|
+
import { ISpectaDocTracker, ISpectaLayoutRegistry, ISpectaUrlFactoryToken } from '../token';
|
|
11
11
|
import { configLabLayout, createFileBrowser, hideAppLoadingIndicator, isSpectaApp, readSpectaConfig, registerDocumentFactory } from '../tool';
|
|
12
12
|
const activate = (app, rendermime, tracker, editorServices, contentFactory, spectaLayoutRegistry, themeManager) => {
|
|
13
13
|
const namespace = 'specta';
|
|
@@ -39,6 +39,29 @@ export const spectaDocument = {
|
|
|
39
39
|
activate,
|
|
40
40
|
provides: ISpectaDocTracker
|
|
41
41
|
};
|
|
42
|
+
export const spectaUrlFactory = {
|
|
43
|
+
id: 'specta/application-extension:urlFactory',
|
|
44
|
+
autoStart: true,
|
|
45
|
+
provides: ISpectaUrlFactoryToken,
|
|
46
|
+
activate() {
|
|
47
|
+
const urlFactory = (path) => {
|
|
48
|
+
const baseUrl = PageConfig.getBaseUrl();
|
|
49
|
+
let appUrl = PageConfig.getOption('appUrl');
|
|
50
|
+
if (!appUrl.endsWith('/')) {
|
|
51
|
+
appUrl = `${appUrl}/`;
|
|
52
|
+
}
|
|
53
|
+
const url = new URL(URLExt.join(baseUrl, appUrl));
|
|
54
|
+
url.searchParams.set('path', path);
|
|
55
|
+
const queries = PageConfig.getOption('query').split('&').filter(Boolean);
|
|
56
|
+
queries.forEach(query => {
|
|
57
|
+
const [key, value] = query.split('=');
|
|
58
|
+
url.searchParams.set(key, value);
|
|
59
|
+
});
|
|
60
|
+
return url.toString();
|
|
61
|
+
};
|
|
62
|
+
return urlFactory;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
42
65
|
export const spectaOpener = {
|
|
43
66
|
id: 'specta/application-extension:opener',
|
|
44
67
|
autoStart: true,
|
|
@@ -48,7 +71,8 @@ export const spectaOpener = {
|
|
|
48
71
|
ISpectaDocTracker,
|
|
49
72
|
IKernelSpecManager
|
|
50
73
|
],
|
|
51
|
-
|
|
74
|
+
optional: [ISpectaUrlFactoryToken],
|
|
75
|
+
activate: async (app, docManager, defaultBrowser, tracker, kernelSpecManager, urlFactory) => {
|
|
52
76
|
const urlParams = new URLSearchParams(window.location.search);
|
|
53
77
|
if (!isSpectaApp()) {
|
|
54
78
|
// Not a specta app
|
|
@@ -61,7 +85,6 @@ export const spectaOpener = {
|
|
|
61
85
|
if (PathExt.extname(path) === '.ipynb') {
|
|
62
86
|
const commands = app.commands;
|
|
63
87
|
const spectaConfig = readSpectaConfig({});
|
|
64
|
-
console.log('spectaConfig', spectaConfig);
|
|
65
88
|
await configLabLayout({
|
|
66
89
|
config: spectaConfig.labConfig,
|
|
67
90
|
labShell,
|
|
@@ -79,7 +102,7 @@ export const spectaOpener = {
|
|
|
79
102
|
// Specta app
|
|
80
103
|
const path = urlParams.get('path');
|
|
81
104
|
if (!path) {
|
|
82
|
-
const browser = createFileBrowser({ defaultBrowser });
|
|
105
|
+
const browser = createFileBrowser({ defaultBrowser, urlFactory });
|
|
83
106
|
app.shell.add(browser, 'main', { rank: 100 });
|
|
84
107
|
hideAppLoadingIndicator();
|
|
85
108
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export * from './tool';
|
|
2
2
|
export * from './token';
|
|
3
|
-
declare const _default: (import("@jupyterlab/application").JupyterFrontEndPlugin<import("@jupyterlab/apputils").IWidgetTracker<import("@lumino/widgets").Widget>, import("./token").ISpectaShell> | import("@jupyterlab/application").JupyterFrontEndPlugin<void, import("@jupyterlab/application").ILabShell> | import("@jupyterlab/application").JupyterFrontEndPlugin<import("./token").ISpectaLayoutRegistry> | import("@jupyterlab/application").JupyterFrontEndPlugin<void, import("./token").ISpectaShell>)[];
|
|
3
|
+
declare const _default: (import("@jupyterlab/application").JupyterFrontEndPlugin<import("@jupyterlab/apputils").IWidgetTracker<import("@lumino/widgets").Widget>, import("./token").ISpectaShell> | import("@jupyterlab/application").JupyterFrontEndPlugin<import("./token").ISpectaUrlFactory> | import("@jupyterlab/application").JupyterFrontEndPlugin<void, import("@jupyterlab/application").ILabShell> | import("@jupyterlab/application").JupyterFrontEndPlugin<import("./token").ISpectaLayoutRegistry> | import("@jupyterlab/application").JupyterFrontEndPlugin<void, import("./token").ISpectaShell>)[];
|
|
4
4
|
export default _default;
|
package/lib/extension_plugins.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { spectaDocument, spectaOpener } from './document/plugin';
|
|
1
|
+
import { spectaDocument, spectaOpener, spectaUrlFactory } from './document/plugin';
|
|
2
2
|
import { spectaLayoutRegistry } from './layout';
|
|
3
3
|
import { appMeta, cellMeta } from './metadata';
|
|
4
4
|
import { topbarPlugin } from './topbar';
|
|
@@ -10,5 +10,6 @@ export default [
|
|
|
10
10
|
spectaLayoutRegistry,
|
|
11
11
|
topbarPlugin,
|
|
12
12
|
appMeta,
|
|
13
|
-
cellMeta
|
|
13
|
+
cellMeta,
|
|
14
|
+
spectaUrlFactory
|
|
14
15
|
];
|
package/lib/token.d.ts
CHANGED
|
@@ -64,5 +64,7 @@ export interface ISpectaCellConfig {
|
|
|
64
64
|
showOutput?: boolean;
|
|
65
65
|
outputSize?: 'Small' | 'Big' | 'Full';
|
|
66
66
|
}
|
|
67
|
+
export type ISpectaUrlFactory = (path: string) => string;
|
|
67
68
|
export declare const ISpectaLayoutRegistry: Token<ISpectaLayoutRegistry>;
|
|
68
69
|
export declare const ISpectaDocTracker: Token<IWidgetTracker<Widget>>;
|
|
70
|
+
export declare const ISpectaUrlFactoryToken: Token<ISpectaUrlFactory>;
|
package/lib/token.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { Token } from '@lumino/coreutils';
|
|
2
2
|
export const ISpectaLayoutRegistry = new Token('specta:ISpectaLayoutRegistry');
|
|
3
3
|
export const ISpectaDocTracker = new Token('exampleDocTracker');
|
|
4
|
+
export const ISpectaUrlFactoryToken = new Token('specta:ISpectaUrlFactoryToken');
|
package/lib/tool.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { ICell, INotebookMetadata } from '@jupyterlab/nbformat';
|
|
|
6
6
|
import { INotebookTracker, NotebookPanel } from '@jupyterlab/notebook';
|
|
7
7
|
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
|
|
8
8
|
import { CommandRegistry } from '@lumino/commands';
|
|
9
|
-
import { ISpectaAppConfig, ISpectaCellConfig, ISpectaLayoutRegistry, ISpectaShell } from './token';
|
|
9
|
+
import { ISpectaAppConfig, ISpectaCellConfig, ISpectaLayoutRegistry, ISpectaShell, ISpectaUrlFactory } from './token';
|
|
10
10
|
export declare function registerDocumentFactory(options: {
|
|
11
11
|
factoryName: string;
|
|
12
12
|
app: JupyterFrontEnd<ISpectaShell>;
|
|
@@ -20,9 +20,10 @@ export declare function registerDocumentFactory(options: {
|
|
|
20
20
|
}): void;
|
|
21
21
|
export declare function createFileBrowser(options: {
|
|
22
22
|
defaultBrowser: IDefaultFileBrowser;
|
|
23
|
+
urlFactory: ISpectaUrlFactory | null;
|
|
23
24
|
}): any;
|
|
24
25
|
export declare function hideAppLoadingIndicator(): void;
|
|
25
|
-
export declare function mergeObjects(
|
|
26
|
+
export declare function mergeObjects(lowerPriority: Record<string, any>, higherPriority: Record<string, any>): Record<string, any>;
|
|
26
27
|
export declare function getSpectaAssetUrl(path: string): string;
|
|
27
28
|
export declare function isSpectaApp(): boolean;
|
|
28
29
|
export declare function readSpectaConfig({ nbMetadata, nbPath }: {
|
package/lib/tool.js
CHANGED
|
@@ -42,27 +42,31 @@ export function registerDocumentFactory(options) {
|
|
|
42
42
|
});
|
|
43
43
|
}
|
|
44
44
|
export function createFileBrowser(options) {
|
|
45
|
-
const { defaultBrowser } = options;
|
|
45
|
+
const { defaultBrowser, urlFactory } = options;
|
|
46
46
|
const browser = defaultBrowser;
|
|
47
47
|
browser.singleClickNavigation = true;
|
|
48
48
|
browser.showFileCheckboxes = false;
|
|
49
49
|
browser.showLastModifiedColumn = false;
|
|
50
50
|
browser.addClass('specta-file-browser');
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
appUrl =
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
51
|
+
const urlFactoryFn = urlFactory
|
|
52
|
+
? urlFactory
|
|
53
|
+
: (path) => {
|
|
54
|
+
const baseUrl = PageConfig.getBaseUrl();
|
|
55
|
+
let appUrl = PageConfig.getOption('appUrl');
|
|
56
|
+
if (!appUrl.endsWith('/')) {
|
|
57
|
+
appUrl = `${appUrl}/`;
|
|
58
|
+
}
|
|
59
|
+
const url = new URL(URLExt.join(baseUrl, appUrl));
|
|
60
|
+
url.searchParams.set('path', path);
|
|
61
|
+
const queries = PageConfig.getOption('query')
|
|
62
|
+
.split('&')
|
|
63
|
+
.filter(Boolean);
|
|
64
|
+
queries.forEach(query => {
|
|
65
|
+
const [key, value] = query.split('=');
|
|
66
|
+
url.searchParams.set(key, value);
|
|
67
|
+
});
|
|
68
|
+
return url.toString();
|
|
69
|
+
};
|
|
66
70
|
const oldHandler = browser.listing.handleOpen.bind(browser.listing);
|
|
67
71
|
browser.listing.handleOpen = (item) => {
|
|
68
72
|
if (item.type === 'directory') {
|
|
@@ -70,7 +74,7 @@ export function createFileBrowser(options) {
|
|
|
70
74
|
return;
|
|
71
75
|
}
|
|
72
76
|
else {
|
|
73
|
-
window.open(
|
|
77
|
+
window.open(urlFactoryFn(item.path), '_blank');
|
|
74
78
|
}
|
|
75
79
|
};
|
|
76
80
|
return browser;
|
|
@@ -87,18 +91,31 @@ export function hideAppLoadingIndicator() {
|
|
|
87
91
|
}, 1000);
|
|
88
92
|
}
|
|
89
93
|
}
|
|
90
|
-
export function mergeObjects(
|
|
91
|
-
const result = {};
|
|
92
|
-
for (const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
export function mergeObjects(lowerPriority, higherPriority) {
|
|
95
|
+
const result = Object.assign({}, lowerPriority);
|
|
96
|
+
for (const key of Object.keys(higherPriority)) {
|
|
97
|
+
const highVal = higherPriority[key];
|
|
98
|
+
const lowVal = lowerPriority[key];
|
|
99
|
+
// If higher is null or undefined, keep lower if it exists
|
|
100
|
+
if (highVal === null || highVal === undefined) {
|
|
101
|
+
if (lowVal !== null && lowVal !== undefined) {
|
|
102
|
+
result[key] = lowVal;
|
|
97
103
|
}
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
// Deep merge plain objects
|
|
107
|
+
if (isPlainObject(lowVal) && isPlainObject(highVal)) {
|
|
108
|
+
result[key] = mergeObjects(lowVal, highVal);
|
|
109
|
+
continue;
|
|
98
110
|
}
|
|
111
|
+
// Otherwise, higher priority wins
|
|
112
|
+
result[key] = highVal;
|
|
99
113
|
}
|
|
100
114
|
return result;
|
|
101
115
|
}
|
|
116
|
+
function isPlainObject(value) {
|
|
117
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
118
|
+
}
|
|
102
119
|
export function getSpectaAssetUrl(path) {
|
|
103
120
|
const labExtension = PageConfig.getOption('fullLabextensionsUrl');
|
|
104
121
|
const url = URLExt.join(labExtension, 'jupyter-specta', 'static', path);
|
package/lib/topbar/widget.js
CHANGED
|
@@ -30,7 +30,6 @@ export function TopbarElement(props) {
|
|
|
30
30
|
document.addEventListener('mousedown', handleClickOutside);
|
|
31
31
|
return () => document.removeEventListener('mousedown', handleClickOutside);
|
|
32
32
|
}, []);
|
|
33
|
-
console.log('config.background ', config.background);
|
|
34
33
|
return (React.createElement("div", { className: "specta-topbar", style: { background: (_a = config.background) !== null && _a !== void 0 ? _a : 'var(--jp-layout-color1)' } },
|
|
35
34
|
React.createElement("div", { className: "specta-topbar-left" },
|
|
36
35
|
React.createElement("div", { className: "specta-topbar-icon-container" }, config.icon && React.createElement("img", { style: { height: '100%' }, src: config.icon })),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jupyter-specta",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"homepage": "https://github.com/trungleduc/specta",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"@jupyterlab/outputarea": "^4.5.0",
|
|
79
79
|
"@jupyterlab/rendermime": "^4.5.0",
|
|
80
80
|
"@jupyterlab/rendermime-extension": "^4.5.0",
|
|
81
|
-
"@jupyterlab/services": "^7.
|
|
81
|
+
"@jupyterlab/services": "^7.5.1",
|
|
82
82
|
"@jupyterlab/services-extension": "^4.5.0",
|
|
83
83
|
"@jupyterlab/settingeditor-extension": "^4.5.0",
|
|
84
84
|
"@jupyterlab/settingregistry": "^4.5.0",
|