2017-11-29 15:44:51 -08:00
|
|
|
import _ from 'lodash';
|
2017-04-28 18:30:23 -07:00
|
|
|
|
2016-08-18 18:23:44 -07:00
|
|
|
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';
|
|
|
|
|
2017-12-13 15:24:36 -08:00
|
|
|
import * as vinyl from '../../../../utils/polyvinyl.js';
|
2017-12-07 16:13:19 -08:00
|
|
|
import castToObservable from '../../../utils/cast-to-observable.js';
|
2016-05-27 17:11:25 -07:00
|
|
|
|
2016-08-18 18:23:44 -07:00
|
|
|
const babelOptions = { presets: [ presetEs2015, presetReact ] };
|
2017-12-07 16:13:19 -08:00
|
|
|
function loopProtectHit(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);
|
2017-12-07 16:13:19 -08:00
|
|
|
}
|
2016-05-20 12:42:26 -07:00
|
|
|
|
2017-04-28 18:30:23 -07:00
|
|
|
// const sourceReg =
|
|
|
|
// /(<!-- fcc-start-source -->)([\s\S]*?)(?=<!-- fcc-end-source -->)/g;
|
|
|
|
const console$logReg = /(?:\b)console(\.log\S+)/g;
|
|
|
|
const NBSPReg = new RegExp(String.fromCharCode(160), 'g');
|
2016-05-20 12:42:26 -07:00
|
|
|
|
2017-11-29 15:44:51 -08:00
|
|
|
const isJS = _.matchesProperty('ext', 'js');
|
|
|
|
const testHTMLJS = _.overSome(isJS, _.matchesProperty('ext', 'html'));
|
|
|
|
const testJS$JSX = _.overSome(isJS, _.matchesProperty('ext', 'jsx'));
|
2017-04-28 18:30:23 -07:00
|
|
|
|
|
|
|
// 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
|
2017-12-13 15:24:36 -08:00
|
|
|
export const proxyLoggerTransformer = _.partial(
|
|
|
|
vinyl.transformHeadTailAndContents,
|
|
|
|
source => (
|
2017-04-28 18:30:23 -07:00
|
|
|
source.replace(console$logReg, (match, methodCall) => {
|
|
|
|
return 'window.__console' + methodCall;
|
2017-12-13 15:24:36 -08:00
|
|
|
})),
|
|
|
|
);
|
|
|
|
|
|
|
|
const addLoopProtect = _.partial(
|
|
|
|
vinyl.transformContents,
|
|
|
|
contents => {
|
|
|
|
/* eslint-disable import/no-unresolved */
|
|
|
|
const loopProtect = require('loop-protect');
|
|
|
|
/* eslint-enable import/no-unresolved */
|
|
|
|
loopProtect.hit = loopProtectHit;
|
|
|
|
return loopProtect(contents);
|
|
|
|
}
|
|
|
|
);
|
2017-04-28 18:30:23 -07:00
|
|
|
|
2017-12-13 15:24:36 -08:00
|
|
|
export const addLoopProtectHtmlJsJsx = _.cond([
|
2017-04-28 18:30:23 -07:00
|
|
|
[
|
2017-12-13 15:24:36 -08:00
|
|
|
_.overEvery(
|
|
|
|
testHTMLJS,
|
|
|
|
_.partial(
|
|
|
|
vinyl.testContents,
|
2017-12-15 12:17:30 +05:30
|
|
|
contents => contents.toLowerCase().includes('<script>')
|
2017-12-13 15:24:36 -08:00
|
|
|
)
|
|
|
|
),
|
|
|
|
addLoopProtect
|
2017-04-28 18:30:23 -07:00
|
|
|
],
|
2017-12-13 15:24:36 -08:00
|
|
|
[ testJS$JSX, addLoopProtect ],
|
2017-11-29 15:44:51 -08:00
|
|
|
[ _.stubTrue, _.identity ]
|
2017-04-28 18:30:23 -07:00
|
|
|
]);
|
2017-12-13 15:24:36 -08:00
|
|
|
|
2017-11-29 15:44:51 -08:00
|
|
|
export const replaceNBSP = _.cond([
|
2017-04-28 18:30:23 -07:00
|
|
|
[
|
|
|
|
testHTMLJS,
|
2017-12-13 15:24:36 -08:00
|
|
|
_.partial(
|
|
|
|
vinyl.transformContents,
|
|
|
|
contents => contents.replace(NBSPReg, ' ')
|
|
|
|
)
|
2017-04-28 18:30:23 -07:00
|
|
|
],
|
2017-11-29 15:44:51 -08:00
|
|
|
[ _.stubTrue, _.identity ]
|
2017-04-28 18:30:23 -07:00
|
|
|
]);
|
|
|
|
|
2017-11-29 15:44:51 -08:00
|
|
|
export const babelTransformer = _.cond([
|
2017-04-28 18:30:23 -07:00
|
|
|
[
|
2017-11-29 15:44:51 -08:00
|
|
|
testJS$JSX,
|
2017-12-13 15:24:36 -08:00
|
|
|
_.flow(
|
|
|
|
_.partial(
|
|
|
|
vinyl.transformContents,
|
|
|
|
contents => babel.transform(contents, babelOptions).code
|
|
|
|
),
|
|
|
|
_.partial(vinyl.setExt, 'js')
|
|
|
|
)
|
2017-04-28 18:30:23 -07:00
|
|
|
],
|
2017-11-29 15:44:51 -08:00
|
|
|
[ _.stubTrue, _.identity ]
|
2017-04-28 18:30:23 -07:00
|
|
|
]);
|
|
|
|
|
|
|
|
export const _transformers = [
|
2017-12-13 15:24:36 -08:00
|
|
|
addLoopProtectHtmlJsJsx,
|
2017-04-28 18:30:23 -07:00
|
|
|
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
|
|
|
}
|