diff options
Diffstat (limited to 'src/lib/handlebars.ts')
-rw-r--r-- | src/lib/handlebars.ts | 97 |
1 files changed, 51 insertions, 46 deletions
diff --git a/src/lib/handlebars.ts b/src/lib/handlebars.ts index 42f8010..6d4f796 100644 --- a/src/lib/handlebars.ts +++ b/src/lib/handlebars.ts @@ -1,50 +1,55 @@ -import { Request } from "express"; -import { ExpressHandlebars } from "express-handlebars"; +import hbs, { ExpressHandlebars } from "express-handlebars"; +import { RenderViewOptions } from "express-handlebars/types/index.js"; -export const renderTemplate = async ( - req: Request, - templateName: string, - data: Record<string, unknown>, -): Promise<string> => { - return new Promise<string>((resolve, reject) => { - req.app - .get("hbsInstance") - .renderView( - `./views/emails/${templateName}.handlebars`, - data, - (err: any, html: string) => { - if (err) { - console.error(err); - reject(err); - } - resolve(html); +export class HandlebarsSingleton { + static #instance: HandlebarsSingleton; + hbsInstance: hbs.ExpressHandlebars; + + private constructor() { + this.hbsInstance = hbs.create({ + defaultLayout: "main", + partialsDir: ["views/partials/"], + layoutsDir: "views/layouts/", + helpers: { + plural: function (number: number, text: string) { + const singular = number === 1; + // If no text parameter was given, just return a conditional s. + if (typeof text !== "string") return singular ? "" : "s"; + // Split with regex into group1/group2 or group1(group3) + const match = text.match(/^([^()\/]+)(?:\/(.+))?(?:\((\w+)\))?/); + // If no match, just append a conditional s. + if (!match) return text + (singular ? "" : "s"); + // We have a good match, so fire away + return ( + (singular && match[1]) || // Singular case + match[2] || // Plural case: 'bagel/bagels' --> bagels + match[1] + (match[3] || "s") + ); // Plural case: 'bagel(s)' or 'bagel' --> bagels + }, + json: function (context: object) { + return JSON.stringify(context); }, - ); - }); -}; + }, + }); + } + + public static get instance(): HandlebarsSingleton { + if (!HandlebarsSingleton.#instance) { + HandlebarsSingleton.#instance = new HandlebarsSingleton(); + } + + return HandlebarsSingleton.#instance; + } + + public get engine(): ExpressHandlebars["engine"] { + return this.hbsInstance.engine; + } -export const renderEmail = async ( - hbsInstance: ExpressHandlebars, - templateName: string, - data: Record<string, unknown>, -): Promise<{ html: string, text: string }> => { - const [html, text] = await Promise.all([ - hbsInstance.renderView( - `./views/emails/${templateName}Html.handlebars`, - { - cache: true, - layout: "email.handlebars", - ...data, - } - ), - hbsInstance.renderView( - `./views/emails/${templateName}Text.handlebars`, - { - cache: true, - layout: "email.handlebars", - ...data, - } - ), - ]); - return { html, text } + /** + * Finally, any singleton can define some business logic, which can be + * executed on its instance. + */ + public renderView(viewPath: string, options: RenderViewOptions): Promise<string> { + return this.hbsInstance.renderView(viewPath, options); + } } |