index.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /*-----------------------------------------------------------------------------
  2. | Copyright (c) Jupyter Development Team.
  3. | Distributed under the terms of the Modified BSD License.
  4. |----------------------------------------------------------------------------*/
  5. import {
  6. PageConfig
  7. } from '@jupyterlab/coreutils';
  8. // eslint-disable-next-line no-undef
  9. __webpack_public_path__ = PageConfig.getOption('fullStaticUrl') + '/';
  10. // This must be after the public path is set.
  11. // This cannot be extracted because the public path is dynamic.
  12. require('./imports.css');
  13. function loadScript(url) {
  14. return new Promise((resolve, reject) => {
  15. const newScript = document.createElement('script');
  16. newScript.onerror = reject;
  17. newScript.onload = resolve;
  18. newScript.async = true;
  19. document.head.appendChild(newScript);
  20. newScript.src = url;
  21. });
  22. }
  23. async function loadComponent(url, scope, module) {
  24. await loadScript(url);
  25. // From MIT-licensed https://github.com/module-federation/module-federation-examples/blob/af043acd6be1718ee195b2511adf6011fba4233c/advanced-api/dynamic-remotes/app1/src/App.js#L6-L12
  26. await __webpack_init_sharing__('default');
  27. const container = window._JUPYTERLAB[scope];
  28. // Initialize the container, it may provide shared modules and may need ours
  29. await container.init(__webpack_share_scopes__.default);
  30. const factory = await window._JUPYTERLAB[scope].get(module);
  31. const Module = factory();
  32. return Module;
  33. }
  34. /**
  35. * The main entry point for the application.
  36. */
  37. async function main() {
  38. var JupyterLab = require('@jupyterlab/application').JupyterLab;
  39. var disabled = [];
  40. var deferred = [];
  41. var ignorePlugins = [];
  42. var register = [];
  43. // This is all the data needed to load and activate plugins. This should be
  44. // gathered by the server and put onto the initial page template.
  45. const extension_data = JSON.parse(
  46. PageConfig.getOption('dynamic_extensions')
  47. );
  48. const mime_extension_data = JSON.parse(
  49. PageConfig.getOption('dynamic_mime_extensions')
  50. );
  51. // Get dynamic plugins
  52. const dynamicPromises = extension_data.map(data =>
  53. loadComponent(
  54. data.path,
  55. data.name,
  56. data.module
  57. )
  58. );
  59. const dynamicPlugins = await Promise.all(dynamicPromises);
  60. const dynamicMimePromises = mime_extension_data.map(data =>
  61. loadComponent(
  62. data.path,
  63. data.name,
  64. data.module
  65. )
  66. );
  67. const dynamicMimePlugins = await Promise.all(dynamicMimePromises);
  68. // Handle the registered mime extensions.
  69. var mimeExtensions = [];
  70. var extension;
  71. var extMod;
  72. var plugins = [];
  73. {{#each jupyterlab_mime_extensions}}
  74. try {
  75. extMod = require('{{@key}}/{{this}}');
  76. extension = extMod.default;
  77. // Handle CommonJS exports.
  78. if (!extMod.hasOwnProperty('__esModule')) {
  79. extension = extMod;
  80. }
  81. plugins = Array.isArray(extension) ? extension : [extension];
  82. plugins.forEach(function(plugin) {
  83. if (PageConfig.Extension.isDeferred(plugin.id)) {
  84. deferred.push(plugin.id);
  85. ignorePlugins.push(plugin.id);
  86. }
  87. if (PageConfig.Extension.isDisabled(plugin.id)) {
  88. disabled.push(plugin.id);
  89. return;
  90. }
  91. mimeExtensions.push(plugin);
  92. });
  93. } catch (e) {
  94. console.error(e);
  95. }
  96. {{/each}}
  97. // Add the dyanmic mime extensions.
  98. dynamicMimePlugins.forEach(plugin => { mimeExtensions.push(plugin); });
  99. // Handled the registered standard extensions.
  100. {{#each jupyterlab_extensions}}
  101. try {
  102. extMod = require('{{@key}}/{{this}}');
  103. extension = extMod.default;
  104. // Handle CommonJS exports.
  105. if (!extMod.hasOwnProperty('__esModule')) {
  106. extension = extMod;
  107. }
  108. plugins = Array.isArray(extension) ? extension : [extension];
  109. plugins.forEach(function(plugin) {
  110. if (PageConfig.Extension.isDeferred(plugin.id)) {
  111. deferred.push(plugin.id);
  112. ignorePlugins.push(plugin.id);
  113. }
  114. if (PageConfig.Extension.isDisabled(plugin.id)) {
  115. disabled.push(plugin.id);
  116. return;
  117. }
  118. register.push(plugin);
  119. });
  120. } catch (e) {
  121. console.error(e);
  122. }
  123. {{/each}}
  124. // Add the dynamic extensions.
  125. dynamicPlugins.forEach(plugin => { register.push(plugin) });
  126. var lab = new JupyterLab({
  127. mimeExtensions: mimeExtensions,
  128. disabled: {
  129. matches: disabled,
  130. patterns: PageConfig.Extension.disabled
  131. .map(function (val) { return val.raw; })
  132. },
  133. deferred: {
  134. matches: deferred,
  135. patterns: PageConfig.Extension.deferred
  136. .map(function (val) { return val.raw; })
  137. },
  138. });
  139. register.forEach(function(item) { lab.registerPluginModule(item); });
  140. lab.start({ ignorePlugins: ignorePlugins });
  141. // Expose global app instance when in dev mode or when toggled explicitly.
  142. var exposeAppInBrowser = (PageConfig.getOption('exposeAppInBrowser') || '').toLowerCase() === 'true';
  143. var devMode = (PageConfig.getOption('devMode') || '').toLowerCase() === 'true';
  144. if (exposeAppInBrowser || devMode) {
  145. window.jupyterlab = lab;
  146. }
  147. // Handle a browser test.
  148. var browserTest = PageConfig.getOption('browserTest');
  149. if (browserTest.toLowerCase() === 'true') {
  150. var el = document.createElement('div');
  151. el.id = 'browserTest';
  152. document.body.appendChild(el);
  153. el.textContent = '[]';
  154. el.style.display = 'none';
  155. var errors = [];
  156. var reported = false;
  157. var timeout = 25000;
  158. var report = function() {
  159. if (reported) {
  160. return;
  161. }
  162. reported = true;
  163. el.className = 'completed';
  164. }
  165. window.onerror = function(msg, url, line, col, error) {
  166. errors.push(String(error));
  167. el.textContent = JSON.stringify(errors)
  168. };
  169. console.error = function(message) {
  170. errors.push(String(message));
  171. el.textContent = JSON.stringify(errors)
  172. };
  173. lab.restored
  174. .then(function() { report(errors); })
  175. .catch(function(reason) { report([`RestoreError: ${reason.message}`]); });
  176. // Handle failures to restore after the timeout has elapsed.
  177. window.setTimeout(function() { report(errors); }, timeout);
  178. }
  179. }
  180. window.addEventListener('load', main);