Skip to content

Instantly share code, notes, and snippets.

@victornpb
Last active January 10, 2023 17:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save victornpb/5a9642b1d5f749695e14 to your computer and use it in GitHub Desktop.
Save victornpb/5a9642b1d5f749695e14 to your computer and use it in GitHub Desktop.
String.format() that supports argument list, array, objects, and nested objects.
/**
* Replace all {{key}} placeholders in a string with the corresponding value from an object array or list of argumments.
* @param {string} str The string template.
* @param {object|array} args The object containing the values to replace the tokens with.
* @param {...args} args The arguments to replace the tokens in the string as a list of arguments
* @returns {string} The new string with the tokens replaced.
* @author victornpb https://gist.github.com/victornpb/5a9642b1d5f749695e14
*
* @example
* format("hello {{0}} world {{1}}!", "foo", "bar"); //"hello foo world bar"
* format("hello {{0}} world {{1}}!", ["foo", "bar"]); //"hello foo world bar"
* format("hello {{name}} world {{test}}!", {name: "foo", test: "bar"}); //"hello foo world bar"
* format("hello {{obj.name}} world {{obj.test[0]}}!", {obj:{name: "foo", test: ["bar"]}}); //"hello foo world bar"
*/
export default function format(string, ...args) {
function get(object, path, defaultValue = undefined) {
if (typeof object === 'undefined' || object === null) return defaultValue;
const pathArray = path.split(/\.|\[["']?|["']?\]/);
for (let i = 0, l = pathArray.length; i < l; i++) {
if (pathArray[i] === '') continue;
object = object[pathArray[i]];
if (typeof object === 'undefined' || object === null) return defaultValue;
}
return (typeof object === 'undefined' || object === null) ? defaultValue : object;
}
let str = String(string);
if (args.length) {
if (args.length === 1 && typeof args[0] === 'object') args = args[0];
str = str.replace(/\{\{([^}]+)\}\}/g, (m, key) => {
return get(args, key, m);
});
}
return str;
}
if (!String.prototype.format) {
/**
* formats a string replacing tokens with an argument list, array, objects, and nested objects.
* @args Can be a list of arguments, array or object
*
* Usage:
* "hello {0} world {0}!".format("foo", "bar"); //"hello foo world bar"
* "hello {0} world {0}!".format(["foo", "bar"]); //"hello foo world bar"
* "hello {name} world {test}!".format({name: "foo", test: "bar"}); //"hello foo world bar"
* "hello {obj.name} world {obj.test[0]}!".format({obj:{name: "foo", test: ["bar"]}}); //"hello foo world bar"
* @author Victor B. https://gist.github.com/victornpb/5a9642b1d5f749695e14
*/
String.prototype.format = function() {
/**
* Access a deep value inside a object
* Works by passing a path like "foo.bar", also works with nested arrays like "foo[0][1].baz"
* @author Victor B. https://gist.github.com/victornpb/4c7882c1b9d36292308e
*/
function getDeepVal(obj, path) {
var path = path.split(/[\.\[\]]/);
for (var i = 0, l = path.length; i < l; i++) {
if (path[i] === "") continue;
obj = obj[path[i]];
};
return obj;
}
var str = this.toString();
if (!arguments.length)
return str;
var args = typeof arguments[0],
args = (("string" == args || "number" == args) ? arguments : arguments[0]);
str = str.replace(/\{([^\}]+)\}/g, function(m, key) {
return getDeepVal(args, key);
});
return str;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment