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 padContentWithJsCatch = partial(compileHeadTail, jsCatch);
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'),
flow(padContentWithJsCatch, wrapInScript, setExtToHTML)
],
[ stubTrue, identity ]
]));
]);
export const cssToHtml = transformErrorProtect(cond([
export const cssToHtml = cond([
[
matchesProperty('ext', 'css'),
flow(padContentWithHTMLCatch, wrapInStyle, setExtToHTML)
],
[ stubTrue, identity ]
]));
]);
// FileStream::concactHtml(
// required: [ ...Object ],

View File

@ -37,7 +37,7 @@ const NBSPReg = new RegExp(String.fromCharCode(160), 'g');
const isJS = matchesProperty('ext', 'js');
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
// this can be replaced with `matchesProperty('ext', 'sass')`
@ -107,42 +107,28 @@ export const replaceNBSP = cond([
[ stubTrue, identity ]
]);
const transformErrorWarn = '/* __fcc--TransformError__ */';
function tryJSTransform(wrap = identity, defaultAssignment = 'code') {
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:', '');
console.error(friendlyError);
return `var ${defaultAssignment} = null; ${transformErrorWarn}`;
throw new Error(friendlyError);
}
return result;
};
}
function checkForTransformError(file) {
const potentialError = file.contents.includes(transformErrorWarn);
if (potentialError) {
return {
...vinyl.setTransformError(true, file)
};
}
return file;
}
export const babelTransformer = cond([
[
testJS$JSX,
flow(
partial(
vinyl.transformHeadTailAndContents,
tryJSTransform(babelTransformCode, 'JSX')
tryTransform(babelTransformCode)
),
partial(vinyl.setExt, 'js'),
checkForTransformError
partial(vinyl.setExt, 'js')
)
],
[ stubTrue, identity ]

View File

@ -42,6 +42,7 @@ export function updateMainEpic(actions, { getState }, { document }) {
const proxyLogger = new Subject();
const frameMain = createMainFramer(document, getState, proxyLogger);
const buildAndFrameMain = actions::ofType(
types.unlockUntrustedCode,
types.modernEditorUpdated,
types.classicEditorUpdated,
types.executeChallenge,
@ -62,7 +63,6 @@ export function updateMainEpic(actions, { getState }, { document }) {
});
}
export function executeChallengeEpic(actions, { getState }, { document }) {
return Observable.of(document)
// if document is not defined then none of this epic will run

View File

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

View File

@ -5,11 +5,11 @@ import castToObservable from '../app/utils/cast-to-observable.js';
// createFileStream(
// files: Dictionary[Path, PolyVinyl]
// files: List[ PolyVinyl ]
// ) => Observable[...Observable[...PolyVinyl]]
export function createFileStream(files = {}) {
export function createFileStream(files = []) {
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,
key: name + ext,
contents,
error: null,
transformError: false
error: null
};
}
@ -156,19 +155,6 @@ export function setError(error, poly) {
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
export function clearHeadTail(poly) {