Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade @nteract/outputs #1663

Merged
merged 20 commits into from Jun 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 14 additions & 7 deletions lib/components/inspector.js
Expand Up @@ -2,12 +2,10 @@

import React from "react";
import { observer } from "mobx-react";
import { richestMimetype, transforms } from "@nteract/transforms";
import { RichMedia, Media } from "@nteract/outputs";

import { INSPECTOR_URI } from "./../utils";

const displayOrder = ["text/html", "text/markdown", "text/plain"];

import type Kernel from "./../kernel";

type Props = { store: { kernel: ?Kernel } };
Expand All @@ -21,10 +19,15 @@ const Inspector = observer(({ store: { kernel } }: Props) => {
if (!kernel) return hide();

const bundle = kernel.inspector.bundle;
const mimetype = richestMimetype(bundle, displayOrder, transforms);

if (!mimetype) return hide();
const Transform = transforms[mimetype];
if (
!bundle["text/html"] &&
!bundle["text/markdown"] &&
!bundle["text/plain"]
) {
return hide();
}

return (
<div
className="native-key-bindings"
Expand All @@ -33,7 +36,11 @@ const Inspector = observer(({ store: { kernel } }: Props) => {
fontSize: atom.config.get(`Hydrogen.outputAreaFontSize`) || "inherit"
}}
>
<Transform data={bundle[mimetype]} />
<RichMedia data={bundle}>
<Media.HTML />
<Media.Markdown />
<Media.Plain />
</RichMedia>
</div>
);
});
Expand Down
61 changes: 61 additions & 0 deletions lib/components/result-view/display.js
@@ -0,0 +1,61 @@
/* @flow */

import React from "react";
import { toJS } from "mobx";
import {
DisplayData,
ExecuteResult,
StreamText,
KernelOutputError,
Output,
Media,
RichMedia
} from "@nteract/outputs";
import PlotlyTransform from "@nteract/transform-plotly";
import { VegaLite1, VegaLite2, Vega2, Vega3 } from "@nteract/transform-vega";

type Props = { output: any };

// All supported media types for output go here
export const supportedMediaTypes = (
<RichMedia>
<Vega3 />
<Vega2 />
<PlotlyTransform />
<VegaLite2 />
<VegaLite1 />
<Media.Json />
<Media.JavaScript />
<Media.HTML />
<Media.Markdown />
<Media.LaTeX />
<Media.SVG />
<Media.Image />
<Media.Plain />
</RichMedia>
);

export function isTextOutputOnly(data: Object) {
const supported = React.Children.map(
supportedMediaTypes.props.children,
mediaComponent => mediaComponent.props.mediaType
);
const bundleMediaTypes = [...Object.keys(data)].filter(mediaType =>
supported.includes(mediaType)
);

return bundleMediaTypes.length === 1 && bundleMediaTypes[0] === "text/plain"
? true
: false;
}

export default function Display(props: Props) {
return (
<Output output={toJS(props.output)}>
<ExecuteResult expanded>{supportedMediaTypes}</ExecuteResult>
<DisplayData expanded>{supportedMediaTypes}</DisplayData>
<StreamText expanded />
<KernelOutputError expanded />
</Output>
);
}
15 changes: 2 additions & 13 deletions lib/components/result-view/history.js
@@ -1,14 +1,10 @@
/* @flow */

import React from "react";
import { toJS } from "mobx";
import { observer } from "mobx-react";
import { Output } from "@nteract/display-area";
import { richestMimetype } from "@nteract/transforms";
import Display from "./display";
import Slider from "react-rangeslider";

import { transforms, displayOrder } from "./transforms";

import type OutputStore from "../../store/output";

const counterStyle = {
Expand Down Expand Up @@ -52,14 +48,7 @@ const History = observer(({ store }: { store: OutputStore }) => {
fontSize: atom.config.get(`Hydrogen.outputAreaFontSize`) || "inherit"
}}
>
<Output
output={toJS(output)}
displayOrder={displayOrder}
transforms={transforms}
theme="light"
models={{}}
expanded
/>
<Display output={output} />
</div>
</div>
) : null;
Expand Down
15 changes: 4 additions & 11 deletions lib/components/result-view/list.js
Expand Up @@ -2,9 +2,7 @@

import React from "react";
import { observer } from "mobx-react";
import { toJS } from "mobx";
import { Display } from "@nteract/display-area";
import { transforms, displayOrder } from "./transforms";
import Display from "./display";

type Props = { outputs: Array<Object> };

Expand Down Expand Up @@ -41,14 +39,9 @@ class ScrollList extends React.Component<Props> {
this.el = el;
}}
>
<Display
outputs={toJS(this.props.outputs)}
displayOrder={displayOrder}
transforms={transforms}
theme="light"
models={{}}
expanded={true}
/>
{this.props.outputs.map((output, index) => (
<Display output={output} key={index} />
))}
</div>
);
}
Expand Down
16 changes: 5 additions & 11 deletions lib/components/result-view/result-view.js
Expand Up @@ -3,9 +3,8 @@
import { CompositeDisposable } from "atom";
import React from "react";
import { observer } from "mobx-react";
import { action, observable, toJS } from "mobx";
import { Display } from "@nteract/display-area";
import { transforms, displayOrder } from "./transforms";
import { action, observable } from "mobx";
import Display from "./display";
import Status from "./status";

import type OutputStore from "./../../store/output";
Expand Down Expand Up @@ -182,14 +181,9 @@ class ResultViewComponent extends React.Component<Props> {
overflowY: "auto"
}}
>
<Display
outputs={toJS(outputs)}
displayOrder={displayOrder}
transforms={transforms}
theme="light"
models={{}}
expanded
/>
{outputs.map((output, index) => (
<Display output={output} key={index} />
))}
</div>
{isPlain ? null : (
<div className="toolbar">
Expand Down
26 changes: 0 additions & 26 deletions lib/components/result-view/transforms.js

This file was deleted.

14 changes: 4 additions & 10 deletions lib/store/output.js
@@ -1,19 +1,14 @@
/* @flow */

import { action, computed, observable } from "mobx";
import { richestMimetype } from "@nteract/transforms";
import _ from "lodash";
import {
escapeCarriageReturn,
escapeCarriageReturnSafe
} from "escape-carriage";

import {
transforms,
displayOrder
} from "./../components/result-view/transforms";

import type { IObservableArray } from "mobx";

import { isTextOutputOnly } from "../components/result-view/display";
const outputTypes = ["execute_result", "display_data", "stream", "error"];

/**
Expand Down Expand Up @@ -96,9 +91,8 @@ export default class OutputStore {
case "execute_result":
case "display_data": {
const bundle = output.data;
const mimetype = richestMimetype(bundle, displayOrder, transforms);
return mimetype === "text/plain"
? isSingleLine(bundle[mimetype], availableSpace)
return isTextOutputOnly(bundle)
? isSingleLine(bundle["text/plain"], availableSpace)
: false;
}
case "stream": {
Expand Down
7 changes: 3 additions & 4 deletions package.json
Expand Up @@ -59,11 +59,10 @@
"@babel/runtime-corejs2": "^7.0.0",
"@jupyterlab/services": "^0.52.0",
"@nteract/commutable": "^7.0.0",
"@nteract/display-area": "^4.4.8",
"@nteract/outputs": "^2.1.5",
"@nteract/mathjax": "^3.0.1",
"@nteract/transform-plotly": "^3.2.5",
"@nteract/transform-vega": "^3.2.6",
"@nteract/transforms": "^4.4.7",
"@nteract/transform-plotly": "^5.0.0",
"@nteract/transform-vega": "^5.0.2",
"anser": "^1.4.4",
"atom-select-list": "^0.7.0",
"escape-carriage": "^1.2.0",
Expand Down
44 changes: 44 additions & 0 deletions spec/components/display-spec.js
@@ -0,0 +1,44 @@
"use babel";

import React from "react";
import Enzyme, { mount } from "enzyme";
import Adapter from "enzyme-adapter-react-16";

import Display, {
isTextOutputOnly,
supportedMediaTypes
} from "../../lib/components/result-view/display";

Enzyme.configure({ adapter: new Adapter() });

const testOutput = {
output_type: "display_data",
data: {
"text/html": "<p>This is some HTML that <b>WILL</b> render</p>",
"text/plain": "This is some plain text that WILL NOT render"
},
metadata: {}
};

describe("Display output", () => {
const wrapper = mount(<Display output={testOutput} />);
it("renders the richest supported output", () => {
expect(wrapper.find("Plain").exists()).toEqual(false);
expect(wrapper.find("HTML").exists()).toEqual(true);
});
});

describe("textOutputOnly", () => {
let plainBundle = {
"text/plain": "I'm very plain",
"text/output-not-supported": "This should be ignored"
};
let richerBundle = {
"text/plain": "I'm very plain",
"text/html": "<div>I am a little <b>richer</b>!</div>"
};
it("should return true if text is the richest supported output", () => {
expect(isTextOutputOnly(plainBundle)).toEqual(true);
expect(isTextOutputOnly(richerBundle)).toEqual(false);
});
});