Feature(challenges): Run user js code through babel

This is a naive implementation.
Ideally we would detect the users environment
and dynamically load only the appropriate plugins
pull/10270/head
Berkeley Martinez 2016-08-18 18:23:44 -07:00
parent bfbe7214cc
commit 7d6250e8af
3 changed files with 48 additions and 7 deletions

View File

@ -1,3 +1,6 @@
import * as babel from 'babel-core';
import presetEs2015 from 'babel-preset-es2015';
import presetReact from 'babel-preset-react';
import { Observable } from 'rx'; import { Observable } from 'rx';
/* eslint-disable import/no-unresolved */ /* eslint-disable import/no-unresolved */
import loopProtect from 'loop-protect'; import loopProtect from 'loop-protect';
@ -5,6 +8,7 @@ import loopProtect from 'loop-protect';
import { updateContents } from '../../common/utils/polyvinyl'; import { updateContents } from '../../common/utils/polyvinyl';
const babelOptions = { presets: [ presetEs2015, presetReact ] };
loopProtect.hit = function hit(line) { loopProtect.hit = function hit(line) {
var err = 'Error: Exiting potential infinite loop at line ' + var err = 'Error: Exiting potential infinite loop at line ' +
line + line +
@ -26,6 +30,21 @@ const transformersForHtmlJS = {
] ]
}; };
const transformersForJs = {
ext: /js/,
transformers: [
{
name: 'babel-transformer',
transformer: function babelTransformer(file) {
const result = babel.transform(file.contents, babelOptions);
return updateContents(
result.code,
file
);
}
}
]
};
// Observable[Observable[File]]::addLoopProtect() => Observable[String] // Observable[Observable[File]]::addLoopProtect() => Observable[String]
export default function transformers() { export default function transformers() {
@ -34,6 +53,16 @@ export default function transformers() {
if (!transformersForHtmlJS.ext.test(file.ext)) { if (!transformersForHtmlJS.ext.test(file.ext)) {
return Observable.just(file); return Observable.just(file);
} }
if (
transformersForJs.ext.test(file.ext) &&
transformersForHtmlJS.ext.test(file.ext)
) {
return Observable.of(
...transformersForHtmlJS.transformers,
...transformersForJs.transformers
)
.reduce((file, context) => context.transformer(file), file);
}
return Observable.from(transformersForHtmlJS.transformers) return Observable.from(transformersForHtmlJS.transformers)
.reduce((file, context) => context.transformer(file), file); .reduce((file, context) => context.transformer(file), file);
})); }));

View File

@ -33,6 +33,9 @@
"dependencies": { "dependencies": {
"accepts": "^1.3.0", "accepts": "^1.3.0",
"async": "^1.5.0", "async": "^1.5.0",
"babel-core": "^6.3.26",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"babel-register": "^6.3.0", "babel-register": "^6.3.0",
"body-parser": "^1.13.2", "body-parser": "^1.13.2",
"cheerio": "~0.20.0", "cheerio": "~0.20.0",
@ -120,13 +123,10 @@
"devDependencies": { "devDependencies": {
"adler32": "~0.1.7", "adler32": "~0.1.7",
"babel-cli": "^6.3.17", "babel-cli": "^6.3.17",
"babel-core": "^6.3.26",
"babel-eslint": "^6.1.2", "babel-eslint": "^6.1.2",
"babel-istanbul": "^0.11.0", "babel-istanbul": "^0.11.0",
"babel-loader": "^6.2.1", "babel-loader": "^6.2.1",
"babel-plugin-add-module-exports": "^0.2.1", "babel-plugin-add-module-exports": "^0.2.1",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"babel-preset-stage-0": "^6.3.13", "babel-preset-stage-0": "^6.3.13",
"browser-sync": "^2.9.12", "browser-sync": "^2.9.12",
"chunk-manifest-webpack-plugin": "0.1.0", "chunk-manifest-webpack-plugin": "0.1.0",
@ -170,4 +170,4 @@
"yargs": "^4.1.0" "yargs": "^4.1.0"
}, },
"snyk": true "snyk": true
} }

View File

@ -10,6 +10,13 @@ module.exports = {
bundle: './client' bundle: './client'
}, },
devtool: __DEV__ ? 'inline-source-map' : null, devtool: __DEV__ ? 'inline-source-map' : null,
node: {
// Mock Node.js modules that Babel require()s but that we don't
// particularly care about.
fs: 'empty',
module: 'empty',
net: 'empty'
},
output: { output: {
filename: __DEV__ ? 'bundle.js' : 'bundle-[hash].js', filename: __DEV__ ? 'bundle.js' : 'bundle-[hash].js',
chunkFilename: __DEV__ ? chunkFilename: __DEV__ ?
@ -43,14 +50,19 @@ module.exports = {
'loop-protect': 'loopProtect' 'loop-protect': 'loopProtect'
}, },
plugins: [ plugins: [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(true),
new webpack.DefinePlugin({ new webpack.DefinePlugin({
'process.env': { 'process.env': {
NODE_ENV: JSON.stringify(__DEV__ ? 'development' : 'production') NODE_ENV: JSON.stringify(__DEV__ ? 'development' : 'production')
}, },
__DEVTOOLS__: !__DEV__ __DEVTOOLS__: !__DEV__
}) }),
// Use browser version of visionmedia-debug
new webpack.NormalModuleReplacementPlugin(
/debug\/node/,
'debug/browser'
),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(true)
] ]
}; };