Commit 1663b469 authored by fxa's avatar fxa

fixed bug with {?empty}

parent ead0b6f0
......@@ -60,6 +60,7 @@ MIT License, see http://mit-license.org/
Release Notes
-------------
* 0.2.3 fixed bug with empty objects ('{?empty}' with '{empty:{}}' shall expand to '?empty=')
* 0.2.2 fixed pct encoding bug with multibyte utf8 chars
* 0.2.1 fixed a bug in package.json
* 0.2.0 heavy project refactoring, splitting source files, introducing jshint (preparation of next steps)
......
(function(e){"use strict";function r(e){var t,o;if(null===e||void 0===e)return!1;if(n.isArray(e)){for(t=0;e.length>t;t+=1)if(r(e[t]))return!0;return!1}if("string"==typeof e||"number"==typeof e||"boolean"==typeof e)return!0;for(o in e)if(e.hasOwnProperty(o)&&r(e[o]))return!0;return!1}var n=function(){function e(e){return"[object Array]"===Object.prototype.toString.apply(e)}function r(e,r,n){var t,o=n;for(t in e)e.hasOwnProperty(t)&&(o=r(o,e[t],t,e));return o}function n(e,r,n){var t,o=n;for(t=0;e.length>t;t+=1)o=r(o,e[t],t,e);return o}function t(t,o,i){return e(t)?n(t,o,i):r(t,o,i)}return{isArray:e,reduce:t}}(),t=function(){function e(e){return e>="a"&&"z">=e||e>="A"&&"Z">=e}function r(e){return e>="0"&&"9">=e}function n(e){return r(e)||e>="a"&&"f">=e||e>="A"&&"F">=e}return{isAlpha:e,isDigit:r,isHexDigit:n}}(),o=function(){function e(e){var r,n,t="",o=u.encode(e);for(n=0;o.length>n;n+=1)r=o.charCodeAt(n),t+="%"+r.toString(16).toUpperCase();return t}function r(e,r){return"%"===e[r]&&t.isHexDigit(e[r+1])&&t.isHexDigit(e[r+2])}function n(e,r){return parseInt(e.substr(r,2),16)}function o(e){if(!r(e,0))return!1;var t=n(e,1),o=u.numBytes(t);if(0===o)return!1;for(var i=1;o>i;i+=1)if(!r(e,3*i)||!u.isValidFollowingCharCode(n(e,3*i+1)))return!1;return!0}function i(e,t){var o=e[t];if(!r(e,t))return o;var i=n(e,t+1),a=u.numBytes(i);if(0===a)return o;for(var s=1;a>s;s+=1)if(!r(e,t+3*s)||!u.isValidFollowingCharCode(n(e,t+3*s+1)))return o;return e.substr(t,3*a)}var u={encode:function(e){return unescape(encodeURIComponent(e))},numBytes:function(e){return 127>=e?1:e>=194&&223>=e?2:e>=224&&239>=e?3:e>=240&&244>=e?4:0},isValidFollowingCharCode:function(e){return e>=128&&191>=e}};return{encodeCharacter:e,isPctEncoded:o,pctCharAt:i}}(),i=function(){function e(e){return t.isAlpha(e)||t.isDigit(e)||"_"===e||o.isPctEncoded(e)}function r(e){return t.isAlpha(e)||t.isDigit(e)||"-"===e||"."===e||"_"===e||"~"===e}function n(e){return":"===e||"/"===e||"?"===e||"#"===e||"["===e||"]"===e||"@"===e||"!"===e||"$"===e||"&"===e||"("===e||")"===e||"*"===e||"+"===e||","===e||";"===e||"="===e||"'"===e}return{isVarchar:e,isUnreserved:r,isReserved:n}}(),u=function(){function e(e,r){var n,t="",u="";for(("number"==typeof e||"boolean"==typeof e)&&(e=""+e),n=0;e.length>n;n+=u.length)u=o.pctCharAt(e,n),t+=u.length>1?u:i.isUnreserved(u)||r&&i.isReserved(u)?u:o.encodeCharacter(u);return t}function r(r){return e(r,!0)}return{encode:e,encodePassReserved:r}}(),a=function(){function e(e){r[e]={symbol:e,separator:"?"===e?"&":""===e||"+"===e||"#"===e?",":e,named:";"===e||"&"===e||"?"===e,ifEmpty:"&"===e||"?"===e?"=":"",first:"+"===e?"":e,encode:"+"===e||"#"===e?u.encodePassReserved:u.encode,toString:function(){return this.symbol}}}var r={};return e(""),e("+"),e("#"),e("."),e("/"),e(";"),e("?"),e("&"),{valueOf:function(e){if(r[e])return r[e];if("=,!@|".indexOf(e)>=0)throw Error('Illegal use of reserved operator "'+e+'"');return r[""]}}}(),s=function(){function e(e){var r,n="",t="";for(r=0;e.length>r;r+=t.length)t=o.pctCharAt(e,r),n+=t.length>0?t:i.isReserved(t)||i.isUnreserved(t)?t:o.encodeCharacter(t);return n}function r(e){this.literal=r.encodeLiteral(e)}return r.encodeLiteral=e,r.prototype.expand=function(){return this.literal},r.prototype.toString=r.prototype.expand,r}(),f=function(){function e(e){function r(){p={varname:u.substring(h,f),exploded:!1,maxLength:null},h=null}function n(){if(d===f)throw Error("after a ':' you have to specify the length. position = "+f);p.maxLength=parseInt(u.substring(d,f),10),d=null}var u,s,f,c=[],p=null,h=null,d=null,g="";for(u=e.substr(1,e.length-2),s=a.valueOf(u.charAt(0)),f=""===s.symbol?0:1,h=f;u.length>f;f+=g.length){if(g=o.pctCharAt(u,f),null!==h){if("."===g){if(h===f)throw Error("a varname MUST NOT start with a dot -- see position "+f);continue}if(i.isVarchar(g))continue;r()}if(null!==d){if(t.isDigit(g))continue;n()}if(":"!==g)if("*"!==g){if(","!==g)throw Error("illegal character '"+g+"' at position "+f+' of "'+u+'"');c.push(p),p=null,h=f+1}else{if(null===p)throw Error("explode exploded at position "+f);if(p.exploded)throw Error("explode exploded twice at position "+f);if(p.maxLength)throw Error("an explode (*) MUST NOT follow to a prefix, see position "+f);p.exploded=!0}else{if(null!==p.maxLength)throw Error("only one :maxLength is allowed per varspec at position "+f);d=f+1}}return null!==h&&r(),null!==d&&n(),c.push(p),new l(e,s,c)}function r(r){var n,t,o=[],i=null,u=0;for(n=0;r.length>n;n+=1)if(t=r.charAt(n),null===u){if(null===i)throw Error("reached unreachable code");if("{"===t)throw Error("brace was opened in position "+i+" and cannot be reopened in position "+n);if("}"===t){if(i+1===n)throw Error("empty braces on position "+i);o.push(e(r.substring(i,n+1))),i=null,u=n+1}}else{if("}"===t)throw Error("brace was closed in position "+n+" but never opened");"{"===t&&(n>u&&o.push(new s(r.substring(u,n))),u=null,i=n)}if(null!==i)throw Error("brace was opened on position "+i+", but never closed");return r.length>u&&o.push(new s(r.substr(u))),new c(r,o)}return r}(),l=function(){function e(e){return JSON?JSON.stringify(e):e}function t(e,r,n){this.templateText=e,this.operator=r,this.varspecs=n}return t.prototype.toString=function(){return this.templateText},t.prototype.expand=function(t){function o(e,n,t){return r(n)&&(e.length>0&&(e+=","),c||(e+=d.encode(t)+","),e+=d.encode(n)),e}function i(e,n,t){return r(n)&&(e.length>0&&(e+=d.separator),e+=c?s.encodeLiteral(f.varname):d.encode(t),e+="="+d.encode(n)),e}function u(e,n,t){return r(n)&&(e.length>0&&(e+=d.separator),c||(e+=d.encode(t)+"="),e+=d.encode(n)),e}var a,f,l,c,p="",h=!0,d=this.operator;for(a=0;this.varspecs.length>a;a+=1)if(f=this.varspecs[a],l=t[f.varname],r(l))if(h?(p+=this.operator.first,h=!1):p+=this.operator.separator,c=n.isArray(l),"string"==typeof l||"number"==typeof l||"boolean"==typeof l){if(l=""+l,this.operator.named){if(p+=s.encodeLiteral(f.varname),""===l){p+=this.operator.ifEmpty;continue}p+="="}f.maxLength&&l.length>f.maxLength&&(l=l.substr(0,f.maxLength)),p+=this.operator.encode(l)}else{if(f.maxLength)throw Error("Prefix modifiers are not applicable to variables that have composite values. You tried to expand "+this+" with "+e(l));if(f.exploded)p+=n.reduce(l,d.named?i:u,"");else{if(d.named){if(p+=s.encodeLiteral(f.varname),!r(l)){p+=this.operator.ifEmpty;continue}p+="="}p+=n.reduce(l,o,"")}}return p},t}(),c=function(){function e(e,r){this.templateText=e,this.expressions=r}return e.prototype.toString=function(){return this.templateText},e.prototype.expand=function(e){var r,n="";for(r=0;this.expressions.length>r;r+=1)n+=this.expressions[r].expand(e);return n},e.parse=f,e}();e(c)})(function(e){"use strict";"undefined"!=typeof module?module.exports=e:"undefined"!=typeof define?define([],function(){return e}):"undefined"!=typeof window?window.UriTemplate=e:global.UriTemplate=e});
\ No newline at end of file
(function(e){"use strict";function n(e){var t,o;if(null===e||void 0===e)return!1;if(r.isArray(e)){for(t=0;e.length>t;t+=1)if(n(e[t]))return!0;return!1}if("string"==typeof e||"number"==typeof e||"boolean"==typeof e)return!0;for(o in e)if(e.hasOwnProperty(o)&&n(e[o]))return!0;return!1}var r=function(){function e(e){return"[object Array]"===Object.prototype.toString.apply(e)}function n(e,n,r){var t,o=r;for(t in e)e.hasOwnProperty(t)&&(o=n(o,e[t],t,e));return o}function r(e,n,r){var t,o=r;for(t=0;e.length>t;t+=1)o=n(o,e[t],t,e);return o}function t(t,o,i){return e(t)?r(t,o,i):n(t,o,i)}return{isArray:e,reduce:t}}(),t=function(){function e(e){return e>="a"&&"z">=e||e>="A"&&"Z">=e}function n(e){return e>="0"&&"9">=e}function r(e){return n(e)||e>="a"&&"f">=e||e>="A"&&"F">=e}return{isAlpha:e,isDigit:n,isHexDigit:r}}(),o=function(){function e(e){var n,r,t="",o=u.encode(e);for(r=0;o.length>r;r+=1)n=o.charCodeAt(r),t+="%"+n.toString(16).toUpperCase();return t}function n(e,n){return"%"===e[n]&&t.isHexDigit(e[n+1])&&t.isHexDigit(e[n+2])}function r(e,n){return parseInt(e.substr(n,2),16)}function o(e){if(!n(e,0))return!1;var t=r(e,1),o=u.numBytes(t);if(0===o)return!1;for(var i=1;o>i;i+=1)if(!n(e,3*i)||!u.isValidFollowingCharCode(r(e,3*i+1)))return!1;return!0}function i(e,t){var o=e[t];if(!n(e,t))return o;var i=r(e,t+1),a=u.numBytes(i);if(0===a)return o;for(var s=1;a>s;s+=1)if(!n(e,t+3*s)||!u.isValidFollowingCharCode(r(e,t+3*s+1)))return o;return e.substr(t,3*a)}var u={encode:function(e){return unescape(encodeURIComponent(e))},numBytes:function(e){return 127>=e?1:e>=194&&223>=e?2:e>=224&&239>=e?3:e>=240&&244>=e?4:0},isValidFollowingCharCode:function(e){return e>=128&&191>=e}};return{encodeCharacter:e,isPctEncoded:o,pctCharAt:i}}(),i=function(){function e(e){return t.isAlpha(e)||t.isDigit(e)||"_"===e||o.isPctEncoded(e)}function n(e){return t.isAlpha(e)||t.isDigit(e)||"-"===e||"."===e||"_"===e||"~"===e}function r(e){return":"===e||"/"===e||"?"===e||"#"===e||"["===e||"]"===e||"@"===e||"!"===e||"$"===e||"&"===e||"("===e||")"===e||"*"===e||"+"===e||","===e||";"===e||"="===e||"'"===e}return{isVarchar:e,isUnreserved:n,isReserved:r}}(),u=function(){function e(e,n){var r,t="",u="";for(("number"==typeof e||"boolean"==typeof e)&&(e=""+e),r=0;e.length>r;r+=u.length)u=o.pctCharAt(e,r),t+=u.length>1?u:i.isUnreserved(u)||n&&i.isReserved(u)?u:o.encodeCharacter(u);return t}function n(n){return e(n,!0)}return{encode:e,encodePassReserved:n}}(),a=function(){function e(e){n[e]={symbol:e,separator:"?"===e?"&":""===e||"+"===e||"#"===e?",":e,named:";"===e||"&"===e||"?"===e,ifEmpty:"&"===e||"?"===e?"=":"",first:"+"===e?"":e,encode:"+"===e||"#"===e?u.encodePassReserved:u.encode,toString:function(){return this.symbol}}}var n={};return e(""),e("+"),e("#"),e("."),e("/"),e(";"),e("?"),e("&"),{valueOf:function(e){if(n[e])return n[e];if("=,!@|".indexOf(e)>=0)throw Error('Illegal use of reserved operator "'+e+'"');return n[""]}}}(),s=function(){function e(e){var n,r="",t="";for(n=0;e.length>n;n+=t.length)t=o.pctCharAt(e,n),r+=t.length>0?t:i.isReserved(t)||i.isUnreserved(t)?t:o.encodeCharacter(t);return r}function n(e){this.literal=n.encodeLiteral(e)}return n.encodeLiteral=e,n.prototype.expand=function(){return this.literal},n.prototype.toString=n.prototype.expand,n}(),f=function(){function e(e){function n(){p={varname:u.substring(d,f),exploded:!1,maxLength:null},d=null}function r(){if(h===f)throw Error("after a ':' you have to specify the length. position = "+f);p.maxLength=parseInt(u.substring(h,f),10),h=null}var u,s,f,c=[],p=null,d=null,h=null,g="";for(u=e.substr(1,e.length-2),s=a.valueOf(u.charAt(0)),f=""===s.symbol?0:1,d=f;u.length>f;f+=g.length){if(g=o.pctCharAt(u,f),null!==d){if("."===g){if(d===f)throw Error("a varname MUST NOT start with a dot -- see position "+f);continue}if(i.isVarchar(g))continue;n()}if(null!==h){if(t.isDigit(g))continue;r()}if(":"!==g)if("*"!==g){if(","!==g)throw Error("illegal character '"+g+"' at position "+f+' of "'+u+'"');c.push(p),p=null,d=f+1}else{if(null===p)throw Error("explode exploded at position "+f);if(p.exploded)throw Error("explode exploded twice at position "+f);if(p.maxLength)throw Error("an explode (*) MUST NOT follow to a prefix, see position "+f);p.exploded=!0}else{if(null!==p.maxLength)throw Error("only one :maxLength is allowed per varspec at position "+f);h=f+1}}return null!==d&&n(),null!==h&&r(),c.push(p),new l(e,s,c)}function n(n){var r,t,o=[],i=null,u=0;for(r=0;n.length>r;r+=1)if(t=n.charAt(r),null===u){if(null===i)throw Error("reached unreachable code");if("{"===t)throw Error("brace was opened in position "+i+" and cannot be reopened in position "+r);if("}"===t){if(i+1===r)throw Error("empty braces on position "+i);o.push(e(n.substring(i,r+1))),i=null,u=r+1}}else{if("}"===t)throw Error("brace was closed in position "+r+" but never opened");"{"===t&&(r>u&&o.push(new s(n.substring(u,r))),u=null,i=r)}if(null!==i)throw Error("brace was opened on position "+i+", but never closed");return n.length>u&&o.push(new s(n.substr(u))),new c(n,o)}return n}(),l=function(){function e(e){return JSON?JSON.stringify(e):e}function t(e,n,r){this.templateText=e,this.operator=n,this.varspecs=r}return t.prototype.toString=function(){return this.templateText},t.prototype.expand=function(t){function o(e,r,t){return n(r)&&(e.length>0&&(e+=","),c||(e+=h.encode(t)+","),e+=h.encode(r)),e}function i(e,r,t){return n(r)&&(e.length>0&&(e+=h.separator),e+=c?s.encodeLiteral(f.varname):h.encode(t),e+="="+h.encode(r)),e}function u(e,r,t){return n(r)&&(e.length>0&&(e+=h.separator),c||(e+=h.encode(t)+"="),e+=h.encode(r)),e}var a,f,l,c,p="",d=!0,h=this.operator;for(a=0;this.varspecs.length>a;a+=1)if(f=this.varspecs[a],l=t[f.varname],n(l))if(d?(p+=h.first,d=!1):p+=h.separator,c=r.isArray(l),"string"==typeof l||"number"==typeof l||"boolean"==typeof l){if(l=""+l,h.named){if(p+=s.encodeLiteral(f.varname),""===l){p+=h.ifEmpty;continue}p+="="}f.maxLength&&l.length>f.maxLength&&(l=l.substr(0,f.maxLength)),p+=h.encode(l)}else{if(f.maxLength)throw Error("Prefix modifiers are not applicable to variables that have composite values. You tried to expand "+this+" with "+e(l));if(f.exploded)p+=r.reduce(l,h.named?i:u,"");else{if(h.named){if(p+=s.encodeLiteral(f.varname),!n(l)){p+=h.ifEmpty;continue}p+="="}p+=r.reduce(l,o,"")}}if(d){var g=!1;for(a=0;this.varspecs.length>a;a+=1)if(this.varspecs[a].exploded){g=!0;break}h.named&&!g&&(p+=h.symbol,p+=f.varname+h.ifEmpty)}return p},t}(),c=function(){function e(e,n){this.templateText=e,this.expressions=n}return e.prototype.toString=function(){return this.templateText},e.prototype.expand=function(e){var n,r="";for(n=0;this.expressions.length>n;n+=1)r+=this.expressions[n].expand(e);return r},e.parse=f,e}();e(c)})(function(e){"use strict";"undefined"!=typeof module?module.exports=e:"undefined"!=typeof define?define([],function(){return e}):"undefined"!=typeof window?window.UriTemplate=e:global.UriTemplate=e});
\ No newline at end of file
......@@ -584,22 +584,22 @@ var VariableExpression = (function () {
varspec = this.varspecs[index];
value = variables[varspec.varname];
if (!isDefined(value)) {
continue;
continue;
}
if (isFirstVarspec) {
result += this.operator.first;
result += operator.first;
isFirstVarspec = false;
}
else {
result += this.operator.separator;
result += operator.separator;
}
valueIsArr = objectHelper.isArray(value);
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
value = value.toString();
if (this.operator.named) {
if (operator.named) {
result += LiteralExpression.encodeLiteral(varspec.varname);
if (value === '') {
result += this.operator.ifEmpty;
result += operator.ifEmpty;
continue;
}
result += '=';
......@@ -607,7 +607,7 @@ var VariableExpression = (function () {
if (varspec.maxLength && value.length > varspec.maxLength) {
value = value.substr(0, varspec.maxLength);
}
result += this.operator.encode(value);
result += operator.encode(value);
}
else if (varspec.maxLength) {
// 2.4.1 of the spec says: "Prefix modifiers are not applicable to variables that have composite values."
......@@ -617,7 +617,7 @@ var VariableExpression = (function () {
if (operator.named) {
result += LiteralExpression.encodeLiteral(varspec.varname);
if (!isDefined(value)) {
result += this.operator.ifEmpty;
result += operator.ifEmpty;
continue;
}
result += '=';
......@@ -629,6 +629,22 @@ var VariableExpression = (function () {
result += objectHelper.reduce(value, operator.named ? reduceNamedExploded : reduceUnnamedExploded, '');
}
}
if (isFirstVarspec) {
// so no varspecs produced output.
var oneExploded = false;
for (index = 0; index < this.varspecs.length; index += 1) {
if (this.varspecs[index].exploded) {
oneExploded = true;
break;
}
}
if (operator.named && !oneExploded) {
result += operator.symbol;
result += varspec.varname + operator.ifEmpty;
}
}
return result;
};
......
......@@ -74,19 +74,19 @@ var VariableExpression = (function () {
continue;
}
if (isFirstVarspec) {
result += this.operator.first;
result += operator.first;
isFirstVarspec = false;
}
else {
result += this.operator.separator;
result += operator.separator;
}
valueIsArr = objectHelper.isArray(value);
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
value = value.toString();
if (this.operator.named) {
if (operator.named) {
result += LiteralExpression.encodeLiteral(varspec.varname);
if (value === '') {
result += this.operator.ifEmpty;
result += operator.ifEmpty;
continue;
}
result += '=';
......@@ -94,7 +94,7 @@ var VariableExpression = (function () {
if (varspec.maxLength && value.length > varspec.maxLength) {
value = value.substr(0, varspec.maxLength);
}
result += this.operator.encode(value);
result += operator.encode(value);
}
else if (varspec.maxLength) {
// 2.4.1 of the spec says: "Prefix modifiers are not applicable to variables that have composite values."
......@@ -104,7 +104,7 @@ var VariableExpression = (function () {
if (operator.named) {
result += LiteralExpression.encodeLiteral(varspec.varname);
if (!isDefined(value)) {
result += this.operator.ifEmpty;
result += operator.ifEmpty;
continue;
}
result += '=';
......@@ -116,6 +116,22 @@ var VariableExpression = (function () {
result += objectHelper.reduce(value, operator.named ? reduceNamedExploded : reduceUnnamedExploded, '');
}
}
if (isFirstVarspec) {
// so no varspecs produced output.
var oneExploded = false;
for (index = 0; index < this.varspecs.length; index += 1) {
if (this.varspecs[index].exploded) {
oneExploded = true;
break;
}
}
if (operator.named && !oneExploded) {
result += operator.symbol;
result += varspec.varname + operator.ifEmpty;
}
}
return result;
};
......
......@@ -58,6 +58,12 @@ module.exports = (function () {
test.fail('chapter ' + chapterName + ', template ' + template + ' threw error: ' + JSON.stringify(exception, null, 4));
return;
}
if (expected.constructor === Array) {
// simplyfy arrays, when only one element is in
if (expected.length === 1) {
expected = expected[0];
}
}
if (expected.constructor === Array) {
// actual must match at least one of the listed elements
for (index = 0; index < expected.length; index += 1) {
......
......@@ -25,16 +25,22 @@ module.exports = (function () {
test.equal(ve.expand({x: 1, y: 2}), '1,2');
test.equal(ve.expand({x: 1, y: null}), '1');
test.done();
}
/* TODO this test fails
"exploded empty lists with ? must show the name": function (test) {
},
"empty lists with ? must show the name": function (test) {
console.log(JSON.stringify(test, null, 4));
var ve = new VariableExpression("{?empty}", operators.valueOf('?'), [
{varname: 'empty', exploded: false, maxLength: null}
]);
test.equal(ve.expand({empty: {}}), '?empty=');
test.done();
},
"exploded empty lists with ? must not show the name": function (test) {
console.log(JSON.stringify(test, null, 4));
var ve = new VariableExpression("{?empty*}", operators.valueOf('?'), [
{varname: 'empty', exploded: true, maxLength: null}
]);
test.equal(ve.expand({empty: {}}), '?empty=');
test.equal(ve.expand({empty: {}}), '');
test.done();
}
*/
};
}());
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment