pageconfig.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import { JSONExt } from '@phosphor/coreutils';
  4. import minimist from 'minimist';
  5. import { PathExt } from './path';
  6. import { URLExt } from './url';
  7. /**
  8. * Declare stubs for the node variables.
  9. */
  10. declare var process: any;
  11. declare var require: any;
  12. /**
  13. * The namespace for Page Config functions.
  14. */
  15. export namespace PageConfig {
  16. /**
  17. * The tree URL construction options.
  18. */
  19. export interface ITreeOptions {
  20. /**
  21. * If `true`, the tree URL will include the current workspace, if any.
  22. */
  23. workspace?: boolean;
  24. }
  25. /**
  26. * Get global configuration data for the Jupyter application.
  27. *
  28. * @param name - The name of the configuration option.
  29. *
  30. * @returns The config value or an empty string if not found.
  31. *
  32. * #### Notes
  33. * All values are treated as strings.
  34. * For browser based applications, it is assumed that the page HTML
  35. * includes a script tag with the id `jupyter-config-data` containing the
  36. * configuration as valid JSON. In order to support the classic Notebook,
  37. * we fall back on checking for `body` data of the given `name`.
  38. *
  39. * For node applications, it is assumed that the process was launched
  40. * with a `--jupyter-config-data` option pointing to a JSON settings
  41. * file.
  42. */
  43. export function getOption(name: string): string {
  44. if (configData) {
  45. return configData[name] || Private.getBodyData(name);
  46. }
  47. configData = Object.create(null);
  48. let found = false;
  49. // Use script tag if available.
  50. if (typeof document !== 'undefined') {
  51. const el = document.getElementById('jupyter-config-data');
  52. if (el) {
  53. configData = JSON.parse(el.textContent || '') as {
  54. [key: string]: string;
  55. };
  56. found = true;
  57. }
  58. }
  59. // Otherwise use CLI if given.
  60. if (!found && typeof process !== 'undefined') {
  61. try {
  62. const cli = minimist(process.argv.slice(2));
  63. const path: any = require('path');
  64. let fullPath = '';
  65. if ('jupyter-config-data' in cli) {
  66. fullPath = path.resolve(cli['jupyter-config-data']);
  67. } else if ('JUPYTER_CONFIG_DATA' in process.env) {
  68. fullPath = path.resolve(process.env['JUPYTER_CONFIG_DATA']);
  69. }
  70. if (fullPath) {
  71. /* tslint:disable */
  72. // Force Webpack to ignore this require.
  73. configData = eval('require')(fullPath) as { [key: string]: string };
  74. /* tslint:enable */
  75. }
  76. } catch (e) {
  77. console.error(e);
  78. }
  79. }
  80. if (!JSONExt.isObject(configData)) {
  81. configData = Object.create(null);
  82. } else {
  83. for (let key in configData) {
  84. // Quote characters are escaped, unescape them.
  85. configData[key] = String(configData[key])
  86. .split(''')
  87. .join('"');
  88. }
  89. }
  90. return configData![name] || Private.getBodyData(name);
  91. }
  92. /**
  93. * Set global configuration data for the Jupyter application.
  94. *
  95. * @param name - The name of the configuration option.
  96. * @param value - The value to set the option to.
  97. *
  98. * @returns The last config value or an empty string if it doesn't exist.
  99. */
  100. export function setOption(name: string, value: string): string {
  101. const last = getOption(name);
  102. configData![name] = value;
  103. return last;
  104. }
  105. /**
  106. * Get the base url for a Jupyter application, or the base url of the page.
  107. */
  108. export function getBaseUrl(): string {
  109. return URLExt.normalize(getOption('baseUrl') || '/');
  110. }
  111. /**
  112. * Get the tree url for a JupyterLab application.
  113. *
  114. * @param options - The tree URL construction options.
  115. */
  116. export function getTreeUrl(options: ITreeOptions = {}): string {
  117. const base = getBaseUrl();
  118. const tree = getOption('treeUrl');
  119. const defaultWorkspace = getOption('defaultWorkspace');
  120. const workspaces = getOption('workspacesUrl');
  121. const workspace = getOption('workspace');
  122. return !!options.workspace && workspace && workspace !== defaultWorkspace
  123. ? URLExt.join(base, workspaces, PathExt.basename(workspace), 'tree')
  124. : URLExt.join(base, tree);
  125. }
  126. /**
  127. * Get the base websocket url for a Jupyter application, or an empty string.
  128. */
  129. export function getWsUrl(baseUrl?: string): string {
  130. let wsUrl = getOption('wsUrl');
  131. if (!wsUrl) {
  132. baseUrl = baseUrl ? URLExt.normalize(baseUrl) : getBaseUrl();
  133. if (baseUrl.indexOf('http') !== 0) {
  134. return '';
  135. }
  136. wsUrl = 'ws' + baseUrl.slice(4);
  137. }
  138. return URLExt.normalize(wsUrl);
  139. }
  140. /**
  141. * Get the authorization token for a Jupyter application.
  142. */
  143. export function getToken(): string {
  144. return getOption('token') || Private.getBodyData('jupyterApiToken');
  145. }
  146. /**
  147. * Get the Notebook version info [major, minor, patch].
  148. */
  149. export function getNotebookVersion(): [number, number, number] {
  150. const notebookVersion = getOption('notebookVersion');
  151. if (notebookVersion === '') {
  152. return [0, 0, 0];
  153. }
  154. return JSON.parse(notebookVersion);
  155. }
  156. /**
  157. * Private page config data for the Jupyter application.
  158. */
  159. let configData: { [key: string]: string } | null = null;
  160. }
  161. /**
  162. * A namespace for module private data.
  163. */
  164. namespace Private {
  165. /**
  166. * Get a url-encoded item from `body.data` and decode it
  167. * We should never have any encoded URLs anywhere else in code
  168. * until we are building an actual request.
  169. */
  170. export function getBodyData(key: string): string {
  171. if (typeof document === 'undefined' || !document.body) {
  172. return '';
  173. }
  174. let val = document.body.dataset[key];
  175. if (typeof val === 'undefined') {
  176. return '';
  177. }
  178. return decodeURIComponent(val);
  179. }
  180. }