123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- /*-----------------------------------------------------------------------------
- | Copyright (c) Jupyter Development Team.
- | Distributed under the terms of the Modified BSD License.
- |----------------------------------------------------------------------------*/
- import {
- nbformat
- } from '@jupyterlab/coreutils';
- import {
- IObservableJSON, ObservableJSON
- } from '@jupyterlab/observables';
- import {
- IRenderMime
- } from '@jupyterlab/rendermime-interfaces';
- import {
- JSONExt, JSONObject, JSONValue, ReadonlyJSONObject
- } from '@phosphor/coreutils';
- import {
- ISignal, Signal
- } from '@phosphor/signaling';
- import {
- MimeModel
- } from './mimemodel';
- /**
- * The interface for an attachment model.
- */
- export
- interface IAttachmentModel extends IRenderMime.IMimeModel {
- /**
- * A signal emitted when the attachment model changes.
- */
- readonly changed: ISignal<this, void>;
- /**
- * Dispose of the resources used by the attachment model.
- */
- dispose(): void;
- /**
- * Serialize the model to JSON.
- */
- toJSON(): nbformat.IMimeBundle;
- }
- /**
- * The namespace for IAttachmentModel sub-interfaces.
- */
- export
- namespace IAttachmentModel {
- /**
- * The options used to create a notebook attachment model.
- */
- export
- interface IOptions {
- /**
- * The raw attachment value.
- */
- value: nbformat.IMimeBundle;
- }
- }
- /**
- * The default implementation of a notebook attachment model.
- */
- export
- class AttachmentModel implements IAttachmentModel {
- /**
- * Construct a new attachment model.
- */
- constructor(options: IAttachmentModel.IOptions) {
- let { data } = Private.getBundleOptions(options);
- this._data = new ObservableJSON({ values: data as JSONObject });
- this._rawData = data;
- // Make a copy of the data.
- let value = options.value;
- for (let key in value) {
- // Ignore data and metadata that were stripped.
- switch (key) {
- case 'data':
- break;
- default:
- this._raw[key] = Private.extract(value, key);
- }
- }
- }
- /**
- * A signal emitted when the attachment model changes.
- */
- get changed(): ISignal<this, void> {
- return this._changed;
- }
- /**
- * Dispose of the resources used by the attachment model.
- */
- dispose(): void {
- this._data.dispose();
- Signal.clearData(this);
- }
- /**
- * The data associated with the model.
- */
- get data(): ReadonlyJSONObject {
- return this._rawData;
- }
- /**
- * The metadata associated with the model.
- */
- get metadata(): ReadonlyJSONObject {
- return undefined;
- }
- /**
- * Set the data associated with the model.
- *
- * #### Notes
- * Depending on the implementation of the mime model,
- * this call may or may not have deferred effects,
- */
- setData(options: IRenderMime.IMimeModel.ISetDataOptions): void {
- if (options.data) {
- this._updateObservable(this._data, options.data);
- this._rawData = options.data;
- }
- this._changed.emit(void 0);
- }
- /**
- * Serialize the model to JSON.
- */
- toJSON(): nbformat.IMimeBundle {
- let attachment: JSONValue = {};
- for (let key in this._raw) {
- attachment[key] = Private.extract(this._raw, key);
- }
- return attachment as nbformat.IMimeBundle;
- }
- // All attachments are untrusted
- readonly trusted = false;
- /**
- * Update an observable JSON object using a readonly JSON object.
- */
- private _updateObservable(observable: IObservableJSON, data: ReadonlyJSONObject) {
- let oldKeys = observable.keys();
- let newKeys = Object.keys(data);
- // Handle removed keys.
- for (let key of oldKeys) {
- if (newKeys.indexOf(key) === -1) {
- observable.delete(key);
- }
- }
- // Handle changed data.
- for (let key of newKeys) {
- let oldValue = observable.get(key);
- let newValue = data[key];
- if (oldValue !== newValue) {
- observable.set(key, newValue as JSONValue);
- }
- }
- }
- private _changed = new Signal<this, void>(this);
- private _raw: JSONObject = {};
- private _rawData: ReadonlyJSONObject;
- private _data: IObservableJSON;
- }
- /**
- * The namespace for AttachmentModel statics.
- */
- export
- namespace AttachmentModel {
- /**
- * Get the data for an attachment.
- *
- * @params bundle - A kernel attachment MIME bundle.
- *
- * @returns - The data for the payload.
- */
- export
- function getData(bundle: nbformat.IMimeBundle): JSONObject {
- return Private.getData(bundle);
- }
- }
- /**
- * The namespace for module private data.
- */
- namespace Private {
- /**
- * Get the data from a notebook attachment.
- */
- export
- function getData(bundle: nbformat.IMimeBundle): JSONObject {
- return convertBundle(bundle);
- }
- /**
- * Get the bundle options given attachment model options.
- */
- export
- function getBundleOptions(options: IAttachmentModel.IOptions): MimeModel.IOptions {
- let data = getData(options.value);
- return { data };
- }
- /**
- * Extract a value from a JSONObject.
- */
- export
- function extract(value: JSONObject, key: string): JSONValue {
- let item = value[key];
- if (JSONExt.isPrimitive(item)) {
- return item;
- }
- return JSONExt.deepCopy(item);
- }
- /**
- * Convert a mime bundle to mime data.
- */
- function convertBundle(bundle: nbformat.IMimeBundle): JSONObject {
- let map: JSONObject = Object.create(null);
- for (let mimeType in bundle) {
- map[mimeType] = extract(bundle, mimeType);
- }
- return map;
- }
- }
|