Repository navigation
Expand file tree
/
Copy pathbootstrap.js
More file actions
180 lines (152 loc) · 5.69 KB
/
Copy pathbootstrap.js
File metadata and controls
180 lines (152 loc) · 5.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
// We copy some of the pageconfig parsing logic in @jupyterlab/coreutils
// below, since this must run before any other files are loaded (including
// @jupyterlab/coreutils).
/**
* Get global configuration data for the Jupyter application.
*
* @param name - The name of the configuration option.
*
* @returns The config value or an empty string if not found.
*
* #### Notes
* All values are treated as strings. For browser based applications, it is
* assumed that the page HTML includes a script tag with the id
* `jupyter-config-data` containing the configuration as valid JSON.
*/
let _CONFIG_DATA = null;
function getOption(name) {
if (_CONFIG_DATA === null) {
let configData = {};
// Use script tag if available.
if (typeof document !== 'undefined' && document) {
const el = document.getElementById('jupyter-config-data');
if (el) {
configData = JSON.parse(el.textContent || '{}');
}
}
_CONFIG_DATA = configData;
}
return _CONFIG_DATA[name] || '';
}
/**
* Hide the loading indicator once the app is fully loaded
*/
function hideAppLoadingIndicator() {
const indicator = document.getElementById('jupyterlite-loading-indicator');
if (indicator) {
indicator.classList.add('hidden');
indicator.addEventListener('animationend', () => {
indicator.remove();
// Remove theme classes after the loading indicator is removed
document.body.classList.remove('jp-mod-dark', 'jp-mod-light');
}, { once: true });
}
}
/**
* Apply theme to loading indicator based on saved settings in IndexedDB
*/
async function applyThemeToAppLoadingIndicator() {
const indicator = document.getElementById('jupyterlite-loading-indicator');
if (!indicator) {
return;
}
// Hide the indicator by default
indicator.classList.add('hidden');
const showLoadingIndicator = getOption('showLoadingIndicator');
// Only show the indicator if explicitly set to true
if (showLoadingIndicator === true) {
indicator.classList.remove('hidden');
} else {
return;
}
try {
const baseUrl = getOption('baseUrl');
const defaultStorageName = `JupyterLite Storage - ${baseUrl}`;
const storageName = getOption('settingsStorageName') || defaultStorageName;
const localforageModule = await import('localforage');
const localforage = localforageModule.default;
const settingsDB = localforage.createInstance({
name: storageName,
storeName: 'settings'
});
const key = '@jupyterlab/apputils-extension:themes';
const settings = await settingsDB.getItem(key);
let isDarkTheme = false;
if (settings) {
// Use regex to find "theme": "name of theme" pattern, since the
// settings are stored as a raw string
const themeRegex = /"theme"\s*:\s*"([^"]+)"/i;
const matches = settings.match(themeRegex);
if (matches && matches[1]) {
const themeName = matches[1].toLowerCase();
isDarkTheme =
themeName.includes('dark') ||
themeName.includes('night') ||
themeName.includes('black');
}
}
document.body.classList.remove('jp-mod-dark', 'jp-mod-light');
if (isDarkTheme) {
document.body.classList.add('jp-mod-dark');
} else {
document.body.classList.add('jp-mod-light');
}
} catch (e) {
console.warn('Could not apply theme to loading indicator:', e);
// Fallback to light theme on error
document.body.classList.remove('jp-mod-dark');
document.body.classList.add('jp-mod-light');
}
}
// eslint-disable-next-line no-undef
__webpack_public_path__ = getOption('fullStaticUrl') + '/';
function loadScript(url) {
return new Promise((resolve, reject) => {
const newScript = document.createElement('script');
newScript.onerror = reject;
newScript.onload = resolve;
newScript.async = true;
document.head.appendChild(newScript);
newScript.src = url;
});
}
async function loadComponent(url, scope) {
await loadScript(url);
// From https://webpack.js.org/concepts/module-federation/#dynamic-remote-containers
await __webpack_init_sharing__('default');
const container = window._JUPYTERLAB[scope];
// Initialize the container, it may provide shared modules and may need ours
await container.init(__webpack_share_scopes__.default);
}
void (async function bootstrap() {
await applyThemeToAppLoadingIndicator();
// This is all the data needed to load and activate plugins. This should be
// gathered by the server and put onto the initial page template.
const extension_data = getOption('federated_extensions');
// We first load all federated components so that the shared module
// deduplication can run and figure out which shared modules from all
// components should be actually used. We have to do this before importing
// and using the module that actually uses these components so that all
// dependencies are initialized.
let labExtensionUrl = getOption('fullLabextensionsUrl');
const extensions = await Promise.allSettled(
extension_data.map(async data => {
await loadComponent(`${labExtensionUrl}/${data.name}/${data.load}`, data.name);
})
);
extensions.forEach(p => {
if (p.status === 'rejected') {
// There was an error loading the component
console.error(p.reason);
}
});
// Now that all federated containers are initialized with the main
// container, we can import the main function.
let main = (await import('./index.js')).main;
await main();
hideAppLoadingIndicator();
})();