meeseeks / src /lib /substitute.ts
AryaYT's picture
init: meeseeks bun docker space (server, ui, samples, receipts)
71c7323
Raw
History Blame Contribute Delete
1.47 kB
// Placeholder substitution for skill text.
// Convention: placeholders look like {{KEY}} (uppercase + underscores).
// Inputs may be passed as either {KEY: value} or {key: value} — both resolve.
export interface SubstituteResult {
text: string;
bound: string[];
unbound: string[];
}
const PLACEHOLDER_RE = /\{\{([A-Z][A-Z0-9_]*)\}\}/g;
export function substitute(text: string, inputs: Record<string, string>): string {
return text.replace(PLACEHOLDER_RE, (match, key: string) => {
if (inputs[key] !== undefined) return inputs[key];
const lc = key.toLowerCase();
if (inputs[lc] !== undefined) return inputs[lc];
return match;
});
}
export function substituteWithReport(
text: string,
inputs: Record<string, string>,
): SubstituteResult {
const bound = new Set<string>();
const unbound = new Set<string>();
const out = text.replace(PLACEHOLDER_RE, (match, key: string) => {
if (inputs[key] !== undefined) {
bound.add(`{{${key}}}`);
return inputs[key];
}
const lc = key.toLowerCase();
if (inputs[lc] !== undefined) {
bound.add(`{{${key}}}`);
return inputs[lc];
}
unbound.add(`{{${key}}}`);
return match;
});
return { text: out, bound: [...bound], unbound: [...unbound] };
}
export function findPlaceholders(text: string): string[] {
const found = new Set<string>();
for (const m of text.matchAll(PLACEHOLDER_RE)) {
found.add(`{{${m[1]}}}`);
}
return [...found];
}