/*eslint max-lines: ["warn", {"max": 300, "skipBlankLines": true, "skipComments": true}]*/ require('./brewRenderer.less'); const React = require('react'); const createClass = require('create-react-class'); const _ = require('lodash'); const cx = require('classnames'); const MarkdownLegacy = require('naturalcrit/markdownLegacy.js'); const Markdown = require('naturalcrit/markdown.js'); const ErrorBar = require('./errorBar/errorBar.jsx'); //TODO: move to the brew renderer const RenderWarnings = require('homebrewery/renderWarnings/renderWarnings.jsx'); const NotificationPopup = require('./notificationPopup/notificationPopup.jsx'); const Frame = require('react-frame-component').default; const Themes = require('themes/themes.json'); const PAGE_HEIGHT = 1056; const PPR_THRESHOLD = 50; const BrewRenderer = createClass({ displayName : 'BrewRenderer', getDefaultProps : function() { return { text : '', style : '', renderer : 'legacy', theme : '5ePHB', lang : '', errors : [] }; }, getInitialState : function() { let pages; if(this.props.renderer == 'legacy') { pages = this.props.text.split('\\page'); } else { pages = this.props.text.split(/^\\page$/gm); } return { viewablePageNumber : 0, height : 0, isMounted : false, pages : pages, usePPR : pages.length >= PPR_THRESHOLD, visibility : 'hidden', initialContent : `
` }; }, height : 0, lastRender :
, componentWillUnmount : function() { window.removeEventListener('resize', this.updateSize); }, componentDidUpdate : function(prevProps) { if(prevProps.text !== this.props.text) { let pages; if(this.props.renderer == 'legacy') { pages = this.props.text.split('\\page'); } else { pages = this.props.text.split(/^\\page$/gm); } this.setState({ pages : pages, usePPR : pages.length >= PPR_THRESHOLD }); } }, updateSize : function() { this.setState({ height : this.refs.main.parentNode.clientHeight, }); }, handleScroll : function(e){ const target = e.target; this.setState((prevState)=>({ viewablePageNumber : Math.floor(target.scrollTop / target.scrollHeight * prevState.pages.length) })); }, shouldRender : function(pageText, index){ if(!this.state.isMounted) return false; const viewIndex = this.state.viewablePageNumber; if(index == viewIndex - 3) return true; if(index == viewIndex - 2) return true; if(index == viewIndex - 1) return true; if(index == viewIndex) return true; if(index == viewIndex + 1) return true; if(index == viewIndex + 2) return true; if(index == viewIndex + 3) return true; //Check for style tages if(pageText.indexOf('` }} />; return
\n${this.props.style}\n` }} />; }, renderPage : function(pageText, index){ if(this.props.renderer == 'legacy') 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) return (
); } }, renderPages : function(){ if(this.state.usePPR){ return _.map(this.state.pages, (page, index)=>{ if(this.shouldRender(page, index) && typeof window !== 'undefined'){ return this.renderPage(page, index); } else { return this.renderDummyPage(index); } }); } if(this.props.errors && this.props.errors.length) return this.lastRender; this.lastRender = _.map(this.state.pages, (page, index)=>{ if(typeof window !== 'undefined') { return this.renderPage(page, index); } else { return this.renderDummyPage(index); } }); return this.lastRender; }, frameDidMount : function(){ //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 this.updateSize(); window.addEventListener('resize', this.updateSize); this.renderPages(); //Make sure page is renderable before showing this.setState({ isMounted : true, visibility : 'visible' }); }, 100); }, render : function(){ //render in iFrame so broken code doesn't crash the site. //Also render dummy page while iframe is mounting. const rendererPath = this.props.renderer == 'V3' ? 'V3' : 'Legacy'; const themePath = this.props.theme ?? '5ePHB'; const baseThemePath = Themes[rendererPath][themePath].baseTheme; return ( {!this.state.isMounted ?
{this.renderDummyPage(1)}
: null}
{baseThemePath && } {/* Apply CSS from Style tab and render pages from Markdown tab */} {this.state.isMounted && <> {this.renderStyle()}
{this.renderPages()}
}
{this.renderPageInfo()} {this.renderPPRmsg()}
); } }); module.exports = BrewRenderer;