fix: render adjacent email template variables correctly (#3153)

This commit is contained in:
Arunendra Tripathi
2026-08-26 11:57:35 +10:00
committed by GitHub
parent 9dc83bdb06
commit ee8360585b
2 changed files with 37 additions and 1 deletions
@@ -0,0 +1,32 @@
import { describe, expect, it } from 'vitest';
import { renderCustomEmailTemplate } from './render-custom-email-template';
describe('renderCustomEmailTemplate', () => {
it('replaces a single variable', () => {
expect(renderCustomEmailTemplate('Hi {name}', { name: 'Sam' })).toBe('Hi Sam');
});
it('replaces multiple variables separated by whitespace', () => {
expect(
renderCustomEmailTemplate('Hi {name}, sign at {url}', { name: 'Sam', url: 'https://x' }),
).toBe('Hi Sam, sign at https://x');
});
it('replaces adjacent variables and variables separated by a non-whitespace character', () => {
expect(
renderCustomEmailTemplate('{day}/{month}/{year}', { day: '01', month: '02', year: '2026' }),
).toBe('01/02/2026');
expect(
renderCustomEmailTemplate('{firstName}-{lastName}', {
firstName: 'Ada',
lastName: 'Lovelace',
}),
).toBe('Ada-Lovelace');
});
it('leaves the key in place when the variable is not provided', () => {
expect(renderCustomEmailTemplate('Unknown {missing} here', {})).toBe('Unknown missing here');
});
});
@@ -1,5 +1,9 @@
export const renderCustomEmailTemplate = <T extends Record<string, string>>(template: string, variables: T): string => {
return template.replace(/\{(\S+)\}/g, (_, key) => {
// Match a run of non-brace, non-whitespace characters between braces. Using
// `\S+` here was greedy across braces, so placeholders separated by a
// non-whitespace character (e.g. "{day}/{month}/{year}") were captured as a
// single bogus key and left unrendered.
return template.replace(/\{([^\s{}]+)\}/g, (_, key) => {
if (key in variables) {
return variables[key];
}