multiple files rendering

This commit is contained in:
catarak 2016-07-11 15:22:29 -04:00
parent ebfd1fce0d
commit 7a164d9cdd
6 changed files with 66 additions and 29 deletions

View file

@ -1,5 +1,6 @@
import React, { PropTypes } from 'react';
import ReactDOM from 'react-dom';
import escapeStringRegexp from 'escape-string-regexp';
class PreviewFrame extends React.Component {
@ -11,11 +12,12 @@ class PreviewFrame extends React.Component {
componentDidUpdate(prevProps) {
if (this.props.isPlaying !== prevProps.isPlaying) {
if (this.props.isPlaying) {
this.renderSketch();
} else {
this.clearPreview();
}
// if (this.props.isPlaying) {
// this.renderSketch();
// } else {
// this.clearPreview();
// }
}
if (this.props.isPlaying && this.props.content !== prevProps.content) {
@ -28,22 +30,47 @@ class PreviewFrame extends React.Component {
}
clearPreview() {
const doc = ReactDOM.findDOMNode(this).contentDocument;
doc.write('');
doc.close();
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;
}
renderSketch() {
const doc = ReactDOM.findDOMNode(this).contentDocument;
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 doc = ReactDOM.findDOMNode(this);
if (this.props.isPlaying) {
doc.srcdoc = this.injectLocalFiles();
} else {
doc.srcdoc = '';
}
const sketchScript = doc.createElement('script');
sketchScript.textContent = this.props.content;
doc.body.appendChild(sketchScript);
// 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);
}
renderFrameContents() {
@ -70,7 +97,11 @@ class PreviewFrame extends React.Component {
PreviewFrame.propTypes = {
isPlaying: PropTypes.bool.isRequired,
head: PropTypes.object.isRequired,
content: PropTypes.string.isRequired,
htmlFile: PropTypes.shape({
content: PropTypes.string.isRequired
}),
jsFiles: PropTypes.array.isRequired
};
export default PreviewFrame;

View file

@ -11,7 +11,7 @@ import * as FileActions from '../actions/files';
import * as IDEActions from '../actions/ide';
import * as PreferencesActions from '../actions/preferences';
import * as ProjectActions from '../actions/project';
import { getFile } from '../reducers/files';
import { getFile, getHTMLFile, getJSFiles } from '../reducers/files';
class IDEView extends React.Component {
componentDidMount() {
@ -58,6 +58,9 @@ class IDEView extends React.Component {
files={this.props.files}
/>
<PreviewFrame
htmlFile={this.props.htmlFile}
jsFiles={this.props.jsFiles}
files={this.props.files}
content={this.props.selectedFile.content}
head={
<link type="text/css" rel="stylesheet" href="/preview-styles.css" />
@ -100,13 +103,17 @@ IDEView.propTypes = {
id: PropTypes.string.isRequired,
content: PropTypes.string.isRequired
}),
setSelectedFile: PropTypes.func.isRequired
setSelectedFile: PropTypes.func.isRequired,
htmlFile: PropTypes.object.isRequired,
jsFiles: PropTypes.array.isRequired
};
function mapStateToProps(state) {
return {
files: state.files,
selectedFile: getFile(state.files, state.ide.selectedFile),
htmlFile: getHTMLFile(state.files),
jsFiles: getJSFiles(state.files),
ide: state.ide,
preferences: state.preferences,
user: state.user,

View file

@ -13,6 +13,7 @@ const defaultHTML =
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.0/p5.min.js"></script>
</head>
<body>
<script src="sketch.js"></script>
@ -55,5 +56,7 @@ const files = (state = initialState, action) => {
};
export const getFile = (state, id) => state.filter(file => file.id === id)[0];
export const getHTMLFile = (state) => state.filter(file => file.name.match(/.*html$/))[0];
export const getJSFiles = (state) => state.filter(file => file.name.match(/.*.js$/));
export default files;

View file

@ -8,17 +8,11 @@ const initialState = {
const ide = (state = initialState, action) => {
switch (action.type) {
case ActionTypes.TOGGLE_SKETCH:
return {
isPlaying: !state.isPlaying
};
return Object.assign({}, state, { isPlaying: !state.isPlaying });
case ActionTypes.START_SKETCH:
return {
isPlaying: true
};
return Object.assign({}, state, { isPlaying: true });
case ActionTypes.STOP_SKETCH:
return {
isPlaying: false
};
return Object.assign({}, state, { isPlaying: false });
case ActionTypes.SET_SELECTED_FILE:
case ActionTypes.SET_PROJECT:
case ActionTypes.NEW_PROJECT:

View file

@ -66,6 +66,7 @@
"connect-mongo": "^1.2.0",
"cookie-parser": "^1.4.1",
"dotenv": "^2.0.0",
"escape-string-regexp": "^1.0.5",
"eslint-loader": "^1.3.0",
"express": "^4.13.4",
"express-session": "^1.13.0",

View file

@ -16,6 +16,7 @@ const defaultHTML =
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.0/p5.min.js"></script>
</head>
<body>
<script src="sketch.js"></script>