import { Document } from "../Document" ; import { RTFJSError } from "../Helper" ; import { RenderChp } from "./RenderChp" ; import { RenderPap } from "./RenderPap" ; export interface IContainerElement { element : HTMLElement ; content : HTMLElement ; } export class Renderer { public _doc : Document ; private _dom : HTMLElement [ ] ; private _curRChp : RenderChp ; private _curRPap : RenderPap ; private _curpar : HTMLElement ; private _cursubpar : HTMLElement ; private _curcont : IContainerElement [ ] ; constructor ( doc ) { this . _doc = doc ; this . _dom = null ; this . _curRChp = null ; this . _curRPap = null ; this . _curpar = null ; this . _cursubpar = null ; this . _curcont = [ ] ; } public pushContainer ( contel ) { if ( this . _curpar == null ) { this . startPar ( ) ; } const len = this . _curcont . push ( contel ) ; if ( len > 1 ) { const prevcontel = this . _curcont [ len - 1 ] ; prevcontel . content . append ( contel . element ) ; } else { if ( this . _cursubpar != null ) { this . _cursubpar . append ( contel . element ) ; } else { this . _curpar . append ( contel . element ) ; } } } public popContainer ( ) { const contel = this . _curcont . pop ( ) ; if ( contel == null ) { throw new RTFJSError ( "No container on rendering stack" ) ; } } public buildHyperlinkElement ( url ) { const link = document . createElement ( "a" ) ; link . href = url ; return link ; } public _appendToPar ( el , newsubpar ? ) { if ( this . _curpar == null ) { this . startPar ( ) ; } if ( newsubpar === true ) { let subpar = document . createElement ( "div" ) ; if ( this . _cursubpar == null ) { subpar . append ( ... Array . from ( this . _curpar . childNodes ) ) ; this . _curpar . append ( subpar ) ; subpar = document . createElement ( "div" ) ; } if ( el ) { subpar . append ( el ) ; } if ( this . _curRPap != null ) { this . _curRPap . apply ( this . _doc , subpar , this . _curRChp , false ) ; } this . _cursubpar = subpar ; this . _curpar . append ( subpar ) ; } else if ( el ) { const contelCnt = this . _curcont . length ; if ( contelCnt > 0 ) { this . _curcont [ contelCnt - 1 ] . content . append ( el ) ; } else if ( this . _cursubpar != null ) { this . _cursubpar . append ( el ) ; } else { this . _curpar . append ( el ) ; } } } public startPar ( ) { this . _curpar = document . createElement ( "div" ) ; if ( this . _curRPap != null ) { this . _curRPap . apply ( this . _doc , this . _curpar , this . _curRChp , true ) ; this . _curRPap . apply ( this . _doc , this . _curpar , this . _curRChp , false ) ; } this . _cursubpar = null ; this . _curcont = [ ] ; this . _dom . push ( this . _curpar ) ; } public lineBreak ( ) { this . _appendToPar ( null , true ) ; } public setChp ( rchp ) { this . _curRChp = rchp ; } public setPap ( rpap ) { this . _curRPap = rpap ; if ( this . _cursubpar != null ) { this . _curRPap . apply ( this . _doc , this . _cursubpar , null , false ) ; } else if ( this . _curpar != null ) { this . _curRPap . apply ( this . _doc , this . _curpar , null , true ) ; this . _curRPap . apply ( this . _doc , this . _curpar , null , false ) ; } } public appendElement ( element ) { this . _appendToPar ( element ) ; } public buildRenderedPicture ( element ) { if ( element == null ) { element = document . createElement ( "span" ) ; element . textContent = "[failed to render image]" ; } return element ; } public renderedPicture ( element ) { this . _appendToPar ( this . buildRenderedPicture ( element ) ) ; } public buildPicture ( mime , data ) { if ( data != null ) { const image = document . createElement ( "img" ) ; image . src = "data:" + mime + ";base64," + btoa ( data ) ; return image ; } else { let err = "image type not supported" ; if ( typeof mime === "string" && mime !== "" ) { err = mime ; } const span = document . createElement ( "span" ) ; span . textContent = "[" + err + "]" ; return span ; } } public picture ( mime , data ) { this . _appendToPar ( this . buildPicture ( mime , data ) ) ; } public buildDom ( ) { if ( this . _dom != null ) { return this . _dom ; } this . _dom = [ ] ; this . _curRChp = null ; this . _curRPap = null ; this . _curpar = null ; const len = this . _doc . _ins . length ; for ( let i = 0 ; i < len ; i ++ ) { const ins = this . _doc . _ins [ i ] ; if ( typeof ins === "string" ) { const span = document . createElement ( "span" ) ; span . textContent = ins ; if ( this . _curRChp != null ) { this . _curRChp . apply ( this . _doc , span ) ; } this . _appendToPar ( span ) ; } else { ins ( this ) ; } } return this . _dom ; } }