Initial work on new framework
This commit is contained in:
21
client/new-framework/add-loop-protect.js
Normal file
21
client/new-framework/add-loop-protect.js
Normal file
@ -0,0 +1,21 @@
|
||||
import loopProtect from 'loopProtect';
|
||||
|
||||
loopProtect.hit = function hit(line) {
|
||||
var err = 'Error: Exiting potential infinite loop at line ' +
|
||||
line +
|
||||
'. To disable loop protection, write: \n\\/\\/ noprotect\nas the first' +
|
||||
'line. Beware that if you do have an infinite loop in your code' +
|
||||
'this will crash your browser.';
|
||||
console.error(err);
|
||||
};
|
||||
|
||||
// Observable[Observable[File]]::addLoopProtect() => Observable[String]
|
||||
export default function addLoopProtect() {
|
||||
const source = this;
|
||||
return source.map(files$ => files$.map(file => {
|
||||
if (file.extname === 'js') {
|
||||
file.contents = loopProtect(file.contents);
|
||||
}
|
||||
return file;
|
||||
}));
|
||||
}
|
13
client/new-framework/execute-challenge-saga.js
Normal file
13
client/new-framework/execute-challenge-saga.js
Normal file
@ -0,0 +1,13 @@
|
||||
import createTypes from '../../common/app/utils/create-types';
|
||||
const filterTypes = [
|
||||
execute
|
||||
];
|
||||
export default function executeChallengeSaga(action$, getState) {
|
||||
return action$
|
||||
.filter(({ type }) => filterTypes.some(_type => _type === type))
|
||||
.map(action => {
|
||||
if (action.type === execute) {
|
||||
const editors = getState().editors;
|
||||
}
|
||||
})
|
||||
}
|
92
client/new-framework/polyvinyl.js
Normal file
92
client/new-framework/polyvinyl.js
Normal file
@ -0,0 +1,92 @@
|
||||
// originally base off of https://github.com/gulpjs/vinyl
|
||||
import path from 'path';
|
||||
import replaceExt from 'replace-ext';
|
||||
|
||||
export default class File {
|
||||
constructor({
|
||||
path,
|
||||
history = [],
|
||||
base,
|
||||
contents = ''
|
||||
} = {}) {
|
||||
// Record path change
|
||||
this.history = path ? [path] : history;
|
||||
this.base = base || this.cwd;
|
||||
this.contents = contents;
|
||||
this._isPolyVinyl = true;
|
||||
this.error = null;
|
||||
}
|
||||
|
||||
static isPolyVinyl = function(file) {
|
||||
return file && file._isPolyVinyl === true || false;
|
||||
};
|
||||
|
||||
isEmpty() {
|
||||
return !this._contents;
|
||||
}
|
||||
|
||||
get contents() {
|
||||
return this._contents;
|
||||
}
|
||||
|
||||
set contents(val) {
|
||||
if (typeof val !== 'string') {
|
||||
throw new TypeError('File.contents can only a String');
|
||||
}
|
||||
this._contents = val;
|
||||
}
|
||||
|
||||
get basename() {
|
||||
if (!this.path) {
|
||||
throw new Error('No path specified! Can not get basename.');
|
||||
}
|
||||
return path.basename(this.path);
|
||||
}
|
||||
|
||||
set basename(basename) {
|
||||
if (!this.path) {
|
||||
throw new Error('No path specified! Can not set basename.');
|
||||
}
|
||||
this.path = path.join(path.dirname(this.path), basename);
|
||||
}
|
||||
|
||||
get extname() {
|
||||
if (!this.path) {
|
||||
throw new Error('No path specified! Can not get extname.');
|
||||
}
|
||||
return path.extname(this.path);
|
||||
}
|
||||
|
||||
set extname(extname) {
|
||||
if (!this.path) {
|
||||
throw new Error('No path specified! Can not set extname.');
|
||||
}
|
||||
this.path = replaceExt(this.path, extname);
|
||||
}
|
||||
|
||||
get path() {
|
||||
return this.history[this.history.length - 1];
|
||||
}
|
||||
|
||||
set path(path) {
|
||||
if (typeof path !== 'string') {
|
||||
throw new TypeError('path should be string');
|
||||
}
|
||||
|
||||
// Record history only when path changed
|
||||
if (path && path !== this.path) {
|
||||
this.history.push(path);
|
||||
}
|
||||
}
|
||||
|
||||
get error() {
|
||||
return this._error;
|
||||
}
|
||||
|
||||
set error(err) {
|
||||
if (typeof err !== 'object') {
|
||||
throw new TypeError('error must be an object or null');
|
||||
}
|
||||
this.error = err;
|
||||
}
|
||||
}
|
0
client/new-framework/redux/types.js
Normal file
0
client/new-framework/redux/types.js
Normal file
89
client/new-framework/throw-unsafe-code.js
Normal file
89
client/new-framework/throw-unsafe-code.js
Normal file
@ -0,0 +1,89 @@
|
||||
import { helpers, Observable } from 'rx';
|
||||
|
||||
const throwForJsHtml = {
|
||||
extname: /js|html/,
|
||||
throwers: [
|
||||
{
|
||||
name: 'multiline-comment',
|
||||
description: 'Detect if a JS multi-line comment is left open',
|
||||
thrower: function checkForComments({ content }) {
|
||||
const openingComments = content.match(/\/\*/gi);
|
||||
const closingComments = content.match(/\*\//gi);
|
||||
if (
|
||||
openingComments &&
|
||||
(!closingComments || openingComments.length > closingComments.length)
|
||||
) {
|
||||
throw new Error('SyntaxError: Unfinished multi-line comment');
|
||||
}
|
||||
}
|
||||
}, {
|
||||
name: 'nested-jQuery',
|
||||
description: 'Nested dollar sign calls breaks browsers',
|
||||
detectUnsafeJQ: /\$\s*?\(\s*?\$\s*?\)/gi,
|
||||
thrower: function checkForNestedJquery({ content }) {
|
||||
if (content.match(this.detectUnsafeJQ)) {
|
||||
throw new Error('Unsafe $($)');
|
||||
}
|
||||
}
|
||||
}, {
|
||||
name: 'unfinished-function',
|
||||
description: 'lonely function keywords breaks browsers',
|
||||
detectFunctionCall: /function\s*?\(|function\s+\w+\s*?\(/gi,
|
||||
thower: function checkForUnfinishedFunction({ content: code }) {
|
||||
if (
|
||||
code.match(/function/g) &&
|
||||
!code.match(this.detectFunctionCall)
|
||||
) {
|
||||
throw new Error(
|
||||
'SyntaxError: Unsafe or unfinished function declaration'
|
||||
);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
name: 'unsafe console call',
|
||||
description: 'console call stops tests scripts from running',
|
||||
detectUnsafeConsoleCall: /if\s\(null\)\sconsole\.log\(1\);/gi,
|
||||
thrower: function checkForUnsafeConsole({ content }) {
|
||||
if (content.match(this.detectUnsafeConsoleCall)) {
|
||||
throw new Error('Invalid if (null) console.log(1); detected');
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export default function pretester() {
|
||||
const source = this;
|
||||
return source.map(file$ => file$.flatMap(file => {
|
||||
if (!throwForJsHtml.extname.test(file.extname)) {
|
||||
return Observable.just(file);
|
||||
}
|
||||
return Observable.from(throwForJsHtml.throwers)
|
||||
.flatMap(({ thrower }) => {
|
||||
try {
|
||||
let finalObs;
|
||||
const maybeObservableOrPromise = thrower(file);
|
||||
if (helpers.isPromise(maybeObservableOrPromise)) {
|
||||
finalObs = Observable.fromPromise(maybeObservableOrPromise);
|
||||
} else if (Observable.isObservable(maybeObservableOrPromise)) {
|
||||
finalObs = maybeObservableOrPromise;
|
||||
} else {
|
||||
finalObs = Observable.just(maybeObservableOrPromise);
|
||||
}
|
||||
return finalObs;
|
||||
} catch (err) {
|
||||
return Observable.throw(err);
|
||||
}
|
||||
})
|
||||
// if none of the throwers throw, wait for last one
|
||||
.last({ defaultValue: null })
|
||||
// then map to the original file
|
||||
.map(file)
|
||||
// if err add it to the file
|
||||
// and return file
|
||||
.catch(err => {
|
||||
file.error = err;
|
||||
return Observable.just(file);
|
||||
});
|
||||
}));
|
||||
}
|
@ -81,6 +81,7 @@
|
||||
"pmx": "~0.6.2",
|
||||
"react": "^15.0.2",
|
||||
"react-bootstrap": "~0.29.4",
|
||||
"react-codemirror": "^0.2.6",
|
||||
"react-css-transition-replace": "^1.2.0-beta",
|
||||
"react-dom": "^15.0.2",
|
||||
"react-fontawesome": "^0.3.3",
|
||||
@ -97,6 +98,7 @@
|
||||
"redux-actions": "^0.9.1",
|
||||
"redux-epic": "^0.1.1",
|
||||
"redux-form": "^5.2.3",
|
||||
"replace-ext": "0.0.1",
|
||||
"request": "^2.65.0",
|
||||
"reselect": "^2.0.2",
|
||||
"rx": "^4.0.0",
|
||||
|
@ -39,16 +39,16 @@ module.exports = {
|
||||
]
|
||||
},
|
||||
externals: {
|
||||
'codemirror': 'CodeMirror'
|
||||
codemirror: 'CodeMirror'
|
||||
},
|
||||
plugins: [
|
||||
new webpack.optimize.DedupePlugin(),
|
||||
new webpack.optimize.OccurenceOrderPlugin(true),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
'NODE_ENV': JSON.stringify(__DEV__ ? 'development' : 'production')
|
||||
NODE_ENV: JSON.stringify(__DEV__ ? 'development' : 'production')
|
||||
},
|
||||
'__DEVTOOLS__': !__DEV__
|
||||
__DEVTOOLS__: !__DEV__
|
||||
})
|
||||
]
|
||||
};
|
||||
|
Reference in New Issue
Block a user