{"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(\"&\", \"&amp;\")\n    .replaceAll(\"<\", \"&lt;\")\n    .replaceAll(\">\", \"&gt;\")\n    .replaceAll('\"', \"&quot;\")\n    .replaceAll(\"'\", \"&#39;\");\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":[]}