|
1 | 1 | import { getAttr } from "../lib";
|
2 | 2 | import { EvaluateOptions } from "../types";
|
3 | 3 |
|
4 |
| -const ATTR_SHORTHAND_REGEX = new RegExp("\\${([\\w]+)#([\\w]+)}", "g"); |
5 |
| - |
6 | 4 | export const evaluateTemplate = (template: string, options: EvaluateOptions) => {
|
7 |
| - const templateToEvaluate = template |
8 |
| - // Replace `{value}` with `${value}` |
9 |
| - .replace(new RegExp(`\{([^{}]+)\}`, "g"), "${$1}") |
10 |
| - // Replace `{${value}}` with `{value}` |
11 |
| - .replace(new RegExp(`\{\\$\{([^{}]+)\}\}`, "g"), "{$1}"); |
| 5 | + const evaluatedTemplateArr: string[] = []; |
12 | 6 |
|
13 | 7 | const templateContext = {
|
14 | 8 | ...options.endpointParams,
|
15 | 9 | ...options.referenceRecord,
|
16 |
| - }; |
17 |
| - |
18 |
| - const attrShortHandList = templateToEvaluate.match(ATTR_SHORTHAND_REGEX) || []; |
19 |
| - |
20 |
| - const attrShortHandMap = attrShortHandList.reduce((acc, attrShortHand) => { |
21 |
| - const indexOfHash = attrShortHand.indexOf("#"); |
22 |
| - const refName = attrShortHand.substring(2, indexOfHash); |
23 |
| - const attrName = attrShortHand.substring(indexOfHash + 1, attrShortHand.length - 1); |
24 |
| - acc[attrShortHand] = getAttr(templateContext[refName] as Record<string, any>, attrName) as string; |
25 |
| - return acc; |
26 |
| - }, {} as Record<string, string>); |
27 |
| - |
28 |
| - const templateWithAttr = Object.entries(attrShortHandMap).reduce( |
29 |
| - (acc, [shortHand, value]) => acc.replace(shortHand, value), |
30 |
| - templateToEvaluate |
31 |
| - ); |
32 |
| - |
33 |
| - const templateContextNames = Object.keys(templateContext); |
34 |
| - const templateContextValues = Object.values(templateContext); |
35 |
| - const templateWithTildeEscaped = templateWithAttr.replace(/\`/g, "\\`"); |
36 |
| - |
37 |
| - return new Function(...templateContextNames, `return \`${templateWithTildeEscaped}\``)(...templateContextValues); |
| 10 | + } as Record<string, string>; |
| 11 | + |
| 12 | + let currentIndex = 0; |
| 13 | + while (currentIndex < template.length) { |
| 14 | + const openingBraceIndex = template.indexOf("{", currentIndex); |
| 15 | + |
| 16 | + if (openingBraceIndex === -1) { |
| 17 | + // No more opening braces, add the rest of the template and break. |
| 18 | + evaluatedTemplateArr.push(template.slice(currentIndex)); |
| 19 | + break; |
| 20 | + } |
| 21 | + |
| 22 | + evaluatedTemplateArr.push(template.slice(currentIndex, openingBraceIndex)); |
| 23 | + const closingBraceIndex = template.indexOf("}", openingBraceIndex); |
| 24 | + |
| 25 | + if (closingBraceIndex === -1) { |
| 26 | + // No more closing braces, add the rest of the template and break. |
| 27 | + evaluatedTemplateArr.push(template.slice(openingBraceIndex)); |
| 28 | + break; |
| 29 | + } |
| 30 | + |
| 31 | + if (template[openingBraceIndex + 1] === "{" && template[closingBraceIndex + 1] === "}") { |
| 32 | + // Escaped expression. Do not evaluate. |
| 33 | + evaluatedTemplateArr.push(template.slice(openingBraceIndex + 1, closingBraceIndex)); |
| 34 | + currentIndex = closingBraceIndex + 2; |
| 35 | + } |
| 36 | + |
| 37 | + const parameterName = template.substring(openingBraceIndex + 1, closingBraceIndex); |
| 38 | + |
| 39 | + if (parameterName.includes("#")) { |
| 40 | + const [refName, attrName] = parameterName.split("#"); |
| 41 | + evaluatedTemplateArr.push(getAttr(templateContext[refName], attrName) as string); |
| 42 | + } else { |
| 43 | + evaluatedTemplateArr.push(templateContext[parameterName]); |
| 44 | + } |
| 45 | + |
| 46 | + currentIndex = closingBraceIndex + 1; |
| 47 | + } |
| 48 | + |
| 49 | + return evaluatedTemplateArr.join(""); |
38 | 50 | };
|
0 commit comments