1/** 2 * Simple unsafe interpolation for template strings. Does NOT escape values. 3 * 4 * Arguments can be named or numeric. 5 * 6 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates 7 * 8 * @example 9 * const t1Closure = unsafeTemplate`${0}${1}${0}!`; 10 * // const t1Closure = unsafeTemplate(["","","","!"],0,1,0); 11 * t1Closure("Y", "A"); // "YAY!" 12 * 13 * @example 14 * const t2Closure = unsafeTemplate`${0} ${"foo"}!`; 15 * // const t2Closure = unsafeTemplate([""," ","!"],0,"foo"); 16 * t2Closure("Hello", { foo: "World" }); // "Hello World!" 17 * 18 * @example 19 * const t3Closure = unsafeTemplate`I'm ${"name"}. I'm almost ${"age"} years old.`; 20 * // const t3Closure = unsafeTemplate(["I'm ", ". I'm almost ", " years old."], "name", "age"); 21 * t3Closure("foo", { name: "MDN", age: 30 }); // "I'm MDN. I'm almost 30 years old." 22 * t3Closure({ name: "MDN", age: 30 }); // "I'm MDN. I'm almost 30 years old." 23 */ 24export function unsafeTemplate(strings: TemplateStringsArray, ...keys: (string | number)[]) { 25 return ( 26 ...values: (string | number)[] | [...(string | number)[], Record<string | number, string>] 27 ) => { 28 const lastValue = values[values.length - 1]; 29 const dict = typeof lastValue === 'object' ? lastValue : {}; 30 const result = [strings[0]]; 31 keys.forEach((key, i) => { 32 const value = typeof key === 'number' && Number.isInteger(key) ? values[key] : dict[key]; 33 result.push(value as string, strings[i + 1]); 34 }); 35 return result.join(''); 36 }; 37} 38