dependencies.halbrowser.vendor.js.uritemplates.js Maven / Gradle / Ivy
The newest version!
/*
UriTemplates Template Processor - Version: @VERSION - Dated: @DATE
(c) [email protected] - 2011-2012
Licensed under ALPv2
*/
;
var uritemplate = (function() {
// Below are the functions we originally used from jQuery.
// The implementations below are often more naive then what is inside jquery, but they suffice for our needs.
function isFunction(fn) {
return typeof fn == 'function';
}
function isEmptyObject (obj) {
for(var name in obj){
return false;
}
return true;
}
function extend(base, newprops) {
for (var name in newprops) {
base[name] = newprops[name];
}
return base;
}
/**
* Create a runtime cache around retrieved values from the context.
* This allows for dynamic (function) results to be kept the same for multiple
* occuring expansions within one template.
* Note: Uses key-value tupples to be able to cache null values as well.
*/
//TODO move this into prep-processing
function CachingContext(context) {
this.raw = context;
this.cache = {};
}
CachingContext.prototype.get = function(key) {
var val = this.lookupRaw(key);
var result = val;
if (isFunction(val)) { // check function-result-cache
var tupple = this.cache[key];
if (tupple !== null && tupple !== undefined) {
result = tupple.val;
} else {
result = val(this.raw);
this.cache[key] = {key: key, val: result};
// NOTE: by storing tupples we make sure a null return is validly consistent too in expansions
}
}
return result;
};
CachingContext.prototype.lookupRaw = function(key) {
return CachingContext.lookup(this, this.raw, key);
};
CachingContext.lookup = function(me, context, key) {
var result = context[key];
if (result !== undefined) {
return result;
} else {
var keyparts = key.split('.');
var i = 0, keysplits = keyparts.length - 1;
for (i = 0; i 0 ? "=" : "") + val;
}
function addNamed(name, key, val, noName) {
noName = noName || false;
if (noName) { name = ""; }
if (!key || key.length === 0) {
key = name;
}
return key + (key.length > 0 ? "=" : "") + val;
}
function addLabeled(name, key, val, noName) {
noName = noName || false;
if (noName) { name = ""; }
if (!key || key.length === 0) {
key = name;
}
return key + (key.length > 0 && val ? "=" : "") + val;
}
var simpleConf = {
prefix : "", joiner : ",", encode : encodeNormal, builder : addUnNamed
};
var reservedConf = {
prefix : "", joiner : ",", encode : encodeReserved, builder : addUnNamed
};
var fragmentConf = {
prefix : "#", joiner : ",", encode : encodeReserved, builder : addUnNamed
};
var pathParamConf = {
prefix : ";", joiner : ";", encode : encodeNormal, builder : addLabeled
};
var formParamConf = {
prefix : "?", joiner : "&", encode : encodeNormal, builder : addNamed
};
var formContinueConf = {
prefix : "&", joiner : "&", encode : encodeNormal, builder : addNamed
};
var pathHierarchyConf = {
prefix : "/", joiner : "/", encode : encodeNormal, builder : addUnNamed
};
var labelConf = {
prefix : ".", joiner : ".", encode : encodeNormal, builder : addUnNamed
};
function Expression(conf, vars ) {
extend(this, conf);
this.vars = vars;
}
Expression.build = function(ops, vars) {
var conf;
switch(ops) {
case '' : conf = simpleConf; break;
case '+' : conf = reservedConf; break;
case '#' : conf = fragmentConf; break;
case ';' : conf = pathParamConf; break;
case '?' : conf = formParamConf; break;
case '&' : conf = formContinueConf; break;
case '/' : conf = pathHierarchyConf; break;
case '.' : conf = labelConf; break;
default : throw "Unexpected operator: '"+ops+"'";
}
return new Expression(conf, vars);
};
Expression.prototype.expand = function(context) {
var joiner = this.prefix;
var nextjoiner = this.joiner;
var buildSegment = this.builder;
var res = "";
var i = 0, cnt = this.vars.length;
for (i = 0 ; i< cnt; i++) {
var varspec = this.vars[i];
varspec.addValues(context, this.encode, function(key, val, noName) {
var segm = buildSegment(varspec.name, key, val, noName);
if (segm !== null && segm !== undefined) {
res += joiner + segm;
joiner = nextjoiner;
}
});
}
return res;
};
var UNBOUND = {};
/**
* Helper class to help grow a string of (possibly encoded) parts until limit is reached
*/
function Buffer(limit) {
this.str = "";
if (limit === UNBOUND) {
this.appender = Buffer.UnboundAppend;
} else {
this.len = 0;
this.limit = limit;
this.appender = Buffer.BoundAppend;
}
}
Buffer.prototype.append = function(part, encoder) {
return this.appender(this, part, encoder);
};
Buffer.UnboundAppend = function(me, part, encoder) {
part = encoder ? encoder(part) : part;
me.str += part;
return me;
};
Buffer.BoundAppend = function(me, part, encoder) {
part = part.substring(0, me.limit - me.len);
me.len += part.length;
part = encoder ? encoder(part) : part;
me.str += part;
return me;
};
function arrayToString(arr, encoder, maxLength) {
var buffer = new Buffer(maxLength);
var joiner = "";
var i = 0, cnt = arr.length;
for (i=0; i