I want to create a simple text templating that allow defining placeholders using {0}
, similar to what .Net does using string.format method.
Basically I want this:
format("{0}", 42), // output `42`
format("{0} {1}", 42, "bar"), // output `42 bar`
format("{1} {1}", 42, "bar"), // output `bar bar` ({0} ignored)
format("{{0", 42), // output `{0` (`{{` is an escaped `{`)
format("{{{0}", 42), // output `{42` : an escaped brace and the formatted value
format("Mix {{0}} and {0}", 42), // outputs `Mix {0} and 42`
I’m trying to play with regex and backtracking to deal with the escaped braces.
function format(template: string, ...values: unknown[]): string {
const regex = /(?!({{)+){(d+)}(?<!(}}))/gm;
return template.replace(regex, ([, index]) => {
const valueIndex = parseInt(index, 10);
if (valueIndex >= values.length) throw new Error("Not enough arguments")
return String(values[valueIndex]);
});
}
console.log([
format("{0}", 42), // output `42`
format("{0} {1}", 42, "bar"), // output `42 bar`
format("{1} {1}", 42, "bar"), // output `bar bar` ({0} ignored)
format("{{0", 42), // output `{0` (`{{` is an escaped `{`)
format("{{{0}", 42), // output `{42` : an escaped brace and the formatted value
format("Mix {{0}} and {0}", 42), // outputs `Mix {0} and 42`
]);
try {
format("{0} {1}", 42); // throw error because not enough argument are passed
} catch (e) {
console.error(e);
}
However, I’m struggling to properly replaced the escaped braces by a single brace
How to fix it ?