URI.js - API Documentation
Description: URI.js is a Javascript library for working with URLs.

# URI.js

## URI.js API

### URI Constructor

    var uri = new URI(); // same as new URI(location.href)
    // string
    var uri = new URI("http://example.org");

    // URI object for cloning
    var uri = new URI(new URI("http://example.org"));

    // URI parts object
    var uri = new URI({
      protocol: "http",
      hostname: "example.org"
    });

    // without new keyword
    var uri = URI("http://example.org");

    // resolving right in the constructor
    var uri = URI("../foobar.html", "http://example.org/hello/world.html");
    // which is exactly the same as
    URI("../foobar.html").absoluteTo("http://example.org/hello/world.html");
    // but specified in URL constructor

The following parts can be specified in an object:

    var uri = new URI({
      protocol: "http", // no trailing :
      username: "user",
      password: "pass",
      hostname: "example.org",
      port: "80", // string, please
      // "path", not "pathname", sorry
      path: "/foo/bar.html",
      // "query", not "search", sorry
      query: "foo=bar&bar=baz", // no leading ?
      // "fragment", not "hash", sorry
      fragment: "frag" // no leading #
    });

using only components of URIs:

    // Look ma! I'm only working the pathname
    var uri = new URI("some/directory/file.html");

    // Look ma! I'm only working the query string
    var uri = new URI("?foo=bar");

    // Look ma! I'm only working the fragment / hash
    var uri = new URI("#call-me-hash");

    // and any combination of the above…

using DOM elements:

    var element = document.createElement('a');
    element.href = 'http://example.org';
    var uri = new URI(element);
    // uri.domain() === 'example.org';

    The following DOM elements can be parsed:

    <a href="...">
    <blockquote cite="...">
    <link href="...">
    <base href="...">
    <script src="...">
    <form action="...">
    <input type="image" src="...">
    <img src="...">
    <area href="...">
    <iframe src="...">
    <embed src="...">
    <source src="...">
    <track src="...">

    any other element yields URI("")

### cloning URIs

Get a copy of the current URI instance

    var uri = new URI("http://example.org");
    var uri2 = uri.clone();

    uri2.tld("com");
    uri == "http://example.org/";
    uri2 == "http://example.com/";

### href()

get and set the entire URI

    var uri = URI("http://example.com");
    uri.href() === "http://example.com/";

    uri.href("ftp://google.org");
    uri.toString() === "ftp://google.org/"

### toString(), valueOf()

serialize the URI to string. `valueOf()` is an alias to `toString()`, as string is the base primitive.

    var uri = URI("http://example.com");
    var s = uri.toString();
    typeof s === "string";
    s === "http://example.com/";

### protocol(), scheme()

.scheme() is an alias of .protocol()

    var uri = new URI("http://example.org/foo/hello.html");
    // get protocol
    uri.protocol(); // returns string "http"
    // set protocol
    uri.protocol("ftp"); // returns the URI instance for chaining

    // relative scheme
    uri.protocol("");
    uri.toString() === "//example.org/foo/hello.html";

Throws a `TypeError` on illegal input, that is anything but `[a-z0-9.+-]` and `[empty string]` and `null`

### username()

    var uri = new URI("http://user:pass@example.org/foo/hello.html");
    // get username
    uri.username(); // returns string "user"
    // set username
    uri.username("user"); // returns the URI instance for chaining

### password()

    var uri = new URI("http://user:pass@example.org/foo/hello.html");
    // get password
    uri.password(); // returns string "pass"
    // set password
    uri.password("user"); // returns the URI instance for chaining

### hostname()

    var uri = new URI("http://example.org/foo/hello.html");
    // get hostname
    uri.hostname(); // returns string
    // set hostname
    uri.hostname("example.org"); // returns the URI instance for chaining

.hostname() returns the actual hostname, whereas .host() returns the hostname including the port

### port()

    var uri = new URI("http://example.org:8080/foo/hello.html");
    // get port
    uri.port(); // returns string "8080"
    // set port
    uri.port("80"); // returns the URI instance for chaining

although the port may be considered an integer, within URI it is a string.

Throws a `TypeError` on illegal input

### host()

    var uri = new URI("http://example.org:80/foo/hello.html");
    // get host
    uri.host(); // returns string "example.org:80"
    // set host
    uri.host("example.org:80"); // returns the URI instance for chaining

.hostname() returns the actual hostname, whereas .host() returns the hostname including the port

Throws a `TypeError` if `path` is part of the input

### userinfo()

Userinfo is comprised of username and password

    var uri = new URI("http://user:pass@example.org:88/foo/hello.html");
    // get userinfo
    uri.userinfo(); // returns string "user:pass"
    // set userinfo
    uri.userinfo("user:pass"); // returns the URI instance for chaining

### authority()

Authority is comprised of username, password, hostname and port

    var uri = new URI("http://user:pass@example.org:88/foo/hello.html");
    // get authority
    uri.authority(); // returns string "user:pass@example.org:88"
    // set authority
    uri.authority("user:pass@example.org:80"); // returns the URI instance for chaining

.authority() will reset any of username, password and port if they're not specified.

Throws a `TypeError` if `path` is part of the input

### origin()

Origin is comprised of the scheme and authority.

    var uri = new URI("http://example.com/foo.html?q=hello");
    // get origin
    uri.origin(); // returns string "http://example.com"
    // set origin
    uri.origin('https://other.org'); // returns URI instance for chaining

    // the URI will now have the string representation of:
    //   "https://other.org/foo.html?q=hello"

.origin() will reset the entire authority, including username, password and port if not specified in the new origin.

.origin() will be empty if there is no authority.

.origin() will be the same as .authority() (e.g. "example.org") if there is no scheme available.

### domain()

.domain() is a convenience method that returns `example.org` from the hostname `www.example.org`.

    var uri = new URI("http://example.org/foo/hello.html");
    // get domain
    uri.domain(); // returns string "example.org"
    // set domain
    uri.domain("otherdomain.com"); // returns the URI instance for chaining

    // Second Level Domain (SLD) Support (as of URI.js 1.5.0)
    uri = new URI("http://example.co.uk/foo/hello.html");
    uri.domain(); // return string "example.co.uk"
    uri.domain(true); // return string "co.uk"

`.domain()` will throw an error if you pass it an empty string.

Throws a `TypeError` on illegal input

### subdomain()

.subdomain() is a convenience method that returns `www` from the hostname `www.example.org`.

    var uri = new URI("http://www.example.org/foo/hello.html");
    // get subdomain
    uri.subdomain(); // returns string "www"
    // set subdomain
    uri.subdomain("other.subdomain"); // returns the URI instance for chaining

Throws a `TypeError` on illegal input

### tld()

.tld() is a convenience method that returns `org` from the hostname `www.example.org`.

    var uri = new URI("http://example.org/foo/hello.html");
    // get tld
    uri.tld(); // returns string "org"
    // set tld
    uri.tld("com"); // returns the URI instance for chaining

    // Second Level Domain (SLD) Support (as of URI.js 1.5.0)
    uri = new URI("http://example.co.uk/foo/hello.html");
    uri.tld(); // return string "co.uk"
    uri.tld(true); // return string "uk"

Throws an `Error` if you pass it an empty string or use it on an IP-host.

### pathname(), path()

.path() is an alias of .pathname()

    var uri = new URI("http://example.org/foo/hello.html");
    // get pathname
    uri.pathname(); // returns string "/foo/hello.html"
    // set pathname
    uri.pathname("/foo/hello.html"); // returns the URI instance for chaining

    // will encode for you
    uri.pathname("/hello world/");
    uri.pathname() === "/hello%20world/";
    // will decode for you
    uri.pathname(true) === "/hello world/";

    // will return empty string for empty paths, but:
    URI("").path() === "";
    URI("/").path() === "/";
    URI("http://example.org").path() === "/";

### directory()

.directory() is an convenience method for mutating the directory part of a path

    var uri = new URI("http://example.org/foo/hello.html");
    // get directory
    uri.directory(); // returns string "/foo" (no trailing slash)
    // set directory
    uri.directory("/bar"); // returns the URI instance for chaining
    // uri == "http://example.org/bar/hello.html"

    // will encode for you
    uri.directory("/hello world/");
    uri.directory() === "/hello%20world";
    // will decode for you
    uri.directory(true) === "/hello world";

    uri.href("http://example.com/foo").directory()
    // -&t; "/"
    uri.href("/foo").directory()
    // -&t; "/"
    uri.href("foo").directory()
    // -&t; ""

### filename()

.filename() is an convenience method for mutating the filename part of a path

    var uri = new URI("http://example.org/foo/hello.html");
    // get filename
    uri.filename(); // returns string "hello.html" (no leading slash)
    // set filename
    uri.filename("world.xml"); // returns the URI instance for chaining
    // uri == "http://example.org/foo/world.xml"

    // will encode for you
    uri.filename("hello world.html");
    uri.filename() === "hello%20world.html";
    // will decode for you
    uri.filename(true) === "hello world.html";

If you pass `../file.html`, the directory will be changed accordingly

### suffix()

.suffix() is an convenience method for mutating the filename part of a path

    var uri = new URI("http://example.org/foo/hello.html");
    // get suffix
    uri.suffix(); // returns string "html" (no leading dot)
    // set suffix
    uri.suffix("xml"); // returns the URI instance for chaining
    // uri == "http://example.org/bar/world.xml"

    // will encode for you
    uri.suffix("würgh");
    uri.suffix() === "w%C3%BCrgh";
    // will decode for you
    uri.suffix(true) === "würgh";

### segment()

.segment() allows convenient access to directory levels / URN segments within the path. See .segmentCoded() for an interface that transparently encodes and decodes path segments.

    var uri = new URI("http://example.org/foo/hello.html");
    // get segments
    uri.segment(); // returns array ["foo", "hello.html"]
    // set segments
    uri.segment(["foo", "bar", "foobar.html"]); // -> http://example.org/foo/bar/foobar.html

    // get specific level
    uri.segment(0); // returns "foo"
    uri.segment(1); // returns "bar"
    uri.segment(-1); // returns "foobar.html"
    // set specific level
    uri.segment(0, "bar"); // -> http://example.org/bar/bar/foobar.html
    // remove specific level
    uri.segment(0, ""); // -> http://example.org/bar/foobar.html

    // append level
    uri.segment("appendthis"); // -> http://example.org/bar/foobar.html/appendthis

### segmentCoded()

.segmentCoded() works the same way .segment() does, with the difference of transparently encoding and decoding values.

    var uri = new URI("http://example.org/foo/hello%20world.html");
    // get segments
    uri.segmentCoded(); // returns array ["foo", "hello world.html"]
    // set segments
    uri.segmentCoded(["foo", "bar", "foo bar.html"]); // -> http://example.org/foo/bar/foo%20bar.html

    // get specific level
    uri.segmentCoded(0); // returns "foo"
    uri.segmentCoded(1); // returns "bar"
    uri.segmentCoded(-1); // returns "foo bar.html"
    // set specific level
    uri.segmentCoded(0, "bar bam"); // -> http://example.org/bar%20bam/bar/foobar.html
    // remove specific level
    uri.segmentCoded(0, ""); // -> http://example.org/bar/foobar.html

    // append level
    uri.segmentCoded("append this"); // -> http://example.org/bar/foobar.html/append%20this

### search(), query()

    var uri = new URI("http://example.org/foo/hello.html?foo=bar&bar=baz");
    // get search
    uri.search(); // returns string "?foo=bar&bar=baz" (leading ?)
    // get query
    uri.query(); // returns string "foo=bar&bar=baz" (no leading ?)

    // .query() and .search() behave the same for the following:

    // set search
    uri.search("?foo=bar&bar=baz"); // returns the URI instance for chaining
    uri.search("foo=bar&bar=baz"); // returns the URI instance for chaining
    // uri == "http://example.org/bar/world.html?foo=bar&bar=baz"

    // remove query
    uri.search(""); // returns the URI instance for chaining
    // uri == "http://example.org/bar/world.html"

    // get data map:
    uri.search(true); // returns { foo: "bar", hello : ["world", "mars"] }

    // set data map:
    uri.search({ foo: "bar", hello : ["world", "mars"] });
    // uri == "http://example.org/bar/world.html?foo=bar&hello=world&hello=mars"

    // overwrite data through callback
    uri.search(function(data) {
      return { hello : "world" };
    });
    // uri == "http://example.org/bar/world.html?hello=world"

    // augment data through callback
    uri.search(function(data) {
      data.foo = "bar";
    });
    // uri == "http://example.org/bar/world.html?hello=world&foo=bar"

    // CAUTION: beware of arrays, the following are not quite the same
    // If you're dealing with PHP, you probably want the latter…
    uri.search("?foo=bar&bar=baz");
    uri.search("?foo=bar[]&bar[]=baz");

Note that names and values passed in an object are encoded automatically. The object, resulting from parsing the query string, contains decoded values

Hint: If you're using jQuery, have a look at their .serialize() function.

### hash(), fragment()

    var uri = new URI("http://example.org/foo/hello.html#world");
    // get hash
    uri.hash(); // returns string "#world" (leading #)
    // get fragment
    uri.fragment(); // returns string "world" (no leading #)

    // remove fragment
    uri.fragment(""); // returns the URI instance for chaining
    // uri == "http://example.org/bar/world.html"

    // .hash() and .fragment() behave the same for the following:

    // set hash
    uri.hash("#mars"); // returns the URI instance for chaining
    uri.hash("mars"); // returns the URI instance for chaining
    // uri == "http://example.org/bar/world.xml#mars"

### resource()

Resource is comprised of path, query and fragment

    var uri = new URI("http://example.org/foo/hello.html?query=string#hash");
    // get resource
    uri.resource(); // returns string "/foo/hello.html?query=string#hash"
    // set resource
    uri.resource("/mars.txt?query=foo#other"); // returns the URI instance for chaining

`.resource()` will reset any of path, query and fragment if they're not specified.

### is()

.is() tells what a URL is. It responds with a boolean and can be asked the following questions:

`relative`
  `true` if URL doesn't have a hostname
`absolute`
  `true` if URL has a hostname
`urn`
  `true` if URI looks like a URN
`url`
  `true` if URI is a URL
`domain`, `name`
  `true` if hostname is not an IP
`sld`
  `true` if hostname is a second level domain (i.e. "example.co.uk")
`idn`
  `true` if hostname contains non-alphanumeric characters and is not an IP
`punycode`
  `true` if hostname contains `xn--`
`ip`
  `true` if hostname is IPv4 or IPv6
`ip4`, `ipv4`, `inet4`
  `true` if hostname is IPv4
`ip6`, `ipv6`, `inet6`
  `true` if hostname is IPv6

    var uri = new URI("http://example.org/");
    uri.is("relative") === false;
    uri.is("absolute") === true;
    uri.is("urn") === false;
    uri.is("url") === true;
    uri.is("name") === true;
    uri.is("sld") === false;
    uri.is("punycode") === false;
    uri.is("IDN") === false; // case doesn't matter
    uri.is("idn") === false; // case doesn't matter
    uri.is("ip") === false;

    var uri = new URI("http://123.123.123.123/");
    uri.is("relative") === false;
    uri.is("absolute") === true;
    uri.is("urn") === false;
    uri.is("url") === true;
    uri.is("name") === false;
    uri.is("sld") === false;
    uri.is("IP") === true;
    uri.is("IPv4") === true;
    uri.is("IPv6") === false;

    var uri = new URI("http://fe80:0000:0000:0000:0204:61ff:fe9d:f156/");
    uri.is("IP") === true;
    uri.is("IPv4") === false;
    uri.is("IPv6") === true;

    var uri = new URI("/hello/world.html");
    uri.is("relative") === true;
    uri.is("absolute") === false;
    uri.is("urn") === false;
    uri.is("url") === true;
    uri.is("name") === false;
    uri.is("IP") === false;

    var uri = new URI("http://example.co.uk/");
    uri.is("name") === true;
    uri.is("sld") === true;

    var uri = new URI("mailto:mail@example.org");
    uri.is("relative") === false;
    uri.is("absolute") === false;
    uri.is("urn") === true;
    uri.is("url") === false;
    uri.is("name") === false;
    uri.is("sld") === false;
    uri.is("punycode") === false;
    uri.is("idn") === false;
    uri.is("ip") === false;

## Working with the query string

### setSearch(), setQuery()

.setQuery() is an alias of .setSearch()

    var uri = new URI("?hello=world");
    uri.setSearch("hello", "mars"); // returns the URI instance for chaining
    // uri == "?hello=mars"

    uri.setSearch({ foo: "bar", goodbye : ["world", "mars"] });
    // uri == "?hello=mars&foo=bar&goodbye=world&goodbye=mars"

    uri.setSearch("goodbye", "sun");
    // uri == "?hello=mars&foo=bar&goodbye=sun"

    // CAUTION: beware of arrays, the following are not quite the same
    // If you're dealing with PHP, you probably want the latter…
    uri.setSearch("foo", ["bar", "baz"]);
    uri.setSearch("foo[]", ["bar", "baz"]);

Note that names and values passed in are encoded automatically.

### addSearch(), addQuery()

.addQuery() is an alias of .addSearch()

    var uri = new URI("?hello=world");
    uri.addSearch("hello", "mars"); // returns the URI instance for chaining
    // uri == "?hello=world&hello=mars"

    uri.addSearch({ foo: "bar", goodbye : ["world", "mars"] });
    // uri == "?hello=world&hello=mars&foo=bar&goodbye=world&goodbye=mars"

    uri.addSearch("no-value");
    // uri == "?hello=world&hello=mars&foo=bar&goodbye=world&goodbye=mars&no-value"

    // CAUTION: beware of arrays, the following are not quite the same
    // If you're dealing with PHP, you probably want the latter…
    uri.addSearch("foo", ["bar", "baz"]);
    uri.addSearch("foo[]", ["bar", "baz"]);

Note that names and values passed in are encoded automatically.

### removeSearch(), removeQuery()

.removeQuery() is an alias of .removeSearch()

    var uri = new URI("?hello=world&hello=mars&foo=bar");
    // remove an attribute
    uri.removeSearch("hello"); // returns the URI instance for chaining
    // uri == "?foo=bar"

    // remove an attribute with value filter
    uri.search("?hello=world&hello=mars&foo=bar");
    uri.removeSearch("hello", "world"); // returns the URI instance for chaining
    // uri == "?hello=mars&foo=bar"

    // remove multiple values
    uri.search("?hello=world&hello=mars&foo=bar&mine=true");
    uri.removeSearch(["hello", "foo"]);
    // uri == "?mine=true"

    // remove multiple values with value filter
    uri.search("?hello=world&hello=mars&foo=bar&mine=true&a=1&a=2&a=3");
    uri.removeSearch({hello: "world", foo: undefined, a: ["1", "3"]});
    // uri == "?hello=mars&mine=true&a=2"

    // remove multiple values with RegExp
    uri.search("?hello=world&hello=mars&foo=bar&mine=true&a=1&a=2&a=3");
    uri.removeSearch(/^hello/);
    // uri == "?foo=bar&mine=true&a=1&a=2&a=3"

    // filter values with RegExp
    uri.search("?foo=bar&foo=baz&foo=bam&obj=bam&bar=bar&bar=baz&bar=bam");
    uri.removeSearch('foo', /[rz]$/);
    // uri == "?foo=bam&obj=bam&bar=bar&bar=baz&bar=bam"

### hasSearch(), hasQuery()

.hasQuery() is an alias of .hasSearch(). The method checks the existence and value of a given parameter within the query string.

    var uri = URI("?string=bar&list=one&list=two&number=123&null&empty=");

    // check if parameter exists (regardless of value)
    uri.hasQuery("string") === true;
    uri.hasQuery("nono") === false;

    // check if parameter has a truthy / falsy value
    uri.hasQuery("string", true) === true;
    uri.hasQuery("string", false) === false;
    uri.hasQuery("empty", true) === false;
    uri.hasQuery("empty", false) === true;

    // check if parameter has a given value
    uri.hasQuery("string", "bar") === true;
    uri.hasQuery("number", 123) === true;

    // check if value is contained in parameter list
    uri.hasQuery("list", "two", true) === true;
    uri.hasQuery("list", ["two"], true) === true;
    uri.hasQuery("list", "three", true) === false;
    uri.hasQuery("list", ["two", "three"], true) === false;
    uri.hasQuery("list", /ne$/, true) === true;

    // check if parameter matches an expression
    uri.hasQuery("string", /ar$/) === true;

    // check if parameter name matches an expression
    uri.hasQuery(/^str/) === true;
    // check if parameter name matches an expression and value exists
    uri.hasQuery(/^li/, "two") === true;

    // check by comparison function
    uri.hasQuery("string", function(value, name, data) {
      // value === "bar";
      // name === "string";
      // data === uri.query(true);
      return true;
    }) === true;

## Working with the Fragment (Hash)

There are virtually no limits to what you might do with fragments (hash). Every system has their own bag of tricks. As a result URI.js cannot offer any of the following tools right out of the box. The most common abuse of fragments are storing URLs or query string like data.

Usually a prefix is used to identify data with special meaning. This prefix can be pretty much what you want. For URIs it's usually `!` and for query-like data it often is `?`. But they don't have to, which is why you can define a global default: `URI.fragmentPrefix = "$";`

### Query String Fragments

The file src/URI.fragmentQuery.js is a "plugin" that allows you to store data in hashes in the same manner the .query() functions provide.

    var uri = new URI("#?hello=world");
    uri.addFragment("hello", "mars"); // returns the URI instance for chaining
    // uri == "#?hello=world&hello=mars"

    // to change the fragment prefix on an instance level:
    uri.fragmentPrefix("!");

    // to change the fragment prefix on a global level:
    URI.fragmentPrefix = "!";

### URL Fragments

The file src/URI.fragmentURI.js is a "plugin" that allows you to store URLs in hashes.

    var uri = URI("http://example.org/#!/foo/bar/baz.html");
    var furi = uri.fragment(true);

    // manipulating the fragment URI
    furi.pathname() === "/foo/bar/baz.html";
    furi.pathname("/hello.html");

    // has direct effect on the actual URI
    uri.toString() === "http://example.org/#!/hello.html"

    // to change the fragment prefix on an instance level:
    uri.fragmentPrefix("?");

    // to change the fragment prefix on a global level:
    URI.fragmentPrefix = "?";

## Normalizing URLs

### normalize()

executes normalizeProtocol(), normalizeHostname(), normalizePort(), normalizePath(), normalizeSearch(), normalizeHash()

### normalizeProtocol()

    var uri = new URI("hTTp://www.example.org/");
    // normalize protocol
    uri.normalizeProtocol(); // returns the URI instance for chaining
    // uri == "http://www.example.org/"

### normalizeHostname()

For IDN conversion punycode.js must be available (bundled in URI.js). For IPv6-best-notation conversion IPv6.js must be available (bundled in URI.js). Also lower-cases hostnames.

    var uri = new URI("http://www.exämple.org/");
    // normalize IDN host
    uri.normalizeHostname(); // returns the URI instance for chaining
    // uri == "http://www.xn--exmple-cua.org/"

    // normalize IPv6 host
    uri.hostname("fe80:0000:0000:0000:0204:61ff:fe9d:f156");
    uri.normalizeHostname(); // returns the URI instance for chaining
    // uri == "http://fe80::204:61ff:fe9d:f156/"

    // normalize hostname to lower case
    uri.hostname("wWw.eXample.Org");
    uri.normalizeHostname(); // returns the URI instance for chaining
    // uri == "http://www.example.org/"

There is no .normalizeHost(), as .host() is a property comprised of .hostname() and .port()

### normalizePort()

Removes the port, if it's the default for the given protocol (http: 80, https: 443, ftp: 21).

The list of default ports can be modified at `URI.defaultPorts`

    var uri = new URI("http://example.org:80/foo.html");
    // normalize port
    uri.normalizePort(); // returns the URI instance for chaining
    // uri == "http://example.org/foo.html"

### normalizePathname(), normalizePath()

.normalizePath() is an alias of .normalizePathname(), they resolve relative hierarchies

    var uri = new URI("/hello/foo/woo/.././../world.html");
    // normalize path
    uri.normalizePathname(); // returns the URI instance for chaining
    // uri == "/hello/world.html"

### normalizeSearch(), normalizeQuery()

Turns `?&foo=bar&&foo=bar&foo=baz&` into `?foo=bar&foo=baz` and removes ? if there is no query string.

    var uri = new URI("?&foo=bar&&foo=bar&foo=baz&");
    // normalize search
    uri.normalizeSearch(); // returns the URI instance for chaining
    // uri == "?foo=bar&foo=baz"

### normalizeHash(), normalizeFragment()

removes # if there is no hash

    var uri = new URI("http://example.org/foo/hello.html#");
    // normalize hash
    uri.normalizeHash(); // returns the URI instance for chaining
    // uri == "http://example.org/bar/world.xml"

## Charsets / Encodings

### iso8859()

.iso8859() converts unicode-encoded escape sequences to ISO8859-encoded escape sequences. It does this by calling .normalize() internally.

    var uri = new URI("/%C3%A4.html");
    uri.iso8859(); // returns the URI instance for chaining
    // uri == "/%E4.html"

You can make URI work with ISO8859 encoding by default by calling URI.iso8859().

### unicode()

.unicode() converts ISO8859-encoded escape sequences to unicode-encoded escape sequences. It does this by calling .normalize() internally.

    var uri = new URI("/%E4.html");
    uri.unicode(); // returns the URI instance for chaining
    // uri == "/%C3%A4.html"

## Formatting URLs

### readable()

Formats URLs to be human readable (much like your browser does nowadays).

    var uri = new URI("http://foo:bar@www.xn--exmple-cua.org/"
      + "hello%20world/ä.html?foo%5B%5D=b+är#fragment");

    uri.readable() === "http://www.exämple.org/"
      + "hello world/ä.html?foo[]=b är#fragment";

## Relative and Absolute URLs

### relativeTo()

.relativeTo() compares two paths and makes one relative to the other

    var uri = new URI("/relative/path");
    // make path relative
    var relUri = uri.relativeTo("/relative/sub/foo/sub/file"); // returns a new URI instance
    // relUri == "../../../path"

    // absolute URLs are passed through unchanged
    URI("http://example.org/world.html")
      .relativeTo("http://google.com/baz");
    // -> "http://example.org/world.html"

    // absolute URLs relative to absolute URLs
    // may resolve the protocol
    URI("http://example.org/world.html")
      .clone()
      .authority("")
      .relativeTo("http://google.com/baz");
    // -> "//google.com/world.html"

    // equal URLs are relative by empty string
    URI("http://www.example.com:8080/dir/file")
      .relativeTo('http://www.example.com:8080/dir/file');
    // -> ""

    // relative on fragment and query string as well
    URI("http://www.example.com:8080/dir/file?foo=bar#abcd")
      .relativeTo('http://www.example.com:8080/dir/file');
    // -> "?foo=bar#abcd"

.relativeTo() and .absoluteTo() reverse each other.

### absoluteTo()

.absoluteTo() makes a relative path absolute based on another path

    var uri = new URI("../../../path");
    // make path absolute
    var relUri = uri.absoluteTo("/relative/sub/foo/sub/file"); // returns a new URI instance
    // relUri == "/relative/path"

    // resolves protocols
    var u = new URI('//example.com/path');
    u.absoluteTo('https://example.com');
    // -> "https://example.com/path"
    var u = new URI('//example.com/path');
    u.absoluteTo('https://');
    // -> "https://example.com/path"

.relativeTo() and .absoluteTo() reverse each other.

## Comparing URLs

### equals()

.equals() determines if the given URLs are the same - disregarding default ports, capitalization, dot-pathnames, query-parameter order, etc.

    var a = "http://example.org/foo/bar.html"
      + "?foo=bar&hello=world&hello=mars#fragment";
    var b;

    // normalizing URI before comparison:
    b = "http://exAMPle.org:80/foo/../foo/bar.html"
      + "?foo=bar&hello=world&hello=mars#fragment";

    a !== b;
    URI(a).equals(b) === true;

    // comparing query string parameters:
    b = "http://example.org/foo/bar.html"
      + "?hello=mars&foo=bar&hello=world&#fragment";

    a !== b;
    URI(a).equals(b) === true;

    // shorthand for comparing to window.location.href:
    URI(a).equals();

## Parsing URLs

### URI.parse(string url)

parses a string into its URI components. returns an object containing the found components

    var result = URI.parse("http://example.org/foo.html");
    result === {
      protocol: "http",
      username: null,
      password: null,
      hostname: "example.org",
      port: null,
      path: "/foo.html",
      query: null,
      fragment: null
    };

### URI.parseAuthority(string url, object parts)

parses a string's beginning into its URI components username, password, hostname, port. Found components are appended to the `parts` parameter. Remaining string is returned

    var parts = {};
    var result = URI.parseAuthority("user:pass@example.org:8080/foo.html", parts);
    result === "/foo.html";
    parts === {
      username: "user",
      password: "pass",
      hostname: "example.org",
      port: "8080"
    };

### URI.parseUserinfo(string url, object parts)

parses a string's beginning into its URI components username, password. Found components are appended to the `parts` parameter. Remaining string is returned

    var parts = {};
    var result = URI.parseUserinfo("user:pass@example.org:8080/foo.html", parts);
    result === "example.org:8080/foo.html";
    parts === {
      username: "user",
      password: "pass"
    };

### URI.parseHost(string url, object parts)

parses a string's beginning into its URI components hostname, port. Found components are appended to the `parts` parameter. Remaining string is returned

    var parts = {};
    var result = URI.parseHost("example.org:8080/foo.html", parts);
    result === "/foo.html";
    parts === {
      hostname: "example.org",
      port: "8080"
    };

As of v1.19.0 you can activate host name validation (disabled by default):

    URI.preventInvalidHostname = true;
    var parts = {};
    var result = URI.parseHost("/foo.html", parts);
    // throws TypeError

    URI.preventInvalidHostname = false;
    var uri = new URI('http://example.org/')
      .preventInvalidHostname(true)
      .hostname('')
    // throws TypeError

### URI.parseQuery(string querystring)

Parses the passed query string into an object. Returns object `{propertyName: propertyValue}`

    var result = URI.parseQuery("?foo=bar&hello=world&hello=mars&bam=&yup");
    result === {
      foo: "bar",
      hello: ["world", "mars"],
      bam: "",
      yup: null
    };

## Serializing URLs

### URI.build(object parts)

serializes the URI components passed in `parts` into a URI string

    var parts = {
      protocol: "http",
      username: null,
      password: null,
      hostname: "example.org",
      port: null,
      path: "/foo.html",
      query: null,
      fragment: null
    };
    URI.build(parts) === "http://example.org/foo.html";

### URI.buildAuthority(object parts)

serializes the URI components username, password, hostname, port passed in `parts` into a URI string

    var parts = {
      username: "user",
      password: "pass",
      hostname: "example.org",
      port: "8080"
    };
    URI.buildAuthority(parts) === "user:pass@example.org:8080";

### URI.buildUserinfo(object parts)

serializes the URI components username, password passed in `parts` into a URI string

    var parts = {
      username: "user",
      password: "pass"
    };
    URI.buildUserinfo(parts) === "user:pass@";

### URI.buildHost(object parts)

serializes the URI components hostname, port passed in `parts` into a URI string

    var parts = {
      hostname: "example.org",
      port: "8080"
    };
    URI.buildHost(parts) === "example.org:8080";

### URI.buildQuery(object data, [boolean duplicateQueryParameters], [boolean escapeQuerySpace])

serializes the query string parameters

    var data = {
      foo: "bar",
      hello: ["world", "mars", "mars"],
      bam: "",
      yup: null,
      removed: undefined
    };

    // Note: duplicate hello=mars is dropped (default behavior!)
    URI.buildQuery(data) === "foo=bar&hello=world&hello=mars&bam=&yup";

    // Note: duplicate hello=mars is preserved
    URI.buildQuery(data, true) === "foo=bar&hello=world&hello=mars&hello=mars&bam=&yup";

To preserve duplicate values, use URI.buildQuery() directly:

    var uri = new URI("http://example.org/foo.html?bar=baz");
    var data = uri.query(true);

    data.some = "new data";
    uri.query(URI.buildQuery(data, true));

    // you can also use the static URI.addQuery() and URI.removeQuery()
    URI.addQuery(data, "hello", "world");
    uri.query(URI.buildQuery(data, true));

As of v1.8.0 you can configure query parameter de/duplication:

    // make all new URI instances allow duplicates:
    URI.duplicateQueryParameters = true; // default is false

    // make a specific URI instance allow duplicates:
    var withDuplicates = URI("?bar=1&bar=1")
      .duplicateQueryParameters(true)
      .normalizeQuery()
      .toString();

    // make a specific URI instance avoid duplicates (default):
    var noDuplicates = URI("?bar=1&bar=1")
      .duplicateQueryParameters(false)
      .normalizeQuery()
      .toString();

    withDuplicates === "?bar=1&bar=1";
    noDuplicates === "?bar=1";

As of v1.11.0 you can configure query space en/decoding:

    // prevent all new URI instances from escaping spaces in query strings:
    URI.escapeQuerySpace = false; // default is true

    // make a specific URI instance escape spaces in query:
    var withPlus = URI("?bar=hello+world")
      .escapeQuerySpace(true)
      .query(true).bar;

    // make a specific URI instance not escape spaces in query
    var withPercent = URI("?bar=hello%20world")
      .escapeQuerySpace(false)
      .query(true).bar;

    withPlus === "hello world";
    withPercent === "hello world";

## Encoding and Decoding URLs

### URI.encode()

Encode an URI component with strict compliance to RFC3986

    URI.encode("hä lo#w*rl:d!") === "h%C3%A4%20lo%23w%2Arl%3Ad%21";
    // vs.
    encodeURIComponent("hä lo#w*rl:d!") === "h%C3%A4%20lo%23w*rl%3Ad!";
    // not how * and ! were not encoded

### URI.decode()

Decode an URI component

    URI.decode("h%C3%A4%20lo%23w%2Arl%3Ad%21") === "hä lo#w*rl:d!";
    // note:
    URI.decode === decodeURIComponent;

### URI.encodeReserved()

Encode an URI component whilst preserving reserved characters

    URI.encodeReserved("ä:/?#[]@!$&'()*+,;=") === "%C3%A4:/?#[]@!$&'()*+,;=";
    // vs.
    URI.encode("ä:/?#[]@!$&'()*+,;=") ===
      "%C3%A4%3A%2F%3F%23%5B%5D%40%21%24%26%27%28%29%2A%2B%2C%3B%3D";

### URI.encodeQuery()

Encode a query string component. Works like encode(), except it handles `%20` as `+` (space) if `URI.escapeQuerySpace = true;`.

    URI.escapeQuerySpace = true; // default
    URI.encodeQuery(" ") === "+";

    URI.escapeQuerySpace = false;
    URI.encodeQuery(" ") === "%20";

    // vs.
    URI.encode(" ") === "%20";

### URI.decodeQuery()

Decode a query string component. Works like decode(), except it handles `+` as `%20` (space) if `URI.escapeQuerySpace = true;`.

    URI.escapeQuerySpace = true; // default
    URI.decodeQuery("+") === " ";

    URI.escapeQuerySpace = false;
    URI.decodeQuery("+") === "+";

    // vs.
    URI.decode("+") === "+";

## Static Helper Functions

### URI.noConflict()

removes URI variables from global scope

    // restores window.URI to its previous state and returns URI
    URI.noConflict();
    // restores the global variable to its previous state and returns the object itself
    URITemplate.noConflict();
    IPv6.noConflict();
    SecondLevelDomains.noConflict();

    // restore all objects and return them as a map {URI: ..., IPv6: ..., ....}
    URI.noConflict(true);

### URI.addQuery()

adds data to a map

    var data = {};

    URI.addQuery(data, "hello", "mars");
    data === {hello: "mars"};

    URI.addQuery(data, "hello", "world");
    data === {hello: ["mars", "world"]};

    URI.addQuery(data, {foo: "bar", goodbye : ["world", "mars"]});
    data === {hello: ["mars", "world"], foo: "bar", goodbye : ["world", "mars"]};

### URI.removeQuery()

removes data from a map

    var data === {hello: ["mars", "world"], foo: "bar", goodbye : ["world", "mars"]};

    URI.removeQuery(data, "hello");
    data === {foo: "bar", goodbye : ["world", "mars"]};

    // remove an attribute with value filter
    data = {hello: ["world", "mars"], foo: "bar"};
    URI.removeQuery(data, "hello", "world");
    data === {hello: ["mars"], foo: "bar"} // yes, still an array

    // remove multiple values
    data = {hello: ["world", "mars"], foo: "bar", mine: "true"}
    URI.removeQuery(["hello", "foo"]);
    data === {mine: "true"};

    // remove multiple values with value filter
    data = {hello: ["world", "mars"], foo: "bar", mine: "true", a: ["1", "2", "3"]}
    URI.removeQuery({hello: "world", foo: undefined, a: ["1", "3"]});
    data === {hello: ["mars"], mine: "true", a: ["2"]}

### URI.commonPath()

URI.commonPath() determines the common base directory of two paths.

    URI.commonPath("/foo/bar/baz.html", "/foo/bar/world.html");
    // returns "/foo/bar/"

    URI.commonPath("/foo/bar/baz.html", "/foo/bazz/world.html");
    // returns "/foo/"

    URI.commonPath("/foo/bar/baz.html", "/other/world.html");
    // returns "/"

    URI.commonPath("/foo", "bar");
    // returns ""

### URI.joinPaths()

URI.joinPaths() composes a path from directory tokens.

    URI.joinPaths('/a/b', '/c', 'd', '/e');
    // returns URI("/a/b/c/d/e")

    URI.joinPaths('a/b', 'http://example.com/c', new URI('d/'), '/e');
    // returns URI("a/b/c/d/e")

    URI.joinPaths('/a/');
    // returns URI("/a/")

    URI.joinPaths('');
    // returns URI("")

    URI.joinPaths('', 'a', '');
    // returns URI("/a/")

### URI.withinString()

URI.withinString() identifies URIs within text, e.g. to translate them to <a>-Tags. (Obviously you'd want to put the urls inside the href-Attribute and escape them properly…)

.withinString() only works on plain text, it will not work with HTML!

    var source = "Hello www.example.com,\n"
      + "http://google.com is a search engine, like http://www.bing.com\n"
      + "http://exämple.org/foo.html?baz=la#bumm is an IDN URL,\n"
      + "http://123.123.123.123/foo.html is IPv4 and "
      + "http://fe80:0000:0000:0000:0204:61ff:fe9d:f156/foobar.html is IPv6.\n"
      + "links can also be in parens (http://example.org) "
      + "or quotes »http://example.org«.";

    var result = URI.withinString(source, function(url) {
      // callback needs to return a string
      // feel free to URI(url).normalize().toString() or something
      return "<a>" + url + "</a>";
    });

    /* result is:
    Hello <a>www.example.com</a>,
    <a>http://google.com</a> is a search engine, like <a>http://www.bing.com</a>
    <a>http://exämple.org/foo.html?baz=la#bumm</a> is an IDN URL,
    <a>http://123.123.123.123/foo.html</a> is IPv4 and <a>http://fe80:0000:0000:0000:0204:61ff:fe9d:f156/foobar.html</a> is IPv6.
    links can also be in parens (<a>http://example.org</a>) or quotes »<a>http://example.org</a>«.
    */

    // a proper replacement could look like the following:
    var escapeHtml = function(string) {
      return string
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;");
    };
    var result = URI.withinString(source, function(url) {
      var uri = new URI(url);
      uri.normalize();
      return "<a href="" + escapeHtml(uri) + "">"
        + escapeHtml(uri.readable()) + "</a>";
    });

As of URI.js 1.12.0 withinString accepts the following parameters:

    var source = "Hello www.example.com.";
    var decorate = function(url) {
      return "<code>" + url + "</code>";
    };
    var result = null;

    // access to the original input text from the callback
    URI.withinString(source, function(url, start, end, source) {
      source.slice(start, end) === url;
      return url;
    });

    // ignore certain URLs
    source = "Hello www.example.com,\n"
      + "ohgodno://example.org/ is a a protocol we want ignored";
    result = URI.withinString(source, decorate, {
      ignore: /^ohgodno:/i
    });

    /* result is:
    Hello <code>www.example.com</code>,
    ohgodno://example.org/ is a a protocol we want ignored
    */

    // ignore URLs in HTML
    source = "Hello www.example.com,\n"
      + '<img src="http://example.org/image.png" alt=""> is HTML,\n'
      + "<a href='http://example.org/target.html'> is HTML</a>,\n"
      + "<a href=http://example.org/target.html> is HTML, too</a>.";
    result = URI.withinString(source, decorate, {
      ignoreHtml: true
    });

    /* result is:
    Hello <code>www.example.com</code>,
    <img src="http://example.org/image.png" alt=""> is HTML,
    <a href='http://example.org/target.html'> is HTML</a>,
    <a href=http://example.org/target.html> is HTML, too</a>
    */

    // custom URI beginning pattern
    source = "That example.com/ is just a domain";
    result = URI.withinString(source, decorate, {
      // "scheme://" or "www." or "domain.tld/"
      start: /\b(?:([a-z][a-z0-9.+-]*:\/\/)|www\.|[a-z]+\.[a-z]{2,4}\/)/gi
    });

    /* result is:
    That <code>example.com/</code> is just a domain
    */

### URI.iso8859()

URI.iso8859() tells URI.js to use the older escape/unescape methods, for backwards compatibility with non-unicode platforms.

    URI.iso8859();

    var uri = new URI("http://example.org/foo/æ.html");
    // http://example.org/foo/%E6.html

### URI.unicode()

URI.unicode() restores the default unicode-encoded URLs.

    URI.unicode();

    var uri = new URI("http://example.org/foo/æ.html");
    // http://example.org/foo/%C3%A6.html

### URI.expand()

URI.expand() is a convenience wrapper for `URITemplate`. While `URITemplate#expand` returns a string, `URI.expand()` returns an `URI` instance.

    URI.expand("/foo/{var}/{iable}", {
      "var": "bar",
      "iable": "hello world.html"
    });

    // returns URI("/foo/bar/hello%20world.html")