Commit 901b8520 authored by fxa's avatar fxa

Restructured the complete project

parent 966f7847
/*jshint */
/*global complete, desc, fail, file, task*/
(function () {
"use strict";
var
async = require('async'),
path = require('path'),
fs = require('fs'),
hinter = require('./build/hinter'),
jake = require('jake'),
nodeunit = require('nodeunit'),
fileConcatter = require('./build/fileConcatter'),
UglifyJS = require('uglify-js');
var
NODEUNIT_OPTIONS = {
"error_prefix": "",
"error_suffix": "",
"ok_prefix": "",
"ok_suffix": "",
"bold_prefix": "",
"bold_suffix": "",
"assertion_prefix": "",
"assertion_suffix": ""
};
var
SRC_HOME = 'src',
SRC_FILES = [
// cannot use the fileList, because the order matters
path.join(SRC_HOME, 'objectHelper.js'),
path.join(SRC_HOME, 'charHelper.js'),
path.join(SRC_HOME, 'pctEncoder.js'),
path.join(SRC_HOME, 'rfcCharHelper.js'),
path.join(SRC_HOME, 'encodingHelper.js'),
path.join(SRC_HOME, 'operators.js'),
path.join(SRC_HOME, 'isDefined.js'),
path.join(SRC_HOME, 'LiteralExpression.js'),
path.join(SRC_HOME, 'parse.js'),
path.join(SRC_HOME, 'VariableExpression.js'),
path.join(SRC_HOME, 'UriTemplate_.js')
],
UNIT_TESTS = new jake.FileList('test/unit/test*.js').toArray(),
INTEGRATION_TESTS = [
path.join('test', 'integration', 'simpleTest.js'),
path.join('test', 'integration', 'testRfcSamples.js')
],
TMP_UNTESTED_UNCOMPRESSED = 'tmp-untested-uritemplate.js',
TMP_UNTESTED_COMPRESSED = 'tmp-unested-uritemplate-min.js',
TARGET_HOME = 'bin',
TARGET_UNCOMPRESSED = path.join(TARGET_HOME, 'uritemplate.js'),
TARGET_COMPRESSED = path.join(TARGET_HOME, 'uritemplate-min.js'),
ASYNC = {async: true};
var all = new jake.FileList();
all.include('./*');
all.include('src/**');
all.include('test/**');
all.exclude(TARGET_COMPRESSED);
var TARGET_UNCOMPRESSED_DEPENDENCIES = all.toArray();
function closeTask(err) {
if (err) {
fail(err);
}
complete();
}
desc('clean');
task('clean', [], function () {
function unlinkWhenExists(filename, callback) {
fs.unlink(filename, function (err) {
callback(err && err.code !== 'ENOENT' ? err : undefined);
});
}
async.forEach([TMP_UNTESTED_UNCOMPRESSED, TMP_UNTESTED_COMPRESSED, TARGET_UNCOMPRESSED, TARGET_COMPRESSED], unlinkWhenExists, closeTask);
}, ASYNC);
file(TARGET_UNCOMPRESSED, TARGET_UNCOMPRESSED_DEPENDENCIES, function () {
global.URI_TEMPLATE_FILE = TMP_UNTESTED_UNCOMPRESSED;
async.series([
function (callback) {
jake.logger.log('looking for jshint warnings ...');
hinter.hint(SRC_FILES, callback);
},
function (callback) {
jake.logger.log('unit testing ...');
nodeunit.reporters['default'].run(UNIT_TESTS, NODEUNIT_OPTIONS, callback);
},
function (callback) {
jake.logger.log('build concatenated version ...');
fileConcatter.concat(SRC_FILES, TMP_UNTESTED_UNCOMPRESSED, callback, {
mapper: [fileConcatter.removeJshintOptions, fileConcatter.removeUseStrict],
preAll: fs.readFileSync('src/pre.txt', 'utf-8'),
postAll: fs.readFileSync('src/post.txt', 'utf-8')
});
},
function (callback) {
jake.logger.log('hinting the concatenated version ... ');
hinter.hint([TMP_UNTESTED_UNCOMPRESSED], callback);
},
function (callback) {
jake.logger.log('integration tests ...');
nodeunit.reporters['default'].run(INTEGRATION_TESTS, NODEUNIT_OPTIONS, callback);
},
function (callback) {
jake.logger.log('move uncompressed version to target directory');
fs.rename(TMP_UNTESTED_UNCOMPRESSED, TARGET_UNCOMPRESSED, callback);
}
], closeTask);
}, ASYNC);
file(TARGET_COMPRESSED, [TARGET_UNCOMPRESSED], function () {
global.URI_TEMPLATE_FILE = TMP_UNTESTED_COMPRESSED;
async.series([
function (callback) {
jake.logger.log('compress to temporary file ... ');
var compressed = UglifyJS.minify(TARGET_UNCOMPRESSED);
fs.writeFile(TMP_UNTESTED_COMPRESSED, compressed.code, 'utf8', callback);
},
function (callback) {
jake.logger.log('integration tests with minified version ... ');
nodeunit.reporters['default'].run(INTEGRATION_TESTS, NODEUNIT_OPTIONS, callback);
},
function (callback) {
jake.logger.log('move compressed version to target ... ');
fs.rename(TMP_UNTESTED_COMPRESSED, TARGET_COMPRESSED, callback);
}
], closeTask);
}, ASYNC);
desc('release');
task('release', [TARGET_COMPRESSED], function () {
jake.logger.log('done.');
});
task('default', ['clean', 'release']);
}());
\ No newline at end of file
......@@ -22,7 +22,7 @@ and then:
var
UriTemplate = require('uritemplate'),
template;
template = UriTemplate.parse('{?query*}');
template = UriTemplate.parse('{?query*})';
template.expand({query: {first: 1, second: 2}});
--> "?first=1&second=2"
......@@ -33,22 +33,29 @@ So you have to to:
git submodule init
git submodule update
Tests
Build
-----
jake clean release
The tests are taken from https://github.com/uri-templates/uritemplate-test as a submodule.
Run the tests with
node test.js
Comming soon
------------
Tests
-----
* A new method extract(uri), which tries to extract the variables from a given uri
* Support of javascript's Date class
The integration tests are taken from https://github.com/uri-templates/uritemplate-test as a submodule.
The tests are integrated in the Jakefile.
License
-------
Copyright 2012 Franz Antesberger
Copyright 2013 Franz Antesberger
MIT License, see http://mit-license.org/
Release Notes
-------------
0.2.0 heavy project refactoring, splitting source files, introducing jshint (preparation of next steps)
Next Steps
----------
* Implementing unit tests (now only dummy test implemented)
* Updating uritemplate-test (mnot added some new tests and removed some wrong. At the moment I cannot update, because the new tests will not pass)
* A new method extract(uri), which tries to extract the variables from a given uri.
This is harder, than you might think
(function(e){"use strict";function t(e){var n,o;if(null===e||void 0===e)return!1;if(r.isArray(e)){for(n=0;e.length>n;n+=1)if(t(e[n]))return!0;return!1}if("string"==typeof e||"number"==typeof e||"boolean"==typeof e)return!0;for(o in e)if(e.hasOwnProperty(o)&&t(e[o]))return!0;return!1}var r=function(){function e(e){return"[object Array]"===Object.prototype.toString.apply(e)}function t(e,t,r){var n,o=r;for(n in e)e.hasOwnProperty(n)&&(o=t(o,e[n],n,e));return o}function r(e,t,r){var n,o=r;for(n=0;e.length>n;n+=1)o=t(o,e[n],n,e);return o}function n(n,o,i){return e(n)?r(n,o,i):t(n,o,i)}return{isArray:e,reduce:n}}(),n=function(){function e(e){return e>="a"&&"z">=e||e>="A"&&"Z">=e}function t(e){return e>="0"&&"9">=e}function r(e){return t(e)||e>="a"&&"f">=e||e>="A"&&"F">=e}return{isAlpha:e,isDigit:t,isHexDigit:r}}(),o=function(){function e(e){return unescape(encodeURIComponent(e))}function t(t){var r,n,o="",i=e(t);for(n=0;i.length>n;n+=1)r=i.charCodeAt(n),o+="%"+r.toString(16).toUpperCase();return o}function r(e){if(3>e.length)return!1;for(var t=0;e.length>t;t+=3)if("%"!==e.charAt(t)||!n.isHexDigit(e.charAt(t+1)||!n.isHexDigit(e.charAt(t+2))))return!1;return!0}function o(e,t){var n=e.charAt(t);return"%"!==n?n:(n=e.substr(t,3),r(n)?n:"%")}return{encodeCharacter:t,decodeCharacter:decodeURIComponent,isPctEncoded:r,pctCharAt:o}}(),i=function(){function e(e){return n.isAlpha(e)||n.isDigit(e)||"_"===e||o.isPctEncoded(e)}function t(e){return n.isAlpha(e)||n.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:t,isReserved:r}}(),a=function(){function e(e,t){var r,n="",a="";for(("number"==typeof e||"boolean"==typeof e)&&(e=""+e),r=0;e.length>r;r+=a.length)a=o.pctCharAt(e,r),n+=a.length>1?a:i.isUnreserved(a)||t&&i.isReserved(a)?a:o.encodeCharacter(a);return n}function t(t){return e(t,!0)}return{encode:e,encodePassReserved:t}}(),u=function(){function e(e){t[e]={symbol:e,separator:"?"===e?"&":""===e||"+"===e||"#"===e?",":e,named:";"===e||"&"===e||"?"===e,ifEmpty:"&"===e||"?"===e?"=":"",first:"+"===e?"":e,encode:"+"===e||"#"===e?a.encodePassReserved:a.encode,toString:function(){return this.symbol}}}var t={};return e(""),e("+"),e("#"),e("."),e("/"),e(";"),e("?"),e("&"),{valueOf:function(e){if(t[e])return t[e];if("=,!@|".indexOf(e)>=0)throw Error('Illegal use of reserved operator "'+e+'"');return t[""]}}}(),s=function(){function e(e){var t,r="",n="";for(t=0;e.length>t;t+=n.length)n=o.pctCharAt(e,t),r+=n.length>0?n:i.isReserved(n)||i.isUnreserved(n)?n:o.encodeCharacter(n);return r}function t(e){this.literal=t.encodeLiteral(e)}return t.encodeLiteral=e,t.prototype.expand=function(){return this.literal},t.prototype.toString=t.prototype.expand,t}(),f=function(){function e(e){function t(){h={varname:a.substring(d,f),exploded:!1,maxLength:null},d=null}function r(){if(g===f)throw Error("after a ':' you have to specify the length. position = "+f);h.maxLength=parseInt(a.substring(g,f),10),g=null}var a,s,f,l,p=[],h=null,d=null,g=null;for(a=e.substr(1,e.length-2),s=u.valueOf(a.charAt(0)),f=""===s.symbol?0:1,d=f;a.length>f;f+=l.length){if(l=o.pctCharAt(a,f),null!==d){if("."===l){if(d===f)throw Error("a varname MUST NOT start with a dot -- see position "+f);continue}if(i.isVarchar(l))continue;t()}if(null!==g){if(n.isDigit(l))continue;r()}if(":"!==l)if("*"!==l){if(","!==l)throw Error("illegal character '"+l+"' at position "+f);p.push(h),h=null,d=f+1}else{if(null===h)throw Error("explode exploded at position "+f);if(h.exploded)throw Error("explode exploded twice at position "+f);if(h.maxLength)throw Error("an explode (*) MUST NOT follow to a prefix, see position "+f);h.exploded=!0}else{if(null!==h.maxLength)throw Error("only one :maxLength is allowed per varspec at position "+f);g=f+1}}return null!==d&&t(),null!==g&&r(),p.push(h),new c(e,s,p)}function t(t){var r,n,o=[],i=null,a=0;for(r=0;t.length>r;r+=1)if(n=t.charAt(r),null===a){if(null===i)throw Error("reached unreachable code");if("{"===n)throw Error("brace was opened in position "+i+" and cannot be reopened in position "+r);if("}"===n){if(i+1===r)throw Error("empty braces on position "+i);o.push(e(t.substring(i,r+1))),i=null,a=r+1}}else{if("}"===n)throw Error("brace was closed in position "+r+" but never opened");"{"===n&&(r>a&&o.push(new s(t.substring(a,r))),a=null,i=r)}if(null!==i)throw Error("brace was opened on position "+i+", but never closed");return t.length>a&&o.push(new s(t.substr(a))),new l(t,o)}return t}(),c=function(){function e(e){return JSON?JSON.stringify(e):e}function n(e,t,r){this.templateText=e,this.operator=t,this.varspecs=r}return n.prototype.toString=function(){return this.templateText},n.prototype.expand=function(n){function o(e,r,n){return t(r)&&(e.length>0&&(e+=","),l||(e+=d.encode(n)+","),e+=d.encode(r)),e}function i(e,r,n){return t(r)&&(e.length>0&&(e+=d.separator),e+=l?s.encodeLiteral(f.varname):d.encode(n),e+="="+d.encode(r)),e}function a(e,r,n){return t(r)&&(e.length>0&&(e+=d.separator),l||(e+=d.encode(n)+"="),e+=d.encode(r)),e}var u,f,c,l,p="",h=!0,d=this.operator;for(u=0;this.varspecs.length>u;u+=1)if(f=this.varspecs[u],c=n[f.varname],h?(p+=this.operator.first,h=!1):p+=this.operator.separator,l=r.isArray(c),"string"==typeof c||"number"==typeof c||"boolean"==typeof c){if(c=""+c,this.operator.named){if(p+=s.encodeLiteral(f.varname),""===c){p+=this.operator.ifEmpty;continue}p+="="}f.maxLength&&c.length>f.maxLength&&(c=c.substr(0,f.maxLength)),p+=this.operator.encode(c)}else{if(f.maxLength)throw Error("Prefix modifiers are not applicable to variables that have composite values. You tried to expand "+this+" with "+e(c));if(f.exploded)p+=r.reduce(c,d.named?i:a,"");else{if(d.named){if(p+=s.encodeLiteral(f.varname),!t(c)){p+=this.operator.ifEmpty;continue}p+="="}p+=r.reduce(c,o,"")}}return p},n}(),l=function(){function e(e,t){this.templateText=e,this.expressions=t}return e.prototype.toString=function(){return this.templateText},e.prototype.expand=function(e){var t,r="";for(t=0;this.expressions.length>t;t+=1)r+=this.expressions[t].expand(e);return r},e.parse=f,e}();e(l)})(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
This diff is collapsed.
module.exports = (function () {
"use strict";
var
fs = require('fs'),
async = require('async');
function readFileUtf8(filename, callback) {
// if you call readFile with encoding, the result is the file content as string.
// without encoding it would be a stream, which can be converted to a string with its toString() method
fs.readFile(filename, 'utf-8', callback);
}
function concat(inputFileArr, outputfile, callback, options) {
async.map(inputFileArr, readFileUtf8, function (err, contents) {
if (err) {
throw new Error('could not read files: ' + err);
}
if (options && options.mapper) {
if (Array.isArray(options.mapper)) {
options.mapper.forEach(function (map) {
contents = contents.map(map);
});
}
else {
contents = contents.map(options.mapper);
}
}
var concatenatedContent = contents.reduce(function (previousValue, currentValue) {
return previousValue + '\n' + currentValue;
});
if (options && options.preAll) {
var pre = typeof options.preAll === 'string' ? options.preAll : options.preAll(concatenatedContent);
concatenatedContent = pre + concatenatedContent;
}
if (options && options.postAll) {
var post = typeof options.postAll === 'string' ? options.postAll : options.postAll(concatenatedContent);
concatenatedContent = concatenatedContent + post;
}
fs.writeFile(outputfile, concatenatedContent, 'utf-8', callback);
});
}
function startsWith(text, beginning) {
return text.substr(0, beginning.length) === beginning;
}
function removeFirstLine(text) {
var indexOfLinebreak = text.indexOf("\n");
if (indexOfLinebreak < 0) {
return "";
}
return text.substr(indexOfLinebreak + 1);
}
function removeUseStrict(text) {
var lines = text.split('\n');
var filteredLines = lines.filter(function (line) {
return line.indexOf('"use strict"') < 0;
});
return filteredLines.join('\n');
}
function removeJshintOptions(source) {
if (startsWith(source, '/*jshint')) {
source = removeFirstLine(source);
}
if (startsWith(source, '/*global')) {
source = removeFirstLine(source);
}
return source;
}
return {
concat: concat,
removeJshintOptions: removeJshintOptions,
removeUseStrict: removeUseStrict
};
}());
\ No newline at end of file
module.exports = (function () {
"use strict";
var
fs = require('fs'),
jshint = require("jshint").JSHINT;
var
// for a full list and description see http://www.jshint.com/options/
JSHINT_OPTIONS = {
bitwise: true, // bitwise is forbidden
curly: true, // must put oneliners in curly braces
eqeqeq: true, // must use ===
forin: true,
immed: true, // wrap immediately called functions
newcap: true, // CAP constructors
noarg: true, // arguments.caller is evil
noempty: true, // empty blocks are forbidden
nonew: true, // forbids new X(); without assignment
regexp: true, // warns with wrong dots -- I would prefer to forbid regexps
strict: true, // must use "use strict"
undef: true, // forbids use of undefined variables
unused: true, // forbids unused variables
maxcomplexity: 17 // much too high. should be max. 10
},
JSHINT_GLOBALS = {
"module": true
};
function hint(jsFiles, callback) {
var
failed = false,
numCheckedFiles = 0;
jsFiles.forEach(function (jsFile) {
fs.readFile(jsFile, 'utf-8', function (err, content) {
if (failed) {
return;
}
if (err) {
throw new Error('could not read file ' + jsFile + ': ' + err);
}
numCheckedFiles += 1;
if (!jshint.jshint(content, JSHINT_OPTIONS, JSHINT_GLOBALS)) {
failed = true;
console.log(jshint.errors);
callback(jshint.errors, jsFile);
}
if (numCheckedFiles === jsFiles.length) {
callback();
}
});
});
}
return {
hint: hint
};
}());
\ No newline at end of file
......@@ -2,27 +2,27 @@
<html>
<head>
<title>Demo of Usage</title>
<script type="text/javascript" src="src/uritemplate.js"></script>
<script type="text/javascript" src="bin/uritemplate.js"></script>
</head>
<body>
<div id="id"></div>
<div id="id"></div>
<script type="text/javascript">
(function () {
"use strict";
var
templateText = "{?query*}",
variables = {
query: {
first: "1",
second: 2
}
};
templateText = "{?query*}",
variables = {
query: {
first: "1",
second: 2
}
};
document.getElementById('id').innerHTML =
"<p>When you have a template of the form</p><p><code>var templateText = \"" + templateText
+ "\";</code></p><p>and params of the form </p><p><code>var variables = " + JSON.stringify(variables)
+ ";</code></p><p>, you can use </p><p><code>UriTemplate.parse(templateText).expand(variables); </code></p><p>to produce </p><p><code>"
+ UriTemplate.parse(templateText).expand(variables)
+ "</code></p><p> Look at the source code of this page!</p>";
+ "\";</code></p><p>and params of the form </p><p><code>var variables = " + JSON.stringify(variables)
+ ";</code></p><p>, you can use </p><p><code>UriTemplate.parse(templateText).expand(variables); </code></p><p>to produce </p><p><code>"
+ UriTemplate.parse(templateText).expand(variables)
+ "</code></p><p> Look at the source code of this page!</p>";
}());
</script>
......
......@@ -5,24 +5,24 @@
<script type="text/javascript" src="require.js"></script>
</head>
<body>
<div id="id"></div>
<div id="id"></div>
<script type="text/javascript">
require(['src/uritemplate.js'],function(UriTemplate) {
require(['bin/uritemplate.js'], function (UriTemplate) {
"use strict";
var
templateText = "{?query*}",
variables = {
query: {
first: "1",
second: 2
}
};
templateText = "{?query*}",
variables = {
query: {
first: "1",
second: 2
}
};
document.getElementById('id').innerHTML =
"<p>When you have a template of the form</p><p><code>var templateText = \"" + templateText
+ "\";</code></p><p>and params of the form </p><p><code>var variables = " + JSON.stringify(variables)
+ ";</code></p><p>, you can use </p><p><code>UriTemplate.parse(templateText).expand(variables); </code></p><p>to produce </p><p><code>"
+ UriTemplate.parse(templateText).expand(variables)
+ "</code></p><p> Look at the source code of this page!</p>";
+ "\";</code></p><p>and params of the form </p><p><code>var variables = " + JSON.stringify(variables)
+ ";</code></p><p>, you can use </p><p><code>UriTemplate.parse(templateText).expand(variables); </code></p><p>to produce </p><p><code>"
+ UriTemplate.parse(templateText).expand(variables)
+ "</code></p><p> Look at the source code of this page!</p>";
});
</script>
......
{
"name" : "uritemplate",
"description" : "An UriTemplate implementation of rfc 6570",
"homepage" : "https://www.github.com/fxa/uritemplate-js",
"keywords" : ["util", "uri", "template", "rfc6570"],
"author" : "Franz Antesberger",
"contributors" : [],
"dependencies" : [],
"main" : "src/uritemplate.js",
"licenses": [{
"type": "MIT",
"url": "http://www.opensource.org/licenses/mit-license.php"
}],
"files": [
"src/uritemplate.js",
"demo.html",
"test.js",
"README.md",
".gitmodules",
"uritemplate-test/extended-tests.json",
"uritemplate-test/negative-tests.json",
"uritemplate-test/README.md",
"uritemplate-test/spec-examples-by-sections.json",
"uritemplate-test/spec-examples.json"
],
"version" : "0.1.4"
"name": "uritemplate",
"description": "An UriTemplate implementation of rfc 6570",
"homepage": "https://www.github.com/fxa/uritemplate-js",
"keywords": ["util", "uri", "template", "rfc6570"],
"author": "Franz Antesberger",
"contributors": [],
"dependencies": [],
"main": "bin/uritemplate.js",
"licenses": [
{
"type": "MIT",
"url": "http://www.opensource.org/licenses/mit-license.php"
}
],
"files": [
"src",
"test",
"bin",
"Jakefile.js",
"own-testcases.json",
"demo.html",
"demo_AMD.html",
"README.md",
"reqire.js",
".gitmodules",
"uritemplate-test/extended-tests.json",
"uritemplate-test/negative-tests.json",
"uritemplate-test/README.md",
"uritemplate-test/spec-examples-by-sections.json",
"uritemplate-test/spec-examples.json"
],
"version": "0.2.0"
}
\ No newline at end of file
/*jshint unused:false */
/*global pctEncoder, rfcCharHelper*/
var LiteralExpression = (function () {
"use strict";
function encodeLiteral(literal) {
var
result = '',
index,
chr = '';
for (index = 0; index < literal.length; index += chr.length) {
chr = pctEncoder.pctCharAt(literal, index);
if (chr.length > 0) {
result += chr;
}
else {
result += rfcCharHelper.isReserved(chr) || rfcCharHelper.isUnreserved(chr) ? chr : pctEncoder.encodeCharacter(chr);
}
}
return result;
}
function LiteralExpression(literal) {
this.literal = LiteralExpression.encodeLiteral(literal);
}
LiteralExpression.encodeLiteral = encodeLiteral;
LiteralExpression.prototype.expand = function () {
return this.literal;
};
LiteralExpression.prototype.toString = LiteralExpression.prototype.expand;
return LiteralExpression;
}());
/*jshint unused:false */
/*global parse*/
var UriTemplate = (function () {
"use strict";
function UriTemplate(templateText, expressions) {
this.templateText = templateText;
this.expressions = expressions;
}
UriTemplate.prototype.toString = function () {
return this.templateText;
};
UriTemplate.prototype.expand = function (variables) {
var
index,
result = '';
for (index = 0; index < this.expressions.length; index += 1) {
result += this.expressions[index].expand(variables);
}
return result;
};
UriTemplate.parse = parse;
return UriTemplate;
}());
/*jshint unused:false */
/*global pctEncoder, rfcCharHelper, isDefined, LiteralExpression, objectHelper*/
var VariableExpression = (function () {
"use strict";
// helper function if JSON is not available
function prettyPrint(value) {
return JSON ? JSON.stringify(value) : value;
}
function VariableExpression(templateText, operator, varspecs) {
this.templateText = templateText;
this.operator = operator;
this.varspecs = varspecs;
}
VariableExpression.prototype.toString = function () {
return this.templateText;
};
VariableExpression.prototype.expand = function expandExpression(variables) {
var
result = '',
index,
varspec,
value,
valueIsArr,
isFirstVarspec = true,
operator = this.operator;
// callback to be used within array.reduce
function reduceUnexploded(result, currentValue, currentKey) {
if (isDefined(currentValue)) {
if (result.length > 0) {
result += ',';
}
if (!valueIsArr) {
result += operator.encode(currentKey) + ',';
}
result += operator.encode(currentValue);
}
return result;
}
function reduceNamedExploded(result, currentValue, currentKey) {
if (isDefined(currentValue)) {
if (result.length > 0) {
result += operator.separator;
}
result += (valueIsArr) ? LiteralExpression.encodeLiteral(varspec.varname) : operator.encode(currentKey);
result += '=' + operator.encode(currentValue);
}
return result;
}
function reduceUnnamedExploded(result, currentValue, currentKey) {
if (isDefined(currentValue)) {
if (result.length > 0) {
result += operator.separator;
}
if (!valueIsArr) {
result += operator.encode(currentKey) + '=';
}
result += operator.encode(currentValue);
}
return result;
}
// expand each varspec and join with operator's separator
for (index = 0; index < this.varspecs.length; index += 1) {
varspec = this.varspecs[index];
value = variables[varspec.varname];
// if (!isDefined(value)) {
// continue;
// }
if (isFirstVarspec) {
result += this.operator.first;
isFirstVarspec = false;
}
else {
result += this.operator.separator;
}
valueIsArr = objectHelper.isArray(value);
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
value = value.toString();
if (this.operator.named) {
result += LiteralExpression.encodeLiteral(varspec.varname);
if (value === '') {
result += this.operator.ifEmpty;
continue;
}
result += '=';
}
if (varspec.maxLength && value.length > varspec.maxLength) {
value = value.substr(0, varspec.maxLength);
}
result += this.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."
throw new Error('Prefix modifiers are not applicable to variables that have composite values. You tried to expand ' + this + " with " + prettyPrint(value));
}
else if (!varspec.exploded) {
if (operator.named) {
result += LiteralExpression.encodeLiteral(varspec.varname);
if (!isDefined(value)) {
result += this.operator.ifEmpty;
continue;
}
result += '=';
}
result += objectHelper.reduce(value, reduceUnexploded, '');
}
else {
// exploded and not string
result += objectHelper.reduce(value, operator.named ? reduceNamedExploded : reduceUnnamedExploded, '');
}
}
return result;
};
return VariableExpression;
}());
/*jshint unused: false */
/*global */
var charHelper = (function () {
"use strict";
function isAlpha(chr) {
return (chr >= 'a' && chr <= 'z') || ((chr >= 'A' && chr <= 'Z'));
}