feat(rechallenge): Remove JS files from build pipline if JS is disabled

This commit is contained in:
Stuart Taylor
2018-01-08 00:00:34 +00:00
parent 5c007e3d53
commit 303ad38b8e
5 changed files with 31 additions and 59 deletions

View File

@ -50,28 +50,22 @@ const wrapInStyle = partial(transformContents, (content) => (
const setExtToHTML = partial(setExt, 'html'); const setExtToHTML = partial(setExt, 'html');
const padContentWithJsCatch = partial(compileHeadTail, jsCatch); const padContentWithJsCatch = partial(compileHeadTail, jsCatch);
const padContentWithHTMLCatch = partial(compileHeadTail, htmlCatch); const padContentWithHTMLCatch = partial(compileHeadTail, htmlCatch);
function transformErrorProtect(fn) {
return cond([
[ matchesProperty('transformError', false), fn ],
[ stubTrue, identity ]
]);
}
export const jsToHtml = transformErrorProtect(cond([ export const jsToHtml = cond([
[ [
matchesProperty('ext', 'js'), matchesProperty('ext', 'js'),
flow(padContentWithJsCatch, wrapInScript, setExtToHTML) flow(padContentWithJsCatch, wrapInScript, setExtToHTML)
], ],
[ stubTrue, identity ] [ stubTrue, identity ]
])); ]);
export const cssToHtml = transformErrorProtect(cond([ export const cssToHtml = cond([
[ [
matchesProperty('ext', 'css'), matchesProperty('ext', 'css'),
flow(padContentWithHTMLCatch, wrapInStyle, setExtToHTML) flow(padContentWithHTMLCatch, wrapInStyle, setExtToHTML)
], ],
[ stubTrue, identity ] [ stubTrue, identity ]
])); ]);
// FileStream::concactHtml( // FileStream::concactHtml(
// required: [ ...Object ], // required: [ ...Object ],

View File

@ -37,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')`
@ -107,42 +107,28 @@ export const replaceNBSP = cond([
[ stubTrue, identity ] [ stubTrue, identity ]
]); ]);
const transformErrorWarn = '/* __fcc--TransformError__ */'; function tryTransform(wrap = identity) {
function tryJSTransform(wrap = identity, defaultAssignment = 'code') {
return function transformWrappedPoly(source) { return function transformWrappedPoly(source) {
const result = attempt(wrap, source); const result = attempt(wrap, source);
if (isError(result)) { if (isError(result)) {
const friendlyError = `${result}` const friendlyError = `${result}`
.match(/[\w\W]+?\n/)[0] .match(/[\w\W]+?\n/)[0]
.replace(' unknown:', ''); .replace(' unknown:', '');
console.error(friendlyError); throw new Error(friendlyError);
return `var ${defaultAssignment} = null; ${transformErrorWarn}`;
} }
return result; return result;
}; };
} }
function checkForTransformError(file) {
const potentialError = file.contents.includes(transformErrorWarn);
if (potentialError) {
return {
...vinyl.setTransformError(true, file)
};
}
return file;
}
export const babelTransformer = cond([ export const babelTransformer = cond([
[ [
testJS$JSX, testJS$JSX,
flow( flow(
partial( partial(
vinyl.transformHeadTailAndContents, vinyl.transformHeadTailAndContents,
tryJSTransform(babelTransformCode, 'JSX') tryTransform(babelTransformCode)
), ),
partial(vinyl.setExt, 'js'), partial(vinyl.setExt, 'js')
checkForTransformError
) )
], ],
[ stubTrue, identity ] [ stubTrue, identity ]

View File

@ -42,6 +42,7 @@ export function updateMainEpic(actions, { getState }, { document }) {
const proxyLogger = new Subject(); const proxyLogger = new Subject();
const frameMain = createMainFramer(document, getState, proxyLogger); const frameMain = createMainFramer(document, getState, proxyLogger);
const buildAndFrameMain = actions::ofType( const buildAndFrameMain = actions::ofType(
types.unlockUntrustedCode,
types.modernEditorUpdated, types.modernEditorUpdated,
types.classicEditorUpdated, types.classicEditorUpdated,
types.executeChallenge, types.executeChallenge,
@ -62,7 +63,6 @@ export function updateMainEpic(actions, { getState }, { document }) {
}); });
} }
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

@ -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,23 +44,27 @@ const globalRequires = [
jQuery jQuery
]; ];
function postTransformCheck(file) { function filterJSIfDisabled(state) {
if (file.transformError) { const isJSEnabled = isJSEnabledSelector(state);
// this will enable us to tap into the dipatch pipeline return file => {
// and disable JS in the preview if (testJS$JSX(file) && !isJSEnabled) {
throw new Error('There was an error whilst transforming your code'); return null;
} }
return file; 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(postTransformCheck)
::pipe(shouldProxyConsole ? proxyLoggerTransformer : identity) ::pipe(shouldProxyConsole ? proxyLoggerTransformer : identity)
::pipe(jsToHtml) ::pipe(jsToHtml)
::pipe(cssToHtml) ::pipe(cssToHtml)

View File

@ -5,11 +5,11 @@ import castToObservable from '../app/utils/cast-to-observable.js';
// createFileStream( // createFileStream(
// files: Dictionary[Path, PolyVinyl] // files: List[ 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)
); );
} }
@ -77,8 +77,7 @@ export function createPoly({
path: name + '.' + ext, path: name + '.' + ext,
key: name + ext, key: name + ext,
contents, contents,
error: null, error: null
transformError: false
}; };
} }
@ -156,19 +155,6 @@ export function setError(error, poly) {
error error
}; };
} }
// setTransformError(transformError: Boolean, poly: PolyVinyl) => PolyVinyl
export function setTransformError(transformError, poly) {
invariant(
typeof transformError === 'boolean',
'transformError must be a boolean, but got %',
transformError
);
checkPoly(poly);
return {
...poly,
transformError
};
}
// clearHeadTail(poly: PolyVinyl) => PolyVinyl // clearHeadTail(poly: PolyVinyl) => PolyVinyl
export function clearHeadTail(poly) { export function clearHeadTail(poly) {