Improve current console (#656)

* init v2

* make replay work

* fix a failing scenary of react-frame

* fix some bugs

* delete/comment some files

* remove

* fix some bugs && remove more comments

* remove unnecessary lines

* minor tweak

* fix some bugs

* try to hook iframe using webpack

* update

* changes according to cassie

* minor tweak

* fix lint

* extract sass

* add icons

* update webpack config

* update webpack configuration

* update

* tweak

* fix a small bug
This commit is contained in:
Liang Tang 2018-07-31 00:20:57 +08:00 committed by Cassie Tarakajian
parent 903713e705
commit 617f00653c
23 changed files with 348 additions and 132 deletions

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="10" height="10" viewBox="0 0 24 24"><path fill="#0c99e2" d="M14,12H10V10H14M14,16H10V14H14M20,8H17.19C16.74,7.22 16.12,6.55 15.37,6.04L17,4.41L15.59,3L13.42,5.17C12.96,5.06 12.5,5 12,5C11.5,5 11.04,5.06 10.59,5.17L8.41,3L7,4.41L8.62,6.04C7.88,6.55 7.26,7.22 6.81,8H4V10H6.09C6.04,10.33 6,10.66 6,11V12H4V14H6V15C6,15.34 6.04,15.67 6.09,16H4V18H6.81C7.85,19.79 9.78,21 12,21C14.22,21 16.15,19.79 17.19,18H20V16H17.91C17.96,15.67 18,15.34 18,15V14H20V12H18V11C18,10.66 17.96,10.33 17.91,10H20V8Z" /></svg>

After

Width:  |  Height:  |  Size: 743 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="10" height="10" viewBox="0 0 24 24"><path fill="#007BBB" d="M14,12H10V10H14M14,16H10V14H14M20,8H17.19C16.74,7.22 16.12,6.55 15.37,6.04L17,4.41L15.59,3L13.42,5.17C12.96,5.06 12.5,5 12,5C11.5,5 11.04,5.06 10.59,5.17L8.41,3L7,4.41L8.62,6.04C7.88,6.55 7.26,7.22 6.81,8H4V10H6.09C6.04,10.33 6,10.66 6,11V12H4V14H6V15C6,15.34 6.04,15.67 6.09,16H4V18H6.81C7.85,19.79 9.78,21 12,21C14.22,21 16.15,19.79 17.19,18H20V16H17.91C17.96,15.67 18,15.34 18,15V14H20V12H18V11C18,10.66 17.96,10.33 17.91,10H20V8Z" /></svg>

After

Width:  |  Height:  |  Size: 743 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="10" height="10" viewBox="0 0 24 24"><path fill="#df3a3d" d="M12,2C17.53,2 22,6.47 22,12C22,17.53 17.53,22 12,22C6.47,22 2,17.53 2,12C2,6.47 6.47,2 12,2M15.59,7L12,10.59L8.41,7L7,8.41L10.59,12L7,15.59L8.41,17L12,13.41L15.59,17L17,15.59L13.41,12L17,8.41L15.59,7Z" /></svg>

After

Width:  |  Height:  |  Size: 510 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="10" height="10" viewBox="0 0 24 24"><path fill="#D11518" d="M12,2C17.53,2 22,6.47 22,12C22,17.53 17.53,22 12,22C6.47,22 2,17.53 2,12C2,6.47 6.47,2 12,2M15.59,7L12,10.59L8.41,7L7,8.41L10.59,12L7,15.59L8.41,17L12,13.41L15.59,17L17,15.59L13.41,12L17,8.41L15.59,7Z" /></svg>

After

Width:  |  Height:  |  Size: 510 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="10" height="10" viewBox="0 0 24 24"><path fill="#a3a3a3" d="M13,9H11V7H13M13,17H11V11H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" /></svg>

After

Width:  |  Height:  |  Size: 414 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="10" height="10" viewBox="0 0 24 24"><path fill="#7D7D7D" d="M13,9H11V7H13M13,17H11V11H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" /></svg>

After

Width:  |  Height:  |  Size: 414 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="10" height="10" viewBox="0 0 24 24"><path fill="#f5bc38" d="M13,14H11V10H13M13,18H11V16H13M1,21H23L12,2L1,21Z" /></svg>

After

Width:  |  Height:  |  Size: 359 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="10" height="10" viewBox="0 0 24 24"><path fill="#FAAF00" d="M13,14H11V10H13M13,18H11V16H13M1,21H23L12,2L1,21Z" /></svg>

After

Width:  |  Height:  |  Size: 359 B

View File

@ -2,13 +2,63 @@ import PropTypes from 'prop-types';
import React from 'react';
import InlineSVG from 'react-inlinesvg';
import classNames from 'classnames';
import { Console as ConsoleFeed } from 'console-feed';
import { CONSOLE_FEED_WITHOUT_ICONS, CONSOLE_FEED_LIGHT_STYLES, CONSOLE_FEED_DARK_STYLES, CONSOLE_FEED_CONTRAST_STYLES } from '../../../styles/components/_console-feed.scss';
import warnLightUrl from '../../../images/console-warn-light.svg';
import warnDarkUrl from '../../../images/console-warn-dark.svg';
import errorLightUrl from '../../../images/console-error-light.svg';
import errorDarkUrl from '../../../images/console-error-dark.svg';
import debugLightUrl from '../../../images/console-debug-light.svg';
import debugDarkUrl from '../../../images/console-debug-dark.svg';
import infoLightUrl from '../../../images/console-info-light.svg';
import infoDarkUrl from '../../../images/console-info-dark.svg';
const upArrowUrl = require('../../../images/up-arrow.svg');
const downArrowUrl = require('../../../images/down-arrow.svg');
class Console extends React.Component {
componentDidUpdate() {
componentDidUpdate(prevProps) {
this.consoleMessages.scrollTop = this.consoleMessages.scrollHeight;
if (this.props.theme !== prevProps.theme) {
this.props.clearConsole();
this.props.dispatchConsoleEvent(this.props.consoleEvents);
}
}
getConsoleFeedStyle(theme, times) {
const style = {};
const CONSOLE_FEED_LIGHT_ICONS = {
LOG_WARN_ICON: `url(${warnLightUrl})`,
LOG_ERROR_ICON: `url(${errorLightUrl})`,
LOG_DEBUG_ICON: `url(${debugLightUrl})`,
LOG_INFO_ICON: `url(${infoLightUrl})`
};
const CONSOLE_FEED_DARK_ICONS = {
LOG_WARN_ICON: `url(${warnDarkUrl})`,
LOG_ERROR_ICON: `url(${errorDarkUrl})`,
LOG_DEBUG_ICON: `url(${debugDarkUrl})`,
LOG_INFO_ICON: `url(${infoDarkUrl})`
};
if (times > 1) {
Object.assign(style, CONSOLE_FEED_WITHOUT_ICONS);
}
switch (theme) {
case 'light':
return Object.assign(CONSOLE_FEED_LIGHT_STYLES, CONSOLE_FEED_LIGHT_ICONS, style);
case 'dark':
return Object.assign(CONSOLE_FEED_DARK_STYLES, CONSOLE_FEED_DARK_ICONS, style);
case 'contrast':
return Object.assign(CONSOLE_FEED_CONTRAST_STYLES, CONSOLE_FEED_DARK_ICONS, style);
default:
return '';
}
}
formatData(args) {
if (!Array.isArray(args)) {
return Array.of(args);
}
return args;
}
render() {
@ -39,17 +89,25 @@ class Console extends React.Component {
</div>
<div ref={(element) => { this.consoleMessages = element; }} className="preview-console__messages">
{this.props.consoleEvents.map((consoleEvent) => {
const { arguments: args, method } = consoleEvent;
const { arguments: args, method, times } = consoleEvent;
const { theme } = this.props;
Object.assign(consoleEvent, { data: this.formatData(args) });
if (Object.keys(args).length === 0) {
return (
<div key={consoleEvent.id} className="preview-console__undefined">
<div key={consoleEvent.id} className="preview-console__message preview-console__message--undefined">
<span key={`${consoleEvent.id}-0`}>undefined</span>
</div>
);
}
return (
<div key={consoleEvent.id} className={`preview-console__${method}`}>
{Object.keys(args).map(key => <span key={`${consoleEvent.id}-${key}`}>{args[key]}</span>)}
<div key={consoleEvent.id} className={`preview-console__message preview-console__message--${method}`}>
{ times > 1 &&
<div className="preview-console__logged-times">{times}</div>
}
<ConsoleFeed
styles={this.getConsoleFeedStyle(theme, times)}
logs={Array.of(consoleEvent)}
/>
</div>
);
})}
@ -67,7 +125,9 @@ Console.propTypes = {
isExpanded: PropTypes.bool.isRequired,
collapseConsole: PropTypes.func.isRequired,
expandConsole: PropTypes.func.isRequired,
clearConsole: PropTypes.func.isRequired
clearConsole: PropTypes.func.isRequired,
dispatchConsoleEvent: PropTypes.func.isRequired,
theme: PropTypes.string.isRequired
};
Console.defaultProps = {

View File

@ -116,8 +116,8 @@ class Editor extends React.Component {
this.props.setUnsavedChanges(true);
this.props.updateFileContent(this.props.file.name, this._cm.getValue());
if (this.props.autorefresh && this.props.isPlaying) {
this.props.startRefreshSketch();
this.props.clearConsole();
this.props.startRefreshSketch();
}
}, 400));

View File

@ -2,10 +2,9 @@ import PropTypes from 'prop-types';
import React from 'react';
import ReactDOM from 'react-dom';
// import escapeStringRegexp from 'escape-string-regexp';
import { isEqual } from 'lodash';
import srcDoc from 'srcdoc-polyfill';
import loopProtect from 'loop-protect';
import loopProtectScript from 'loop-protect/dist/loop-protect.min';
import { JSHINT } from 'jshint';
import decomment from 'decomment';
import { getBlobUrl } from '../actions/files';
@ -18,38 +17,20 @@ import {
EXTERNAL_LINK_REGEX,
NOT_EXTERNAL_LINK_REGEX
} from '../../../../server/utils/fileUtils';
import { hijackConsole, hijackConsoleErrorsScript, startTag, getAllScriptOffsets }
import { hijackConsoleErrorsScript, startTag, getAllScriptOffsets }
from '../../../utils/consoleUtils';
class PreviewFrame extends React.Component {
componentDidMount() {
if (this.props.isPlaying) {
this.renderFrameContents();
}
constructor(props) {
super(props);
this.handleConsoleEvent = this.handleConsoleEvent.bind(this);
}
window.addEventListener('message', (messageEvent) => {
console.log(messageEvent);
messageEvent.data.forEach((message) => {
const args = message.arguments;
Object.keys(args).forEach((key) => {
if (args[key].includes('Exiting potential infinite loop')) {
this.props.stopSketch();
this.props.expandConsole();
}
});
});
this.props.dispatchConsoleEvent(messageEvent.data);
});
componentDidMount() {
window.addEventListener('message', this.handleConsoleEvent);
}
componentDidUpdate(prevProps) {
// if sketch starts or stops playing, want to rerender
if (this.props.isPlaying !== prevProps.isPlaying) {
this.renderSketch();
return;
}
// if the user explicitly clicks on the play button
if (this.props.isPlaying && this.props.previewIsRefreshing) {
this.renderSketch();
@ -86,12 +67,43 @@ class PreviewFrame extends React.Component {
}
componentWillUnmount() {
window.removeEventListener('message', this.handleConsoleEvent);
ReactDOM.unmountComponentAtNode(this.iframeElement.contentDocument.body);
}
clearPreview() {
const doc = this.iframeElement;
doc.srcDoc = '';
handleConsoleEvent(messageEvent) {
if (Array.isArray(messageEvent.data)) {
messageEvent.data.every((message, index, arr) => {
const { arguments: args } = message;
let hasInfiniteLoop = false;
Object.keys(args).forEach((key) => {
if (typeof args[key] === 'string' && args[key].includes('Exiting potential infinite loop')) {
this.props.stopSketch();
this.props.expandConsole();
hasInfiniteLoop = true;
}
});
if (hasInfiniteLoop) {
return false;
}
if (index === arr.length - 1) {
Object.assign(message, { times: 1 });
return false;
}
const cur = Object.assign(message, { times: 1 });
const nextIndex = index + 1;
while (isEqual(cur.arguments, arr[nextIndex].arguments) && cur.method === arr[nextIndex].method) {
cur.times += 1;
arr.splice(nextIndex, 1);
if (nextIndex === arr.length) {
return false;
}
}
return true;
});
this.props.dispatchConsoleEvent(messageEvent.data);
}
}
addLoopProtect(sketchDoc) {
@ -121,9 +133,7 @@ class PreviewFrame extends React.Component {
injectLocalFiles() {
const htmlFile = this.props.htmlFile.content;
let scriptOffs = [];
const resolvedFiles = this.resolveJSAndCSSLinks(this.props.files);
const parser = new DOMParser();
const sketchDoc = parser.parseFromString(htmlFile, 'text/html');
@ -138,10 +148,6 @@ class PreviewFrame extends React.Component {
this.resolveScripts(sketchDoc, resolvedFiles);
this.resolveStyles(sketchDoc, resolvedFiles);
const scriptsToInject = [
loopProtectScript,
hijackConsole
];
const accessiblelib = sketchDoc.createElement('script');
accessiblelib.setAttribute(
'src',
@ -156,7 +162,6 @@ class PreviewFrame extends React.Component {
const textSection = sketchDoc.createElement('section');
textSection.setAttribute('id', 'textOutput-content');
sketchDoc.getElementById('accessible-outputs').appendChild(textSection);
this.iframeElement.focus();
}
if (this.props.gridOutput) {
sketchDoc.body.appendChild(accessibleOutputs);
@ -164,7 +169,6 @@ class PreviewFrame extends React.Component {
const gridSection = sketchDoc.createElement('section');
gridSection.setAttribute('id', 'gridOutput-content');
sketchDoc.getElementById('accessible-outputs').appendChild(gridSection);
this.iframeElement.focus();
}
if (this.props.soundOutput) {
sketchDoc.body.appendChild(accessibleOutputs);
@ -174,11 +178,9 @@ class PreviewFrame extends React.Component {
sketchDoc.getElementById('accessible-outputs').appendChild(soundSection);
}
scriptsToInject.forEach((scriptToInject) => {
const script = sketchDoc.createElement('script');
script.text = scriptToInject;
sketchDoc.head.appendChild(script);
});
const previewScripts = sketchDoc.createElement('script');
previewScripts.src = '/previewScripts.js';
sketchDoc.head.appendChild(previewScripts);
const sketchDocString = `<!DOCTYPE HTML>\n${sketchDoc.documentElement.outerHTML}`;
scriptOffs = getAllScriptOffsets(sketchDocString);
@ -320,15 +322,6 @@ class PreviewFrame extends React.Component {
}
}
renderFrameContents() {
const doc = this.iframeElement.contentDocument;
if (doc.readyState === 'complete') {
this.renderSketch();
} else {
setTimeout(this.renderFrameContents, 0);
}
}
render() {
return (
<iframe

View File

@ -366,6 +366,8 @@ class IDEView extends React.Component {
expandConsole={this.props.expandConsole}
collapseConsole={this.props.collapseConsole}
clearConsole={this.props.clearConsole}
dispatchConsoleEvent={this.props.dispatchConsoleEvent}
theme={this.props.preferences.theme}
/>
</SplitPane>
<div className="preview-frame-holder">

View File

@ -5,6 +5,10 @@ $p5js-pink: #ed225d;
$white: #fff;
$black: #000;
$yellow: #F5DC23;
$orange: #ffa500;
$red: #ff0000;
$lightsteelblue: #B0C4DE;
$dodgerblue: #1E90FF;
$primary-text-color: #333;
$icon-color: #8b8b8b;
$icon-hover-color: #333;
@ -37,8 +41,13 @@ $themes: (
icon-toast-hover-color: $white,
shadow-color: rgba(0, 0, 0, 0.16),
console-background-color: #eee,
console-color: $white,
console-header-background-color: #d6d6d6,
console-header-color: #b1b1b1,
console-info-background-color: $lightsteelblue,
console-warn-background-color: $orange,
console-debug-background-color: $dodgerblue,
console-error-background-color: $red,
ide-border-color: #f4f4f4,
editor-gutter-color: #f4f4f4,
file-selected-color: #f4f4f4,
@ -78,8 +87,13 @@ $themes: (
icon-toast-hover-color: $white,
shadow-color: rgba(0, 0, 0, 0.16),
console-background-color: #4f4f4f,
console-color: $black,
console-header-background-color: #3f3f3f,
console-header-color: #b5b5b5,
console-info-background-color: $lightsteelblue,
console-warn-background-color: $orange,
console-debug-background-color: $dodgerblue,
console-error-background-color: $red,
ide-border-color: #949494,
editor-gutter-color: #363636,
file-selected-color: #404040,
@ -118,8 +132,13 @@ $themes: (
icon-toast-hover-color: $yellow,
shadow-color: rgba(0, 0, 0, 0.16),
console-background-color: #4f4f4f,
console-color: $black,
console-header-background-color: #3f3f3f,
console-header-color: #b5b5b5,
console-info-background-color: $lightsteelblue,
console-warn-background-color: $orange,
console-debug-background-color: $dodgerblue,
console-error-background-color: $red,
ide-border-color: #949494,
editor-gutter-color: #454545,
file-selected-color: #404040,
@ -152,4 +171,4 @@ $form-button-active-color: $white;
$form-navigation-options-color: #999999;
$about-play-background-color: rgba(255, 255, 255, 0.7);
$about-button-border-color: rgba(151, 151, 151, 0.7);
$about-button-border-color: rgba(151, 151, 151, 0.7);

View File

@ -0,0 +1,47 @@
$CONSOLE_FEED_WITHOUT_ICONS: (
LOG_WARN_ICON: 'none',
LOG_ERROR_ICON: 'none',
LOG_DEBUG_ICON: 'none',
LOG_INFO_ICON: 'none'
);
$CONSOLE_FEED_LIGHT_STYLES: (
BASE_BACKGROUND_COLOR: '',
LOG_ERROR_BACKGROUND: 'hsl(0, 100%, 97%)',
LOG_ERROR_COLOR: '#D11518',
LOG_ERROR_BORDER: 'hsl(0, 100%, 92%)',
LOG_WARN_BACKGROUND: 'hsl(50, 100%, 95%)',
LOG_WARN_COLOR: '#FAAF00',
LOG_WARN_BORDER: 'hsl(50, 100%, 88%)',
LOG_INFO_COLOR: '#7D7D7D',
LOG_DEBUG_COLOR: '#007BBB',
LOG_COLOR: 'rgb(128, 128, 128)'
);
$CONSOLE_FEED_DARK_STYLES: (
BASE_BACKGROUND_COLOR: '',
BASE_COLOR: 'white',
OBJECT_NAME_COLOR: 'white',
OBJECT_VALUE_NULL_COLOR: 'hsl(230, 100%, 80%)',
OBJECT_VALUE_UNDEFINED_COLOR: 'hsl(230, 100%, 80%)',
OBJECT_VALUE_REGEXP_COLOR: 'hsl(230, 100%, 80%)',
OBJECT_VALUE_STRING_COLOR: 'hsl(230, 100%, 80%)',
OBJECT_VALUE_SYMBOL_COLOR: 'hsl(230, 100%, 80%)',
OBJECT_VALUE_NUMBER_COLOR: 'hsl(230, 100%, 80%)',
OBJECT_VALUE_BOOLEAN_COLOR: 'hsl(230, 100%, 80%)',
OBJECT_VALUE_FUNCTION_KEYWORD_COLOR: 'hsl(230, 100%, 80%)',
LOG_ERROR_BACKGROUND: 'hsl(0, 100%, 8%)',
LOG_ERROR_COLOR: '#df3a3d',
LOG_WARN_BACKGROUND: 'hsl(50, 100%, 10%)',
LOG_WARN_COLOR: '#f5bc38',
LOG_INFO_COLOR: '#a3a3a3',
LOG_DEBUG_COLOR: '#0c99e2',
TABLE_BORDER_COLOR: 'grey',
TABLE_TH_BACKGROUND_COLOR: 'transparent',
TABLE_TH_HOVER_COLOR: 'grey',
TABLE_SORT_ICON_COLOR: 'grey',
TABLE_DATA_BACKGROUND_IMAGE: 'grey',
TABLE_DATA_BACKGROUND_SIZE: 'grey'
);
$CONSOLE_FEED_CONTRAST_STYLES: $CONSOLE_FEED_DARK_STYLES;

View File

@ -17,29 +17,12 @@
text-align:left;
}
// assign styles to different types of console messages
.preview-console__log {
@include themify(){
color: getThemifyVariable('secondary-text-color');
.preview-console__message {
@include themify() {
color: getThemifyVariable('console-color');
}
flex: 1 0 auto;
}
.preview-console__undefined {
@include themify(){
color: getThemifyVariable('inactive-text-color');
}
flex: 1 0 auto;
}
.preview-console__error {
color: $console-error-color;
flex: 1 0 auto;
}
.preview-console__warn {
color: $console-warn-color;
flex: 1 0 auto;
position: relative;
}
}
@ -102,4 +85,36 @@
.preview-console--collapsed & {
display: none;
}
}
.preview-console__logged-times {
font-size: #{10 / $base-font-size}rem;
font-weight: bold;
margin: #{2 / $base-font-size}rem 0 0 #{8 / $base-font-size}rem;
border-radius: 10px;
padding: #{1 / $base-font-size}rem #{4 / $base-font-size}rem;
z-index: 100;
left: 0;
position: absolute;
.preview-console__message--info &, .preview-console__message--log & {
@include themify() {
background-color: getThemifyVariable('console-info-background-color');
}
}
.preview-console__message--warn & {
@include themify() {
background-color: getThemifyVariable('console-warn-background-color');
}
}
.preview-console__message--debug & {
@include themify() {
background-color: getThemifyVariable('console-debug-background-color');
}
}
.preview-console__message--error & {
@include themify() {
background-color: getThemifyVariable('console-error-background-color');
}
}
}

View File

@ -2,6 +2,7 @@
min-height: 100%;
min-width: 100%;
position: absolute;
border-width: 0;
}

View File

@ -2,42 +2,6 @@ import {
EXTERNAL_LINK_REGEX
} from '../../server/utils/fileUtils';
export const hijackConsole = `var iframeWindow = window;
var originalConsole = iframeWindow.console;
iframeWindow.console = {};
var methods = [
'debug', 'clear', 'error', 'info', 'log', 'warn'
];
var consoleBuffer = [];
var LOGWAIT = 500;
methods.forEach( function(method) {
iframeWindow.console[method] = function() {
originalConsole[method].apply(originalConsole, arguments);
var args = Array.from(arguments);
args = args.map(function(i) {
// catch objects
return (typeof i === 'string') ? i : JSON.stringify(i);
});
consoleBuffer.push({
method: method,
arguments: args,
source: 'sketch'
});
};
});
setInterval(function() {
if (consoleBuffer.length > 0) {
window.parent.postMessage(consoleBuffer, '*');
consoleBuffer.length = 0;
}
}, LOGWAIT);`;
export const hijackConsoleErrorsScript = (offs) => {
const s = `
function getScriptOff(line) {

View File

@ -0,0 +1,21 @@
import loopProtect from 'loop-protect';
import Hook from 'console-feed/lib/Hook/index';
window.loopProtect = loopProtect;
const consoleBuffer = [];
const LOGWAIT = 500;
Hook(window.console, (log) => {
const { method, data: args } = log[0];
consoleBuffer.push({
method,
arguments: args,
source: 'sketch'
});
});
setInterval(() => {
if (consoleBuffer.length > 0) {
window.parent.postMessage(consoleBuffer, '*');
consoleBuffer.length = 0;
}
}, LOGWAIT);

View File

@ -73,6 +73,7 @@
"clipboard": "^1.7.1",
"codemirror": "^5.38.0",
"connect-mongo": "^1.2.0",
"console-feed": "^2.8.1",
"cookie-parser": "^1.4.1",
"cors": "^2.8.1",
"cross-env": "^5.1.3",
@ -106,9 +107,8 @@
"project-name-generator": "^2.1.3",
"prop-types": "^15.6.0",
"q": "^1.4.1",
"raw-loader": "^0.5.1",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react": "^16.4.0",
"react-dom": "^16.4.0",
"react-helmet": "^5.1.3",
"react-hot-loader": "^4.1.2",
"react-inlinesvg": "^0.7.5",
@ -126,6 +126,9 @@
"request-promise": "^4.1.1",
"s3": "^4.4.0",
"s3-policy": "^0.2.0",
"sass-extract": "^2.1.0",
"sass-extract-js": "^0.4.0",
"sass-extract-loader": "^1.1.0",
"shortid": "^2.2.6",
"slugify": "^1.2.9",
"srcdoc-polyfill": "^0.2.0",

View File

@ -39,7 +39,7 @@ const corsOriginsWhitelist = [
// Run Webpack dev server in development mode
if (process.env.NODE_ENV === 'development') {
const compiler = webpack(config);
app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: config.output.publicPath }));
app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: config[0].output.publicPath }));
app.use(webpackHotMiddleware(compiler));
corsOriginsWhitelist.push(/localhost/);

View File

@ -18,7 +18,7 @@ module.exports = {
module: {
loaders: [
{
test: /\.scss$/,
test: /main\.scss$/,
exclude: /node_modules/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',

View File

@ -1,7 +1,8 @@
const webpack = require('webpack');
const path = require('path');
require('dotenv').config();
module.exports = {
module.exports = [{
devtool: 'cheap-module-eval-source-map',
entry: {
app: [
@ -70,7 +71,7 @@ module.exports = {
// }
},
{
test: /\.scss$/,
test: /main\.scss$/,
loaders: ['style-loader', 'css-loader', 'sass-loader']
},
{
@ -82,9 +83,52 @@ module.exports = {
loader: 'file-loader'
},
{
test: /.*loop-protect.min.js$/,
loader: 'raw-loader'
test: /_console-feed.scss/,
loader: 'sass-extract-loader',
options: {
plugins: [{ plugin: 'sass-extract-js', options: { camelCase: false } }]
}
}
],
},
};
},
{
entry: path.resolve(__dirname, 'client/utils/previewEntry.js'),
target: 'web',
output: {
path: `${__dirname}`,
filename: 'previewScripts.js',
publicPath: '/'
},
resolve: {
extensions: ['*', '.js', '.jsx'],
modules: [
'client',
'node_modules',
],
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: [
'react',
'env',
'stage-0',
],
plugins: [
[
'babel-plugin-webpack-loaders', {
'config': './webpack.config.babel.js',
"verbose": false
}
]
]
},
}
],
},
}]

View File

@ -8,7 +8,7 @@ const postcssReporter = require('postcss-reporter');
const cssnano = require('cssnano');
require('dotenv').config();
module.exports = {
module.exports = [{
devtool: 'source-map',
entry: {
@ -53,7 +53,7 @@ module.exports = {
module: {
loaders: [
{
test: /\.scss$/,
test: /main\.scss$/,
exclude: /node_modules/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
@ -74,8 +74,11 @@ module.exports = {
loader: 'file-loader'
},
{
test: /.*loop-protect.min.js$/,
loader: 'raw-loader'
test: /_console-feed.scss/,
loader: 'sass-extract-loader',
options: {
plugins: [{ plugin: 'sass-extract-js', options: { camelCase: false } }]
}
}
]
},
@ -126,4 +129,40 @@ module.exports = {
})
],
};
},
{
entry: {
app: [
'./client/utils/previewEntry.js'
]
},
target: 'web',
output: {
path: `${__dirname}/dist/static`,
filename: 'previewScripts.js',
publicPath: '/'
},
resolve: {
extensions: ['*', '.js', '.jsx'],
modules: [
'client',
'node_modules',
],
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
]
}];