-
Notifications
You must be signed in to change notification settings - Fork 44
/
preview.tsx
88 lines (72 loc) · 2.37 KB
/
preview.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import React = require("react");
import falafel from "./falafel";
import LoopInserter from "./loop-inserter";
import makeImplicitSketch from "./implicit-sketch";
import PureComponent from "./pure-component";
import * as PreviewFrame from "./preview-frame-interface";
const LOOP_CHECK_FUNC_NAME = '__loopCheck';
interface Props {
p5version: string,
width: number,
content: string,
baseSketchURL: string,
timestamp: number,
maxRunTime: number,
onError: PreviewFrame.ErrorReporter
}
interface State {
}
export default class Preview extends PureComponent<Props, State> {
_iframe: HTMLIFrameElement
resetIframe() {
let content = this.props.content;
content = makeImplicitSketch(content);
try {
content = falafel(content, {}, LoopInserter(function(node) {
return LOOP_CHECK_FUNC_NAME + "(" +
JSON.stringify(node.range) + ");";
})).toString();
} catch (e) {
// There's almost definitely a syntax error in the user's code;
// just leave it unmangled and let the preview frame bubble up
// the error.
}
if (this._iframe) {
this._iframe.parentNode.removeChild(this._iframe);
this._iframe = null;
}
let iframe = document.createElement('iframe');
iframe.setAttribute('src', 'preview-frame.html');
iframe.setAttribute('width', this.props.width.toString());
iframe.addEventListener('load', () => {
// Note that this should never be called if we're already unmounted,
// since that means the iframe will have been removed from the DOM,
// in which case it shouldn't be emitting events anymore.
let frame = iframe.contentWindow as PreviewFrame.Runner;
frame.startSketch(content, this.props.p5version, this.props.maxRunTime,
LOOP_CHECK_FUNC_NAME,
this.props.baseSketchURL,
this.props.onError);
});
this.refs.container.appendChild(iframe);
this._iframe = iframe;
}
componentDidUpdate(prevProps: Props, prevState: State) {
if (prevProps.timestamp !== this.props.timestamp) {
this.resetIframe();
}
}
componentDidMount() {
this.resetIframe();
}
componentWillUnmount() {
this._iframe = null;
}
refs: {
[key: string]: (Element)
container: HTMLDivElement
}
render() {
return <div ref="container" className="preview-holder"></div>;
}
}