File size: 1,989 Bytes
46252cd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
 * Shared server-side text template renderer — the single templating helper for the gateway.
 *
 * Substitutes `{{name}}` placeholders (the canonical, Handlebars-style convention) with values from
 * the provided `vars` map. Placeholders whose key is absent from `vars` are left untouched (the
 * literal placeholder is preserved) so missing variables stay visible rather than silently blanked.
 *
 * Legacy single-brace `{name}` placeholders are ALSO substituted, for backward compatibility with
 * the bulk-message API that historically used them. Single-brace is deprecated — prefer `{{name}}`.
 */

// Ordered alternation: the double-brace branch is tried first at each position, so `{{name}}` is
// consumed as a unit and the single-brace branch never sees its interior (no `{{name}}` -> `{value}`
// mangling). The legacy branch keeps the historical shape exactly: `{name}`, word chars only, no
// surrounding whitespace — so existing single-brace bulk content renders bit-for-bit as before.
const PLACEHOLDER_PATTERN = /\{\{\s*([\w.-]+)\s*\}\}|\{(\w+)\}/g;

/**
 * Render a template body by replacing `{{key}}` (canonical) or `{key}` (legacy) placeholders with
 * `vars[key]`.
 *
 * @param body Template text containing `{{key}}` and/or `{key}` placeholders.
 * @param vars Map of placeholder keys to substitution values.
 * @returns The rendered text with known placeholders substituted and unknown placeholders left
 *          literal.
 */
export function renderTemplate(body: string, vars: Record<string, string> = {}): string {
  if (!body) {
    return body;
  }

  return body.replace(PLACEHOLDER_PATTERN, (match, doubleKey: string | undefined, singleKey: string | undefined) => {
    const key = doubleKey ?? singleKey;
    if (key !== undefined && Object.prototype.hasOwnProperty.call(vars, key) && vars[key] != null) {
      return String(vars[key]);
    }
    // Leave unmatched placeholders literal so missing variables stay visible.
    return match;
  });
}