@jupyterlab/application
Version:
JupyterLab - Application
184 lines (166 loc) • 5.82 kB
text/typescript
// 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
});
}