From 7a164d9cdd0155b117fdae1f92722e59eef0ff6c Mon Sep 17 00:00:00 2001 From: catarak Date: Mon, 11 Jul 2016 15:22:29 -0400 Subject: [PATCH] multiple files rendering --- client/modules/IDE/components/PreviewFrame.js | 67 ++++++++++++++----- client/modules/IDE/pages/IDEView.js | 11 ++- client/modules/IDE/reducers/files.js | 3 + client/modules/IDE/reducers/ide.js | 12 +--- package.json | 1 + server/models/project.js | 1 + 6 files changed, 66 insertions(+), 29 deletions(-) diff --git a/client/modules/IDE/components/PreviewFrame.js b/client/modules/IDE/components/PreviewFrame.js index 94d5d7ce..0706901e 100644 --- a/client/modules/IDE/components/PreviewFrame.js +++ b/client/modules/IDE/components/PreviewFrame.js @@ -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(); - } + this.renderSketch(); + // 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(`([\s\S]*?)<\/script>`, 'gmi'); + htmlFile = htmlFile.replace(fileRegex, ``); + }); + + const htmlHead = htmlFile.match(/(?:)([\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 += '\n'; + htmlFile = htmlFile.replace(/(?:)([\s\S]*?)(?:<\/head>)/gmi, `\n${htmlHeadContents}\n`); + + 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 + content: PropTypes.string.isRequired, + htmlFile: PropTypes.shape({ + content: PropTypes.string.isRequired + }), + jsFiles: PropTypes.array.isRequired }; export default PreviewFrame; diff --git a/client/modules/IDE/pages/IDEView.js b/client/modules/IDE/pages/IDEView.js index 95d1876d..ad78daa2 100644 --- a/client/modules/IDE/pages/IDEView.js +++ b/client/modules/IDE/pages/IDEView.js @@ -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} /> @@ -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, diff --git a/client/modules/IDE/reducers/files.js b/client/modules/IDE/reducers/files.js index a8bb6991..c96c23e5 100644 --- a/client/modules/IDE/reducers/files.js +++ b/client/modules/IDE/reducers/files.js @@ -13,6 +13,7 @@ const defaultHTML = + @@ -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; diff --git a/client/modules/IDE/reducers/ide.js b/client/modules/IDE/reducers/ide.js index 5d80ca81..9c4c5b88 100644 --- a/client/modules/IDE/reducers/ide.js +++ b/client/modules/IDE/reducers/ide.js @@ -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: diff --git a/package.json b/package.json index 6d64719d..e33b4385 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/server/models/project.js b/server/models/project.js index b000843d..94cf17d3 100644 --- a/server/models/project.js +++ b/server/models/project.js @@ -16,6 +16,7 @@ const defaultHTML = +