diff --git a/src/components/ContentWrap.jsx b/src/components/ContentWrap.jsx
index da9327b..4bd14b8 100644
--- a/src/components/ContentWrap.jsx
+++ b/src/components/ContentWrap.jsx
@@ -34,7 +34,6 @@ export default class ContentWrap extends Component {
this.logCount = 0;
window.onMessageFromConsole = this.onMessageFromConsole.bind(this);
-
window.previewException = this.previewException.bind(this);
// `clearConsole` is on window because it gets called from inside iframe also.
window.clearConsole = this.clearConsole.bind(this);
diff --git a/src/components/ContentWrap2.jsx b/src/components/ContentWrapFiles.jsx
similarity index 81%
rename from src/components/ContentWrap2.jsx
rename to src/components/ContentWrapFiles.jsx
index 798cd9f..97fc9f9 100644
--- a/src/components/ContentWrap2.jsx
+++ b/src/components/ContentWrapFiles.jsx
@@ -1,19 +1,19 @@
import { h, Component } from 'preact';
-import UserCodeMirror from './UserCodeMirror.jsx';
-import { computeHtml, computeCss, computeJs } from '../computes';
+import UserCodeMirror from './UserCodeMirror';
import { modes, HtmlModes, CssModes, JsModes } from '../codeModes';
-import { log, writeFile, loadJS, getCompleteHtml } from '../utils';
-import { SplitPane } from './SplitPane.jsx';
+import { log, loadJS } from '../utils';
+import { SplitPane } from './SplitPane';
import { trackEvent } from '../analytics';
import CodeMirror from '../CodeMirror';
-import CodeMirrorBox from './CodeMirrorBox';
import { deferred } from '../deferred';
import { SidePane } from './SidePane';
+import { Console } from './Console';
+
const minCodeWrapSize = 33;
/* global htmlCodeEl, jsCodeEl, cssCodeEl, logCountEl
*/
-export default class ContentWrap2 extends Component {
+export default class ContentWrapFiles extends Component {
constructor(props) {
super(props);
this.state = {
@@ -28,8 +28,12 @@ export default class ContentWrap2 extends Component {
this.prefs = {};
this.codeInPreview = { html: null, css: null, js: null };
this.cmCodes = { html: props.currentItem.html, css: '', js: '' };
- // this.cm = {};
this.logCount = 0;
+
+ window.onMessageFromConsole = this.onMessageFromConsole.bind(this);
+ window.previewException = this.previewException.bind(this);
+ // `clearConsole` is on window because it gets called from inside iframe also.
+ window.clearConsole = this.clearConsole.bind(this);
}
shouldComponentUpdate(nextProps, nextState) {
return (
@@ -130,6 +134,19 @@ export default class ContentWrap2 extends Component {
var obj = {};
this.props.currentItem.files.forEach(file => {
obj[`/user/${file.name}`] = file.content || '';
+
+ // Add screenlog to index.html
+ if (file.name === 'index.html') {
+ obj[`/user/${file.name}`] =
+ '' +
+ obj[`/user/${file.name}`];
+ }
});
navigator.serviceWorker.controller.postMessage(obj);
@@ -422,6 +439,92 @@ export default class ContentWrap2 extends Component {
this.cm.focus();
}
+ updateLogCount() {
+ if (window.logCountEl) {
+ logCountEl.textContent = this.logCount;
+ }
+ }
+
+ onMessageFromConsole() {
+ /* eslint-disable no-param-reassign */
+ [...arguments].forEach(arg => {
+ if (
+ arg &&
+ arg.indexOf &&
+ arg.indexOf('filesystem:chrome-extension') !== -1
+ ) {
+ arg = arg.replace(
+ /filesystem:chrome-extension.*\.js:(\d+):*(\d*)/g,
+ 'script $1:$2'
+ );
+ }
+ try {
+ this.consoleCm.replaceRange(
+ arg +
+ ' ' +
+ ((arg + '').match(/\[object \w+]/) ? JSON.stringify(arg) : '') +
+ '\n',
+ {
+ line: Infinity
+ }
+ );
+ } catch (e) {
+ this.consoleCm.replaceRange('🌀\n', {
+ line: Infinity
+ });
+ }
+ this.consoleCm.scrollTo(0, Infinity);
+ this.logCount++;
+ });
+ this.updateLogCount();
+
+ /* eslint-enable no-param-reassign */
+ }
+
+ previewException(error) {
+ console.error('Possible infinite loop detected.', error.stack);
+ this.onMessageFromConsole('Possible infinite loop detected.', error.stack);
+ }
+
+ toggleConsole() {
+ this.setState({ isConsoleOpen: !this.state.isConsoleOpen });
+ trackEvent('ui', 'consoleToggle');
+ }
+ consoleHeaderDblClickHandler(e) {
+ if (!e.target.classList.contains('js-console__header')) {
+ return;
+ }
+ trackEvent('ui', 'consoleToggleDblClick');
+ this.toggleConsole();
+ }
+ clearConsole() {
+ this.consoleCm.setValue('');
+ this.logCount = 0;
+ this.updateLogCount();
+ }
+ clearConsoleBtnClickHandler() {
+ this.clearConsole();
+ trackEvent('ui', 'consoleClearBtnClick');
+ }
+
+ evalConsoleExpr(e) {
+ // Clear console on CTRL + L
+ if ((e.which === 76 || e.which === 12) && e.ctrlKey) {
+ this.clearConsole();
+ trackEvent('ui', 'consoleClearKeyboardShortcut');
+ } else if (e.which === 13) {
+ this.onMessageFromConsole('> ' + e.target.value);
+
+ /* eslint-disable no-underscore-dangle */
+ this.frame.contentWindow._wmEvaluate(e.target.value);
+
+ /* eslint-enable no-underscore-dangle */
+
+ e.target.value = '';
+ trackEvent('fn', 'evalConsoleExpr');
+ }
+ }
+
render() {
return (
+ (this.consoleCm = el)}
+ />
);
diff --git a/src/components/app.jsx b/src/components/app.jsx
index 8f2f3c9..74cb0f3 100644
--- a/src/components/app.jsx
+++ b/src/components/app.jsx
@@ -4,7 +4,8 @@
import { h, Component } from 'preact';
import '../service-worker-registration';
import { MainHeader } from './MainHeader.jsx';
-import ContentWrap2 from './ContentWrap2.jsx';
+import ContentWrap from './ContentWrap.jsx';
+import ContentWrapFiles from './ContentWrapFiles.jsx';
import Footer from './Footer.jsx';
import SavedItemPane from './SavedItemPane.jsx';
import AddLibrary from './AddLibrary.jsx';
@@ -1222,18 +1223,32 @@ export default class App extends Component {
user={this.state.user}
unsavedEditCount={this.state.unsavedEditCount}
/>
- (this.contentWrap = comp)}
- prefs={this.state.prefs}
- onEditorFocus={this.editorFocusHandler.bind(this)}
- onSplitUpdate={this.splitUpdateHandler.bind(this)}
- onAddFile={this.addFileHandler.bind(this)}
- onRemoveFile={this.removeFileHandler.bind(this)}
- />
+ {this.state.currentItem && this.state.currentItem.files ? (
+ (this.contentWrap = comp)}
+ prefs={this.state.prefs}
+ onEditorFocus={this.editorFocusHandler.bind(this)}
+ onSplitUpdate={this.splitUpdateHandler.bind(this)}
+ onAddFile={this.addFileHandler.bind(this)}
+ onRemoveFile={this.removeFileHandler.bind(this)}
+ />
+ ) : (
+ (this.contentWrap = comp)}
+ prefs={this.state.prefs}
+ onEditorFocus={this.editorFocusHandler.bind(this)}
+ onSplitUpdate={this.splitUpdateHandler.bind(this)}
+ />
+ )}