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

View file

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

View file

@ -13,6 +13,7 @@ const defaultHTML =
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.0/p5.min.js"></script>
</head> </head>
<body> <body>
<script src="sketch.js"></script> <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 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; export default files;

View file

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

View file

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

View file

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