123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955 |
- // Copyright (c) Jupyter Development Team.
- // Distributed under the terms of the Modified BSD License.
- import {
- IKernel, Contents, Kernel, Session
- } from '@jupyterlab/services';
- import {
- EmptyIterator, IIterator, each, iter
- } from 'phosphor/lib/algorithm/iteration';
- import {
- find, findIndex, indexOf
- } from 'phosphor/lib/algorithm/searching';
- import {
- Vector
- } from 'phosphor/lib/collections/vector';
- import {
- IDisposable, DisposableDelegate
- } from 'phosphor/lib/core/disposable';
- import {
- ISignal, defineSignal
- } from 'phosphor/lib/core/signaling';
- import {
- Token
- } from 'phosphor/lib/core/token';
- import {
- Widget
- } from 'phosphor/lib/ui/widget';
- import {
- IChangedArgs as IChangedArgsGeneric
- } from '../common/interfaces';
- /* tslint:disable */
- /**
- * The document registry token.
- */
- export
- const IDocumentRegistry = new Token<IDocumentRegistry>('jupyter.services.document-registry');
- /* tslint:enable */
- /**
- * The interface for a document registry.
- */
- export
- interface IDocumentRegistry extends DocumentRegistry {}
- /**
- * The document registry.
- */
- export
- class DocumentRegistry {
- /**
- * A signal emitted when the registry has changed.
- */
- readonly changed: ISignal<this, DocumentRegistry.IChangedArgs>;
- /**
- * Get whether the document registry has been disposed.
- */
- get isDisposed(): boolean {
- return this._widgetFactories === null;
- }
- /**
- * Dispose of the resources held by the document registery.
- */
- dispose(): void {
- if (this.isDisposed) {
- return;
- }
- for (let modelName in this._modelFactories) {
- this._modelFactories[modelName].dispose();
- }
- this._modelFactories = null;
- for (let widgetName in this._widgetFactories) {
- this._widgetFactories[widgetName].dispose();
- }
- this._widgetFactories = null;
- this._fileTypes.clear();
- this._creators.clear();
- for (let widgetName in this._extenders) {
- this._extenders[widgetName].clear();
- }
- }
- /**
- * Add a widget factory to the registry.
- *
- * @param factory - The factory instance to register.
- *
- * @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.
- */
- addWidgetFactory(factory: DocumentRegistry.IWidgetFactory<Widget, DocumentRegistry.IModel>): IDisposable {
- let name = factory.name.toLowerCase();
- if (this._widgetFactories[name]) {
- console.warn(`Duplicate registered factory ${name}`);
- return new DisposableDelegate(null);
- }
- this._widgetFactories[name] = factory;
- for (let ext of factory.defaultFor) {
- if (factory.fileExtensions.indexOf(ext) === -1) {
- continue;
- }
- if (ext === '*') {
- this._defaultWidgetFactory = name;
- } else {
- this._defaultWidgetFactories[ext] = name;
- }
- }
- // For convenience, store a mapping of ext -> name
- for (let ext of factory.fileExtensions) {
- if (!this._widgetFactoryExtensions[ext]) {
- this._widgetFactoryExtensions[ext] = new Vector<string>();
- }
- this._widgetFactoryExtensions[ext].pushBack(name);
- }
- this.changed.emit({
- type: 'widgetFactory',
- name,
- change: 'added'
- });
- return new DisposableDelegate(() => {
- delete this._widgetFactories[name];
- if (this._defaultWidgetFactory === name) {
- this._defaultWidgetFactory = '';
- }
- for (let ext of Object.keys(this._defaultWidgetFactories)) {
- if (this._defaultWidgetFactories[ext] === name) {
- delete this._defaultWidgetFactories[ext];
- }
- }
- for (let ext of Object.keys(this._widgetFactoryExtensions)) {
- this._widgetFactoryExtensions[ext].remove(name);
- if (this._widgetFactoryExtensions[ext].length === 0) {
- delete this._widgetFactoryExtensions[ext];
- }
- }
- this.changed.emit({
- type: 'widgetFactory',
- name,
- change: 'removed'
- });
- });
- }
- /**
- * 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.
- */
- addModelFactory(factory: DocumentRegistry.IModelFactory<DocumentRegistry.IModel>): IDisposable {
- let name = factory.name.toLowerCase();
- if (this._modelFactories[name]) {
- console.warn(`Duplicate registered factory ${name}`);
- return new DisposableDelegate(null);
- }
- this._modelFactories[name] = factory;
- this.changed.emit({
- type: 'modelFactory',
- name,
- change: 'added'
- });
- return new DisposableDelegate(() => {
- delete this._modelFactories[name];
- this.changed.emit({
- type: 'modelFactory',
- name,
- change: 'removed'
- });
- });
- }
- /**
- * 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.
- */
- addWidgetExtension(widgetName: string, extension: DocumentRegistry.IWidgetExtension<Widget, DocumentRegistry.IModel>): IDisposable {
- widgetName = widgetName.toLowerCase();
- if (!(widgetName in this._extenders)) {
- this._extenders[widgetName] = new Vector<DocumentRegistry.IWidgetExtension<Widget, DocumentRegistry.IModel>>();
- }
- let extenders = this._extenders[widgetName];
- let index = indexOf(extenders, extension);
- if (index !== -1) {
- console.warn(`Duplicate registered extension for ${widgetName}`);
- return new DisposableDelegate(null);
- }
- this._extenders[widgetName].pushBack(extension);
- this.changed.emit({
- type: 'widgetExtension',
- name: null,
- change: 'added'
- });
- return new DisposableDelegate(() => {
- this._extenders[widgetName].remove(extension);
- this.changed.emit({
- type: 'widgetExtension',
- name: null,
- change: 'removed'
- });
- });
- }
- /**
- * 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.
- */
- addFileType(fileType: DocumentRegistry.IFileType): IDisposable {
- this._fileTypes.pushBack(fileType);
- this.changed.emit({
- type: 'fileType',
- name: fileType.name,
- change: 'added'
- });
- return new DisposableDelegate(() => {
- this._fileTypes.remove(fileType);
- this.changed.emit({
- type: 'fileType',
- name: fileType.name,
- change: 'removed'
- });
- });
- }
- /**
- * Add a creator to the registry.
- *
- * @params creator - The file creator object to register.
- *
- * @returns A disposable which will unregister the creator.
- */
- addCreator(creator: DocumentRegistry.IFileCreator): IDisposable {
- let index = findIndex(this._creators, (value) => {
- return value.name.localeCompare(creator.name) > 0;
- });
- if (index !== -1) {
- this._creators.insert(index, creator);
- } else {
- this._creators.pushBack(creator);
- }
- this.changed.emit({
- type: 'fileCreator',
- name: creator.name,
- change: 'added'
- });
- return new DisposableDelegate(() => {
- this._creators.remove(creator);
- this.changed.emit({
- type: 'fileCreator',
- name: creator.name,
- change: 'removed'
- });
- });
- }
- /**
- * Get an iterator over the preferred widget factories.
- *
- * @param ext - An optional file extension to filter the results.
- *
- * @returns A new iterator of widget factories.
- *
- * #### Notes
- * Only the widget factories whose associated model factory have
- * been registered will be returned.
- * The first item is considered the default. The returned iterator
- * has widget factories in the following order:
- * - extension-specific default factory
- * - global default factory
- * - all other extension-specific factories
- * - all other global factories
- */
- preferredWidgetFactories(ext: string = '*'): IIterator<DocumentRegistry.IWidgetFactory<Widget, DocumentRegistry.IModel>> {
- let factories = new Set<string>();
- 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) {
- each(this._widgetFactoryExtensions[ext], n => {
- factories.add(n);
- });
- }
- }
- // Add the rest of the global factories, in registration order.
- if ('*' in this._widgetFactoryExtensions) {
- each(this._widgetFactoryExtensions['*'], n => {
- factories.add(n);
- });
- }
- // Construct the return list, checking to make sure the corresponding
- // model factories are registered.
- let factoryList: DocumentRegistry.IWidgetFactory<Widget, DocumentRegistry.IModel>[] = [];
- factories.forEach(name => {
- if (this._widgetFactories[name].modelName in this._modelFactories) {
- factoryList.push(this._widgetFactories[name]);
- }
- });
- return iter(factoryList);
- }
- /**
- * Create an iterator over the widget factories that have been registered.
- *
- * @returns A new iterator of widget factories.
- */
- getWidgetFactories(): IIterator<DocumentRegistry.IWidgetFactory<Widget, DocumentRegistry.IModel>> {
- let factories: DocumentRegistry.IWidgetFactory<Widget, DocumentRegistry.IModel>[] = [];
- for (let name in this._widgetFactories) {
- factories.push(this._widgetFactories[name]);
- }
- return iter(factories);
- }
- /**
- * Create an iterator over the model factories that have been registered.
- *
- * @returns A new iterator of model factories.
- */
- getModelFactories(): IIterator<DocumentRegistry.IModelFactory<DocumentRegistry.IModel>> {
- let factories: DocumentRegistry.IModelFactory<DocumentRegistry.IModel>[] = [];
- for (let name in this._modelFactories) {
- factories.push(this._modelFactories[name]);
- }
- return iter(factories);
- }
- /**
- * Create an iterator over the registered extensions for a given widget.
- *
- * @param widgetName - The name of the widget factory.
- *
- * @returns A new iterator over the widget extensions.
- */
- getWidgetExtensions(widgetName: string): IIterator<DocumentRegistry.IWidgetExtension<Widget, DocumentRegistry.IModel>> {
- widgetName = widgetName.toLowerCase();
- if (!(widgetName in this._extenders)) {
- return EmptyIterator.instance;
- }
- return this._extenders[widgetName].iter();
- }
- /**
- * Create an iterator over the file types that have been registered.
- *
- * @returns A new iterator of file types.
- */
- getFileTypes(): IIterator<DocumentRegistry.IFileType> {
- return this._fileTypes.iter();
- }
- /**
- * Create an iterator over the file creators that have been registered.
- *
- * @returns A new iterator of file creatores.
- */
- getCreators(): IIterator<DocumentRegistry.IFileCreator> {
- return this._creators.iter();
- }
- /**
- * Get a widget factory by name.
- *
- * @param widgetName - The name of the widget factory.
- *
- * @returns A widget factory instance.
- */
- getWidgetFactory(widgetName: string): DocumentRegistry.IWidgetFactory<Widget, DocumentRegistry.IModel> {
- return this._widgetFactories[widgetName.toLowerCase()];
- }
- /**
- * Get a model factory by name.
- *
- * @param name - The name of the model factory.
- *
- * @returns A model factory instance.
- */
- getModelFactory(name: string): DocumentRegistry.IModelFactory<DocumentRegistry.IModel> {
- return this._modelFactories[name.toLowerCase()];
- }
- /**
- * Get a file type by name.
- */
- getFileType(name: string): DocumentRegistry.IFileType {
- name = name.toLowerCase();
- return find(this._fileTypes, fileType => {
- return fileType.name.toLowerCase() === name;
- });
- }
- /**
- * Get a creator by name.
- */
- getCreator(name: string): DocumentRegistry.IFileCreator {
- name = name.toLowerCase();
- return find(this._creators, creator => {
- return creator.name.toLowerCase() === name;
- });
- }
- /**
- * Get a kernel preference.
- *
- * @param ext - The file extension.
- *
- * @param widgetName - The name of the widget factory.
- *
- * @returns A kernel preference.
- */
- getKernelPreference(ext: string, widgetName: string): DocumentRegistry.IKernelPreference {
- ext = Private.normalizeExtension(ext);
- widgetName = widgetName.toLowerCase();
- let widgetFactory = this._widgetFactories[widgetName];
- if (!widgetFactory) {
- return void 0;
- }
- let modelFactory = this.getModelFactory(widgetFactory.modelName);
- if (!modelFactory) {
- return void 0;
- }
- let language = modelFactory.preferredLanguage(ext);
- return {
- language,
- preferKernel: widgetFactory.preferKernel,
- canStartKernel: widgetFactory.canStartKernel
- };
- }
- private _modelFactories: { [key: string]: DocumentRegistry.IModelFactory<DocumentRegistry.IModel> } = Object.create(null);
- private _widgetFactories: { [key: string]: DocumentRegistry.IWidgetFactory<Widget, DocumentRegistry.IModel> } = Object.create(null);
- private _defaultWidgetFactory = '';
- private _defaultWidgetFactories: { [key: string]: string } = Object.create(null);
- private _widgetFactoryExtensions: {[key: string]: Vector<string> } = Object.create(null);
- private _fileTypes = new Vector<DocumentRegistry.IFileType>();
- private _creators = new Vector<DocumentRegistry.IFileCreator>();
- private _extenders: { [key: string] : Vector<DocumentRegistry.IWidgetExtension<Widget, DocumentRegistry.IModel>> } = Object.create(null);
- }
- /**
- * The namespace for the `DocumentRegistry` class statics.
- */
- export
- namespace DocumentRegistry {
- /**
- * The interface for a document model.
- */
- export
- interface IModel extends IDisposable {
- /**
- * A signal emitted when the document content changes.
- */
- contentChanged: ISignal<this, void>;
- /**
- * A signal emitted when the model state changes.
- */
- stateChanged: ISignal<this, IChangedArgsGeneric<any>>;
- /**
- * The dirty state of the model.
- *
- * #### Notes
- * This should be cleared when the document is loaded from
- * or saved to disk.
- */
- dirty: boolean;
- /**
- * The read-only state of the model.
- */
- readOnly: boolean;
- /**
- * The default kernel name of the document.
- */
- readonly defaultKernelName: string;
- /**
- * The default kernel language of the document.
- */
- readonly defaultKernelLanguage: string;
- /**
- * Serialize the model to a string.
- */
- toString(): string;
- /**
- * Deserialize the model from a string.
- *
- * #### Notes
- * Should emit a [contentChanged] signal.
- */
- fromString(value: string): void;
- /**
- * Serialize the model to JSON.
- */
- toJSON(): any;
- /**
- * Deserialize the model from JSON.
- *
- * #### Notes
- * Should emit a [contentChanged] signal.
- */
- fromJSON(value: any): void;
- }
- /**
- * The document context object.
- */
- export
- interface IContext<T extends IModel> extends IDisposable {
- /**
- * A signal emitted when the kernel changes.
- */
- kernelChanged: ISignal<this, IKernel>;
- /**
- * A signal emitted when the path changes.
- */
- pathChanged: ISignal<this, string>;
- /**
- * A signal emitted when the contentsModel changes.
- */
- fileChanged: ISignal<this, Contents.IModel>;
- /**
- * A signal emitted when the context is fully populated for the first time.
- */
- populated: ISignal<this, void>;
- /**
- * A signal emitted when the context is disposed.
- */
- disposed: ISignal<this, void>;
- /**
- * Get the model associated with the document.
- */
- readonly model: T;
- /**
- * The current kernel associated with the document.
- */
- readonly kernel: IKernel;
- /**
- * The current path associated with the document.
- */
- readonly path: string;
- /**
- * The current contents model associated with the document
- *
- * #### Notes
- * The model will have an empty `contents` field.
- * It will be `null` until the context is populated.
- */
- readonly contentsModel: Contents.IModel;
- /**
- * Get the kernel spec information.
- */
- readonly kernelspecs: Kernel.ISpecModels;
- /**
- * Test whether the context is fully populated.
- */
- readonly isPopulated: boolean;
- /**
- * Change the current kernel associated with the document.
- *
- * #### Notes
- * If no options are given, the session is shut down.
- */
- changeKernel(options?: Kernel.IModel): Promise<IKernel>;
- /**
- * Save the document contents to disk.
- */
- save(): Promise<void>;
- /**
- * Save the document to a different path chosen by the user.
- */
- saveAs(): Promise<void>;
- /**
- * Revert the document contents to disk contents.
- */
- revert(): Promise<void>;
- /**
- * Create a checkpoint for the file.
- *
- * @returns A promise which resolves with the new checkpoint model when the
- * checkpoint is created.
- */
- createCheckpoint(): Promise<Contents.ICheckpointModel>;
- /**
- * Delete a checkpoint for the file.
- *
- * @param checkpointID - The id of the checkpoint to delete.
- *
- * @returns A promise which resolves when the checkpoint is deleted.
- */
- deleteCheckpoint(checkpointID: string): Promise<void>;
- /**
- * Restore the file to a known checkpoint state.
- *
- * @param checkpointID - The optional id of the checkpoint to restore,
- * defaults to the most recent checkpoint.
- *
- * @returns A promise which resolves when the checkpoint is restored.
- */
- restoreCheckpoint(checkpointID?: string): Promise<void>;
- /**
- * List available checkpoints for the file.
- *
- * @returns A promise which resolves with a list of checkpoint models for
- * the file.
- */
- listCheckpoints(): Promise<Contents.ICheckpointModel[]>;
- /**
- * Get the list of running sessions.
- */
- listSessions(): Promise<Session.IModel[]>;
- /**
- * Resolve a url to a correct server path.
- */
- resolveUrl(url: string): string;
- /**
- * Add a sibling widget to the document manager.
- *
- * @param widget - The widget to add to the document manager.
- *
- * @returns A disposable used to remove the sibling if desired.
- *
- * #### Notes
- * It is assumed that the widget has the same model and context
- * as the original widget.
- */
- addSibling(widget: Widget): IDisposable;
- }
- /**
- * The interface for a widget factory.
- */
- export
- interface IWidgetFactory<T extends Widget, U extends IModel> extends IDisposable {
- /**
- * A signal emitted when a widget is created.
- */
- widgetCreated: ISignal<IWidgetFactory<T, U>, T>;
- /**
- * The file extensions the widget can view.
- *
- * #### Notes
- * Use "*" to denote all files. Specific file extensions must be preceded
- * with '.', like '.png', '.txt', etc.
- */
- readonly fileExtensions: string[];
- /**
- * The name of the widget to display in dialogs.
- */
- readonly name: string;
- /**
- * The registered name of the model type used to create the widgets.
- */
- readonly modelName: string;
- /**
- * The file extensions for which the factory should be the default.
- *
- * #### Notes
- * Use "*" to denote all files. Specific file extensions must be preceded
- * with '.', like '.png', '.txt', etc. Entries in this attribute must also
- * be included in the fileExtensions attribute.
- * The default is an empty array.
- *
- * **See also:** [[fileExtensions]].
- */
- readonly defaultFor: string[];
- /**
- * Whether the widgets prefer having a kernel started.
- */
- readonly preferKernel: boolean;
- /**
- * Whether the widgets can start a kernel when opened.
- */
- readonly canStartKernel: boolean;
- /**
- * Create a new widget.
- *
- * #### Notes
- * It should emit the [widgetCreated] signal with the new widget.
- */
- createNew(context: IContext<U>, kernel?: Kernel.IModel): T;
- }
- /**
- * An interface for a widget extension.
- */
- export
- interface IWidgetExtension<T extends Widget, U extends IModel> {
- /**
- * Create a new extension for a given widget.
- */
- createNew(widget: T, context: IContext<U>): IDisposable;
- }
- /**
- * The interface for a model factory.
- */
- export
- interface IModelFactory<T extends IModel> extends IDisposable {
- /**
- * The name of the model.
- */
- readonly name: string;
- /**
- * The content type of the file (defaults to `"file"`).
- */
- readonly contentType: Contents.ContentType;
- /**
- * The format of the file (defaults to `"text"`).
- */
- readonly fileFormat: Contents.FileFormat;
- /**
- * Create a new model for a given path.
- *
- * @param languagePreference - An optional kernel language preference.
- *
- * @returns A new document model.
- */
- createNew(languagePreference?: string): T;
- /**
- * Get the preferred kernel language given an extension.
- */
- preferredLanguage(ext: string): string;
- }
- /**
- * A kernel preference for a given file path and widget.
- */
- export
- interface IKernelPreference {
- /**
- * The preferred kernel language.
- */
- readonly language: string;
- /**
- * Whether to prefer having a kernel started when opening.
- */
- readonly preferKernel: boolean;
- /**
- * Whether a kernel when can be started when opening.
- */
- readonly canStartKernel: boolean;
- }
- /**
- * An interface for a file type.
- */
- export
- interface IFileType {
- /**
- * The name of the file type.
- */
- readonly name: string;
- /**
- * The extension of the file type (e.g. `".txt"`).
- */
- readonly extension: string;
- /**
- * The optional mimetype of the file type.
- */
- readonly mimetype?: string;
- /**
- * The optional icon class to use for the file type.
- */
- readonly icon?: string;
- /**
- * The content type of the new file (defaults to `"file"`).
- */
- readonly contentType?: Contents.ContentType;
- /**
- * The format of the new file (default to `"text"`).
- */
- readonly fileFormat?: Contents.FileFormat;
- }
- /**
- * An interface for a "Create New" item.
- */
- export
- interface IFileCreator {
- /**
- * The name of the file creator.
- */
- readonly name: string;
- /**
- * The filetype name associated with the creator.
- */
- readonly fileType: string;
- /**
- * The optional widget name.
- */
- readonly widgetName?: string;
- /**
- * The optional kernel name.
- */
- readonly kernelName?: string;
- }
- /**
- * An arguments object for the `changed` signal.
- */
- export
- interface IChangedArgs {
- /**
- * The type of the changed item.
- */
- readonly type: 'widgetFactory' | 'modelFactory' | 'widgetExtension' | 'fileCreator' | 'fileType';
- /**
- * The name of the item.
- */
- readonly name: string;
- /**
- * Whether the item was added or removed.
- */
- readonly change: 'added' | 'removed';
- }
- }
- // Define the signals for the `DocumentRegistry` class.
- defineSignal(DocumentRegistry.prototype, 'changed');
- /**
- * A private namespace for DocumentRegistry data.
- */
- namespace Private {
- /**
- * Normalize a file extension to be of the type `'.foo'`.
- *
- * Adds a leading dot if not present and converts to lower case.
- */
- export
- function normalizeExtension(extension: string): string {
- if (extension === '*') {
- return extension;
- }
- if (extension === '.*') {
- return '*';
- }
- if (extension.indexOf('.') !== 0) {
- extension = `.${extension}`;
- }
- return extension.toLowerCase();
- }
- }
|