You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
temptress-bot/src/util/renderableText.ts

58 lines
2.0 KiB

import { shuffleWeightedList, WeightedList } from './weightedList'
import { PRNG } from 'seedrandom'
export type RenderableText = string | WeightedList<string>
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
},
)
}