merge in master
1
client/images/console-debug-dark.svg
Normal 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 |
1
client/images/console-debug-light.svg
Normal 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 |
1
client/images/console-error-dark.svg
Normal 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 |
1
client/images/console-error-light.svg
Normal 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 |
1
client/images/console-info-dark.svg
Normal 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 |
1
client/images/console-info-light.svg
Normal 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 |
1
client/images/console-warn-dark.svg
Normal 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 |
1
client/images/console-warn-light.svg
Normal 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 |
|
@ -2,13 +2,63 @@ import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
import InlineSVG from 'react-inlinesvg';
|
||||||
import classNames from 'classnames';
|
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 upArrowUrl = require('../../../images/up-arrow.svg');
|
||||||
const downArrowUrl = require('../../../images/down-arrow.svg');
|
const downArrowUrl = require('../../../images/down-arrow.svg');
|
||||||
|
|
||||||
class Console extends React.Component {
|
class Console extends React.Component {
|
||||||
componentDidUpdate() {
|
componentDidUpdate(prevProps) {
|
||||||
this.consoleMessages.scrollTop = this.consoleMessages.scrollHeight;
|
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() {
|
render() {
|
||||||
|
@ -39,17 +89,25 @@ class Console extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
<div ref={(element) => { this.consoleMessages = element; }} className="preview-console__messages">
|
<div ref={(element) => { this.consoleMessages = element; }} className="preview-console__messages">
|
||||||
{this.props.consoleEvents.map((consoleEvent) => {
|
{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) {
|
if (Object.keys(args).length === 0) {
|
||||||
return (
|
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>
|
<span key={`${consoleEvent.id}-0`}>undefined</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div key={consoleEvent.id} className={`preview-console__${method}`}>
|
<div key={consoleEvent.id} className={`preview-console__message preview-console__message--${method}`}>
|
||||||
{Object.keys(args).map(key => <span key={`${consoleEvent.id}-${key}`}>{args[key]}</span>)}
|
{ times > 1 &&
|
||||||
|
<div className="preview-console__logged-times">{times}</div>
|
||||||
|
}
|
||||||
|
<ConsoleFeed
|
||||||
|
styles={this.getConsoleFeedStyle(theme, times)}
|
||||||
|
logs={Array.of(consoleEvent)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -67,7 +125,9 @@ Console.propTypes = {
|
||||||
isExpanded: PropTypes.bool.isRequired,
|
isExpanded: PropTypes.bool.isRequired,
|
||||||
collapseConsole: PropTypes.func.isRequired,
|
collapseConsole: PropTypes.func.isRequired,
|
||||||
expandConsole: 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 = {
|
Console.defaultProps = {
|
||||||
|
|
|
@ -116,8 +116,8 @@ class Editor extends React.Component {
|
||||||
this.props.setUnsavedChanges(true);
|
this.props.setUnsavedChanges(true);
|
||||||
this.props.updateFileContent(this.props.file.name, this._cm.getValue());
|
this.props.updateFileContent(this.props.file.name, this._cm.getValue());
|
||||||
if (this.props.autorefresh && this.props.isPlaying) {
|
if (this.props.autorefresh && this.props.isPlaying) {
|
||||||
this.props.startRefreshSketch();
|
|
||||||
this.props.clearConsole();
|
this.props.clearConsole();
|
||||||
|
this.props.startRefreshSketch();
|
||||||
}
|
}
|
||||||
}, 400));
|
}, 400));
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,9 @@ import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
// import escapeStringRegexp from 'escape-string-regexp';
|
// import escapeStringRegexp from 'escape-string-regexp';
|
||||||
|
import { isEqual } from 'lodash';
|
||||||
import srcDoc from 'srcdoc-polyfill';
|
import srcDoc from 'srcdoc-polyfill';
|
||||||
|
|
||||||
import loopProtect from 'loop-protect';
|
import loopProtect from 'loop-protect';
|
||||||
import loopProtectScript from 'loop-protect/dist/loop-protect.min';
|
|
||||||
import { JSHINT } from 'jshint';
|
import { JSHINT } from 'jshint';
|
||||||
import decomment from 'decomment';
|
import decomment from 'decomment';
|
||||||
import { getBlobUrl } from '../actions/files';
|
import { getBlobUrl } from '../actions/files';
|
||||||
|
@ -18,29 +17,17 @@ import {
|
||||||
EXTERNAL_LINK_REGEX,
|
EXTERNAL_LINK_REGEX,
|
||||||
NOT_EXTERNAL_LINK_REGEX
|
NOT_EXTERNAL_LINK_REGEX
|
||||||
} from '../../../../server/utils/fileUtils';
|
} from '../../../../server/utils/fileUtils';
|
||||||
import { hijackConsole, hijackConsoleErrorsScript, startTag, getAllScriptOffsets }
|
import { hijackConsoleErrorsScript, startTag, getAllScriptOffsets }
|
||||||
from '../../../utils/consoleUtils';
|
from '../../../utils/consoleUtils';
|
||||||
|
|
||||||
|
|
||||||
class PreviewFrame extends React.Component {
|
class PreviewFrame extends React.Component {
|
||||||
componentDidMount() {
|
constructor(props) {
|
||||||
if (this.props.isPlaying) {
|
super(props);
|
||||||
this.renderFrameContents();
|
this.handleConsoleEvent = this.handleConsoleEvent.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('message', (messageEvent) => {
|
componentDidMount() {
|
||||||
console.log(messageEvent);
|
window.addEventListener('message', this.handleConsoleEvent);
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
|
@ -86,12 +73,43 @@ class PreviewFrame extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
window.removeEventListener('message', this.handleConsoleEvent);
|
||||||
ReactDOM.unmountComponentAtNode(this.iframeElement.contentDocument.body);
|
ReactDOM.unmountComponentAtNode(this.iframeElement.contentDocument.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
clearPreview() {
|
handleConsoleEvent(messageEvent) {
|
||||||
const doc = this.iframeElement;
|
if (Array.isArray(messageEvent.data)) {
|
||||||
doc.srcDoc = '';
|
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) {
|
addLoopProtect(sketchDoc) {
|
||||||
|
@ -121,9 +139,7 @@ class PreviewFrame extends React.Component {
|
||||||
injectLocalFiles() {
|
injectLocalFiles() {
|
||||||
const htmlFile = this.props.htmlFile.content;
|
const htmlFile = this.props.htmlFile.content;
|
||||||
let scriptOffs = [];
|
let scriptOffs = [];
|
||||||
|
|
||||||
const resolvedFiles = this.resolveJSAndCSSLinks(this.props.files);
|
const resolvedFiles = this.resolveJSAndCSSLinks(this.props.files);
|
||||||
|
|
||||||
const parser = new DOMParser();
|
const parser = new DOMParser();
|
||||||
const sketchDoc = parser.parseFromString(htmlFile, 'text/html');
|
const sketchDoc = parser.parseFromString(htmlFile, 'text/html');
|
||||||
|
|
||||||
|
@ -138,10 +154,6 @@ class PreviewFrame extends React.Component {
|
||||||
this.resolveScripts(sketchDoc, resolvedFiles);
|
this.resolveScripts(sketchDoc, resolvedFiles);
|
||||||
this.resolveStyles(sketchDoc, resolvedFiles);
|
this.resolveStyles(sketchDoc, resolvedFiles);
|
||||||
|
|
||||||
const scriptsToInject = [
|
|
||||||
loopProtectScript,
|
|
||||||
hijackConsole
|
|
||||||
];
|
|
||||||
const accessiblelib = sketchDoc.createElement('script');
|
const accessiblelib = sketchDoc.createElement('script');
|
||||||
accessiblelib.setAttribute(
|
accessiblelib.setAttribute(
|
||||||
'src',
|
'src',
|
||||||
|
@ -156,15 +168,13 @@ class PreviewFrame extends React.Component {
|
||||||
const textSection = sketchDoc.createElement('section');
|
const textSection = sketchDoc.createElement('section');
|
||||||
textSection.setAttribute('id', 'textOutput-content');
|
textSection.setAttribute('id', 'textOutput-content');
|
||||||
sketchDoc.getElementById('accessible-outputs').appendChild(textSection);
|
sketchDoc.getElementById('accessible-outputs').appendChild(textSection);
|
||||||
this.iframeElement.focus();
|
|
||||||
}
|
}
|
||||||
if (this.props.gridOutput) {
|
if (this.props.gridOutput) {
|
||||||
sketchDoc.body.appendChild(accessibleOutputs);
|
sketchDoc.body.appendChild(accessibleOutputs);
|
||||||
sketchDoc.body.appendChild(accessiblelib);
|
sketchDoc.body.appendChild(accessiblelib);
|
||||||
const gridSection = sketchDoc.createElement('section');
|
const gridSection = sketchDoc.createElement('section');
|
||||||
gridSection.setAttribute('id', 'gridOutput-content');
|
gridSection.setAttribute('id', 'tableOutput-content');
|
||||||
sketchDoc.getElementById('accessible-outputs').appendChild(gridSection);
|
sketchDoc.getElementById('accessible-outputs').appendChild(gridSection);
|
||||||
this.iframeElement.focus();
|
|
||||||
}
|
}
|
||||||
if (this.props.soundOutput) {
|
if (this.props.soundOutput) {
|
||||||
sketchDoc.body.appendChild(accessibleOutputs);
|
sketchDoc.body.appendChild(accessibleOutputs);
|
||||||
|
@ -174,11 +184,9 @@ class PreviewFrame extends React.Component {
|
||||||
sketchDoc.getElementById('accessible-outputs').appendChild(soundSection);
|
sketchDoc.getElementById('accessible-outputs').appendChild(soundSection);
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptsToInject.forEach((scriptToInject) => {
|
const previewScripts = sketchDoc.createElement('script');
|
||||||
const script = sketchDoc.createElement('script');
|
previewScripts.src = '/previewScripts.js';
|
||||||
script.text = scriptToInject;
|
sketchDoc.head.appendChild(previewScripts);
|
||||||
sketchDoc.head.appendChild(script);
|
|
||||||
});
|
|
||||||
|
|
||||||
const sketchDocString = `<!DOCTYPE HTML>\n${sketchDoc.documentElement.outerHTML}`;
|
const sketchDocString = `<!DOCTYPE HTML>\n${sketchDoc.documentElement.outerHTML}`;
|
||||||
scriptOffs = getAllScriptOffsets(sketchDocString);
|
scriptOffs = getAllScriptOffsets(sketchDocString);
|
||||||
|
@ -320,15 +328,6 @@ class PreviewFrame extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderFrameContents() {
|
|
||||||
const doc = this.iframeElement.contentDocument;
|
|
||||||
if (doc.readyState === 'complete') {
|
|
||||||
this.renderSketch();
|
|
||||||
} else {
|
|
||||||
setTimeout(this.renderFrameContents, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<iframe
|
<iframe
|
||||||
|
|
|
@ -366,6 +366,8 @@ class IDEView extends React.Component {
|
||||||
expandConsole={this.props.expandConsole}
|
expandConsole={this.props.expandConsole}
|
||||||
collapseConsole={this.props.collapseConsole}
|
collapseConsole={this.props.collapseConsole}
|
||||||
clearConsole={this.props.clearConsole}
|
clearConsole={this.props.clearConsole}
|
||||||
|
dispatchConsoleEvent={this.props.dispatchConsoleEvent}
|
||||||
|
theme={this.props.preferences.theme}
|
||||||
/>
|
/>
|
||||||
</SplitPane>
|
</SplitPane>
|
||||||
<div className="preview-frame-holder">
|
<div className="preview-frame-holder">
|
||||||
|
|
|
@ -5,6 +5,10 @@ $p5js-pink: #ed225d;
|
||||||
$white: #fff;
|
$white: #fff;
|
||||||
$black: #000;
|
$black: #000;
|
||||||
$yellow: #F5DC23;
|
$yellow: #F5DC23;
|
||||||
|
$orange: #ffa500;
|
||||||
|
$red: #ff0000;
|
||||||
|
$lightsteelblue: #B0C4DE;
|
||||||
|
$dodgerblue: #1E90FF;
|
||||||
$primary-text-color: #333;
|
$primary-text-color: #333;
|
||||||
$icon-color: #8b8b8b;
|
$icon-color: #8b8b8b;
|
||||||
$icon-hover-color: #333;
|
$icon-hover-color: #333;
|
||||||
|
@ -37,8 +41,13 @@ $themes: (
|
||||||
icon-toast-hover-color: $white,
|
icon-toast-hover-color: $white,
|
||||||
shadow-color: rgba(0, 0, 0, 0.16),
|
shadow-color: rgba(0, 0, 0, 0.16),
|
||||||
console-background-color: #eee,
|
console-background-color: #eee,
|
||||||
|
console-color: $white,
|
||||||
console-header-background-color: #d6d6d6,
|
console-header-background-color: #d6d6d6,
|
||||||
console-header-color: #b1b1b1,
|
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,
|
ide-border-color: #f4f4f4,
|
||||||
editor-gutter-color: #f4f4f4,
|
editor-gutter-color: #f4f4f4,
|
||||||
file-selected-color: #f4f4f4,
|
file-selected-color: #f4f4f4,
|
||||||
|
@ -78,8 +87,13 @@ $themes: (
|
||||||
icon-toast-hover-color: $white,
|
icon-toast-hover-color: $white,
|
||||||
shadow-color: rgba(0, 0, 0, 0.16),
|
shadow-color: rgba(0, 0, 0, 0.16),
|
||||||
console-background-color: #4f4f4f,
|
console-background-color: #4f4f4f,
|
||||||
|
console-color: $black,
|
||||||
console-header-background-color: #3f3f3f,
|
console-header-background-color: #3f3f3f,
|
||||||
console-header-color: #b5b5b5,
|
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,
|
ide-border-color: #949494,
|
||||||
editor-gutter-color: #363636,
|
editor-gutter-color: #363636,
|
||||||
file-selected-color: #404040,
|
file-selected-color: #404040,
|
||||||
|
@ -118,8 +132,13 @@ $themes: (
|
||||||
icon-toast-hover-color: $yellow,
|
icon-toast-hover-color: $yellow,
|
||||||
shadow-color: rgba(0, 0, 0, 0.16),
|
shadow-color: rgba(0, 0, 0, 0.16),
|
||||||
console-background-color: #4f4f4f,
|
console-background-color: #4f4f4f,
|
||||||
|
console-color: $black,
|
||||||
console-header-background-color: #3f3f3f,
|
console-header-background-color: #3f3f3f,
|
||||||
console-header-color: #b5b5b5,
|
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,
|
ide-border-color: #949494,
|
||||||
editor-gutter-color: #454545,
|
editor-gutter-color: #454545,
|
||||||
file-selected-color: #404040,
|
file-selected-color: #404040,
|
||||||
|
|
47
client/styles/components/_console-feed.scss
Normal 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;
|
|
@ -17,29 +17,12 @@
|
||||||
text-align:left;
|
text-align:left;
|
||||||
}
|
}
|
||||||
|
|
||||||
// assign styles to different types of console messages
|
.preview-console__message {
|
||||||
.preview-console__log {
|
|
||||||
@include themify() {
|
@include themify() {
|
||||||
color: getThemifyVariable('secondary-text-color');
|
color: getThemifyVariable('console-color');
|
||||||
}
|
}
|
||||||
flex: 1 0 auto;
|
flex: 1 0 auto;
|
||||||
}
|
position: relative;
|
||||||
|
|
||||||
.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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,3 +86,35 @@
|
||||||
display: none;
|
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');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
border-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,42 +2,6 @@ import {
|
||||||
EXTERNAL_LINK_REGEX
|
EXTERNAL_LINK_REGEX
|
||||||
} from '../../server/utils/fileUtils';
|
} 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) => {
|
export const hijackConsoleErrorsScript = (offs) => {
|
||||||
const s = `
|
const s = `
|
||||||
function getScriptOff(line) {
|
function getScriptOff(line) {
|
||||||
|
|
21
client/utils/previewEntry.js
Normal 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);
|
|
@ -77,6 +77,7 @@
|
||||||
"clipboard": "^1.7.1",
|
"clipboard": "^1.7.1",
|
||||||
"codemirror": "^5.38.0",
|
"codemirror": "^5.38.0",
|
||||||
"connect-mongo": "^1.2.0",
|
"connect-mongo": "^1.2.0",
|
||||||
|
"console-feed": "^2.8.1",
|
||||||
"cookie-parser": "^1.4.1",
|
"cookie-parser": "^1.4.1",
|
||||||
"cors": "^2.8.1",
|
"cors": "^2.8.1",
|
||||||
"cross-env": "^5.1.3",
|
"cross-env": "^5.1.3",
|
||||||
|
@ -110,9 +111,8 @@
|
||||||
"project-name-generator": "^2.1.3",
|
"project-name-generator": "^2.1.3",
|
||||||
"prop-types": "^15.6.0",
|
"prop-types": "^15.6.0",
|
||||||
"q": "^1.4.1",
|
"q": "^1.4.1",
|
||||||
"raw-loader": "^0.5.1",
|
"react": "^16.4.0",
|
||||||
"react": "^16.2.0",
|
"react-dom": "^16.4.0",
|
||||||
"react-dom": "^16.2.0",
|
|
||||||
"react-helmet": "^5.1.3",
|
"react-helmet": "^5.1.3",
|
||||||
"react-hot-loader": "^4.1.2",
|
"react-hot-loader": "^4.1.2",
|
||||||
"react-inlinesvg": "^0.7.5",
|
"react-inlinesvg": "^0.7.5",
|
||||||
|
@ -130,6 +130,9 @@
|
||||||
"request-promise": "^4.1.1",
|
"request-promise": "^4.1.1",
|
||||||
"s3": "^4.4.0",
|
"s3": "^4.4.0",
|
||||||
"s3-policy": "^0.2.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",
|
"shortid": "^2.2.6",
|
||||||
"slugify": "^1.2.9",
|
"slugify": "^1.2.9",
|
||||||
"srcdoc-polyfill": "^0.2.0",
|
"srcdoc-polyfill": "^0.2.0",
|
||||||
|
|
|
@ -39,7 +39,7 @@ const corsOriginsWhitelist = [
|
||||||
// Run Webpack dev server in development mode
|
// Run Webpack dev server in development mode
|
||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
const compiler = webpack(config);
|
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));
|
app.use(webpackHotMiddleware(compiler));
|
||||||
|
|
||||||
corsOriginsWhitelist.push(/localhost/);
|
corsOriginsWhitelist.push(/localhost/);
|
||||||
|
@ -61,6 +61,7 @@ if (process.env.NODE_ENV === 'production') {
|
||||||
} else {
|
} else {
|
||||||
mongoConnectionString = process.env.MONGO_URL;
|
mongoConnectionString = process.env.MONGO_URL;
|
||||||
}
|
}
|
||||||
|
app.set('trust proxy', true);
|
||||||
|
|
||||||
// Enable Cross-Origin Resource Sharing (CORS) for all origins
|
// Enable Cross-Origin Resource Sharing (CORS) for all origins
|
||||||
const corsMiddleware = cors({
|
const corsMiddleware = cors({
|
||||||
|
|
|
@ -29,7 +29,8 @@ function resolveLinksInString(content, files, projectId) {
|
||||||
while (resolvedFilePath.startsWith('/')) {
|
while (resolvedFilePath.startsWith('/')) {
|
||||||
resolvedFilePath = resolvedFilePath.substr(1);
|
resolvedFilePath = resolvedFilePath.substr(1);
|
||||||
}
|
}
|
||||||
newContent = newContent.replace(filePath, `/sketches/${projectId}/assets/${resolvedFilePath}`);
|
const replacement = `/sketches/${projectId}/assets/${resolvedFilePath}`;
|
||||||
|
newContent = newContent.replace(filePath, replacement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ module.exports = {
|
||||||
module: {
|
module: {
|
||||||
loaders: [
|
loaders: [
|
||||||
{
|
{
|
||||||
test: /\.scss$/,
|
test: /main\.scss$/,
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
loader: ExtractTextPlugin.extract({
|
loader: ExtractTextPlugin.extract({
|
||||||
fallback: 'style-loader',
|
fallback: 'style-loader',
|
||||||
|
|
|
@ -3,7 +3,7 @@ if (process.env.NODE_ENV === 'development') {
|
||||||
require('dotenv').config();
|
require('dotenv').config();
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = [{
|
||||||
devtool: 'cheap-module-eval-source-map',
|
devtool: 'cheap-module-eval-source-map',
|
||||||
entry: {
|
entry: {
|
||||||
app: [
|
app: [
|
||||||
|
@ -72,7 +72,7 @@ module.exports = {
|
||||||
// }
|
// }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.scss$/,
|
test: /main\.scss$/,
|
||||||
loaders: ['style-loader', 'css-loader', 'sass-loader']
|
loaders: ['style-loader', 'css-loader', 'sass-loader']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -84,9 +84,52 @@ module.exports = {
|
||||||
loader: 'file-loader'
|
loader: 'file-loader'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /.*loop-protect.min.js$/,
|
test: /_console-feed.scss/,
|
||||||
loader: 'raw-loader'
|
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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}]
|
||||||
|
|
|
@ -10,7 +10,7 @@ if (process.env.NODE_ENV === "development") {
|
||||||
require('dotenv').config();
|
require('dotenv').config();
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = [{
|
||||||
devtool: 'source-map',
|
devtool: 'source-map',
|
||||||
|
|
||||||
entry: {
|
entry: {
|
||||||
|
@ -55,7 +55,7 @@ module.exports = {
|
||||||
module: {
|
module: {
|
||||||
loaders: [
|
loaders: [
|
||||||
{
|
{
|
||||||
test: /\.scss$/,
|
test: /main\.scss$/,
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
loader: ExtractTextPlugin.extract({
|
loader: ExtractTextPlugin.extract({
|
||||||
fallback: 'style-loader',
|
fallback: 'style-loader',
|
||||||
|
@ -76,8 +76,11 @@ module.exports = {
|
||||||
loader: 'file-loader'
|
loader: 'file-loader'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /.*loop-protect.min.js$/,
|
test: /_console-feed.scss/,
|
||||||
loader: 'raw-loader'
|
loader: 'sass-extract-loader',
|
||||||
|
options: {
|
||||||
|
plugins: [{ plugin: 'sass-extract-js', options: { camelCase: false } }]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -132,4 +135,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
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}];
|
||||||
|
|