index.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*-----------------------------------------------------------------------------
  2. | Copyright (c) Jupyter Development Team.
  3. | Distributed under the terms of the Modified BSD License.
  4. |----------------------------------------------------------------------------*/
  5. import { PageConfig } from '@jupyterlab/coreutils';
  6. // This must be after the public path is set.
  7. // This cannot be extracted because the public path is dynamic.
  8. require('./imports.css');
  9. async function createModule(scope, module) {
  10. try {
  11. const factory = await window._JUPYTERLAB[scope].get(module);
  12. return factory();
  13. } catch(e) {
  14. console.warn(`Failed to create module: package: ${scope}; module: ${module}`);
  15. throw e;
  16. }
  17. }
  18. /**
  19. * The main entry point for the application.
  20. */
  21. export async function main() {
  22. var JupyterLab = require('@jupyterlab/application').JupyterLab;
  23. var disabled = [];
  24. var deferred = [];
  25. var ignorePlugins = [];
  26. var register = [];
  27. const federatedExtensionPromises = [];
  28. const federatedMimeExtensionPromises = [];
  29. const federatedStylePromises = [];
  30. // Start initializing the federated extensions
  31. const extensions = JSON.parse(
  32. PageConfig.getOption('federated_extensions')
  33. );
  34. extensions.forEach(data => {
  35. if (data.extension) {
  36. federatedExtensionPromises.push(createModule(data.name, data.extension));
  37. }
  38. if (data.mimeExtension) {
  39. federatedMimeExtensionPromises.push(createModule(data.name, data.mimeExtension));
  40. }
  41. if (data.style) {
  42. federatedStylePromises.push(createModule(data.name, data.style));
  43. }
  44. });
  45. /**
  46. * Iterate over active plugins in an extension.
  47. *
  48. * #### Notes
  49. * This also populates the disabled, deferred, and ignored arrays.
  50. */
  51. function* activePlugins(extension) {
  52. // Handle commonjs or es2015 modules
  53. let exports;
  54. if (extension.hasOwnProperty('__esModule')) {
  55. exports = extension.default;
  56. } else {
  57. // CommonJS exports.
  58. exports = extension;
  59. }
  60. let plugins = Array.isArray(exports) ? exports : [exports];
  61. for (let plugin of plugins) {
  62. if (PageConfig.Extension.isDisabled(plugin.id)) {
  63. disabled.push(plugin.id);
  64. continue;
  65. }
  66. if (PageConfig.Extension.isDeferred(plugin.id)) {
  67. deferred.push(plugin.id);
  68. ignorePlugins.push(plugin.id);
  69. }
  70. yield plugin;
  71. }
  72. }
  73. // Handle the registered mime extensions.
  74. const mimeExtensions = [];
  75. {{#each jupyterlab_mime_extensions}}
  76. try {
  77. let ext = require('{{@key}}{{#if this}}/{{this}}{{/if}}');
  78. for (let plugin of activePlugins(ext)) {
  79. mimeExtensions.push(plugin);
  80. }
  81. } catch (e) {
  82. console.error(e);
  83. }
  84. {{/each}}
  85. // Add the federated mime extensions.
  86. const federatedMimeExtensions = await Promise.allSettled(federatedMimeExtensionPromises);
  87. federatedMimeExtensions.forEach(p => {
  88. if (p.status === "fulfilled") {
  89. for (let plugin of activePlugins(p.value)) {
  90. mimeExtensions.push(plugin);
  91. }
  92. } else {
  93. console.error(p.reason);
  94. }
  95. });
  96. // Handled the registered standard extensions.
  97. {{#each jupyterlab_extensions}}
  98. try {
  99. let ext = require('{{@key}}{{#if this}}/{{this}}{{/if}}');
  100. for (let plugin of activePlugins(ext)) {
  101. register.push(plugin);
  102. }
  103. } catch (e) {
  104. console.error(e);
  105. }
  106. {{/each}}
  107. // Add the federated extensions.
  108. const federatedExtensions = await Promise.allSettled(federatedExtensionPromises);
  109. federatedExtensions.forEach(p => {
  110. if (p.status === "fulfilled") {
  111. for (let plugin of activePlugins(p.value)) {
  112. register.push(plugin);
  113. }
  114. } else {
  115. console.error(p.reason);
  116. }
  117. });
  118. // Load all federated component styles and log errors for any that do not
  119. (await Promise.allSettled(federatedStylePromises)).filter(({status}) => status === "rejected").forEach(({reason}) => {
  120. console.error(reason);
  121. });
  122. const lab = new JupyterLab({
  123. mimeExtensions,
  124. disabled: {
  125. matches: disabled,
  126. patterns: PageConfig.Extension.disabled
  127. .map(function (val) { return val.raw; })
  128. },
  129. deferred: {
  130. matches: deferred,
  131. patterns: PageConfig.Extension.deferred
  132. .map(function (val) { return val.raw; })
  133. },
  134. });
  135. register.forEach(function(item) { lab.registerPluginModule(item); });
  136. lab.start({ ignorePlugins });
  137. // Expose global app instance when in dev mode or when toggled explicitly.
  138. var exposeAppInBrowser = (PageConfig.getOption('exposeAppInBrowser') || '').toLowerCase() === 'true';
  139. var devMode = (PageConfig.getOption('devMode') || '').toLowerCase() === 'true';
  140. if (exposeAppInBrowser || devMode) {
  141. window.jupyterlab = lab;
  142. }
  143. // Handle a browser test.
  144. var browserTest = PageConfig.getOption('browserTest');
  145. if (browserTest.toLowerCase() === 'true') {
  146. var el = document.createElement('div');
  147. el.id = 'browserTest';
  148. document.body.appendChild(el);
  149. el.textContent = '[]';
  150. el.style.display = 'none';
  151. var errors = [];
  152. var reported = false;
  153. var timeout = 25000;
  154. var report = function() {
  155. if (reported) {
  156. return;
  157. }
  158. reported = true;
  159. el.className = 'completed';
  160. }
  161. window.onerror = function(msg, url, line, col, error) {
  162. errors.push(String(error));
  163. el.textContent = JSON.stringify(errors)
  164. };
  165. console.error = function(message) {
  166. errors.push(String(message));
  167. el.textContent = JSON.stringify(errors)
  168. };
  169. lab.restored
  170. .then(function() { report(errors); })
  171. .catch(function(reason) { report([`RestoreError: ${reason.message}`]); });
  172. // Handle failures to restore after the timeout has elapsed.
  173. window.setTimeout(function() { report(errors); }, timeout);
  174. }
  175. }