feat: conditionally include files (#42205)
Co-authored-by: Shaun Hamilton <51722130+ShaunSHamilton@users.noreply.github.com>pull/42379/head
parent
7b65909522
commit
440169a7cb
|
@ -56,6 +56,18 @@ export const cssToHtml = cond([
|
|||
[stubTrue, identity]
|
||||
]);
|
||||
|
||||
export function findIndexHtml(files) {
|
||||
const filtered = files.filter(file => wasHtmlFile(file));
|
||||
if (filtered.length > 1) {
|
||||
throw new Error('Too many html blocks in the challenge seed');
|
||||
}
|
||||
return filtered[0];
|
||||
}
|
||||
|
||||
function wasHtmlFile(file) {
|
||||
return file.history[0] === 'index.html';
|
||||
}
|
||||
|
||||
export function concatHtml({ required = [], template, files = [] } = {}) {
|
||||
const createBody = template ? _template(template) : defaultTemplate;
|
||||
const head = required
|
||||
|
@ -75,10 +87,19 @@ A required file can not have both a src and a link: src = ${src}, link = ${link}
|
|||
})
|
||||
.reduce((head, element) => head.concat(element));
|
||||
|
||||
const source = files.reduce(
|
||||
(source, file) => source.concat(file.contents, htmlCatch),
|
||||
''
|
||||
);
|
||||
const indexHtml = findIndexHtml(files);
|
||||
|
||||
const source = files.reduce((source, file) => {
|
||||
if (!indexHtml) return source.concat(file.contents, htmlCatch);
|
||||
if (
|
||||
indexHtml.importedFiles.includes(file.history[0]) ||
|
||||
wasHtmlFile(file)
|
||||
) {
|
||||
return source.concat(file.contents, htmlCatch);
|
||||
} else {
|
||||
return source;
|
||||
}
|
||||
}, '');
|
||||
|
||||
return `<head>${head}</head>${createBody({ source })}`;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* global expect */
|
||||
import { findIndexHtml } from './builders.js';
|
||||
|
||||
const withHTML = [
|
||||
{ history: ['index.html'], contents: 'the index html' },
|
||||
{ history: ['index.css', 'index.html'], contents: 'the style file' }
|
||||
];
|
||||
|
||||
const withoutHTML = [
|
||||
{ history: ['index.css', 'index.html'], contents: 'the js file' },
|
||||
{ history: ['index.js', 'index.html'], contents: 'the style file' }
|
||||
];
|
||||
|
||||
const tooMuchHTML = [
|
||||
{ history: ['index.html'], contents: 'the index html' },
|
||||
{ history: ['index.css', 'index.html'], contents: 'index html two' },
|
||||
{ history: ['index.html'], contents: 'index html three' }
|
||||
];
|
||||
|
||||
// TODO: write tests for concatHtml instead, since findIndexHtml should not be
|
||||
// exported.
|
||||
|
||||
describe('findIndexHtml', () => {
|
||||
it('should return the index.html file from an array', () => {
|
||||
expect.assertions(1);
|
||||
|
||||
expect(findIndexHtml(withHTML)).toStrictEqual({
|
||||
history: ['index.html'],
|
||||
contents: 'the index html'
|
||||
});
|
||||
});
|
||||
|
||||
it('should return undefined when the index.html file is missing', () => {
|
||||
expect.assertions(1);
|
||||
|
||||
expect(findIndexHtml(withoutHTML)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should throw if there are two or more index.htmls', () => {
|
||||
expect.assertions(1);
|
||||
|
||||
expect(() => findIndexHtml(tooMuchHTML)).toThrowError(
|
||||
'Too many html blocks in the challenge seed'
|
||||
);
|
||||
});
|
||||
});
|
|
@ -16,6 +16,7 @@ import {
|
|||
transformContents,
|
||||
transformHeadTailAndContents,
|
||||
setExt,
|
||||
setImportedFiles,
|
||||
compileHeadTail
|
||||
} from '../../../../../utils/polyvinyl';
|
||||
import createWorker from '../utils/worker-executor';
|
||||
|
@ -213,6 +214,35 @@ const transformHtml = async function (file) {
|
|||
return transformContents(() => div.innerHTML, file);
|
||||
};
|
||||
|
||||
// Find if the base html refers to the css or js files and record if they do. If
|
||||
// the link or script exists we remove those elements since those files don't
|
||||
// exist on the site, only in the editor
|
||||
const transformIncludes = async function (fileP) {
|
||||
const file = await fileP;
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = file.contents;
|
||||
const link =
|
||||
div.querySelector('link[href="styles.css"]') ??
|
||||
div.querySelector('link[href="./styles.css"]');
|
||||
const script =
|
||||
div.querySelector('script[src="script.js"]') ??
|
||||
div.querySelector('script[src="./script.js"]');
|
||||
const importedFiles = [];
|
||||
if (link) {
|
||||
importedFiles.push('index.css');
|
||||
link.remove();
|
||||
}
|
||||
if (script) {
|
||||
importedFiles.push('index.js');
|
||||
script.remove();
|
||||
}
|
||||
|
||||
return flow(
|
||||
partial(setImportedFiles, importedFiles),
|
||||
partial(transformContents, () => div.innerHTML)
|
||||
)(file);
|
||||
};
|
||||
|
||||
export const composeHTML = cond([
|
||||
[
|
||||
testHTML,
|
||||
|
@ -229,7 +259,7 @@ export const composeHTML = cond([
|
|||
]);
|
||||
|
||||
export const htmlTransformer = cond([
|
||||
[testHTML, transformHtml],
|
||||
[testHTML, flow(transformHtml, transformIncludes)],
|
||||
[stubTrue, identity]
|
||||
]);
|
||||
|
||||
|
|
|
@ -87,6 +87,16 @@ function setExt(ext, poly) {
|
|||
return newPoly;
|
||||
}
|
||||
|
||||
// setImportedFiles(importedFiles: String[], poly: PolyVinyl) => PolyVinyl
|
||||
function setImportedFiles(importedFiles, poly) {
|
||||
checkPoly(poly);
|
||||
const newPoly = {
|
||||
...poly,
|
||||
importedFiles: [...importedFiles]
|
||||
};
|
||||
return newPoly;
|
||||
}
|
||||
|
||||
// clearHeadTail(poly: PolyVinyl) => PolyVinyl
|
||||
function clearHeadTail(poly) {
|
||||
checkPoly(poly);
|
||||
|
@ -139,6 +149,7 @@ module.exports = {
|
|||
isPoly,
|
||||
setContent,
|
||||
setExt,
|
||||
setImportedFiles,
|
||||
compileHeadTail,
|
||||
transformContents,
|
||||
transformHeadTailAndContents
|
||||
|
|
Loading…
Reference in New Issue