import React, { PropTypes } from 'react'; import ReactDOM from 'react-dom'; import escapeStringRegexp from 'escape-string-regexp'; import srcDoc from 'srcdoc-polyfill'; /** * Stringify all of the console objects from an array for proxying */ function stringifyArgs(args) { var newArgs = []; // TODO this was forEach but when the array is [undefined] it wouldn't // iterate over them var i = 0, length = args.length, arg; for(; i < length; i++) { arg = args[i]; if (typeof arg === 'undefined') { newArgs.push('undefined'); } else { newArgs.push(stringify(arg)); } } return newArgs; }; function hijackConsoleScript(lineOffset) { return ``; } class PreviewFrame extends React.Component { componentDidMount() { if (this.props.isPlaying) { this.renderFrameContents(); } if (this.props.dispatchConsoleEvent) { window.addEventListener('message', (msg) => { if (msg.data.source === 'sketch') { this.props.dispatchConsoleEvent(msg); } }); } } componentDidUpdate(prevProps) { if (this.props.isPlaying !== prevProps.isPlaying) { this.renderSketch(); } if (this.props.isPlaying && this.props.content !== prevProps.content) { this.renderSketch(); } // I apologize for this, it is a hack. if (this.props.isPlaying && this.props.files[0].id !== prevProps.files[0].id) { this.renderSketch(); } } componentWillUnmount() { ReactDOM.unmountComponentAtNode(ReactDOM.findDOMNode(this).contentDocument.body); } clearPreview() { const doc = ReactDOM.findDOMNode(this); doc.srcDoc = ''; } injectLocalFiles() { let htmlFile = this.props.htmlFile.content; // have to build the array manually because the spread operator is only // one level down... const jsFiles = []; this.props.jsFiles.forEach(jsFile => { const newJSFile = { ...jsFile }; let jsFileStrings = newJSFile.content.match(/(['"])((\\\1|.)*?)\1/gm); jsFileStrings = jsFileStrings || []; jsFileStrings.forEach(jsFileString => { if (jsFileString.match(/^('|")(?!(http:\/\/|https:\/\/)).*\.(png|jpg|jpeg|gif|bmp|mp3|wav|aiff|ogg|json)('|")$/i)) { const filePath = jsFileString.substr(1, jsFileString.length - 2); let fileName = filePath; if (fileName.match(/^\.\//)) { fileName = fileName.substr(2, fileName.length - 1); } else if (fileName.match(/^\//)) { fileName = fileName.substr(1, fileName.length - 1); } this.props.files.forEach(file => { if (file.name === fileName) { newJSFile.content = newJSFile.content.replace(filePath, file.blobURL); // eslint-disable-line } }); } }); jsFiles.push(newJSFile); }); jsFiles.forEach(jsFile => { const fileName = escapeStringRegexp(jsFile.name); const fileRegex = new RegExp(`([\s\S]*?)<\/script>`, 'gmi'); htmlFile = htmlFile.replace(fileRegex, ``); }); this.props.cssFiles.forEach(cssFile => { const fileName = escapeStringRegexp(cssFile.name); const fileRegex = new RegExp(``, 'gmi'); htmlFile = htmlFile.replace(fileRegex, ``); }); if (this.props.textOutput || this.props.isTextOutputPlaying) { 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'; htmlHeadContents += '\n'; htmlHeadContents += '\n'; htmlHeadContents += ''; htmlFile = htmlFile.replace(/(?:)([\s\S]*?)(?:<\/head>)/gmi, `\n${htmlHeadContents}\n`); } var lineOffset = htmlFile.substring(0, htmlFile.indexOf('