import PageSetup from './page-setup' ; import { ViewerMode , SheetSize , SheetLayout , SheetMarks } from './constants' ; import defaultRules from './defaults' ; import type { BookContent } from './types' ; import makeBook from './makeBook' ; import { getContentAsElement } from './makeBook/getContent' ; import Viewer from './viewer' ; import rules from './rules' ; import { validateRuntimeOptions , RuntimeTypes } from './runtimeOptionChecker' ; import { Book } from './book' ; import { Rule } from './rules/Rule' ; const vals = ( obj ) => { return Object . keys ( obj ) . map ( k => obj [ k ] ) ; } ; const nextFrame = ( ) => new Promise ( resolve => { requestAnimationFrame ( t => resolve ( t ) ) ; } ) ; declare const BINDERY_VERSION ; interface PrintSetup { layout : SheetLayout ; marks : SheetMarks ; } interface BinderyOptions { autoupdate ? : boolean ; autorun ? : boolean ; content : BookContent ; pageNumberOffset ? : number ; printSetup ? : PrintSetup ; pageSetup ? : { } ; rules ? : any [ ] ; view ? : ViewerMode ; } class Bindery { autorun : boolean ; autoupdate : boolean ; viewer : Viewer ; content ! : HTMLElement ; pageSetup : PageSetup ; rules : Rule [ ] ; constructor ( opts ) { console . log ( `📖 Bindery ${ BINDERY_VERSION }` ) ; validateRuntimeOptions ( opts , { name : 'makeBook' , autorun : RuntimeTypes . bool , content : RuntimeTypes . any , view : RuntimeTypes . enum ( ... vals ( ViewerMode ) ) , pageNumberOffset : RuntimeTypes . number , pageSetup : RuntimeTypes . shape ( { name : 'pageSetup' , margin : RuntimeTypes . margin , size : RuntimeTypes . size , } ) , printSetup : RuntimeTypes . shape ( { name : 'printSetup' , bleed : RuntimeTypes . length , layout : RuntimeTypes . enum ( ... vals ( SheetLayout ) ) , marks : RuntimeTypes . enum ( ... vals ( SheetMarks ) ) , paper : RuntimeTypes . enum ( ... vals ( SheetSize ) ) , } ) , rules : RuntimeTypes . array , } ) ; this . autorun = opts . autorun ?? true ; this . autoupdate = opts . autoupdate ?? false ; this . pageSetup = new PageSetup ( opts . pageSetup , opts . printSetup ) ; const startLayout = opts . printSetup ?. layout ?? SheetLayout . PAGES ; const startMarks = opts . printSetup ?. marks ?? SheetMarks . CROP ; this . viewer = new Viewer ( { pageSetup : this . pageSetup , mode : opts . view ?? ViewerMode . PREVIEW , marks : startMarks , layout : startLayout , } ) ; if ( ! opts . content ) { this . viewer . displayError ( 'Content not specified' , 'You must include a source element, selector, or url' ) ; throw Error ( 'Bindery: You must include a source element or selector' ) ; } if ( opts . hasOwnProperty ( 'ControlsComponent' ) ) { this . viewer . displayError ( 'Controls are now included' , 'Please remove the controls component' ) ; throw Error ( 'Bindery: controls are now included' ) ; } this . rules = defaultRules ; this . rules . push ( new Rule ( { pageNumberOffset : opts . pageNumberOffset ?? 0 } ) ) ; opts . rules ?. forEach ( rule => { if ( rule instanceof rules . Rule ) { this . rules . push ( rule ) ; } else { throw Error ( `Bindery: The following is not an instance of Bindery.Rule and will be ignored: ${ rule }` ) ; } } ) ; if ( this . autorun ) this . makeBook ( opts . content ) ; } static makeBook ( opts ) { opts . autorun = opts . autorun ?? true ; return new Bindery ( opts ) ; } cancel ( ) { this . viewer . hide ( ) ; if ( this . content ) this . content . style . display = '' ; } async makeBook ( contentDescription ) { try { this . content = await getContentAsElement ( contentDescription ) ; } catch ( e ) { this . viewer . show ( ) ; this . viewer . displayError ( '' , e . message ) ; return undefined ; } this . content . style . display = '' ; const content = this . content . cloneNode ( true ) as HTMLElement ; this . content . style . display = 'none' ; this . viewer . clear ( ) ; this . viewer . show ( ) ; this . pageSetup . updateStyleVars ( ) ; this . viewer . setInProgress ( true ) ; const onProgress = ( currentBook , progress ) => { this . viewer . updateProgress ( currentBook , progress ) ; } ; try { const book = await makeBook ( content , this . rules , onProgress ) ; this . viewer . setProgressAmount ( 1 ) ; await nextFrame ( ) ; this . viewer . render ( book ) ; this . viewer . setInProgress ( false ) ; return book ; } catch ( e ) { this . viewer . setInProgress ( false ) ; this . viewer . displayError ( "Layout couldn't complete" , e . message ) ; return undefined ; } } } export default Bindery ;