import path from "path" ; import fs from "fs-extra" ; import { default as Handlebars , TemplateDelegate , RuntimeOptions , } from "handlebars" ; type CompileOptions = Parameters < typeof Handlebars . compile > [ "1" ] ; export type TemplateCache < T = object > = Map < string , TemplateDelegate < T > > ; export type FormatterOptions = { handlebars ? : typeof Handlebars ; templates ? : TemplateCache ; } ; export class Formatter < TemplateData extends object > { /**
     * Directory containing all default templates
     */ static readonly TEMPLATES_DIR = path . resolve ( __dirname , "../../resources/diff/templates" ) ; /**
     * Handlebars instance available for all Formatter instances to use
     */ static readonly handlebars = Handlebars . create ( ) ; /**
     * Template cache available for all Formatter instances to use
     */ static readonly templates : TemplateCache = new Map ( ) ; readonly handlebars : typeof Handlebars ; readonly templates : TemplateCache ; param handlebars param templates constructor ( options ? ) { this . handlebars = options ?. handlebars || new . target . handlebars ; this . templates = options ?. templates || new . target . templates ; } param filepath param name returns registerPartial ( filepath , name ? ) { if ( ! name ) { name = path . basename ( filepath , path . extname ( filepath ) ) . replace ( /\./g , ":" ) ; } if ( name in this . handlebars . partials ) { return false ; } this . handlebars . registerPartial ( name , fs . readFileSync ( filepath , "utf8" ) ) ; return true ; } param filepath param options protected loadTemplate ( filepath , options ? ) { const id = path . resolve ( filepath ) ; const cached = this . templates . get ( id ) ; if ( cached !== undefined ) { return cached ; } const template = this . handlebars . compile ( fs . readFileSync ( filepath , "utf8" ) , options ) ; this . templates . set ( id , template ) ; return template ; } param template param data param compileOptions param runtimeOptions render ( template , data , compileOptions ? , runtimeOptions ? ) { const renderTemplate = this . loadTemplate ( template , compileOptions ) ; return renderTemplate ( data , runtimeOptions ) ; } }