p5.js-web-editor/client/modules/IDE/components/PreviewFrame.js

117 lines
3.5 KiB
JavaScript
Raw Normal View History

2016-06-27 21:47:48 +02:00
import React, { PropTypes } from 'react';
2016-06-24 00:29:55 +02:00
import ReactDOM from 'react-dom';
2016-07-11 21:22:29 +02:00
import escapeStringRegexp from 'escape-string-regexp';
import srcDoc from 'srcdoc-polyfill';
2016-06-24 00:29:55 +02:00
2016-07-11 22:12:31 +02:00
// sandbox="allow-scripts allow-pointer-lock allow-same-origin allow-popups allow-modals allow-forms"
2016-06-24 00:29:55 +02:00
class PreviewFrame extends React.Component {
componentDidMount() {
if (this.props.isPlaying) {
this.renderFrameContents();
}
}
2016-06-27 21:47:48 +02:00
componentDidUpdate(prevProps) {
if (this.props.isPlaying !== prevProps.isPlaying) {
2016-07-11 21:22:29 +02:00
this.renderSketch();
// if (this.props.isPlaying) {
// this.renderSketch();
// } else {
// this.clearPreview();
// }
2016-06-27 21:47:48 +02:00
}
if (this.props.isPlaying && this.props.content !== prevProps.content) {
this.renderSketch();
}
}
componentWillUnmount() {
ReactDOM.unmountComponentAtNode(ReactDOM.findDOMNode(this).contentDocument.body);
}
2016-06-24 00:29:55 +02:00
clearPreview() {
2016-07-11 21:22:29 +02:00
const doc = ReactDOM.findDOMNode(this);
doc.srcDoc = '';
}
injectLocalFiles() {
let htmlFile = this.props.htmlFile.content;
this.props.jsFiles.forEach(jsFile => {
const fileName = escapeStringRegexp(jsFile.name);
const fileRegex = new RegExp(`<script.*?src=('|")((\.\/)|\/)?${fileName}('|").*?>([\s\S]*?)<\/script>`, 'gmi');
htmlFile = htmlFile.replace(fileRegex, `<script>\n${jsFile.content}\n</script>`);
});
const htmlHead = htmlFile.match(/(?:<head.*?>)([\s\S]*?)(?:<\/head>)/gmi);
const headRegex = new RegExp('head', 'i');
let htmlHeadContents = htmlHead[0].split(headRegex)[1];
htmlHeadContents = htmlHeadContents.slice(1, htmlHeadContents.length - 2);
htmlHeadContents += '<link rel="stylesheet" type="text/css" href="/preview-styles.css" />\n';
htmlFile = htmlFile.replace(/(?:<head.*?>)([\s\S]*?)(?:<\/head>)/gmi, `<head>\n${htmlHeadContents}\n</head>`);
return htmlFile;
2016-06-24 00:29:55 +02:00
}
renderSketch() {
2016-07-11 21:22:29 +02:00
const doc = ReactDOM.findDOMNode(this);
if (this.props.isPlaying) {
// TODO add polyfill for this
// doc.srcdoc = this.injectLocalFiles();
srcDoc.set(doc, this.injectLocalFiles());
2016-07-11 21:22:29 +02:00
} else {
// doc.srcdoc = '';
srcDoc.set(doc, '');
doc.contentWindow.document.open();
doc.contentWindow.document.write('');
doc.contentWindow.document.close();
2016-07-11 21:22:29 +02:00
}
// this.clearPreview();
// ReactDOM.render(this.props.head, doc.head);
// const p5Script = doc.createElement('script');
// p5Script.setAttribute('src', 'https://cdnjs.cloudflare.com/ajax/libs/
// p5.js/0.5.0/p5.min.js');
// doc.body.appendChild(p5Script);
// const sketchScript = doc.createElement('script');
// sketchScript.textContent = this.props.content;
// doc.body.appendChild(sketchScript);
2016-06-24 00:29:55 +02:00
}
2016-06-27 21:47:48 +02:00
renderFrameContents() {
const doc = ReactDOM.findDOMNode(this).contentDocument;
if (doc.readyState === 'complete') {
2016-06-27 23:22:54 +02:00
this.renderSketch();
2016-06-27 21:47:48 +02:00
} else {
setTimeout(this.renderFrameContents, 0);
2016-06-24 00:29:55 +02:00
}
}
render() {
2016-06-27 21:47:48 +02:00
return (
<iframe
className="preview-frame"
frameBorder="0"
title="sketch output"
2016-07-11 23:32:13 +02:00
sandbox="allow-scripts allow-pointer-lock allow-same-origin allow-popups allow-modals allow-forms"
2016-06-27 21:47:48 +02:00
></iframe>
);
2016-06-24 00:29:55 +02:00
}
}
2016-06-27 21:47:48 +02:00
PreviewFrame.propTypes = {
isPlaying: PropTypes.bool.isRequired,
head: PropTypes.object.isRequired,
2016-07-11 21:22:29 +02:00
content: PropTypes.string.isRequired,
htmlFile: PropTypes.shape({
content: PropTypes.string.isRequired
}),
jsFiles: PropTypes.array.isRequired
2016-06-27 21:47:48 +02:00
};
2016-06-24 00:29:55 +02:00
export default PreviewFrame;