@eristack/email-template
Version:
{{var}} HTML/text email template render and key extraction — pair with @eristack/comms
1 lines • 1.91 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.ts","../src/core/template.ts"],"sourcesContent":["export * from \"./core/index.js\";\n","const PLACEHOLDER_RE = /\\{\\{\\s*([\\w.]+)\\s*\\}\\}/g;\n\nexport type RenderEmailTemplateOptions = {\n /** When true, substitute values are HTML-escaped (for HTML bodies). */\n escapeHtml?: boolean;\n};\n\nexport function extractTemplateKeys(template: string): string[] {\n const keys = new Set<string>();\n for (const match of template.matchAll(PLACEHOLDER_RE)) {\n keys.add(match[1]!);\n }\n return [...keys].sort();\n}\n\nfunction htmlEscape(value: string): string {\n return value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\")\n .replaceAll(\"'\", \"'\");\n}\n\n/**\n * Replace `{{key}}` placeholders with vars. Missing keys become empty string.\n */\nexport function renderEmailTemplate(\n template: string,\n vars: Record<string, string | undefined>,\n options?: RenderEmailTemplateOptions,\n): string {\n const escape = options?.escapeHtml ?? false;\n return template.replace(PLACEHOLDER_RE, (_full, key: string) => {\n const raw = vars[key];\n if (raw === undefined) return \"\";\n return escape ? htmlEscape(raw) : raw;\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAM,iBAAiB;AAOhB,SAAS,oBAAoB,UAA4B;AAC9D,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,SAAS,SAAS,SAAS,cAAc,GAAG;AACrD,SAAK,IAAI,MAAM,CAAC,CAAE;AAAA,EACpB;AACA,SAAO,CAAC,GAAG,IAAI,EAAE,KAAK;AACxB;AAEA,SAAS,WAAW,OAAuB;AACzC,SAAO,MACJ,WAAW,KAAK,OAAO,EACvB,WAAW,KAAK,MAAM,EACtB,WAAW,KAAK,MAAM,EACtB,WAAW,KAAK,QAAQ,EACxB,WAAW,KAAK,OAAO;AAC5B;AAKO,SAAS,oBACd,UACA,MACA,SACQ;AACR,QAAM,SAAS,SAAS,cAAc;AACtC,SAAO,SAAS,QAAQ,gBAAgB,CAAC,OAAO,QAAgB;AAC9D,UAAM,MAAM,KAAK,GAAG;AACpB,QAAI,QAAQ,OAAW,QAAO;AAC9B,WAAO,SAAS,WAAW,GAAG,IAAI;AAAA,EACpC,CAAC;AACH;","names":[]}