Fork me on GitHub

URI.js

URI Template

As of version 1.7.0 URI.js includes an implementation of URI Templates, as specified in RFC 6570 (Level 4, March 2012).

Using URI Templates

// creating a new URI Template
var template = new URITemplate("http://example.org/{file}");
var result = template.expand({file: "hello world.html"});
result === "http://example.org/hello%20world.html";

// of course you can call the constructor like a function and chain things:
result = URITemplate("http://example.org/{file}")
  .expand({file: "hello world.html"});
result === "http://example.org/hello%20world.html";

// access via URI
result = URI.expand("http://example.org/{file}", {file: "hello world.html"});
// result == new URI("http://example.org/hello%20world.html");

// expand() accepts data-callbacks:
template.expand(function(key) {
    var data = {file: "hello world.html"};
    return data[key];
});

// expand() accepts key-callbacks:
template.expand({file : function(key) {
    return "hello world.html";
}});

// Using strict mode
var template = new URITemplate("http://example.org/{file}");
var result = template.expand({filename: "hello world.html"}, { strict: true });
// Uncaught Error: Missing expansion value for variable "file"

URI Template Syntax

Expressions are placeholders which are to be substituted by the values their variables reference.

An expression consists of an operator and a (comma-separated) list of variable-specifications. A variable-specification consists of a variable and an optional modifier.


Given the template

http://example.org/~{username}/{term:1}/{term}{?q*,lang}

and the following data:

{username: "rodneyrehm", term: "hello world", q: {a: "mars", b: "jupiter"}, lang: "en"}

the expansion looks as follows:

"http://example.org/~rodneyrehm/h/hello%20world?a=mars&b=jupiter&lang=en"

List of supported operators:

OperatorDescription
NoneSimple String Expansion;
+Reserved character strings;
#Fragment identifiers prefixed by "#";
.Name labels or extensions prefixed by ".";
/Path segments prefixed by "/";
;Path parameter name or name=value pairs prefixed by ";";
?Query component beginning with "?" and consisting of name=value pairs separated by "&"; and,
&Continuation of query-style &name=value pairs within a literal query component.

List of supported modifiers:

ModifierDescription
NoneNo modification, arrays and objects are joined with ","
*Explode arrays and objects (see tables below)
:3Substring of the first 3 characters of the variable's value

Strings and Numbers

Given {"var": "hello[world]"}, the expression {var} expands to hello%5Bworld%5D. The following table shows an output matrix for every possible operator/modifier combination produced for string input.

Modifier
OperatorNone*:2
Nonehello%5Bworld%5Dhello%5Bworld%5Dhe
+hello[world]hello[world]he
##hello[world]#hello[world]#he
..hello%5Bworld%5D.hello%5Bworld%5D.he
//hello%5Bworld%5D/hello%5Bworld%5D/he
;;var=hello%5Bworld%5D;var=hello%5Bworld%5D;var=he
??var=hello%5Bworld%5D?var=hello%5Bworld%5D?var=he
&&var=hello%5Bworld%5D&var=hello%5Bworld%5D&var=he

Arrays

Given {"var": ["one", "two", "three"]}, the expression {var} expands to one,two,three. The following table shows an output matrix for every possible operator/modifier combination produced for array input.

Modifier
OperatorNone*:2
Noneone,two,threeone,two,threeon,tw,th
+one,two,threeone,two,threeon,tw,th
##one,two,three#one,two,three#on,tw,th
..one,two,three.one.two.three.on,tw,th
//one,two,three/one/two/three/on,tw,th
;;var=one,two,three;var=one;var=two;var=three;var=on,tw,th
??var=one,two,three?var=one&var=two&var=three?var=on,tw,th
&&var=one,two,three&var=one&var=two&var=three&var=on,tw,th

Objects ("plain objects" / "hash maps")

Given {"var": {"one": "alpha", "two": "bravo"}}, the expression {var} expands to one,two,three. The following table shows an output matrix for every possible operator/modifier combination produced for object input.

Modifier
OperatorNone*:2
Noneone,alpha,two,bravoone=alpha,two=bravoon,al,tw,br
+one,alpha,two,bravoone=alpha,two=bravoon,al,tw,br
##one,alpha,two,bravo#one=alpha,two=bravo#on,al,tw,br
..one,alpha,two,bravo.one=alpha.two=bravo.on,al,tw,br
//one,alpha,two,bravo/one=alpha/two=bravo/on,al,tw,br
;;var=one,alpha,two,bravo;one=alpha;two=bravo;var=on,al,tw,br
??var=one,alpha,two,bravo?one=alpha&two=bravo?var=on,al,tw,br
&&var=one,alpha,two,bravo&one=alpha&two=bravo&var=on,al,tw,br

Limitations

URI Template is a Proposed Standard and because of that I did not want to deviate from it. That said I'm not at all happy with how the specification turned out. Here are some of my thoughts: