jupyterlab-emrys
Version:
A computational environment for Jupyter. Powered by Emrys
479 lines (478 loc) • 17.8 kB
JavaScript
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
"use strict";
var phosphor_disposable_1 = require('phosphor-disposable');
/**
* The document registry.
*/
var DocumentRegistry = (function () {
function DocumentRegistry() {
this._modelFactories = Object.create(null);
this._widgetFactories = Object.create(null);
this._defaultWidgetFactory = '';
this._defaultWidgetFactories = Object.create(null);
this._widgetFactoryExtensions = Object.create(null);
this._fileTypes = [];
this._creators = [];
this._extenders = Object.create(null);
}
Object.defineProperty(DocumentRegistry.prototype, "isDisposed", {
/**
* Get whether the document registry has been disposed.
*/
get: function () {
return this._widgetFactories === null;
},
enumerable: true,
configurable: true
});
/**
* Dispose of the resources held by the document registery.
*/
DocumentRegistry.prototype.dispose = function () {
if (this.isDisposed) {
return;
}
for (var modelName in this._modelFactories) {
this._modelFactories[modelName].dispose();
}
this._modelFactories = null;
for (var widgetName in this._widgetFactories) {
this._widgetFactories[widgetName].factory.dispose();
}
this._widgetFactories = null;
this._fileTypes = null;
this._creators = null;
this._extenders = null;
};
/**
* Add a widget factory to the registry.
*
* @param factory - The factory instance to register.
*
* @param options - The options used to register the factory.
*
* @returns A disposable which will unregister the factory.
*
* #### Notes
* If a factory with the given `'displayName'` is already registered,
* a warning will be logged, and this will be a no-op.
* If `'*'` is given as a default extension, the factory will be registered
* as the global default.
* If an extension or global default is already registered, this factory
* will override the existing default.
*/
DocumentRegistry.prototype.addWidgetFactory = function (factory, options) {
var _this = this;
var name = options.displayName.toLowerCase();
if (this._widgetFactories[name]) {
console.warn("Duplicate registered factory " + name);
return new phosphor_disposable_1.DisposableDelegate(null);
}
var record = Private.createRecord(factory, options);
this._widgetFactories[name] = record;
for (var _i = 0, _a = record.defaultFor; _i < _a.length; _i++) {
var ext = _a[_i];
if (record.fileExtensions.indexOf(ext) === -1) {
continue;
}
if (ext === '*') {
this._defaultWidgetFactory = name;
}
else {
this._defaultWidgetFactories[ext] = name;
}
}
// For convenience, store a mapping of ext -> name
for (var _b = 0, _c = record.fileExtensions; _b < _c.length; _b++) {
var ext = _c[_b];
if (!this._widgetFactoryExtensions[ext]) {
this._widgetFactoryExtensions[ext] = new Set();
}
this._widgetFactoryExtensions[ext].add(name);
}
return new phosphor_disposable_1.DisposableDelegate(function () {
delete _this._widgetFactories[name];
if (_this._defaultWidgetFactory === name) {
_this._defaultWidgetFactory = '';
}
for (var _i = 0, _a = Object.keys(_this._defaultWidgetFactories); _i < _a.length; _i++) {
var ext = _a[_i];
if (_this._defaultWidgetFactories[ext] === name) {
delete _this._defaultWidgetFactories[ext];
}
}
for (var _b = 0, _c = Object.keys(_this._widgetFactoryExtensions); _b < _c.length; _b++) {
var ext = _c[_b];
_this._widgetFactoryExtensions[ext].delete(name);
if (_this._widgetFactoryExtensions[ext].size === 0) {
delete _this._widgetFactoryExtensions[ext];
}
}
});
};
/**
* Add a model factory to the registry.
*
* @param factory - The factory instance.
*
* @returns A disposable which will unregister the factory.
*
* #### Notes
* If a factory with the given `name` is already registered, or
* the given factory is already registered, a warning will be logged
* and this will be a no-op.
*/
DocumentRegistry.prototype.addModelFactory = function (factory) {
var _this = this;
var name = factory.name.toLowerCase();
if (this._modelFactories[name]) {
console.warn("Duplicate registered factory " + name);
return new phosphor_disposable_1.DisposableDelegate(null);
}
this._modelFactories[name] = factory;
return new phosphor_disposable_1.DisposableDelegate(function () {
delete _this._modelFactories[name];
});
};
/**
* Add a widget extension to the registry.
*
* @param widgetName - The name of the widget factory.
*
* @param extension - A widget extension.
*
* @returns A disposable which will unregister the extension.
*
* #### Notes
* If the extension is already registered for the given
* widget name, a warning will be logged and this will be a no-op.
*/
DocumentRegistry.prototype.addWidgetExtension = function (widgetName, extension) {
var _this = this;
widgetName = widgetName.toLowerCase();
if (!(widgetName in this._extenders)) {
this._extenders[widgetName] = [];
}
var extenders = this._extenders[widgetName];
var index = extenders.indexOf(extension);
if (index !== -1) {
console.warn("Duplicate registered extension for " + widgetName);
return new phosphor_disposable_1.DisposableDelegate(null);
}
this._extenders[widgetName].push(extension);
return new phosphor_disposable_1.DisposableDelegate(function () {
index = _this._extenders[widgetName].indexOf(extension);
_this._extenders[widgetName].splice(index, 1);
});
};
/**
* Add a file type to the document registry.
*
* @params fileType - The file type object to register.
*
* @returns A disposable which will unregister the command.
*
* #### Notes
* These are used to populate the "Create New" dialog.
* If the file type with the same name is already registered, a warning will
* be logged and this will be a no-op.
*/
DocumentRegistry.prototype.addFileType = function (fileType) {
var _this = this;
for (var _i = 0, _a = this._fileTypes; _i < _a.length; _i++) {
var fType = _a[_i];
if (fType.name.toLowerCase() === fileType.name.toLowerCase()) {
console.warn("Duplicate registered file types for " + fType.name);
return new phosphor_disposable_1.DisposableDelegate(null);
}
}
fileType.extension = Private.normalizeExtension(fileType.extension);
this._fileTypes.push(fileType);
this._fileTypes.sort(function (a, b) { return a.name.localeCompare(b.name); });
return new phosphor_disposable_1.DisposableDelegate(function () {
var index = _this._fileTypes.indexOf(fileType);
_this._fileTypes.splice(index, 1);
});
};
/**
* Add a creator to the registry.
*
* @params creator - The file creator object to register.
*
* @params after - The optional item name to insert after.
*
* @returns A disposable which will unregister the creator.
*
* #### Notes
* If a creator of the same name is already registered,
* a warning will be logged and this will be a no-op.
* If `after` is not given or not already registered, it will be moved
* to the end.
*/
DocumentRegistry.prototype.addCreator = function (creator, after) {
var _this = this;
for (var _i = 0, _a = this._creators; _i < _a.length; _i++) {
var c = _a[_i];
if (c.name.toLowerCase() === creator.name.toLowerCase()) {
console.warn("Duplicate registered file creator named " + creator.name);
return new phosphor_disposable_1.DisposableDelegate(null);
}
}
var added = false;
if (after) {
for (var _b = 0, _c = this._creators; _b < _c.length; _b++) {
var existing = _c[_b];
if (existing.name.toLowerCase() === after.toLowerCase()) {
var index = this._creators.indexOf(existing);
this._creators.splice(index, 0, creator);
added = true;
break;
}
}
}
if (!added) {
this._creators.push(creator);
}
return new phosphor_disposable_1.DisposableDelegate(function () {
var index = _this._creators.indexOf(creator);
_this._creators.splice(index, 1);
});
};
/**
* List the names of the valid registered widget factories.
*
* @param ext - An optional file extension to filter the results.
*
* @returns A new array of registered widget factory names.
*
* #### Notes
* Only the widget factories whose associated model factory have
* been registered will be returned.
* The first item in the list is considered the default. The returned list
* has widget factories in the following order:
* - extension-specific default factory
* - global default factory
* - all other extension-specific factories
* - all other global factories
*/
DocumentRegistry.prototype.listWidgetFactories = function (ext) {
var _this = this;
if (ext === void 0) { ext = '*'; }
var factories = new Set();
ext = Private.normalizeExtension(ext);
// Start with the extension-specific default factory.
if (ext.length > 1) {
if (ext in this._defaultWidgetFactories) {
factories.add(this._defaultWidgetFactories[ext]);
}
}
// Add the global default factory.
if (this._defaultWidgetFactory) {
factories.add(this._defaultWidgetFactory);
}
// Add the extension-specific factories in registration order.
if (ext.length > 1) {
if (ext in this._widgetFactoryExtensions) {
this._widgetFactoryExtensions[ext].forEach(function (n) { factories.add(n); });
}
}
// Add the rest of the global factories, in registration order.
if ('*' in this._widgetFactoryExtensions) {
this._widgetFactoryExtensions['*'].forEach(function (n) { factories.add(n); });
}
// Construct the return list, checking to make sure the corresponding
// model factories are registered.
var factoryList = [];
factories.forEach(function (name) {
if (_this._widgetFactories[name].modelName in _this._modelFactories) {
name = _this._widgetFactories[name].displayName;
factoryList.push(name);
}
});
return factoryList;
};
/**
* Return the name of the default widget factory for a given extension.
*
* @param ext - An optional file extension.
*
* @returns The default widget factory name for the extension (if given) or the global default.
*/
DocumentRegistry.prototype.defaultWidgetFactory = function (ext) {
if (ext === void 0) { ext = '*'; }
var widgets = this.listWidgetFactories(ext);
return widgets ? widgets[0] : void 0;
};
/**
* List the names of the registered model factories.
*
* @returns A new array of registered model factory names.
*/
DocumentRegistry.prototype.listModelFactories = function () {
return Object.keys(this._modelFactories);
};
/**
* Get a list of file types that have been registered.
*
* @returns A new array of registered file type objects.
*/
DocumentRegistry.prototype.listFileTypes = function () {
return this._fileTypes.slice();
};
/**
* Get an ordered list of the file creators that have been registered.
*
* @returns A new array of registered file creator objects.
*/
DocumentRegistry.prototype.listCreators = function () {
return this._creators.slice();
};
/**
* Get a file type by name.
*/
DocumentRegistry.prototype.getFileType = function (name) {
name = name.toLowerCase();
for (var i = 0; i < this._fileTypes.length; i++) {
var fileType = this._fileTypes[i];
if (fileType.name === name) {
return fileType;
}
}
};
/**
* Get a creator by name.
*/
DocumentRegistry.prototype.getCreator = function (name) {
name = name.toLowerCase();
for (var i = 0; i < this._creators.length; i++) {
var creator = this._creators[i];
if (creator.name.toLowerCase() === name) {
return creator;
}
}
};
/**
* Get a kernel preference.
*
* @param ext - The file extension.
*
* @param widgetName - The name of the widget factory.
*
* @returns A kernel preference.
*/
DocumentRegistry.prototype.getKernelPreference = function (ext, widgetName) {
ext = Private.normalizeExtension(ext);
widgetName = widgetName.toLowerCase();
var widgetFactoryEx = this._getWidgetFactoryEx(widgetName);
if (!widgetFactoryEx) {
return void 0;
}
var modelFactory = this.getModelFactoryFor(widgetName);
var language = modelFactory.preferredLanguage(ext);
return {
language: language,
preferKernel: widgetFactoryEx.preferKernel,
canStartKernel: widgetFactoryEx.canStartKernel
};
};
/**
* Get the model factory registered for a given widget factory.
*
* @param widgetName - The name of the widget factory.
*
* @returns A model factory instance.
*/
DocumentRegistry.prototype.getModelFactoryFor = function (widgetName) {
widgetName = widgetName.toLowerCase();
var wFactoryEx = this._getWidgetFactoryEx(widgetName);
if (!wFactoryEx) {
return;
}
return this._modelFactories[wFactoryEx.modelName.toLowerCase()];
};
/**
* Get a widget factory by name.
*
* @param widgetName - The name of the widget factory.
*
* @returns A widget factory instance.
*/
DocumentRegistry.prototype.getWidgetFactory = function (widgetName) {
widgetName = widgetName.toLowerCase();
var ex = this._getWidgetFactoryEx(widgetName);
return ex ? ex.factory : void 0;
};
/**
* Get the registered extensions for a given widget.
*
* @param widgetName - The name of the widget factory.
*
* @returns A new array of widget extensions.
*/
DocumentRegistry.prototype.getWidgetExtensions = function (widgetName) {
widgetName = widgetName.toLowerCase();
if (!(widgetName in this._extenders)) {
return [];
}
return this._extenders[widgetName].slice();
};
/**
* Get the appropriate widget factory by name.
*/
DocumentRegistry.prototype._getWidgetFactoryEx = function (widgetName) {
widgetName = widgetName.toLowerCase();
var options;
if (widgetName === 'default') {
options = this._widgetFactories[this._defaultWidgetFactory];
}
else {
options = this._widgetFactories[widgetName];
}
return options;
};
return DocumentRegistry;
}());
exports.DocumentRegistry = DocumentRegistry;
/**
* A private namespace for DocumentRegistry data.
*/
var Private;
(function (Private) {
/**
* Create a widget factory record.
*/
function createRecord(factory, options) {
var fileExtensions = options.fileExtensions.map(function (ext) { return normalizeExtension(ext); });
var defaultFor = options.defaultFor || [];
defaultFor = defaultFor.map(function (ext) { return normalizeExtension(ext); });
return {
factory: factory,
fileExtensions: fileExtensions,
defaultFor: defaultFor,
displayName: options.displayName,
modelName: options.modelName.toLowerCase(),
preferKernel: !!options.preferKernel,
canStartKernel: !!options.canStartKernel
};
}
Private.createRecord = createRecord;
/**
* Normalize a file extension to be of the type `'.foo'`.
*
* Adds a leading dot if not present and converts to lower case.
*/
function normalizeExtension(extension) {
if (extension === '*') {
return extension;
}
if (extension === '.*') {
return '*';
}
if (extension.indexOf('.') !== 0) {
extension = "." + extension;
}
return extension.toLowerCase();
}
Private.normalizeExtension = normalizeExtension;
})(Private || (Private = {}));