@jupyterlab/rendermime
Version:
JupyterLab - RenderMime
248 lines • 7.63 kB
JavaScript
/* -----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
import * as nbformat from '@jupyterlab/nbformat';
import { ObservableJSON, ObservableString } from '@jupyterlab/observables';
import { JSONExt } from '@lumino/coreutils';
import { Signal } from '@lumino/signaling';
/**
* The default implementation of a notebook output model.
*/
export class OutputModel {
/**
* Construct a new output model.
*/
constructor(options) {
this._changed = new Signal(this);
this._raw = {};
this._text = undefined;
const { data, metadata, trusted } = Private.getBundleOptions(options);
this._rawData = data;
if (options.value !== undefined && nbformat.isStream(options.value)) {
this._text = new ObservableString(typeof options.value.text === 'string'
? options.value.text
: options.value.text.join(''));
}
this._metadata = new ObservableJSON({ values: metadata });
this._rawMetadata = metadata;
this.trusted = trusted;
// Make a copy of the data.
const value = options.value;
for (const key in value) {
// Ignore data and metadata that were stripped.
switch (key) {
case 'data':
case 'metadata':
break;
default:
this._raw[key] = Private.extract(value, key);
}
}
this.type = value.output_type;
if (nbformat.isExecuteResult(value)) {
this.executionCount = value.execution_count;
}
else {
this.executionCount = null;
}
}
/**
* A signal emitted when the output model changes.
*/
get changed() {
return this._changed;
}
/**
* Dispose of the resources used by the output model.
*/
dispose() {
var _a;
(_a = this._text) === null || _a === void 0 ? void 0 : _a.dispose();
this._metadata.dispose();
Signal.clearData(this);
}
/**
* The data associated with the model.
*/
get data() {
return Private.getData(this.toJSON());
}
get streamText() {
return this._text;
}
/**
* The metadata associated with the model.
*/
get metadata() {
return this._rawMetadata;
}
/**
* 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) {
if (options.data) {
this._rawData = options.data;
}
if (options.metadata) {
this._updateObservable(this._metadata, options.metadata);
this._rawMetadata = options.metadata;
}
this._changed.emit();
}
/**
* Serialize the model to JSON.
*/
toJSON() {
const output = {};
for (const key in this._raw) {
output[key] = Private.extract(this._raw, key);
}
if (this._text !== undefined) {
output['text'] = this._text.text;
}
switch (this.type) {
case 'display_data':
case 'execute_result':
case 'update_display_data':
output['data'] = this._rawData;
output['metadata'] = this.metadata;
break;
default:
break;
}
// Remove transient data.
delete output['transient'];
return output;
}
/**
* Update an observable JSON object using a readonly JSON object.
*/
_updateObservable(observable, data) {
const oldKeys = observable.keys();
const newKeys = Object.keys(data);
// Handle removed keys.
for (const key of oldKeys) {
if (newKeys.indexOf(key) === -1) {
observable.delete(key);
}
}
// Handle changed data.
for (const key of newKeys) {
const oldValue = observable.get(key);
const newValue = data[key];
if (oldValue !== newValue) {
observable.set(key, newValue);
}
}
}
}
/**
* The namespace for OutputModel statics.
*/
(function (OutputModel) {
/**
* Get the data for an output.
*
* @param output - A kernel output message payload.
*
* @returns - The data for the payload.
*/
function getData(output) {
return Private.getData(output);
}
OutputModel.getData = getData;
/**
* Get the metadata from an output message.
*
* @param output - A kernel output message payload.
*
* @returns - The metadata for the payload.
*/
function getMetadata(output) {
return Private.getMetadata(output);
}
OutputModel.getMetadata = getMetadata;
})(OutputModel || (OutputModel = {}));
/**
* The namespace for module private data.
*/
var Private;
(function (Private) {
/**
* Get the data from a notebook output.
*/
function getData(output) {
let bundle = {};
if (nbformat.isExecuteResult(output) ||
nbformat.isDisplayData(output) ||
nbformat.isDisplayUpdate(output)) {
bundle = output.data;
}
else if (nbformat.isStream(output)) {
if (output.name === 'stderr') {
bundle['application/vnd.jupyter.stderr'] = output.text;
}
else {
bundle['application/vnd.jupyter.stdout'] = output.text;
}
}
else if (nbformat.isError(output)) {
bundle['application/vnd.jupyter.error'] = output;
const traceback = output.traceback.join('\n');
bundle['application/vnd.jupyter.stderr'] =
traceback || `${output.ename}: ${output.evalue}`;
}
return convertBundle(bundle);
}
Private.getData = getData;
/**
* Get the metadata from an output message.
*/
function getMetadata(output) {
const value = Object.create(null);
if (nbformat.isExecuteResult(output) || nbformat.isDisplayData(output)) {
for (const key in output.metadata) {
value[key] = extract(output.metadata, key);
}
}
return value;
}
Private.getMetadata = getMetadata;
/**
* Get the bundle options given output model options.
*/
function getBundleOptions(options) {
const data = getData(options.value);
const metadata = getMetadata(options.value);
const trusted = !!options.trusted;
return { data, metadata, trusted };
}
Private.getBundleOptions = getBundleOptions;
/**
* Extract a value from a JSONObject.
*/
function extract(value, key) {
const item = value[key];
if (item === undefined || JSONExt.isPrimitive(item)) {
return item;
}
return JSON.parse(JSON.stringify(item));
}
Private.extract = extract;
/**
* Convert a mime bundle to mime data.
*/
function convertBundle(bundle) {
const map = Object.create(null);
for (const mimeType in bundle) {
map[mimeType] = extract(bundle, mimeType);
}
return map;
}
})(Private || (Private = {}));
//# sourceMappingURL=outputmodel.js.map