feat: allow creation of project preview frames

This commit is contained in:
Oliver Eyton-Williams
2021-10-20 11:41:58 +02:00
committed by moT01
parent e04ac51147
commit 8deef3099a

View File

@ -3,9 +3,11 @@ import { format } from '../../../utils/format';
// we use two different frames to make them all essentially pure functions // we use two different frames to make them all essentially pure functions
// main iframe is responsible rendering the preview and is where we proxy the // main iframe is responsible rendering the preview and is where we proxy the
const mainId = 'fcc-main-frame'; const mainPreviewId = 'fcc-main-frame';
// the test frame is responsible for running the assert tests // the test frame is responsible for running the assert tests
const testId = 'fcc-test-frame'; const testId = 'fcc-test-frame';
// the project preview frame demos the finished project
const projectPreviewId = 'fcc-project-preview-frame';
// base tag here will force relative links // base tag here will force relative links
// within iframe to point to '' instead of // within iframe to point to '' instead of
@ -16,7 +18,7 @@ const testId = 'fcc-test-frame';
// window.onerror is added here to report any errors thrown during the building // window.onerror is added here to report any errors thrown during the building
// of the frame. React dom errors already appear in the console, so onerror // of the frame. React dom errors already appear in the console, so onerror
// does not need to pass them on to the default error handler. // does not need to pass them on to the default error handler.
const createHeader = (id = mainId) => ` const createHeader = (id = mainPreviewId) => `
<base href='' /> <base href='' />
<script> <script>
window.__frameId = '${id}'; window.__frameId = '${id}';
@ -68,13 +70,15 @@ const createFrame = (document, id) => ctx => {
const hiddenFrameClassName = 'hide-test-frame'; const hiddenFrameClassName = 'hide-test-frame';
const mountFrame = const mountFrame =
document => (document, id) =>
({ element, ...rest }) => { ({ element, ...rest }) => {
const oldFrame = document.getElementById(element.id); const oldFrame = document.getElementById(element.id);
if (oldFrame) { if (oldFrame) {
element.className = oldFrame.className || hiddenFrameClassName; element.className = oldFrame.className || hiddenFrameClassName;
oldFrame.parentNode.replaceChild(element, oldFrame); oldFrame.parentNode.replaceChild(element, oldFrame);
} else { // only test frames can be added (and hidden) here, other frames must be
// added by react
} else if (id === testId) {
element.className = hiddenFrameClassName; element.className = hiddenFrameClassName;
document.body.appendChild(element); document.body.appendChild(element);
} }
@ -134,6 +138,11 @@ const initMainFrame = (frameReady, proxyLogger) => ctx => {
return ctx; return ctx;
}; };
const initPreviewFrame = frameReady => ctx => {
waitForFrame(ctx).then(() => frameReady());
return ctx;
};
const waitForFrame = ctx => { const waitForFrame = ctx => {
return new Promise(resolve => { return new Promise(resolve => {
if (ctx.document.readyState === 'loading') { if (ctx.document.readyState === 'loading') {
@ -156,8 +165,17 @@ const writeContentToFrame = ctx => {
return ctx; return ctx;
}; };
export const createMainFramer = (document, frameReady, proxyLogger) => export const createMainPreviewFramer = (document, frameReady, proxyLogger) =>
createFramer(document, frameReady, proxyLogger, mainId, initMainFrame); createFramer(document, frameReady, proxyLogger, mainPreviewId, initMainFrame);
export const createProjectPreviewFramer = (document, frameReady, proxyLogger) =>
createFramer(
document,
frameReady,
proxyLogger,
projectPreviewId,
initPreviewFrame
);
export const createTestFramer = (document, frameReady, proxyLogger) => export const createTestFramer = (document, frameReady, proxyLogger) =>
createFramer(document, frameReady, proxyLogger, testId, initTestFrame); createFramer(document, frameReady, proxyLogger, testId, initTestFrame);
@ -165,7 +183,7 @@ export const createTestFramer = (document, frameReady, proxyLogger) =>
const createFramer = (document, frameReady, proxyLogger, id, init) => const createFramer = (document, frameReady, proxyLogger, id, init) =>
flow( flow(
createFrame(document, id), createFrame(document, id),
mountFrame(document), mountFrame(document, id),
buildProxyConsole(proxyLogger), buildProxyConsole(proxyLogger),
writeContentToFrame, writeContentToFrame,
init(frameReady, proxyLogger) init(frameReady, proxyLogger)