Files
freeCodeCamp/client/src/templates/Challenges/rechallenge/transformers.js

145 lines
3.5 KiB
JavaScript
Raw Normal View History

2018-04-06 14:51:52 +01:00
import {
attempt,
cond,
flow,
identity,
isError,
matchesProperty,
overSome,
partial,
stubTrue
} from 'lodash';
2018-09-11 22:57:13 +03:00
import * as Babel from '@babel/standalone';
import presetEnv from '@babel/preset-env';
import presetReact from '@babel/preset-react';
2018-04-06 14:51:52 +01:00
import protect from 'loop-protect';
import * as vinyl from '../utils/polyvinyl.js';
import createWorker from '../utils/worker-executor';
2018-04-06 14:51:52 +01:00
const protectTimeout = 100;
Babel.registerPlugin('loopProtection', protect(protectTimeout));
2018-11-26 02:17:38 +03:00
const babelOptionsJSX = {
2018-04-06 14:51:52 +01:00
plugins: ['loopProtection'],
2018-09-11 22:57:13 +03:00
presets: [presetEnv, presetReact]
2018-04-06 14:51:52 +01:00
};
2018-11-26 02:17:38 +03:00
const babelOptionsJS = {
presets: [presetEnv]
};
const babelTransformCode = options => code =>
Babel.transform(code, options).code;
2018-04-06 14:51:52 +01:00
// const sourceReg =
// /(<!-- fcc-start-source -->)([\s\S]*?)(?=<!-- fcc-end-source -->)/g;
const NBSPReg = new RegExp(String.fromCharCode(160), 'g');
2018-11-26 02:17:38 +03:00
const testJS = matchesProperty('ext', 'js');
const testJSX = matchesProperty('ext', 'jsx');
const testHTML = matchesProperty('ext', 'html');
2018-11-26 02:17:38 +03:00
const testHTML$JS$JSX = overSome(testHTML, testJS, testJSX);
export const testJS$JSX = overSome(testJS, testJSX);
2018-04-06 14:51:52 +01:00
export const replaceNBSP = cond([
[
2018-11-26 02:17:38 +03:00
testHTML$JS$JSX,
partial(vinyl.transformContents, contents => contents.replace(NBSPReg, ' '))
2018-04-06 14:51:52 +01:00
],
[stubTrue, identity]
]);
function tryTransform(wrap = identity) {
return function transformWrappedPoly(source) {
const result = attempt(wrap, source);
if (isError(result)) {
console.error(result);
// note(Bouncey): Error thrown here to collapse the build pipeline
// At the minute, it will not bubble up
// We collapse the pipeline so the app doesn't fall over trying
// parse bad code (syntax/type errors etc...)
throw result;
2018-04-06 14:51:52 +01:00
}
return result;
};
}
export const babelTransformer = cond([
[
2018-11-26 02:17:38 +03:00
testJS,
flow(
partial(
vinyl.transformHeadTailAndContents,
tryTransform(babelTransformCode(babelOptionsJS))
)
)
],
[
testJSX,
2018-04-06 14:51:52 +01:00
flow(
partial(
vinyl.transformHeadTailAndContents,
2018-11-26 02:17:38 +03:00
tryTransform(babelTransformCode(babelOptionsJSX))
2018-04-06 14:51:52 +01:00
),
partial(vinyl.setExt, 'js')
)
],
[stubTrue, identity]
]);
const sassWorker = createWorker('sass-compile');
2018-12-12 17:12:30 +03:00
async function transformSASS(element) {
const styleTags = element.querySelectorAll('style[type="text/sass"]');
await Promise.all(
[].map.call(styleTags, async style => {
style.type = 'text/css';
2018-12-10 18:06:05 +03:00
style.innerHTML = await sassWorker.execute(style.innerHTML, 5000);
2018-12-12 17:12:30 +03:00
})
);
}
function transformScript(element) {
const scriptTags = element.querySelectorAll('script');
scriptTags.forEach(script => {
script.innerHTML = tryTransform(babelTransformCode(babelOptionsJSX))(
script.innerHTML
);
});
}
2018-12-12 17:12:30 +03:00
const transformHtml = async function(file) {
const div = document.createElement('div');
div.innerHTML = file.contents;
2018-12-12 17:12:30 +03:00
await Promise.all([transformSASS(div), transformScript(div)]);
return vinyl.transformContents(() => div.innerHTML, file);
};
2018-12-12 17:12:30 +03:00
export const composeHTML = cond([
[
testHTML,
flow(
2018-12-10 18:06:05 +03:00
partial(vinyl.transformHeadTailAndContents, source => {
const div = document.createElement('div');
div.innerHTML = source;
return div.innerHTML;
}),
2018-12-12 17:12:30 +03:00
partial(vinyl.compileHeadTail, '')
)
],
[stubTrue, identity]
]);
export const htmlTransformer = cond([
[testHTML, transformHtml],
2018-04-06 14:51:52 +01:00
[stubTrue, identity]
]);
export const transformers = [
replaceNBSP,
babelTransformer,
2018-12-12 17:12:30 +03:00
composeHTML,
htmlTransformer
];