Transformers
Transformers decide what a variable tag renders, and which parts of a value a template can reach.
Where a parser implements a tag, a transformer supplies a value. Your app seeds them by name on each run call, and a variable parser hands the tag to the matching one.
import { Interpreter, StrictVarsParser, StringTransformer } from 'tagscript';
const ts = new Interpreter(new StrictVarsParser());
const response = await ts.run('Hi {args}', { args: new StringTransformer('How are you?') });
response.body; // 'Hi How are you?'A transformer receives the whole tag, so the parameter can mean whatever suits the value. StringTransformer reads it as a word index, SafeObjectTransformer reads it as a property path, and the Discord transformers read it as a field name.
This is also the boundary that keeps a template away from your objects. A transformer answers with the keys it chooses to expose and nothing else, so seeding new MemberTransformer(member) gives the template {member.displayName} without giving it the client, the token, or any method on the member.
Built-in transformers
| Page | Use it for |
|---|---|
| String | Text, with word and segment indexing through the parameter. |
| Integer | A number that a template can increment or decrement. |
| Safe object | A plain object, reachable by dotted path, with private keys refused. |
| Function | A value you compute at render time. |
The Discord plugin adds transformers for users, members, roles, channels, guilds and interactions.
Writing your own
Implement ITransformer. The one method takes the tag and returns a string, or null to decline, which leaves the tag in the output as written.
import type { ITransformer, Lexer } from 'tagscript';
export class TemperatureTransformer implements ITransformer {
public constructor(private readonly celsius: number) {}
public transform(tag: Lexer) {
if (tag.parameter === 'f') return `${(this.celsius * 9) / 5 + 32}`;
if (tag.parameter === null) return `${this.celsius}`;
return null;
}
}{temp} is {temp(f)} in Fahrenheit
# 20 is 68 in FahrenheitReturning null for anything you do not recognise is the right default. It keeps unknown parameters visible in the output instead of rendering an empty string, and it lets another parser handle the tag instead.
transform is synchronous. Anything that needs to await belongs in a parser.
API reference
Last updated on