xref: /expo/packages/@expo/cli/src/utils/template.ts (revision ae9cd511)
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