${cleanStyle} ` }} />;
};
const renderPage = (pageText, index)=>{
if(props.renderer == 'legacy') {
const html = MarkdownLegacy.render(pageText);
return
;
} else {
pageText += `\n\n \n\\column\n `; //Artificial column break at page end to emulate column-fill:auto (until `wide` is used, when column-fill:balance will reappear)
const html = Markdown.render(pageText, index);
return
;
}
};
const renderPages = ()=>{
if(props.errors && props.errors.length)
return renderedPages;
if(rawPages.length != renderedPages.length) // Re-render all pages when page count changes
renderedPages.length = 0;
// Render currently-edited page first so cross-page effects (variables, links) can propagate out first
renderedPages[props.currentEditorPage] = renderPage(rawPages[props.currentEditorPage], props.currentEditorPage);
_.forEach(rawPages, (page, index)=>{
if((isInView(index) || !renderedPages[index]) && typeof window !== 'undefined'){
renderedPages[index] = renderPage(page, index); // Render any page not yet rendered, but only re-render those in PPR range
}
});
return renderedPages;
};
const handleControlKeys = (e)=>{
if(!(e.ctrlKey || e.metaKey)) return;
const P_KEY = 80;
if(e.keyCode == P_KEY && props.allowPrint) printCurrentBrew();
if(e.keyCode == P_KEY) {
e.stopPropagation();
e.preventDefault();
}
};
const frameDidMount = ()=>{ //This triggers when iFrame finishes internal "componentDidMount"
setTimeout(()=>{ //We still see a flicker where the style isn't applied yet, so wait 100ms before showing iFrame
updateSize();
window.addEventListener('resize', updateSize);
renderPages(); //Make sure page is renderable before showing
setState((prevState)=>({
...prevState,
isMounted : true,
visibility : 'visible'
}));
}, 100);
};
const emitClick = ()=>{ // Allow clicks inside iFrame to interact with dropdowns, etc. from outside
if(!window || !document) return;
document.dispatchEvent(new MouseEvent('click'));
};
const toggleHeaderNav = ()=>{
setState((prevState)=>({
...prevState,
showHeaderNav : !prevState.showHeaderNav
}));
};
const renderHeaderNav = ()=>{
return <>
{state.showHeaderNav && renderHeaderLinks()}
>;
};
const renderHeaderLinks = ()=>{
if(!pagesRef.current) return;
const elements = pagesRef.current.querySelectorAll('[id]');
if(!elements) return;
const navList = [];
elements.forEach((el)=>{
if(el.className.match(/\bpage\b/)) {
navList.push({
depth : 0,
text : `Page ${el.id.slice(1)}`,
link : el.id
});
return;
}
if(el.localName.match(/^h[1-6]/)){
navList.push({
depth : el.localName[1],
text : el.innerText,
link : el.id
});
return;
}
navList.push({
depth : 7,
text : el.innerText,
link : el.id
});
});
return _.map(navList, (navItem)=>{
return
{`${'-'.repeat(navItem.depth)}${navItem.text}`}
;
});
};
const rendererPath = props.renderer == 'V3' ? 'V3' : 'Legacy';
const themePath = props.theme ?? '5ePHB';
const baseThemePath = Themes[rendererPath][themePath].baseTheme;
return (
<>
{/*render dummy page while iFrame is mounting.*/}
{!state.isMounted
?
: null}
{/*render in iFrame so broken code doesn't crash the site.*/}
{emitClick();}}
>
{baseThemePath &&
}
{/* Apply CSS from Style tab and render pages from Markdown tab */}
{state.isMounted
&&
<>
{renderStyle()}
{renderPages()}
>
}
{props.showHeaderNav ?
{renderHeaderNav()}
:
<>>
}
{renderPageInfo()}
>
);
};
module.exports = BrewRenderer;