substitute.js revision 838d626f7e69c325fea41507371d80369a69026c
7380653a55868892cb97060c61641fc73ba22cbeDav GlassYUI.add('substitute', function(Y) {
7380653a55868892cb97060c61641fc73ba22cbeDav Glass
9271f9c6e942b68a4fbfa228f67ab46b72c76780Ryan Grove/**
9271f9c6e942b68a4fbfa228f67ab46b72c76780Ryan Grove * String variable substitution and string formatting.
7380653a55868892cb97060c61641fc73ba22cbeDav Glass * If included, the substitute method is added to the YUI instance.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove *
7380653a55868892cb97060c61641fc73ba22cbeDav Glass * @module substitute
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove */
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove var L = Y.Lang, DUMP='dump', SPACE=' ', LBRACE='{', RBRACE='}',
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove /**
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * The following methods are added to the YUI instance
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * @class YUI~substitute
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove */
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove /**
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * Does variable substitution on a string. It scans through the string
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * looking for expressions enclosed in { } braces. If an expression
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * is found, it is used a key on the object. If there is a space in
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * the key, the first word is used for the key and the rest is provided
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * to an optional function to be used to programatically determine the
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * value (the extra information might be used for this decision). If
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * the value for the key in the object, or what is returned from the
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * function has a string value, number value, or object value, it is
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * substituted for the bracket expression and it repeats. If this
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * value is an object, it uses the Object's toString() if this has
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * been overridden, otherwise it does a shallow dump of the key/value
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * pairs if Y.dump is available (if dump isn't available, toString()
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * is used).
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove *
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * This method is included in the 'substitute' module. It is not included
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * in the YUI module.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove *
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * @method substitute
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * @param s {string} The string that will be modified.
c0d83403b13f02bc6fdcf62a712de150a7f974e2Dav Glass * @param o An object containing the replacement values
7380653a55868892cb97060c61641fc73ba22cbeDav Glass * @param f {function} An optional function that can be used to
7380653a55868892cb97060c61641fc73ba22cbeDav Glass * process each match. It receives the key,
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * value, and any extra metadata included with
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * the key inside of the braces.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove * @return {string} the substituted string
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove */
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove substitute = function (s, o, f, recurse) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove var i, j, k, key, v, meta, saved=[], token, dump,
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove lidx = s.length;
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove for (;;) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove i = s.lastIndexOf(LBRACE, lidx);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove if (i < 0) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove break;
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove }
7380653a55868892cb97060c61641fc73ba22cbeDav Glass j = s.indexOf(RBRACE, i);
7380653a55868892cb97060c61641fc73ba22cbeDav Glass if (i + 1 >= j) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove break;
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove }
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove //Extract key and meta info
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove token = s.substring(i + 1, j);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove key = token;
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove meta = null;
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove k = key.indexOf(SPACE);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove if (k > -1) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove meta = key.substring(k + 1);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove key = key.substring(0, k);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove }
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // lookup the value
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove v = o[key];
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // if a substitution function was provided, execute it
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove if (f) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove v = f(key, v, meta);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove }
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove if (L.isObject(v)) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove if (!Y.dump) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove v = v.toString();
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove } else {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove if (L.isArray(v)) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove v = Y.dump(v, parseInt(meta, 10));
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove } else {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove meta = meta || "";
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // look for the keyword 'dump', if found force obj dump
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove dump = meta.indexOf(DUMP);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove if (dump > -1) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove meta = meta.substring(4);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove }
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // use the toString if it is not the Object toString
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // and the 'dump' meta info was not found
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove if (v.toString===Object.prototype.toString||dump>-1) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove v = Y.dump(v, parseInt(meta, 10));
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove } else {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove v = v.toString();
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove }
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove }
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove }
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove } else if (!L.isString(v) && !L.isNumber(v)) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // This {block} has no replace string. Save it for later.
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove v = "~-" + saved.length + "-~";
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove saved[saved.length] = token;
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // break;
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove }
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove s = s.substring(0, i) + v + s.substring(j + 1);
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove if (!recurse) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove lidx = i-1;
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove }
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove }
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove // restore saved {block}s
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove for (i=saved.length-1; i>=0; i=i-1) {
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove s = s.replace(new RegExp("~-" + i + "-~"), LBRACE + saved[i] + RBRACE, "g");
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove }
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove return s;
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove };
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove Y.substitute = substitute;
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove L.substitute = substitute;
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove}, '@VERSION@' ,{optional:['dump']});
92e597e015cd0d9a07055436b637d9cfdb9c1164Ryan Grove