I am working on developing a text templating system that allows for defining placeholders using {0}
, similar to the functionality of .Net's string.format method.
Here is an example of what I am aiming for:
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`
format("Invalid closing brace }"), // should fail, since the closing brace does close an opening one
format("Invalid placeholder {z}"), // should fail, not an integer
format("{0}", "With { in value"), // output `With { in value`, inner { should be broke the format
I am experimenting with regex and backtracking to handle 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`
format("Invalid closing brace }"), // should fail, since the closing brace does not close an opening one
format("Invalid placeholder {z}"), // should fail, not an integer
format("{0}", "With { in value"), // output `With { in value`, inner { should be broke the format
]);
try {
format("{0} {1}", 42); // throw error because not enough argument are passed
} catch (e) {
console.log(e.message);
}
Despite my efforts, I am struggling to properly replace the escaped braces with a single brace.
How can I resolve this issue?