index.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import {
  4. Widget
  5. } from '@phosphor/widgets';
  6. import {
  7. IRenderMime
  8. } from '@jupyterlab/rendermime-interfaces';
  9. /**
  10. * Import vega-embed in this manner due to how it is exported.
  11. */
  12. import embed = require('vega-embed');
  13. /**
  14. * The CSS class to add to the Vega and Vega-Lite widget.
  15. */
  16. const VEGA_COMMON_CLASS = 'jp-RenderedVegaCommon';
  17. /**
  18. * The CSS class to add to the Vega.
  19. */
  20. const VEGA_CLASS = 'jp-RenderedVega';
  21. /**
  22. * The CSS class to add to the Vega-Lite.
  23. */
  24. const VEGALITE_CLASS = 'jp-RenderedVegaLite';
  25. /**
  26. * The MIME type for Vega.
  27. *
  28. * #### Notes
  29. * The version of this follows the major version of Vega.
  30. */
  31. export
  32. const VEGA_MIME_TYPE = 'application/vnd.vega.v2+json';
  33. /**
  34. * The MIME type for Vega-Lite.
  35. *
  36. * #### Notes
  37. * The version of this follows the major version of Vega-Lite.
  38. */
  39. export
  40. const VEGALITE_MIME_TYPE = 'application/vnd.vegalite.v1+json';
  41. /**
  42. * A widget for rendering Vega or Vega-Lite data, for usage with rendermime.
  43. */
  44. export
  45. class RenderedVega extends Widget implements IRenderMime.IRenderer {
  46. /**
  47. * Create a new widget for rendering Vega/Vega-Lite.
  48. */
  49. constructor(options: IRenderMime.IRendererOptions) {
  50. super();
  51. this.addClass(VEGA_COMMON_CLASS);
  52. // Handle things related to the MIME type.
  53. let mimeType = this._mimeType = options.mimeType;
  54. if (mimeType === VEGA_MIME_TYPE) {
  55. this.addClass(VEGA_CLASS);
  56. this._mode = 'vega';
  57. } else {
  58. this.addClass(VEGALITE_CLASS);
  59. this._mode = 'vega-lite';
  60. }
  61. }
  62. /**
  63. * Render Vega/Vega-Lite into this widget's node.
  64. */
  65. renderModel(model: IRenderMime.IMimeModel): Promise<void> {
  66. let data = model.data[this._mimeType];
  67. let embedSpec = {
  68. mode: this._mode,
  69. spec: data
  70. };
  71. return new Promise<void>((resolve, reject) => {
  72. embed(this.node, embedSpec, (error: any, result: any): any => {
  73. resolve(undefined);
  74. // This is copied out for now as there is a bug in JupyterLab
  75. // that triggers and infinite rendering loop when this is done.
  76. // let imageData = result.view.toImageURL();
  77. // imageData = imageData.split(',')[1];
  78. // this._injector('image/png', imageData);
  79. });
  80. });
  81. }
  82. private _mimeType: string;
  83. private _mode: string;
  84. }
  85. /**
  86. * A mime renderer factory for vega data.
  87. */
  88. export
  89. const rendererFactory: IRenderMime.IRendererFactory = {
  90. safe: true,
  91. mimeTypes: [VEGA_MIME_TYPE, VEGALITE_MIME_TYPE],
  92. createRenderer: options => new RenderedVega(options)
  93. };
  94. const extensions: IRenderMime.IExtension | IRenderMime.IExtension[] = [
  95. // Vega
  96. {
  97. mimeType: VEGA_MIME_TYPE,
  98. rendererFactory,
  99. rank: 0,
  100. dataType: 'json',
  101. documentWidgetFactoryOptions: {
  102. name: 'Vega',
  103. fileExtensions: ['.vg', '.vg.json', 'json'],
  104. defaultFor: ['.vg', '.vg.json'],
  105. readOnly: true
  106. }
  107. },
  108. // Vega-Lite
  109. {
  110. mimeType: VEGALITE_MIME_TYPE,
  111. rendererFactory,
  112. rank: 0,
  113. dataType: 'json',
  114. documentWidgetFactoryOptions: {
  115. name: 'Vega-Lite',
  116. fileExtensions: ['.vl', '.vl.json', 'json'],
  117. defaultFor: ['.vl', '.vl.json'],
  118. readOnly: true
  119. }
  120. }
  121. ];
  122. export default extensions;