import { shuffleWeightedList, WeightedList } from './weightedList' import { PRNG } from 'seedrandom' export type RenderableText = string | WeightedList export interface TextSource { [key: string]: RenderableText } export function renderText(text: RenderableText, data: TextSource, rng: PRNG): string { const result = shuffleWeightedList(text, '', rng) if (needsSubstitution(result)) { return substituteText(result, data, rng) } else { return result } } const textReplacementRE = /\\(.)|\{\{\s*([A-Za-z0-9_]+)\s*}}/g function needsSubstitution(text: string): boolean { return textReplacementRE.test(text) } function substituteText(text: string, data: TextSource, random: PRNG): string { return text.replaceAll( textReplacementRE, (substring, escapedCharacter: string | undefined, fieldName: string | undefined): string => { let result: undefined | RenderableText = undefined let errType = 'substitution' if (typeof escapedCharacter === 'string') { if (escapedCharacter === '\\' || escapedCharacter === '{') { result = escapedCharacter } else { errType = 'escape' } } if (typeof fieldName === 'string') { errType = 'variable or commonText' result = data[fieldName] if (typeof result === 'string') { if (needsSubstitution(result)) { return substituteText(result, data, random) } } else if (typeof result === 'undefined') { errType = 'variable or commonText' } else { return renderText(result, data, random) } } if (typeof result === 'undefined') { throw Error(`unknown ${errType} ${substring}`) } return result }, ) }