import { create as createHandlebars , HelperDelegate , HelperOptions } from 'handlebars' ; import { encode , RisonValue } from 'rison-node' ; import dateMath from '@elastic/datemath' ; import moment , { Moment } from 'moment' ; import numeral from '@elastic/numeral' ; import { url } from '../../../../../../src/plugins/kibana_utils/public' ; const handlebars = createHandlebars ( ) ; function createSerializationHelper ( fnName , serializeFn ) { return ( ... args ) => { const { hash } = args . slice ( - 1 ) [ 0 ] as HelperOptions ; const hasHash = Object . keys ( hash ) . length > 0 ; const hasValues = args . length > 1 ; if ( hasHash && hasValues ) { throw new Error ( `[${ fnName }]: both value list and hash are not supported` ) ; } if ( hasHash ) { if ( Object . values ( hash ) . some ( ( v ) => typeof v === 'undefined' ) ) throw new Error ( `[${ fnName }]: unknown variable` ) ; return serializeFn ( hash ) ; } else { const values = args . slice ( 0 , - 1 ) as unknown [ ] ; if ( values . some ( ( value ) => typeof value === 'undefined' ) ) throw new Error ( `[${ fnName }]: unknown variable` ) ; if ( values . length === 0 ) throw new Error ( `[${ fnName }]: unknown variable` ) ; if ( values . length === 1 ) return serializeFn ( values [ 0 ] ) ; return serializeFn ( values ) ; } } ; } handlebars . registerHelper ( 'json' , createSerializationHelper ( 'json' , JSON . stringify ) ) ; handlebars . registerHelper ( 'rison' , createSerializationHelper ( 'rison' , ( v ) => encode ( v as RisonValue ) ) ) ; handlebars . registerHelper ( 'date' , ( ... args ) => { const values = args . slice ( 0 , - 1 ) as [ string | Date , string | undefined ] ; let [ date , format ] = values ; if ( typeof date === 'undefined' ) throw new Error ( `[date]: unknown variable` ) ; let momentDate ; if ( typeof date === 'string' ) { momentDate = dateMath . parse ( date ) ; if ( ! momentDate || ! momentDate . isValid ( ) ) { const ts = Number ( date ) ; if ( ! Number . isNaN ( ts ) ) { momentDate = moment ( ts ) ; } } } else { momentDate = moment ( date ) ; } if ( ! momentDate || ! momentDate . isValid ( ) ) { return date ; } return format ? momentDate . format ( format ) : momentDate . toISOString ( ) ; } ) ; handlebars . registerHelper ( 'formatNumber' , ( rawValue , pattern ) => { if ( ! pattern || typeof pattern !== 'string' ) throw new Error ( `[formatNumber]: pattern string is required` ) ; const value = Number ( rawValue ) ; if ( rawValue == null || Number . isNaN ( value ) ) return rawValue ; return numeral ( value ) . format ( pattern ) ; } ) ; handlebars . registerHelper ( 'lowercase' , ( rawValue ) => String ( rawValue ) . toLowerCase ( ) ) ; handlebars . registerHelper ( 'uppercase' , ( rawValue ) => String ( rawValue ) . toUpperCase ( ) ) ; handlebars . registerHelper ( 'trim' , ( rawValue ) => String ( rawValue ) . trim ( ) ) ; handlebars . registerHelper ( 'trimLeft' , ( rawValue ) => String ( rawValue ) . trimLeft ( ) ) ; handlebars . registerHelper ( 'trimRight' , ( rawValue ) => String ( rawValue ) . trimRight ( ) ) ; handlebars . registerHelper ( 'left' , ( rawValue , numberOfChars ) => { if ( typeof numberOfChars !== 'number' ) throw new Error ( '[left]: expected "number of characters to extract" to be a number' ) ; return String ( rawValue ) . slice ( 0 , numberOfChars ) ; } ) ; handlebars . registerHelper ( 'right' , ( rawValue , numberOfChars ) => { if ( typeof numberOfChars !== 'number' ) throw new Error ( '[left]: expected "number of characters to extract" to be a number' ) ; return String ( rawValue ) . slice ( - numberOfChars ) ; } ) ; handlebars . registerHelper ( 'mid' , ( rawValue , start , length ) => { if ( typeof start !== 'number' ) throw new Error ( '[left]: expected "start" to be a number' ) ; if ( typeof length !== 'number' ) throw new Error ( '[left]: expected "length" to be a number' ) ; return String ( rawValue ) . substr ( start , length ) ; } ) ; handlebars . registerHelper ( 'concat' , ( ... args ) => { const values = args . slice ( 0 , - 1 ) as unknown [ ] ; return values . join ( '' ) ; } ) ; handlebars . registerHelper ( 'split' , ( ... args ) => { const [ str , splitter ] = args . slice ( 0 , - 1 ) as [ string , string ] ; if ( typeof splitter !== 'string' ) throw new Error ( '[split] "splitter" expected to be a string' ) ; return String ( str ) . split ( splitter ) ; } ) ; handlebars . registerHelper ( 'replace' , ( ... args ) => { const [ str , searchString , valueString ] = args . slice ( 0 , - 1 ) as [ string , string , string ] ; if ( typeof searchString !== 'string' || typeof valueString !== 'string' ) throw new Error ( '[replace]: "searchString" and "valueString" parameters expected to be strings, but not a string or missing' ) ; return String ( str ) . split ( searchString ) . join ( valueString ) ; } ) ; handlebars . registerHelper ( 'encodeURIComponent' , ( component ) => { const str = String ( component ) ; return encodeURIComponent ( str ) ; } ) ; handlebars . registerHelper ( 'encodeURIQuery' , ( component ) => { const str = String ( component ) ; return url . encodeUriQuery ( str ) ; } ) ; export { handlebars } ;