import { isDefined } from '@typebot.io/lib' import { Variable, VariableWithValue } from '@typebot.io/schemas' import { safeStringify } from '@typebot.io/lib/safeStringify' export type ParseVariablesOptions = { fieldToParse?: 'value' | 'id' escapeForJson?: boolean takeLatestIfList?: boolean escapeHtml?: boolean } export const defaultParseVariablesOptions: ParseVariablesOptions = { fieldToParse: 'value', escapeForJson: false, takeLatestIfList: false, escapeHtml: false, } export const parseVariables = ( variables: Variable[], options: ParseVariablesOptions = defaultParseVariablesOptions ) => (text: string | undefined): string => { if (!text || text === '') return '' // Capture {{variable}} and ${{{variable}}} (variables in template litterals) const pattern = /\{\{([^{}]+)\}\}|(\$)\{\{([^{}]+)\}\}/g return text.replace( pattern, (_full, nameInCurlyBraces, _dollarSign, nameInTemplateLitteral) => { const dollarSign = (_dollarSign ?? '') as string const matchedVarName = nameInCurlyBraces ?? nameInTemplateLitteral const variable = variables.find((variable) => { return ( matchedVarName === variable.name && (options.fieldToParse === 'id' || isDefined(variable.value)) ) }) as VariableWithValue | undefined if (!variable) return dollarSign + '' if (options.fieldToParse === 'id') return dollarSign + variable.id const { value } = variable if (options.escapeForJson) return ( dollarSign + (typeof value === 'string' ? jsonParse(value) : JSON.stringify(value)) ) const parsedValue = dollarSign + safeStringify( options.takeLatestIfList && Array.isArray(value) ? value[value.length - 1] : value ) if (!parsedValue) return dollarSign + '' if (options.escapeHtml) return parsedValue.replace(//g, '>') return parsedValue } ) } const jsonParse = (str: string) => str .replace(/\n/g, `\\n`) .replace(/"/g, `\\"`) .replace(/\\[^n"]/g, `\\\\ `)