Skip to content

Commit deddebc

Browse files
committed
switch to TypeScript
1 parent 36da745 commit deddebc

15 files changed

+13981
-15290
lines changed

.babelrc

-5
This file was deleted.

package-lock.json

+13,410-14,828
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+19-13
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "react-jupyter-notebook",
33
"version": "0.3.2",
44
"homepage": "https://Joeyonng.github.io/react-jupyter-notebook",
5-
"license" : "MIT",
5+
"license": "MIT",
66
"private": false,
77
"description": "A simple React component that renders .ipynb files just like how they are rendered by Jupyter Lab",
88
"repository": {
@@ -22,12 +22,15 @@
2222
"files": [
2323
"dist"
2424
],
25-
"main": "dist/JupyterViewer.js",
25+
"main": "dist/index.js",
26+
"module": "dist/index.mjs",
27+
"typeings": "dist/index.d.ts",
2628
"dependencies": {
27-
"@babel/runtime": "^7.14.0",
29+
"@codemirror/gutter": "^0.19.9",
30+
"@codemirror/lang-javascript": "^0.19.7",
31+
"@codemirror/view": "^0.19.47",
2832
"ansi-to-react": "^6.1.4",
2933
"katex": "^0.13.2",
30-
"prop-types": "^15.7.2",
3134
"react": "^17.0.1",
3235
"react-dom": "^17.0.1",
3336
"react-markdown": "^6.0.2",
@@ -37,18 +40,21 @@
3740
"remark-math": "^4.0.0"
3841
},
3942
"devDependencies": {
40-
"@babel/cli": "^7.14.3",
41-
"@babel/core": "^7.14.3",
42-
"babel-preset-react-app": "^10.0.0",
43+
"@types/node": "^17.0.23",
44+
"@types/react": "^17.0.42",
45+
"@types/react-dom": "^17.0.14",
46+
"@types/react-syntax-highlighter": "^13.5.2",
4347
"gh-pages": "^3.2.0",
44-
"node-sass": "^6.0.0",
45-
"react-scripts": "4.0.3",
46-
"rimraf": "^3.0.2"
48+
"node-sass": "^6.0.1",
49+
"react-scripts": "5.0.0",
50+
"rimraf": "^3.0.2",
51+
"rollup": "^2.70.1",
52+
"rollup-plugin-dts": "^4.2.0",
53+
"rollup-plugin-postcss": "^4.0.2",
54+
"rollup-plugin-typescript2": "^0.31.2",
55+
"typescript": "^4.6.2"
4756
},
4857
"scripts": {
49-
"predeploy": "npm run build",
50-
"deploy": "gh-pages -d build",
51-
"prepublish": "set NODE_ENV=production&& rimraf dist && mkdir dist && babel src/lib -d dist --copy-files",
5258
"start": "react-scripts start",
5359
"build": "react-scripts build",
5460
"test": "react-scripts test",

rollup.config.js

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import externals from "rollup-plugin-node-externals";
2+
import typescript from 'rollup-plugin-typescript2';
3+
import postcss from "rollup-plugin-postcss";
4+
import dts from "rollup-plugin-dts";
5+
6+
import packageJson from "./package.json";
7+
8+
export default [
9+
{
10+
input: "src/lib/JupyterViewer.tsx",
11+
output: [
12+
{
13+
file: packageJson.main,
14+
format: "cjs",
15+
sourcemap: true,
16+
},
17+
],
18+
plugins: [
19+
externals(),
20+
typescript({
21+
tsconfig: "tsconfig.json",
22+
tsconfigOverride: {compilerOptions: {declaration: true}},
23+
}),
24+
postcss(),
25+
],
26+
},
27+
{
28+
input: "dist/JupyterViewer.d.ts",
29+
output: [{file: packageJson.typeings, format: "es"}],
30+
external: [/\.scss$/],
31+
plugins: [dts()],
32+
},
33+
];

src/App.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import nb_test from "./nb_test.json"
44
import JupyterViewer from "./lib/JupyterViewer";
55
import hljsStyles from "./lib/hljsStyles";
66

7-
8-
function App(props) {
7+
function App() {
98
const [state, setState] = useState({
109
rawIpynb: nb_test,
1110
mediaAlign: "left",

src/lib/BlockOutput.tsx

+152
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
import React, {useCallback, useState} from "react";
2+
import Ansi from "ansi-to-react";
3+
4+
import {BlockOutputPropsType} from "./types";
5+
6+
function BlockOutput(props:BlockOutputPropsType) {
7+
const metadata = props.cell['metadata'];
8+
const outputs = props.cell['outputs']
9+
10+
const [state, setState] = useState({
11+
highlighted: false,
12+
prevDisplay: 1,
13+
display: 1,
14+
contentHeight: 0,
15+
})
16+
const contentRef = useCallback((node) => {
17+
if (node) {
18+
setState(state => ({...state, contentHeight: node.offsetHeight}));
19+
}
20+
}, [])
21+
22+
if (props.display !== state.prevDisplay) {
23+
let newDisplay = props.display;
24+
if (newDisplay === -1) {
25+
if (metadata['collapsed'] || (metadata['jupyter'] !== undefined && metadata['jupyter']['outputs_hidden'])) {
26+
newDisplay = 0;
27+
}
28+
else if (metadata['scrolled']) {
29+
newDisplay = 2;
30+
}
31+
}
32+
33+
setState({...state, prevDisplay: props.display, display: newDisplay});
34+
}
35+
36+
return (
37+
<div
38+
className="block-output"
39+
>
40+
<div
41+
className={props.highlighted ? "block-light-selected" : "block-light"}
42+
onClick={() => {
43+
setState({...state, display: (state.display + 1) % 3})
44+
}}
45+
/>
46+
{state.display === 0 ? <div className="block-hidden"/> :
47+
<div
48+
className="block-output-content"
49+
style={state.display !== 2 ? undefined : {
50+
maxHeight: state.contentHeight,
51+
height: 200,
52+
boxShadow: "inset 0 0 6px 2px rgb(0 0 0 / 30%)",
53+
resize: "vertical",
54+
}}
55+
>
56+
<div ref={contentRef}>
57+
{!outputs ? null : outputs.map((output, index) => {
58+
let executionCount;
59+
let htmlContent;
60+
if ('output_type' in output) {
61+
let output_type = output['output_type'];
62+
switch (output_type) {
63+
// Stdout and stderr
64+
case 'stream':
65+
htmlContent = (
66+
<pre className={`cell-content ${output['name'] === 'stdout' ? 'output-std' : 'output-err'}`}>
67+
{!output['text'] ? '' : output['text'].join('')}
68+
</pre>
69+
)
70+
71+
break;
72+
// Output with execution_count
73+
// @ts-expect-error
74+
case 'execute_result':
75+
executionCount = output['execution_count']
76+
77+
// Output without execution_count
78+
case 'display_data':
79+
const output_data = output['data'];
80+
if (output_data) {
81+
if ('image/png' in output_data) {
82+
let output_metadata = output['metadata'];
83+
let size = output_metadata && output_metadata['image/png'];
84+
htmlContent = (
85+
<div
86+
className="cell-content output-display"
87+
style={{
88+
justifyContent: props.mediaAlign,
89+
}}
90+
>
91+
<img
92+
src={`data:image/png;base64,${output_data['image/png']}`}
93+
width={size ? size['width'] : 'auto'}
94+
height={size ? size['height'] : 'auto'}
95+
alt=""
96+
/>
97+
</div>
98+
)
99+
}
100+
else if ('text/html' in output_data) {
101+
htmlContent = (
102+
<div
103+
className="cell-content output-display"
104+
style={{
105+
justifyContent: props.mediaAlign,
106+
}}
107+
dangerouslySetInnerHTML={{__html: output_data['text/html'].join('')}}
108+
/>
109+
)
110+
}
111+
else if ('text/plain' in output_data) {
112+
htmlContent = (
113+
<pre className="cell-content output-std">{output_data['text/plain'].join('')}</pre>
114+
)
115+
}
116+
}
117+
118+
break;
119+
// Exceptions
120+
case 'error':
121+
htmlContent = (
122+
<pre className="cell-content output-err">
123+
<Ansi>
124+
{!output.traceback ? undefined : output.traceback.join('\n')}
125+
</Ansi>
126+
</pre>
127+
)
128+
129+
break;
130+
default:
131+
console.log('Unexpected output_type: ', output_type);
132+
}
133+
}
134+
135+
return (
136+
<div
137+
key={index}
138+
className="cell-row"
139+
>
140+
<pre className="cell-header output">{executionCount ? `[${executionCount}]: ` : null}</pre>
141+
{htmlContent}
142+
</div>
143+
);
144+
})}
145+
</div>
146+
</div>
147+
}
148+
</div>
149+
)
150+
}
151+
152+
export default BlockOutput;

0 commit comments

Comments
 (0)