Merge pull request #16370 from Bouncey/fix/babelPipeline

fix(rechallenge): Remove JS files from build pipeline when JS is disabled
This commit is contained in:
Berkeley Martinez
2018-02-26 12:10:11 -08:00
committed by GitHub
6 changed files with 55 additions and 17 deletions

View File

@ -1,4 +1,5 @@
import React, { PropTypes, PureComponent } from 'react'; import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import ns from './ns.json'; import ns from './ns.json';

View File

@ -1,7 +1,9 @@
import { import {
attempt,
cond, cond,
flow, flow,
identity, identity,
isError,
matchesProperty, matchesProperty,
overEvery, overEvery,
overSome, overSome,
@ -35,7 +37,7 @@ const NBSPReg = new RegExp(String.fromCharCode(160), 'g');
const isJS = matchesProperty('ext', 'js'); const isJS = matchesProperty('ext', 'js');
const testHTMLJS = overSome(isJS, matchesProperty('ext', 'html')); const testHTMLJS = overSome(isJS, matchesProperty('ext', 'html'));
const testJS$JSX = overSome(isJS, matchesProperty('ext', 'jsx')); export const testJS$JSX = overSome(isJS, matchesProperty('ext', 'jsx'));
// work around the absence of multi-flile editing // work around the absence of multi-flile editing
// this can be replaced with `matchesProperty('ext', 'sass')` // this can be replaced with `matchesProperty('ext', 'sass')`
@ -105,13 +107,26 @@ export const replaceNBSP = cond([
[ stubTrue, identity ] [ stubTrue, identity ]
]); ]);
function tryTransform(wrap = identity) {
return function transformWrappedPoly(source) {
const result = attempt(wrap, source);
if (isError(result)) {
const friendlyError = `${result}`
.match(/[\w\W]+?\n/)[0]
.replace(' unknown:', '');
throw new Error(friendlyError);
}
return result;
};
}
export const babelTransformer = cond([ export const babelTransformer = cond([
[ [
testJS$JSX, testJS$JSX,
flow( flow(
partial( partial(
vinyl.transformHeadTailAndContents, vinyl.transformHeadTailAndContents,
babelTransformCode tryTransform(babelTransformCode)
), ),
partial(vinyl.setExt, 'js') partial(vinyl.setExt, 'js')
) )

View File

@ -12,7 +12,8 @@ import {
codeLockedSelector, codeLockedSelector,
showPreviewSelector, showPreviewSelector,
testsSelector testsSelector,
disableJSOnError
} from './'; } from './';
import { import {
buildFromFiles, buildFromFiles,
@ -26,7 +27,8 @@ import {
import { import {
createErrorObservable, createErrorObservable,
challengeSelector challengeSelector,
doActionOnError
} from '../../../redux'; } from '../../../redux';
@ -55,13 +57,12 @@ export function updateMainEpic(actions, { getState }, { document }) {
.flatMapLatest(() => buildFromFiles(getState(), true) .flatMapLatest(() => buildFromFiles(getState(), true)
.map(frameMain) .map(frameMain)
.ignoreElements() .ignoreElements()
.catch(createErrorObservable) .catch(doActionOnError(() => disableJSOnError()))
); );
return Observable.merge(buildAndFrameMain, proxyLogger.map(updateOutput)); return Observable.merge(buildAndFrameMain, proxyLogger.map(updateOutput));
}); });
} }
export function executeChallengeEpic(actions, { getState }, { document }) { export function executeChallengeEpic(actions, { getState }, { document }) {
return Observable.of(document) return Observable.of(document)
// if document is not defined then none of this epic will run // if document is not defined then none of this epic will run

View File

@ -77,6 +77,7 @@ export const types = createTypes([
'checkChallenge', 'checkChallenge',
createAsyncTypes('submitChallenge'), createAsyncTypes('submitChallenge'),
'moveToNextChallenge', 'moveToNextChallenge',
'disableJSOnError',
'checkForNextBlock', 'checkForNextBlock',
// help // help
@ -153,6 +154,8 @@ export const submitChallengeComplete = createAction(
export const moveToNextChallenge = createAction(types.moveToNextChallenge); export const moveToNextChallenge = createAction(types.moveToNextChallenge);
export const checkForNextBlock = createAction(types.checkForNextBlock); export const checkForNextBlock = createAction(types.checkForNextBlock);
export const disableJSOnError = createAction(types.disableJSOnError);
// help // help
export const openHelpModal = createAction(types.openHelpModal); export const openHelpModal = createAction(types.openHelpModal);
export const closeHelpModal = createAction(types.closeHelpModal); export const closeHelpModal = createAction(types.closeHelpModal);
@ -308,6 +311,7 @@ export default combineReducers(
[ [
combineActions( combineActions(
types.classicEditorUpdated, types.classicEditorUpdated,
types.disableJSOnError,
types.modernEditorUpdated types.modernEditorUpdated
) )
]: state => ({ ]: state => ({

View File

@ -6,11 +6,13 @@ import throwers from '../rechallenge/throwers';
import { import {
backendFormValuesSelector, backendFormValuesSelector,
challengeTemplateSelector, challengeTemplateSelector,
challengeRequiredSelector challengeRequiredSelector,
isJSEnabledSelector
} from '../redux'; } from '../redux';
import { import {
applyTransformers, applyTransformers,
proxyLoggerTransformer proxyLoggerTransformer,
testJS$JSX
} from '../rechallenge/transformers'; } from '../rechallenge/transformers';
import { import {
cssToHtml, cssToHtml,
@ -42,11 +44,25 @@ const globalRequires = [
jQuery jQuery
]; ];
function filterJSIfDisabled(state) {
const isJSEnabled = isJSEnabledSelector(state);
return file => {
if (testJS$JSX(file) && !isJSEnabled) {
return null;
}
return file;
};
}
export function buildFromFiles(state, shouldProxyConsole) { export function buildFromFiles(state, shouldProxyConsole) {
const files = filesSelector(state); const files = filesSelector(state);
const required = challengeRequiredSelector(state); const required = challengeRequiredSelector(state);
const finalRequires = [...globalRequires, ...required ]; const finalRequires = [...globalRequires, ...required ];
return createFileStream(files) const requiredFiles = Object.keys(files)
.map(key => files[key])
.filter(filterJSIfDisabled(state))
.filter(Boolean);
return createFileStream(requiredFiles)
::pipe(throwers) ::pipe(throwers)
::pipe(applyTransformers) ::pipe(applyTransformers)
::pipe(shouldProxyConsole ? proxyLoggerTransformer : identity) ::pipe(shouldProxyConsole ? proxyLoggerTransformer : identity)

View File

@ -5,11 +5,11 @@ import castToObservable from '../app/utils/cast-to-observable.js';
// createFileStream( // createFileStream(
// files: Dictionary[Path, PolyVinyl] // files: [...PolyVinyl]
// ) => Observable[...Observable[...PolyVinyl]] // ) => Observable[...Observable[...PolyVinyl]]
export function createFileStream(files = {}) { export function createFileStream(files = []) {
return Observable.of( return Observable.of(
Observable.from(Object.keys(files).map(key => files[key])) Observable.from(files)
); );
} }
@ -116,7 +116,7 @@ export function setContent(contents, poly) {
}; };
} }
// setExt(contents: String, poly: PolyVinyl) => PolyVinyl // setExt(ext: String, poly: PolyVinyl) => PolyVinyl
export function setExt(ext, poly) { export function setExt(ext, poly) {
checkPoly(poly); checkPoly(poly);
const newPoly = { const newPoly = {
@ -129,7 +129,7 @@ export function setExt(ext, poly) {
return newPoly; return newPoly;
} }
// setName(contents: String, poly: PolyVinyl) => PolyVinyl // setName(name: String, poly: PolyVinyl) => PolyVinyl
export function setName(name, poly) { export function setName(name, poly) {
checkPoly(poly); checkPoly(poly);
const newPoly = { const newPoly = {
@ -142,7 +142,7 @@ export function setName(name, poly) {
return newPoly; return newPoly;
} }
// setError(contents: String, poly: PolyVinyl) => PolyVinyl // setError(error: Object, poly: PolyVinyl) => PolyVinyl
export function setError(error, poly) { export function setError(error, poly) {
invariant( invariant(
typeof error === 'object', typeof error === 'object',
@ -166,6 +166,7 @@ export function clearHeadTail(poly) {
}; };
} }
// appendToTail (tail: String, poly: PolyVinyl) => PolyVinyl
export function appendToTail(tail, poly) { export function appendToTail(tail, poly) {
checkPoly(poly); checkPoly(poly);
return { return {
@ -174,7 +175,7 @@ export function appendToTail(tail, poly) {
}; };
} }
// compileHeadTail(contents: String, poly: PolyVinyl) => PolyVinyl // compileHeadTail(padding: String, poly: PolyVinyl) => PolyVinyl
export function compileHeadTail(padding = '', poly) { export function compileHeadTail(padding = '', poly) {
return clearHeadTail(transformContents( return clearHeadTail(transformContents(
() => [ poly.head, poly.contents, poly.tail ].join(padding), () => [ poly.head, poly.contents, poly.tail ].join(padding),