diff --git a/client/src/templates/Challenges/rechallenge/builders.js b/client/src/templates/Challenges/rechallenge/builders.js index fb82572f42..9adb1ec881 100644 --- a/client/src/templates/Challenges/rechallenge/builders.js +++ b/client/src/templates/Challenges/rechallenge/builders.js @@ -63,10 +63,12 @@ export const cssToHtml = cond([ // ) => Observable[{ build: String, sources: Dictionary }] export function concatHtml(required, template, files) { const createBody = template ? _template(template) : defaultTemplate; - const sourceMap = files.reduce((sources, file) => { - sources[file.name] = file.source || file.contents; - return sources; - }, {}); + const sourceMap = Promise.all(files).then( + files => files.reduce((sources, file) => { + sources[file.name] = file.source || file.contents; + return sources; + }, {}) + ); const head = required .map(({ link, src }) => { @@ -91,12 +93,13 @@ A required file can not have both a src and a link: src = ${src}, link = ${link} return head.concat(element); }, ''); - const body = files - .reduce( + const body = Promise.all(files).then( + files => files.reduce( (body, file) => [...body, file.contents + file.tail + htmlCatch], [] ) - .map(source => createBody({ source })); + .map(source => createBody({ source })) + ); const frameRunner = ''; diff --git a/client/src/templates/Challenges/rechallenge/transformers.js b/client/src/templates/Challenges/rechallenge/transformers.js index 59ae255896..c3583647de 100644 --- a/client/src/templates/Challenges/rechallenge/transformers.js +++ b/client/src/templates/Challenges/rechallenge/transformers.js @@ -13,8 +13,6 @@ import { import * as Babel from '@babel/standalone'; import presetEnv from '@babel/preset-env'; import presetReact from '@babel/preset-react'; -import { of } from 'rxjs'; -import { switchMap } from 'rxjs/operators'; import protect from 'loop-protect'; import * as vinyl from '../utils/polyvinyl.js'; @@ -86,20 +84,17 @@ const htmlSassTransformCode = file => { if (styleTags.length === 0 || typeof Sass === 'undefined') { return vinyl.transformContents(() => doc.body.innerHTML, file); } - return styleTags.reduce((obs, style) => { - return obs.pipe( - switchMap( - file => - new Promise(resolve => { - window.Sass.compile(style.innerHTML, function(result) { - style.type = 'text/css'; - style.innerHTML = result.text; - resolve(vinyl.transformContents(() => doc.body.innerHTML, file)); - }); - }) - ) - ); - }, of(file)); + return Promise.all(styleTags.map(style => ( + new Promise(resolve => { + window.Sass.compile(style.innerHTML, function(result) { + style.type = 'text/css'; + style.innerHTML = result.text; + resolve(); + }); + }) + ))).then(() => ( + vinyl.transformContents(() => doc.body.innerHTML, file) + )); }; export const htmlSassTransformer = cond([ diff --git a/client/src/templates/Challenges/utils/build.js b/client/src/templates/Challenges/utils/build.js index cf8e92cce2..f3540dd9fa 100644 --- a/client/src/templates/Challenges/utils/build.js +++ b/client/src/templates/Challenges/utils/build.js @@ -11,6 +11,7 @@ import { } from '../redux'; import { transformers, testJS$JSX } from '../rechallenge/transformers'; import { cssToHtml, jsToHtml, concatHtml } from '../rechallenge/builders.js'; +import { isPromise } from './polyvinyl'; const jQueryCDN = 'https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js'; @@ -34,18 +35,34 @@ function filterJSIfDisabled(state) { return file => !(testJS$JSX(file) && !isJSEnabled); } +const applyFunction = fn => file => { + if (file.error) { + return file; + } + try { + let newFile = fn(file); + if (typeof newFile !== 'undefined') { + if (isPromise(newFile)) { + newFile = newFile.catch(() => { + // file.error = e.message; + return file; + }); + } + return newFile; + } + return file; + } catch { + // file.error = e.message; + return file; + } +}; + const applyFunctions = fns => file => fns.reduce((file, fn) => { - if (file.error) { - return file; - } - try { - fn(file); - } catch (e) { - // file.error = e.message; - } finally { - return file; + if (isPromise(file)) { + return file.then(applyFunction(fn)); } + return applyFunction(fn)(file); }, file); const toHtml = [jsToHtml, cssToHtml]; const pipeLine = flow( diff --git a/client/src/templates/Challenges/utils/polyvinyl.js b/client/src/templates/Challenges/utils/polyvinyl.js index ca3e5eec99..042e439ef8 100644 --- a/client/src/templates/Challenges/utils/polyvinyl.js +++ b/client/src/templates/Challenges/utils/polyvinyl.js @@ -1,9 +1,9 @@ // originally based off of https://github.com/gulpjs/vinyl import invariant from 'invariant'; -import { of, Observable, from, isObservable } from 'rxjs'; +import { of, from, isObservable } from 'rxjs'; import { map, switchMap } from 'rxjs/operators'; -const isPromise = value => +export const isPromise = value => value && typeof value.subscribe !== 'function' && typeof value.then === 'function'; @@ -13,7 +13,7 @@ export function castToObservable(maybe) { return maybe; } if (isPromise(maybe)) { - return Observable.fromPromise(maybe); + return from(maybe); } return of(maybe); }