import { i18n } from '@kbn/i18n' ; import concat from 'concat-stream' ; import _ from 'lodash' ; import path from 'path' ; import Printer from 'pdfmake' ; import { Content , ContentImage , ContentText } from 'pdfmake/interfaces' ; import type { Layout } from '../../../../../screenshotting/server' ; import { getDocOptions , REPORTING_TABLE_LAYOUT } from './get_doc_options' ; import { getFont } from './get_font' ; import { getTemplate } from './get_template' ; const assetPath = path . resolve ( __dirname , '..' , '..' , 'common' , 'assets' ) ; const tableBorderWidth = 1 ; export class PdfMaker { private _layout : Layout ; private _logo : string | undefined ; private _title : string ; private _content : Content [ ] ; private _printer : Printer ; private _pdfDoc : PDFKit . PDFDocument | undefined ; constructor ( layout , logo ) { const fontPath = ( filename ) => path . resolve ( assetPath , 'fonts' , filename ) ; const fonts = { Roboto : { normal : fontPath ( 'roboto/Roboto-Regular.ttf' ) , bold : fontPath ( 'roboto/Roboto-Medium.ttf' ) , italics : fontPath ( 'roboto/Roboto-Italic.ttf' ) , bolditalics : fontPath ( 'roboto/Roboto-Italic.ttf' ) , } , 'noto-cjk' : { normal : fontPath ( 'noto/NotoSansCJKtc-Regular.ttf' ) , bold : fontPath ( 'noto/NotoSansCJKtc-Medium.ttf' ) , italics : fontPath ( 'noto/NotoSansCJKtc-Regular.ttf' ) , bolditalics : fontPath ( 'noto/NotoSansCJKtc-Medium.ttf' ) , } , } ; this . _layout = layout ; this . _logo = logo ; this . _title = '' ; this . _content = [ ] ; this . _printer = new Printer ( fonts ) ; } _addContents ( contents ) { const groupCount = this . _content . length ; if ( groupCount > 0 && groupCount % this . _layout . groupCount === 0 ) { contents = [ { text : '' , pageBreak : 'after' , } as ContentText as Content , ] . concat ( contents ) ; } this . _content . push ( contents ) ; } addBrandedImage ( img , { title = '' , description = '' } ) { const contents = [ ] ; if ( title && title . length > 0 ) { contents . push ( { text : title , style : 'heading' , font : getFont ( title ) , noWrap : false , } ) ; } if ( description && description . length > 0 ) { contents . push ( { text : description , style : 'subheading' , font : getFont ( description ) , noWrap : false , } ) ; } const wrappedImg = { table : { body : [ [ img ] ] , } , layout : REPORTING_TABLE_LAYOUT , } ; contents . push ( wrappedImg ) ; this . _addContents ( contents ) ; } addImage ( image , opts = { title : '' , description : '' } ) { const size = this . _layout . getPdfImageSize ( ) ; const img = { image : `data:image/png;base64,${ image . toString ( 'base64' ) }` , alignment : 'center' as 'center' , height : size . height , width : size . width , } ; if ( this . _layout . useReportingBranding ) { return this . addBrandedImage ( img , opts ) ; } this . _addContents ( [ img ] ) ; } setTitle ( title ) { this . _title = title ; } generate ( ) { const docTemplate = _ . assign ( getTemplate ( this . _layout , this . _logo , this . _title , tableBorderWidth , assetPath ) , { content : this . _content , } ) ; this . _pdfDoc = this . _printer . createPdfKitDocument ( docTemplate , getDocOptions ( tableBorderWidth ) ) ; return this ; } getBuffer ( ) { return new Promise ( ( resolve , reject ) => { if ( ! this . _pdfDoc ) { throw new Error ( i18n . translate ( 'xpack.reporting.exportTypes.printablePdf.documentStreamIsNotgeneratedErrorMessage' , { defaultMessage : 'Document stream has not been generated' , } ) ) ; } const concatStream = concat ( function ( pdfBuffer ) { resolve ( pdfBuffer ) ; } ) ; this . _pdfDoc . on ( 'error' , reject ) ; this . _pdfDoc . pipe ( concatStream ) ; this . _pdfDoc . end ( ) ; } ) ; } }