Files
freeCodeCamp/client/rechallenge/transformers.js

109 lines
3.0 KiB
JavaScript
Raw Normal View History

import cond from 'lodash/cond';
import identity from 'lodash/identity';
import matchesProperty from 'lodash/matchesProperty';
import stubTrue from 'lodash/stubTrue';
import conforms from 'lodash/conforms';
import * as babel from 'babel-core';
import presetEs2015 from 'babel-preset-es2015';
import presetReact from 'babel-preset-react';
2016-05-20 12:42:26 -07:00
import { Observable } from 'rx';
/* eslint-disable import/no-unresolved */
2016-05-20 12:42:26 -07:00
import loopProtect from 'loop-protect';
/* eslint-enable import/no-unresolved */
2016-05-20 12:42:26 -07:00
import {
transformHeadTailAndContents,
setContent
} from '../../common/utils/polyvinyl.js';
import castToObservable from '../../common/app/utils/cast-to-observable.js';
const babelOptions = { presets: [ presetEs2015, presetReact ] };
2016-05-20 12:42:26 -07:00
loopProtect.hit = function hit(line) {
2016-10-25 10:58:46 +01:00
var err = 'Exiting potential infinite loop at line ' +
2016-05-20 12:42:26 -07:00
line +
2016-10-25 10:58:46 +01:00
'. To disable loop protection, write: \n\/\/ noprotect\nas the first ' +
'line. Beware that if you do have an infinite loop in your code, ' +
2016-05-20 12:42:26 -07:00
'this will crash your browser.';
2016-10-25 10:58:46 +01:00
throw new Error(err);
2016-05-20 12:42:26 -07:00
};
// const sourceReg =
// /(<!-- fcc-start-source -->)([\s\S]*?)(?=<!-- fcc-end-source -->)/g;
const HTML$JSReg = /html|js/;
const console$logReg = /(?:\b)console(\.log\S+)/g;
const NBSPReg = new RegExp(String.fromCharCode(160), 'g');
2016-05-20 12:42:26 -07:00
const testHTMLJS = conforms({ ext: (ext) => HTML$JSReg.test(ext) });
const testJS = matchesProperty('ext', 'js');
// if shouldProxyConsole then we change instances of console log
// to `window.__console.log`
// this let's us tap into logging into the console.
// currently we only do this to the main window and not the test window
export function proxyLoggerTransformer(file) {
return transformHeadTailAndContents(
(source) => (
source.replace(console$logReg, (match, methodCall) => {
return 'window.__console' + methodCall;
})),
file
);
}
export const addLoopProtect = cond([
[
testHTMLJS,
function(file) {
const _contents = file.contents.toLowerCase();
if (file.ext === 'html' && !_contents.indexOf('<script>') !== -1) {
// No JavaScript in user code, so no need for loopProtect
return file;
}
return setContent(loopProtect(file.contents), file);
}
],
[ stubTrue, identity ]
]);
export const replaceNBSP = cond([
[
testHTMLJS,
function(file) {
return setContent(
file.contents.replace(NBSPReg, ' '),
file
);
2016-05-20 12:42:26 -07:00
}
],
[ stubTrue, identity ]
]);
export const babelTransformer = cond([
[
testJS,
function(file) {
const result = babel.transform(file.contents, babelOptions);
return setContent(
result.code,
file
);
}
],
[ stubTrue, identity ]
]);
export const _transformers = [
addLoopProtect,
replaceNBSP,
babelTransformer
];
export function applyTransformers(file, transformers = _transformers) {
return transformers.reduce(
(obs, transformer) => {
return obs.flatMap(file => castToObservable(transformer(file)));
},
Observable.of(file)
);
2016-05-20 12:42:26 -07:00
}