UNPKG

@jupyterlab/application

Version:
184 lines (166 loc) 5.82 kB
// Copyright (c) Jupyter Development Team. // Distributed under the terms of the Modified BSD License. import { IWidgetTracker, WidgetTracker } from '@jupyterlab/apputils'; import { DocumentRegistry, MimeDocument, MimeDocumentFactory } from '@jupyterlab/docregistry'; import { IRenderMimeRegistry } from '@jupyterlab/rendermime'; import { IRenderMime } from '@jupyterlab/rendermime-interfaces'; import { ITranslator } from '@jupyterlab/translation'; import { LabIcon } from '@jupyterlab/ui-components'; import { Token } from '@lumino/coreutils'; import { AttachedProperty } from '@lumino/properties'; import { JupyterFrontEnd, JupyterFrontEndPlugin } from './index'; import { ILayoutRestorer } from './layoutrestorer'; /** * A class that tracks mime documents. */ export interface IMimeDocumentTracker extends IWidgetTracker<MimeDocument> {} /** * The mime document tracker token. */ export const IMimeDocumentTracker = new Token<IMimeDocumentTracker>( '@jupyterlab/application:IMimeDocumentTracker', 'A widget tracker for documents rendered using a mime renderer extension. Use this if you want to list and interact with documents rendered by such extensions.' ); /** * Create rendermime plugins for rendermime extension modules. */ export function createRendermimePlugins( extensions: IRenderMime.IExtensionModule[] ): JupyterFrontEndPlugin<void | IMimeDocumentTracker, any, any>[] { const plugins: JupyterFrontEndPlugin<void | IMimeDocumentTracker>[] = []; const namespace = 'application-mimedocuments'; const tracker = new WidgetTracker<MimeDocument>({ namespace }); extensions.forEach(mod => { let data = mod.default; // Handle CommonJS exports. if (!mod.hasOwnProperty('__esModule')) { data = mod as any; } if (!Array.isArray(data)) { data = [data] as ReadonlyArray<IRenderMime.IExtension>; } (data as ReadonlyArray<IRenderMime.IExtension>).forEach(item => { plugins.push(createRendermimePlugin(tracker, item)); }); }); // Also add a meta-plugin handling state restoration // and exposing the mime document widget tracker. plugins.push({ id: '@jupyterlab/application:mimedocument', description: 'Provides a mime document widget tracker.', optional: [ILayoutRestorer], provides: IMimeDocumentTracker, autoStart: true, activate: (app: JupyterFrontEnd, restorer: ILayoutRestorer | null) => { if (restorer) { void restorer.restore(tracker, { command: 'docmanager:open', args: widget => ({ path: widget.context.path, factory: Private.factoryNameProperty.get(widget) }), name: widget => `${widget.context.path}:${Private.factoryNameProperty.get(widget)}` }); } return tracker; } }); return plugins; } /** * Create rendermime plugins for rendermime extension modules. */ export function createRendermimePlugin( tracker: WidgetTracker<MimeDocument>, item: IRenderMime.IExtension ): JupyterFrontEndPlugin<void> { return { id: item.id, description: item.description, requires: [IRenderMimeRegistry, ITranslator], autoStart: true, activate: ( app: JupyterFrontEnd, rendermime: IRenderMimeRegistry, translator: ITranslator ) => { // Add the mime renderer. if (item.rank !== undefined) { rendermime.addFactory(item.rendererFactory, item.rank); } else { rendermime.addFactory(item.rendererFactory); } // Handle the widget factory. if (!item.documentWidgetFactoryOptions) { return; } const registry = app.docRegistry; let options: IRenderMime.IDocumentWidgetFactoryOptions[] = []; if (Array.isArray(item.documentWidgetFactoryOptions)) { options = item.documentWidgetFactoryOptions; } else { options = [ item.documentWidgetFactoryOptions as IRenderMime.IDocumentWidgetFactoryOptions ]; } if (item.fileTypes) { item.fileTypes.forEach(ft => { if (ft.icon) { // upconvert the contents of the icon field to a proper LabIcon ft = { ...ft, icon: LabIcon.resolve({ icon: ft.icon }) }; } app.docRegistry.addFileType(ft as DocumentRegistry.IFileType); }); } options.forEach(option => { const toolbarFactory = option.toolbarFactory ? (w: MimeDocument) => option.toolbarFactory!(w.content.renderer) : undefined; const factory = new MimeDocumentFactory({ renderTimeout: item.renderTimeout, dataType: item.dataType, rendermime, modelName: option.modelName, name: option.name, primaryFileType: registry.getFileType(option.primaryFileType), fileTypes: option.fileTypes, defaultFor: option.defaultFor, defaultRendered: option.defaultRendered, toolbarFactory, translator, factory: item.rendererFactory }); registry.addWidgetFactory(factory); factory.widgetCreated.connect((sender, widget) => { Private.factoryNameProperty.set(widget, factory.name); // Notify the widget tracker if restore data needs to update. widget.context.pathChanged.connect(() => { void tracker.save(widget); }); void tracker.add(widget); }); }); } }; } /** * Private namespace for the module. */ namespace Private { /** * An attached property for keeping the factory name * that was used to create a mimedocument. */ export const factoryNameProperty = new AttachedProperty< MimeDocument, string | undefined >({ name: 'factoryName', create: () => undefined }); }