UNPKG

jupyterlab-emrys

Version:

A computational environment for Jupyter. Powered by Emrys

479 lines (478 loc) 17.8 kB
// 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 = {}));