(input: string)
| 889 | } |
| 890 | |
| 891 | protected async replaceVariableInString(input: string) { |
| 892 | let output = input; |
| 893 | |
| 894 | // Pass 1: resolve named suggester definitions up front (see above). |
| 895 | await this.resolveNamedSuggesterDefinitions(output); |
| 896 | |
| 897 | // Pass 2: replace every VALUE token in document order. |
| 898 | const regex = new RegExp(VARIABLE_REGEX.source, 'gi'); // preserve case-insensitive + global |
| 899 | const propertyTypesEnabled = this.isTemplatePropertyTypesEnabled(); |
| 900 | let match: RegExpExecArray | null; |
| 901 | |
| 902 | while ((match = regex.exec(output)) !== null) { |
| 903 | if (!match[1]) { |
| 904 | throw new Error(`Unable to parse variable. Invalid syntax in: "${output.substring(Math.max(0, match.index - 10), Math.min(output.length, match.index + 30))}..."`); |
| 905 | } |
| 906 | |
| 907 | const parsed = parseValueToken(match[1]); |
| 908 | if (!parsed) { |
| 909 | throw new Error(`Unable to parse variable. Invalid syntax in: "${output.substring(Math.max(0, match.index - 10), Math.min(output.length, match.index + 30))}..."`); |
| 910 | } |
| 911 | |
| 912 | const { variableName } = parsed; |
| 913 | |
| 914 | const effectiveKey = await this.ensureValueVariableResolved(parsed); |
| 915 | |
| 916 | // Get the raw value from variables |
| 917 | const rawValue = this.variables.get(effectiveKey); |
| 918 | const effectiveRawValue = this.applyValueTokenOptions(rawValue, parsed); |
| 919 | |
| 920 | // Offer this variable to the property collector for YAML post-processing. |
| 921 | // Collecting structured values (arrays/objects/numbers/booleans) into a |
| 922 | // processFrontMatter pass is always-on inside a collection scope so that |
| 923 | // scripts returning real arrays produce valid YAML regardless of the |
| 924 | // beta toggle. Only the string -> structured *heuristic* is flag-gated. |
| 925 | const collectionActive = this.templatePropertyCollectionDepth > 0; |
| 926 | const structuredYamlValue = this.propertyCollector.maybeCollect({ |
| 927 | input: output, |
| 928 | matchStart: match.index, |
| 929 | matchEnd: match.index + match[0].length, |
| 930 | rawValue: effectiveRawValue, |
| 931 | fallbackKey: variableName, |
| 932 | collectionActive, |
| 933 | // |type:text forces a string: never run the string->structured |
| 934 | // heuristic on it, or a comma/bracket value (`a,b`, `[x]`) would be |
| 935 | // collected as a List and bypass the quoting path below. |
| 936 | heuristicEnabled: |
| 937 | propertyTypesEnabled && |
| 938 | collectionActive && |
| 939 | parsed.inputTypeOverride !== "text", |
| 940 | }); |
| 941 | |
| 942 | // Keep the interim frontmatter YAML-parseable until post-processing |
| 943 | // writes the real structured value back through Obsidian. Coerce the |
| 944 | // fallback replacement to a string so non-string variable values (e.g. |
| 945 | // arrays from scripts on the non-collected path) don't desync the scanner. |
| 946 | const placeholder = getYamlPlaceholder(structuredYamlValue); |
| 947 | let replacement: string; |
| 948 | if (placeholder !== undefined) { |
nothing calls this directly
no test coverage detected