From 1baddfcaa2e6e7b14be11af663ef9f28d372f9d2 Mon Sep 17 00:00:00 2001 From: deltreey Date: Mon, 3 Aug 2015 23:43:26 -0400 Subject: [PATCH] Release: 0.0.3 --- .../img/glyphicons-halflings-white.png | Bin 0 -> 8777 bytes documentation/img/glyphicons-halflings.png | Bin 0 -> 12799 bytes documentation/index.html | 206 + documentation/scripts/URI.js | 1429 ++++ documentation/scripts/bootstrap-dropdown.js | 169 + documentation/scripts/bootstrap-tab.js | 144 + documentation/scripts/docstrap.lib.js | 9 + .../scripts/prettify/Apache-License-2.0.txt | 202 + documentation/scripts/prettify/jquery.min.js | 6 + documentation/scripts/prettify/lang-css.js | 21 + documentation/scripts/prettify/prettify.js | 496 ++ documentation/scripts/sunlight.js | 1157 +++ documentation/scripts/toc.js | 104 + documentation/styles/darkstrap.css | 960 +++ documentation/styles/prettify-tomorrow.css | 132 + documentation/styles/site.cerulean.css | 6688 +++++++++++++++ documentation/styles/site.cosmo.css | 6844 +++++++++++++++ documentation/styles/site.cyborg.css | 6828 +++++++++++++++ documentation/styles/site.darkly.css | 6960 ++++++++++++++++ documentation/styles/site.darkstrap.css | 5638 +++++++++++++ documentation/styles/site.flatly.css | 6939 ++++++++++++++++ documentation/styles/site.journal.css | 6756 +++++++++++++++ documentation/styles/site.lumen.css | 7073 ++++++++++++++++ documentation/styles/site.paper.css | 7374 +++++++++++++++++ documentation/styles/site.readable.css | 6799 +++++++++++++++ documentation/styles/site.sandstone.css | 6837 +++++++++++++++ documentation/styles/site.simplex.css | 6803 +++++++++++++++ documentation/styles/site.slate.css | 7110 ++++++++++++++++ documentation/styles/site.spacelab.css | 6859 +++++++++++++++ documentation/styles/site.superhero.css | 6913 +++++++++++++++ documentation/styles/site.united.css | 6697 +++++++++++++++ documentation/styles/site.yeti.css | 6996 ++++++++++++++++ documentation/styles/sunlight.dark.css | 345 + documentation/styles/sunlight.default.css | 344 + package.json | 2 +- 35 files changed, 121839 insertions(+), 1 deletion(-) create mode 100644 documentation/img/glyphicons-halflings-white.png create mode 100644 documentation/img/glyphicons-halflings.png create mode 100644 documentation/index.html create mode 100644 documentation/scripts/URI.js create mode 100644 documentation/scripts/bootstrap-dropdown.js create mode 100644 documentation/scripts/bootstrap-tab.js create mode 100644 documentation/scripts/docstrap.lib.js create mode 100644 documentation/scripts/prettify/Apache-License-2.0.txt create mode 100644 documentation/scripts/prettify/jquery.min.js create mode 100644 documentation/scripts/prettify/lang-css.js create mode 100644 documentation/scripts/prettify/prettify.js create mode 100644 documentation/scripts/sunlight.js create mode 100644 documentation/scripts/toc.js create mode 100644 documentation/styles/darkstrap.css create mode 100644 documentation/styles/prettify-tomorrow.css create mode 100644 documentation/styles/site.cerulean.css create mode 100644 documentation/styles/site.cosmo.css create mode 100644 documentation/styles/site.cyborg.css create mode 100644 documentation/styles/site.darkly.css create mode 100644 documentation/styles/site.darkstrap.css create mode 100644 documentation/styles/site.flatly.css create mode 100644 documentation/styles/site.journal.css create mode 100644 documentation/styles/site.lumen.css create mode 100644 documentation/styles/site.paper.css create mode 100644 documentation/styles/site.readable.css create mode 100644 documentation/styles/site.sandstone.css create mode 100644 documentation/styles/site.simplex.css create mode 100644 documentation/styles/site.slate.css create mode 100644 documentation/styles/site.spacelab.css create mode 100644 documentation/styles/site.superhero.css create mode 100644 documentation/styles/site.united.css create mode 100644 documentation/styles/site.yeti.css create mode 100644 documentation/styles/sunlight.dark.css create mode 100644 documentation/styles/sunlight.default.css diff --git a/documentation/img/glyphicons-halflings-white.png b/documentation/img/glyphicons-halflings-white.png new file mode 100644 index 0000000000000000000000000000000000000000..3bf6484a29d8da269f9bc874b25493a45fae3bae GIT binary patch literal 8777 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 B7G?kd literal 0 HcmV?d00001 diff --git a/documentation/img/glyphicons-halflings.png b/documentation/img/glyphicons-halflings.png new file mode 100644 index 0000000000000000000000000000000000000000..a9969993201f9cee63cf9f49217646347297b643 GIT binary patch literal 12799 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 literal 0 HcmV?d00001 diff --git a/documentation/index.html b/documentation/index.html new file mode 100644 index 0000000..8ad3384 --- /dev/null +++ b/documentation/index.html @@ -0,0 +1,206 @@ + + + + + + wildstring Index + + + + + + + + + + + + + +
+
+ + +
+ +
+

Index

+ + + + Index + + + + + + + + + + + + + + + + + + + + +
+

wildstring

Simple String Wildcard Handling

+

build status +npm version +Codacy Badge +Code Climate +bitHound Score +Join the chat at https://gitter.im/deltreey/wildstring

+

Shake it shake it

Installing wildstring is a snap. wildstring has no dependencies, so you don't need anything else to run it. If you want to use tools though, here's some tips on how to install it with popular installers.

+

node.js

npm install wildstring

then:

+
var wildstring = require('wildstring');

bower

bower install wildstring

html

make sure you rename the index.js file to wildstring.js when you add it to your project

+
<script src="wildstring.js"></script>

Hold me tight

Especially with something that does something new, it's important to see how it works. Below are some examples, but here's a brief explanation as well.

+

In this explanation, I'll use * as my wildcard for simplicity. If you put a wildcard at the beginning, for example *Thing then you can match anything or nothing before your string. So your string could be Wild Thing or just Thing and it would match fine. The same is true for the end. Wild* would match Wild Thing or just Wild. If you want to match text in the middle of the string, it works the same way. Wild*Thing matches both WildThing and Wild and crazy Thing.

+
wildstring.match('Test*', 'Testing');                 // true, wildcard matches 'ing'
+wildstring.match('*ing', 'testing');                  // true, wildcard matches 'test'
+wildstring.match('Test*', 'Test');                    // true, wildcard can match empty strings
+wildstring.match('*ing', 'Testing it');               // false, no wildcard do match ' it'
+wildstring.match('Test', 'Testing');                  // false, no wildcard to match 'ing'
+wildstring.match('Test*ing', 'Testing this thing');   // true, matches 'Test' and the end of 'thing', the rest is wildcard matched
+wildstring.match('*))))))*', ')))))');                // false, not enough parenthesis

You make my heart string

You can use wildstring for string interpolation, which makes for an easier interface to parse data from users who maybe don't know regular expressions.

+
wildstring.replace('I * node.*', [ 'love', 'js' ]);   // 'I love node.js'
+wildstring.replace('I * node.*', 'script');           // 'I script node.script' * this behavior is the same as "I * node.*".replace("*", "script") and actually uses that method
+wildstring.replace('I * node.*', [ 'love' ]);         // THROWS AN ERROR, wildcard count and number of strings to insert must match
+wildstring.replace('*/*/*', [ new Date.getMonth() + 1, new Date.getDate(), new Date.getFullYear]);
+// 7/15/2015 (or whatever day it is), probably better to learn the js date parser though

You make everything, groovy

You can use your own wildcards with wildstring, so you can wildstring everything. You can even turn off case sensitive matching if you want.

+
wildstring.wildcard = 'stuff';
+wildstring.match('Test stuff', 'Test wild');            // true, wildcard 'stuff' matches 'wild'
+wildstring.replace('stuff and stuffthings', [ 'WILD', 'thing' ]); // 'WILD and thingthings'
+// turn off case sensitive matching
+wildstring.caseSensitive = false;
+wildstring.match('tEsT', 'TeSt');                       // true, 'test' matches 'test'

I think I love you

If you want to contribute to wildstring, it's really easy. Just make sure you have nodejs installed and do the following.

+
git clone https://github.com/deltreey/wildstring
+# npm install -g grunt-cli # if you don't have it
+npm install
+grunt

grunt will run all the tests and jshint, so just make sure it passes before submitting a pull request

+
+ + + + + + + +
+
+ +
+ + +
+
+
+ + +
+
+ + +
+ + + + DocStrap Copyright © 2012-2014 The contributors to the JSDoc3 and DocStrap projects. + +
+ + + Documentation generated by JSDoc 3.3.2 + on Mon Aug 3rd 2015 using the DocStrap template. + +
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documentation/scripts/URI.js b/documentation/scripts/URI.js new file mode 100644 index 0000000..91b01ee --- /dev/null +++ b/documentation/scripts/URI.js @@ -0,0 +1,1429 @@ +/*! + * URI.js - Mutating URLs + * + * Version: 1.8.3 + * + * Author: Rodney Rehm + * Web: http://medialize.github.com/URI.js/ + * + * Licensed under + * MIT License http://www.opensource.org/licenses/mit-license + * GPL v3 http://opensource.org/licenses/GPL-3.0 + * + */ +(function(root, factory) { + // https://github.com/umdjs/umd/blob/master/returnExports.js + if (typeof exports === 'object') { + // Node + module.exports = factory(require('./punycode'), require('./IPv6'), require('./SecondLevelDomains')); + } else if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['./punycode', './IPv6', './SecondLevelDomains'], factory); + } else { + // Browser globals (root is window) + root.URI = factory(root.punycode, root.IPv6, root.SecondLevelDomains); + } +}(this, function(punycode, IPv6, SLD) { + "use strict"; + + function URI(url, base) { + // Allow instantiation without the 'new' keyword + if (!(this instanceof URI)) { + return new URI(url, base); + } + if (url === undefined) { + if (typeof location !== 'undefined') { + url = location.href + ""; + } else { + url = ""; + } + } + this.href(url); + // resolve to base according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#constructor + if (base !== undefined) { + return this.absoluteTo(base); + } + return this; + }; + var p = URI.prototype; + var hasOwn = Object.prototype.hasOwnProperty; + + function escapeRegEx(string) { + // https://github.com/medialize/URI.js/commit/85ac21783c11f8ccab06106dba9735a31a86924d#commitcomment-821963 + return string.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); + } + + function isArray(obj) { + return String(Object.prototype.toString.call(obj)) === "[object Array]"; + } + + function filterArrayValues(data, value) { + var lookup = {}; + var i, length; + if (isArray(value)) { + for (i = 0, length = value.length; i < length; i++) { + lookup[value[i]] = true; + } + } else { + lookup[value] = true; + } + for (i = 0, length = data.length; i < length; i++) { + if (lookup[data[i]] !== undefined) { + data.splice(i, 1); + length--; + i--; + } + } + return data; + } + URI._parts = function() { + return { + protocol: null, + username: null, + password: null, + hostname: null, + urn: null, + port: null, + path: null, + query: null, + fragment: null, + // state + duplicateQueryParameters: URI.duplicateQueryParameters + }; + }; + // state: allow duplicate query parameters (a=1&a=1) + URI.duplicateQueryParameters = false; + // static properties + URI.protocol_expression = /^[a-z][a-z0-9-+-]*$/i; + URI.idn_expression = /[^a-z0-9\.-]/i; + URI.punycode_expression = /(xn--)/i; + // well, 333.444.555.666 matches, but it sure ain't no IPv4 - do we care? + URI.ip4_expression = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/; + // credits to Rich Brown + // source: http://forums.intermapper.com/viewtopic.php?p=1096#1096 + // specification: http://www.ietf.org/rfc/rfc4291.txt + URI.ip6_expression = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/; + // gruber revised expression - http://rodneyrehm.de/t/url-regex.html + URI.find_uri_expression = /\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/ig; + // http://www.iana.org/assignments/uri-schemes.html + // http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports + URI.defaultPorts = { + http: "80", + https: "443", + ftp: "21", + gopher: "70", + ws: "80", + wss: "443" + }; + // allowed hostname characters according to RFC 3986 + // ALPHA DIGIT "-" "." "_" "~" "!" "$" "&" "'" "(" ")" "*" "+" "," ";" "=" %encoded + // I've never seen a (non-IDN) hostname other than: ALPHA DIGIT . - + URI.invalid_hostname_characters = /[^a-zA-Z0-9\.-]/; + // encoding / decoding according to RFC3986 + + function strictEncodeURIComponent(string) { + // see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/encodeURIComponent + return encodeURIComponent(string).replace(/[!'()*]/g, escape).replace(/\*/g, "%2A"); + } + URI.encode = strictEncodeURIComponent; + URI.decode = decodeURIComponent; + URI.iso8859 = function() { + URI.encode = escape; + URI.decode = unescape; + }; + URI.unicode = function() { + URI.encode = strictEncodeURIComponent; + URI.decode = decodeURIComponent; + }; + URI.characters = { + pathname: { + encode: { + // RFC3986 2.1: For consistency, URI producers and normalizers should + // use uppercase hexadecimal digits for all percent-encodings. + expression: /%(24|26|2B|2C|3B|3D|3A|40)/ig, + map: { + // -._~!'()* + "%24": "$", + "%26": "&", + "%2B": "+", + "%2C": ",", + "%3B": ";", + "%3D": "=", + "%3A": ":", + "%40": "@" + } + }, + decode: { + expression: /[\/\?#]/g, + map: { + "/": "%2F", + "?": "%3F", + "#": "%23" + } + } + }, + reserved: { + encode: { + // RFC3986 2.1: For consistency, URI producers and normalizers should + // use uppercase hexadecimal digits for all percent-encodings. + expression: /%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/ig, + map: { + // gen-delims + "%3A": ":", + "%2F": "/", + "%3F": "?", + "%23": "#", + "%5B": "[", + "%5D": "]", + "%40": "@", + // sub-delims + "%21": "!", + "%24": "$", + "%26": "&", + "%27": "'", + "%28": "(", + "%29": ")", + "%2A": "*", + "%2B": "+", + "%2C": ",", + "%3B": ";", + "%3D": "=" + } + } + } + }; + URI.encodeQuery = function(string) { + return URI.encode(string + "").replace(/%20/g, '+'); + }; + URI.decodeQuery = function(string) { + return URI.decode((string + "").replace(/\+/g, '%20')); + }; + URI.recodePath = function(string) { + var segments = (string + "").split('/'); + for (var i = 0, length = segments.length; i < length; i++) { + segments[i] = URI.encodePathSegment(URI.decode(segments[i])); + } + return segments.join('/'); + }; + URI.decodePath = function(string) { + var segments = (string + "").split('/'); + for (var i = 0, length = segments.length; i < length; i++) { + segments[i] = URI.decodePathSegment(segments[i]); + } + return segments.join('/'); + }; + // generate encode/decode path functions + var _parts = { + 'encode': 'encode', + 'decode': 'decode' + }; + var _part; + var generateAccessor = function(_group, _part) { + return function(string) { + return URI[_part](string + "").replace(URI.characters[_group][_part].expression, function(c) { + return URI.characters[_group][_part].map[c]; + }); + }; + }; + for (_part in _parts) { + URI[_part + "PathSegment"] = generateAccessor("pathname", _parts[_part]); + } + URI.encodeReserved = generateAccessor("reserved", "encode"); + URI.parse = function(string, parts) { + var pos, t; + if (!parts) { + parts = {}; + } + // [protocol"://"[username[":"password]"@"]hostname[":"port]"/"?][path]["?"querystring]["#"fragment] + // extract fragment + pos = string.indexOf('#'); + if (pos > -1) { + // escaping? + parts.fragment = string.substring(pos + 1) || null; + string = string.substring(0, pos); + } + // extract query + pos = string.indexOf('?'); + if (pos > -1) { + // escaping? + parts.query = string.substring(pos + 1) || null; + string = string.substring(0, pos); + } + // extract protocol + if (string.substring(0, 2) === '//') { + // relative-scheme + parts.protocol = ''; + string = string.substring(2); + // extract "user:pass@host:port" + string = URI.parseAuthority(string, parts); + } else { + pos = string.indexOf(':'); + if (pos > -1) { + parts.protocol = string.substring(0, pos); + if (parts.protocol && !parts.protocol.match(URI.protocol_expression)) { + // : may be within the path + parts.protocol = undefined; + } else if (parts.protocol === 'file') { + // the file scheme: does not contain an authority + string = string.substring(pos + 3); + } else if (string.substring(pos + 1, pos + 3) === '//') { + string = string.substring(pos + 3); + // extract "user:pass@host:port" + string = URI.parseAuthority(string, parts); + } else { + string = string.substring(pos + 1); + parts.urn = true; + } + } + } + // what's left must be the path + parts.path = string; + // and we're done + return parts; + }; + URI.parseHost = function(string, parts) { + // extract host:port + var pos = string.indexOf('/'); + var bracketPos; + var t; + if (pos === -1) { + pos = string.length; + } + if (string[0] === "[") { + // IPv6 host - http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04#section-6 + // I claim most client software breaks on IPv6 anyways. To simplify things, URI only accepts + // IPv6+port in the format [2001:db8::1]:80 (for the time being) + bracketPos = string.indexOf(']'); + parts.hostname = string.substring(1, bracketPos) || null; + parts.port = string.substring(bracketPos + 2, pos) || null; + } else if (string.indexOf(':') !== string.lastIndexOf(':')) { + // IPv6 host contains multiple colons - but no port + // this notation is actually not allowed by RFC 3986, but we're a liberal parser + parts.hostname = string.substring(0, pos) || null; + parts.port = null; + } else { + t = string.substring(0, pos).split(':'); + parts.hostname = t[0] || null; + parts.port = t[1] || null; + } + if (parts.hostname && string.substring(pos)[0] !== '/') { + pos++; + string = "/" + string; + } + return string.substring(pos) || '/'; + }; + URI.parseAuthority = function(string, parts) { + string = URI.parseUserinfo(string, parts); + return URI.parseHost(string, parts); + }; + URI.parseUserinfo = function(string, parts) { + // extract username:password + var pos = string.indexOf('@'); + var firstSlash = string.indexOf('/'); + var t; + // authority@ must come before /path + if (pos > -1 && (firstSlash === -1 || pos < firstSlash)) { + t = string.substring(0, pos).split(':'); + parts.username = t[0] ? URI.decode(t[0]) : null; + t.shift(); + parts.password = t[0] ? URI.decode(t.join(':')) : null; + string = string.substring(pos + 1); + } else { + parts.username = null; + parts.password = null; + } + return string; + }; + URI.parseQuery = function(string) { + if (!string) { + return {}; + } + // throw out the funky business - "?"[name"="value"&"]+ + string = string.replace(/&+/g, '&').replace(/^\?*&*|&+$/g, ''); + if (!string) { + return {}; + } + var items = {}; + var splits = string.split('&'); + var length = splits.length; + var v, name, value; + for (var i = 0; i < length; i++) { + v = splits[i].split('='); + name = URI.decodeQuery(v.shift()); + // no "=" is null according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#collect-url-parameters + value = v.length ? URI.decodeQuery(v.join('=')) : null; + if (items[name]) { + if (typeof items[name] === "string") { + items[name] = [items[name]]; + } + items[name].push(value); + } else { + items[name] = value; + } + } + return items; + }; + URI.build = function(parts) { + var t = ""; + if (parts.protocol) { + t += parts.protocol + ":"; + } + if (!parts.urn && (t || parts.hostname)) { + t += '//'; + } + t += (URI.buildAuthority(parts) || ''); + if (typeof parts.path === "string") { + if (parts.path[0] !== '/' && typeof parts.hostname === "string") { + t += '/'; + } + t += parts.path; + } + if (typeof parts.query === "string" && parts.query) { + t += '?' + parts.query; + } + if (typeof parts.fragment === "string" && parts.fragment) { + t += '#' + parts.fragment; + } + return t; + }; + URI.buildHost = function(parts) { + var t = ""; + if (!parts.hostname) { + return ""; + } else if (URI.ip6_expression.test(parts.hostname)) { + if (parts.port) { + t += "[" + parts.hostname + "]:" + parts.port; + } else { + // don't know if we should always wrap IPv6 in [] + // the RFC explicitly says SHOULD, not MUST. + t += parts.hostname; + } + } else { + t += parts.hostname; + if (parts.port) { + t += ':' + parts.port; + } + } + return t; + }; + URI.buildAuthority = function(parts) { + return URI.buildUserinfo(parts) + URI.buildHost(parts); + }; + URI.buildUserinfo = function(parts) { + var t = ""; + if (parts.username) { + t += URI.encode(parts.username); + if (parts.password) { + t += ':' + URI.encode(parts.password); + } + t += "@"; + } + return t; + }; + URI.buildQuery = function(data, duplicates) { + // according to http://tools.ietf.org/html/rfc3986 or http://labs.apache.org/webarch/uri/rfc/rfc3986.html + // being »-._~!$&'()*+,;=:@/?« %HEX and alnum are allowed + // the RFC explicitly states ?/foo being a valid use case, no mention of parameter syntax! + // URI.js treats the query string as being application/x-www-form-urlencoded + // see http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type + var t = ""; + var unique, key, i, length; + for (key in data) { + if (hasOwn.call(data, key) && key) { + if (isArray(data[key])) { + unique = {}; + for (i = 0, length = data[key].length; i < length; i++) { + if (data[key][i] !== undefined && unique[data[key][i] + ""] === undefined) { + t += "&" + URI.buildQueryParameter(key, data[key][i]); + if (duplicates !== true) { + unique[data[key][i] + ""] = true; + } + } + } + } else if (data[key] !== undefined) { + t += '&' + URI.buildQueryParameter(key, data[key]); + } + } + } + return t.substring(1); + }; + URI.buildQueryParameter = function(name, value) { + // http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type -- application/x-www-form-urlencoded + // don't append "=" for null values, according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#url-parameter-serialization + return URI.encodeQuery(name) + (value !== null ? "=" + URI.encodeQuery(value) : ""); + }; + URI.addQuery = function(data, name, value) { + if (typeof name === "object") { + for (var key in name) { + if (hasOwn.call(name, key)) { + URI.addQuery(data, key, name[key]); + } + } + } else if (typeof name === "string") { + if (data[name] === undefined) { + data[name] = value; + return; + } else if (typeof data[name] === "string") { + data[name] = [data[name]]; + } + if (!isArray(value)) { + value = [value]; + } + data[name] = data[name].concat(value); + } else { + throw new TypeError("URI.addQuery() accepts an object, string as the name parameter"); + } + }; + URI.removeQuery = function(data, name, value) { + var i, length, key; + if (isArray(name)) { + for (i = 0, length = name.length; i < length; i++) { + data[name[i]] = undefined; + } + } else if (typeof name === "object") { + for (key in name) { + if (hasOwn.call(name, key)) { + URI.removeQuery(data, key, name[key]); + } + } + } else if (typeof name === "string") { + if (value !== undefined) { + if (data[name] === value) { + data[name] = undefined; + } else if (isArray(data[name])) { + data[name] = filterArrayValues(data[name], value); + } + } else { + data[name] = undefined; + } + } else { + throw new TypeError("URI.addQuery() accepts an object, string as the first parameter"); + } + }; + URI.commonPath = function(one, two) { + var length = Math.min(one.length, two.length); + var pos; + // find first non-matching character + for (pos = 0; pos < length; pos++) { + if (one[pos] !== two[pos]) { + pos--; + break; + } + } + if (pos < 1) { + return one[0] === two[0] && one[0] === '/' ? '/' : ''; + } + // revert to last / + if (one[pos] !== '/') { + pos = one.substring(0, pos).lastIndexOf('/'); + } + return one.substring(0, pos + 1); + }; + URI.withinString = function(string, callback) { + // expression used is "gruber revised" (@gruber v2) determined to be the best solution in + // a regex sprint we did a couple of ages ago at + // * http://mathiasbynens.be/demo/url-regex + // * http://rodneyrehm.de/t/url-regex.html + return string.replace(URI.find_uri_expression, callback); + }; + URI.ensureValidHostname = function(v) { + // Theoretically URIs allow percent-encoding in Hostnames (according to RFC 3986) + // they are not part of DNS and therefore ignored by URI.js + if (v.match(URI.invalid_hostname_characters)) { + // test punycode + if (!punycode) { + throw new TypeError("Hostname '" + v + "' contains characters other than [A-Z0-9.-] and Punycode.js is not available"); + } + if (punycode.toASCII(v).match(URI.invalid_hostname_characters)) { + throw new TypeError("Hostname '" + v + "' contains characters other than [A-Z0-9.-]"); + } + } + }; + p.build = function(deferBuild) { + if (deferBuild === true) { + this._deferred_build = true; + } else if (deferBuild === undefined || this._deferred_build) { + this._string = URI.build(this._parts); + this._deferred_build = false; + } + return this; + }; + p.clone = function() { + return new URI(this); + }; + p.valueOf = p.toString = function() { + return this.build(false)._string; + }; + // generate simple accessors + _parts = { + protocol: 'protocol', + username: 'username', + password: 'password', + hostname: 'hostname', + port: 'port' + }; + generateAccessor = function(_part) { + return function(v, build) { + if (v === undefined) { + return this._parts[_part] || ""; + } else { + this._parts[_part] = v; + this.build(!build); + return this; + } + }; + }; + for (_part in _parts) { + p[_part] = generateAccessor(_parts[_part]); + } + // generate accessors with optionally prefixed input + _parts = { + query: '?', + fragment: '#' + }; + generateAccessor = function(_part, _key) { + return function(v, build) { + if (v === undefined) { + return this._parts[_part] || ""; + } else { + if (v !== null) { + v = v + ""; + if (v[0] === _key) { + v = v.substring(1); + } + } + this._parts[_part] = v; + this.build(!build); + return this; + } + }; + }; + for (_part in _parts) { + p[_part] = generateAccessor(_part, _parts[_part]); + } + // generate accessors with prefixed output + _parts = { + search: ['?', 'query'], + hash: ['#', 'fragment'] + }; + generateAccessor = function(_part, _key) { + return function(v, build) { + var t = this[_part](v, build); + return typeof t === "string" && t.length ? (_key + t) : t; + }; + }; + for (_part in _parts) { + p[_part] = generateAccessor(_parts[_part][1], _parts[_part][0]); + } + p.pathname = function(v, build) { + if (v === undefined || v === true) { + var res = this._parts.path || (this._parts.urn ? '' : '/'); + return v ? URI.decodePath(res) : res; + } else { + this._parts.path = v ? URI.recodePath(v) : "/"; + this.build(!build); + return this; + } + }; + p.path = p.pathname; + p.href = function(href, build) { + var key; + if (href === undefined) { + return this.toString(); + } + this._string = ""; + this._parts = URI._parts(); + var _URI = href instanceof URI; + var _object = typeof href === "object" && (href.hostname || href.path); + // window.location is reported to be an object, but it's not the sort + // of object we're looking for: + // * location.protocol ends with a colon + // * location.query != object.search + // * location.hash != object.fragment + // simply serializing the unknown object should do the trick + // (for location, not for everything...) + if (!_URI && _object && Object.prototype.toString.call(href) !== "[object Object]") { + href = href.toString(); + } + if (typeof href === "string") { + this._parts = URI.parse(href, this._parts); + } else if (_URI || _object) { + var src = _URI ? href._parts : href; + for (key in src) { + if (hasOwn.call(this._parts, key)) { + this._parts[key] = src[key]; + } + } + } else { + throw new TypeError("invalid input"); + } + this.build(!build); + return this; + }; + // identification accessors + p.is = function(what) { + var ip = false; + var ip4 = false; + var ip6 = false; + var name = false; + var sld = false; + var idn = false; + var punycode = false; + var relative = !this._parts.urn; + if (this._parts.hostname) { + relative = false; + ip4 = URI.ip4_expression.test(this._parts.hostname); + ip6 = URI.ip6_expression.test(this._parts.hostname); + ip = ip4 || ip6; + name = !ip; + sld = name && SLD && SLD.has(this._parts.hostname); + idn = name && URI.idn_expression.test(this._parts.hostname); + punycode = name && URI.punycode_expression.test(this._parts.hostname); + } + switch (what.toLowerCase()) { + case 'relative': + return relative; + case 'absolute': + return !relative; + // hostname identification + case 'domain': + case 'name': + return name; + case 'sld': + return sld; + case 'ip': + return ip; + case 'ip4': + case 'ipv4': + case 'inet4': + return ip4; + case 'ip6': + case 'ipv6': + case 'inet6': + return ip6; + case 'idn': + return idn; + case 'url': + return !this._parts.urn; + case 'urn': + return !!this._parts.urn; + case 'punycode': + return punycode; + } + return null; + }; + // component specific input validation + var _protocol = p.protocol; + var _port = p.port; + var _hostname = p.hostname; + p.protocol = function(v, build) { + if (v !== undefined) { + if (v) { + // accept trailing :// + v = v.replace(/:(\/\/)?$/, ''); + if (v.match(/[^a-zA-z0-9\.+-]/)) { + throw new TypeError("Protocol '" + v + "' contains characters other than [A-Z0-9.+-]"); + } + } + } + return _protocol.call(this, v, build); + }; + p.scheme = p.protocol; + p.port = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (v !== undefined) { + if (v === 0) { + v = null; + } + if (v) { + v += ""; + if (v[0] === ":") { + v = v.substring(1); + } + if (v.match(/[^0-9]/)) { + throw new TypeError("Port '" + v + "' contains characters other than [0-9]"); + } + } + } + return _port.call(this, v, build); + }; + p.hostname = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (v !== undefined) { + var x = {}; + URI.parseHost(v, x); + v = x.hostname; + } + return _hostname.call(this, v, build); + }; + // compound accessors + p.host = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (v === undefined) { + return this._parts.hostname ? URI.buildHost(this._parts) : ""; + } else { + URI.parseHost(v, this._parts); + this.build(!build); + return this; + } + }; + p.authority = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (v === undefined) { + return this._parts.hostname ? URI.buildAuthority(this._parts) : ""; + } else { + URI.parseAuthority(v, this._parts); + this.build(!build); + return this; + } + }; + p.userinfo = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (v === undefined) { + if (!this._parts.username) { + return ""; + } + var t = URI.buildUserinfo(this._parts); + return t.substring(0, t.length - 1); + } else { + if (v[v.length - 1] !== '@') { + v += '@'; + } + URI.parseUserinfo(v, this._parts); + this.build(!build); + return this; + } + }; + p.resource = function(v, build) { + var parts; + if (v === undefined) { + return this.path() + this.search() + this.hash(); + } + parts = URI.parse(v); + this._parts.path = parts.path; + this._parts.query = parts.query; + this._parts.fragment = parts.fragment; + this.build(!build); + return this; + }; + // fraction accessors + p.subdomain = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + // convenience, return "www" from "www.example.org" + if (v === undefined) { + if (!this._parts.hostname || this.is('IP')) { + return ""; + } + // grab domain and add another segment + var end = this._parts.hostname.length - this.domain().length - 1; + return this._parts.hostname.substring(0, end) || ""; + } else { + var e = this._parts.hostname.length - this.domain().length; + var sub = this._parts.hostname.substring(0, e); + var replace = new RegExp('^' + escapeRegEx(sub)); + if (v && v[v.length - 1] !== '.') { + v += "."; + } + if (v) { + URI.ensureValidHostname(v); + } + this._parts.hostname = this._parts.hostname.replace(replace, v); + this.build(!build); + return this; + } + }; + p.domain = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (typeof v === 'boolean') { + build = v; + v = undefined; + } + // convenience, return "example.org" from "www.example.org" + if (v === undefined) { + if (!this._parts.hostname || this.is('IP')) { + return ""; + } + // if hostname consists of 1 or 2 segments, it must be the domain + var t = this._parts.hostname.match(/\./g); + if (t && t.length < 2) { + return this._parts.hostname; + } + // grab tld and add another segment + var end = this._parts.hostname.length - this.tld(build).length - 1; + end = this._parts.hostname.lastIndexOf('.', end - 1) + 1; + return this._parts.hostname.substring(end) || ""; + } else { + if (!v) { + throw new TypeError("cannot set domain empty"); + } + URI.ensureValidHostname(v); + if (!this._parts.hostname || this.is('IP')) { + this._parts.hostname = v; + } else { + var replace = new RegExp(escapeRegEx(this.domain()) + "$"); + this._parts.hostname = this._parts.hostname.replace(replace, v); + } + this.build(!build); + return this; + } + }; + p.tld = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (typeof v === 'boolean') { + build = v; + v = undefined; + } + // return "org" from "www.example.org" + if (v === undefined) { + if (!this._parts.hostname || this.is('IP')) { + return ""; + } + var pos = this._parts.hostname.lastIndexOf('.'); + var tld = this._parts.hostname.substring(pos + 1); + if (build !== true && SLD && SLD.list[tld.toLowerCase()]) { + return SLD.get(this._parts.hostname) || tld; + } + return tld; + } else { + var replace; + if (!v) { + throw new TypeError("cannot set TLD empty"); + } else if (v.match(/[^a-zA-Z0-9-]/)) { + if (SLD && SLD.is(v)) { + replace = new RegExp(escapeRegEx(this.tld()) + "$"); + this._parts.hostname = this._parts.hostname.replace(replace, v); + } else { + throw new TypeError("TLD '" + v + "' contains characters other than [A-Z0-9]"); + } + } else if (!this._parts.hostname || this.is('IP')) { + throw new ReferenceError("cannot set TLD on non-domain host"); + } else { + replace = new RegExp(escapeRegEx(this.tld()) + "$"); + this._parts.hostname = this._parts.hostname.replace(replace, v); + } + this.build(!build); + return this; + } + }; + p.directory = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (v === undefined || v === true) { + if (!this._parts.path && !this._parts.hostname) { + return ''; + } + if (this._parts.path === '/') { + return '/'; + } + var end = this._parts.path.length - this.filename().length - 1; + var res = this._parts.path.substring(0, end) || (this._parts.hostname ? "/" : ""); + return v ? URI.decodePath(res) : res; + } else { + var e = this._parts.path.length - this.filename().length; + var directory = this._parts.path.substring(0, e); + var replace = new RegExp('^' + escapeRegEx(directory)); + // fully qualifier directories begin with a slash + if (!this.is('relative')) { + if (!v) { + v = '/'; + } + if (v[0] !== '/') { + v = "/" + v; + } + } + // directories always end with a slash + if (v && v[v.length - 1] !== '/') { + v += '/'; + } + v = URI.recodePath(v); + this._parts.path = this._parts.path.replace(replace, v); + this.build(!build); + return this; + } + }; + p.filename = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (v === undefined || v === true) { + if (!this._parts.path || this._parts.path === '/') { + return ""; + } + var pos = this._parts.path.lastIndexOf('/'); + var res = this._parts.path.substring(pos + 1); + return v ? URI.decodePathSegment(res) : res; + } else { + var mutatedDirectory = false; + if (v[0] === '/') { + v = v.substring(1); + } + if (v.match(/\.?\//)) { + mutatedDirectory = true; + } + var replace = new RegExp(escapeRegEx(this.filename()) + "$"); + v = URI.recodePath(v); + this._parts.path = this._parts.path.replace(replace, v); + if (mutatedDirectory) { + this.normalizePath(build); + } else { + this.build(!build); + } + return this; + } + }; + p.suffix = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (v === undefined || v === true) { + if (!this._parts.path || this._parts.path === '/') { + return ""; + } + var filename = this.filename(); + var pos = filename.lastIndexOf('.'); + var s, res; + if (pos === -1) { + return ""; + } + // suffix may only contain alnum characters (yup, I made this up.) + s = filename.substring(pos + 1); + res = (/^[a-z0-9%]+$/i).test(s) ? s : ""; + return v ? URI.decodePathSegment(res) : res; + } else { + if (v[0] === '.') { + v = v.substring(1); + } + var suffix = this.suffix(); + var replace; + if (!suffix) { + if (!v) { + return this; + } + this._parts.path += '.' + URI.recodePath(v); + } else if (!v) { + replace = new RegExp(escapeRegEx("." + suffix) + "$"); + } else { + replace = new RegExp(escapeRegEx(suffix) + "$"); + } + if (replace) { + v = URI.recodePath(v); + this._parts.path = this._parts.path.replace(replace, v); + } + this.build(!build); + return this; + } + }; + p.segment = function(segment, v, build) { + var separator = this._parts.urn ? ':' : '/'; + var path = this.path(); + var absolute = path.substring(0, 1) === '/'; + var segments = path.split(separator); + if (typeof segment !== 'number') { + build = v; + v = segment; + segment = undefined; + } + if (segment !== undefined && typeof segment !== 'number') { + throw new Error("Bad segment '" + segment + "', must be 0-based integer"); + } + if (absolute) { + segments.shift(); + } + if (segment < 0) { + // allow negative indexes to address from the end + segment = Math.max(segments.length + segment, 0); + } + if (v === undefined) { + return segment === undefined ? segments : segments[segment]; + } else if (segment === null || segments[segment] === undefined) { + if (isArray(v)) { + segments = v; + } else if (v || (typeof v === "string" && v.length)) { + if (segments[segments.length - 1] === "") { + // empty trailing elements have to be overwritten + // to prefent results such as /foo//bar + segments[segments.length - 1] = v; + } else { + segments.push(v); + } + } + } else { + if (v || (typeof v === "string" && v.length)) { + segments[segment] = v; + } else { + segments.splice(segment, 1); + } + } + if (absolute) { + segments.unshift(""); + } + return this.path(segments.join(separator), build); + }; + // mutating query string + var q = p.query; + p.query = function(v, build) { + if (v === true) { + return URI.parseQuery(this._parts.query); + } else if (v !== undefined && typeof v !== "string") { + this._parts.query = URI.buildQuery(v, this._parts.duplicateQueryParameters); + this.build(!build); + return this; + } else { + return q.call(this, v, build); + } + }; + p.addQuery = function(name, value, build) { + var data = URI.parseQuery(this._parts.query); + URI.addQuery(data, name, value === undefined ? null : value); + this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters); + if (typeof name !== "string") { + build = value; + } + this.build(!build); + return this; + }; + p.removeQuery = function(name, value, build) { + var data = URI.parseQuery(this._parts.query); + URI.removeQuery(data, name, value); + this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters); + if (typeof name !== "string") { + build = value; + } + this.build(!build); + return this; + }; + p.addSearch = p.addQuery; + p.removeSearch = p.removeQuery; + // sanitizing URLs + p.normalize = function() { + if (this._parts.urn) { + return this.normalizeProtocol(false).normalizeQuery(false).normalizeFragment(false).build(); + } + return this.normalizeProtocol(false).normalizeHostname(false).normalizePort(false).normalizePath(false).normalizeQuery(false).normalizeFragment(false).build(); + }; + p.normalizeProtocol = function(build) { + if (typeof this._parts.protocol === "string") { + this._parts.protocol = this._parts.protocol.toLowerCase(); + this.build(!build); + } + return this; + }; + p.normalizeHostname = function(build) { + if (this._parts.hostname) { + if (this.is('IDN') && punycode) { + this._parts.hostname = punycode.toASCII(this._parts.hostname); + } else if (this.is('IPv6') && IPv6) { + this._parts.hostname = IPv6.best(this._parts.hostname); + } + this._parts.hostname = this._parts.hostname.toLowerCase(); + this.build(!build); + } + return this; + }; + p.normalizePort = function(build) { + // remove port of it's the protocol's default + if (typeof this._parts.protocol === "string" && this._parts.port === URI.defaultPorts[this._parts.protocol]) { + this._parts.port = null; + this.build(!build); + } + return this; + }; + p.normalizePath = function(build) { + if (this._parts.urn) { + return this; + } + if (!this._parts.path || this._parts.path === '/') { + return this; + } + var _was_relative; + var _was_relative_prefix; + var _path = this._parts.path; + var _parent, _pos; + // handle relative paths + if (_path[0] !== '/') { + if (_path[0] === '.') { + _was_relative_prefix = _path.substring(0, _path.indexOf('/')); + } + _was_relative = true; + _path = '/' + _path; + } + // resolve simples + _path = _path.replace(/(\/(\.\/)+)|\/{2,}/g, '/'); + // resolve parents + while (true) { + _parent = _path.indexOf('/../'); + if (_parent === -1) { + // no more ../ to resolve + break; + } else if (_parent === 0) { + // top level cannot be relative... + _path = _path.substring(3); + break; + } + _pos = _path.substring(0, _parent).lastIndexOf('/'); + if (_pos === -1) { + _pos = _parent; + } + _path = _path.substring(0, _pos) + _path.substring(_parent + 3); + } + // revert to relative + if (_was_relative && this.is('relative')) { + if (_was_relative_prefix) { + _path = _was_relative_prefix + _path; + } else { + _path = _path.substring(1); + } + } + _path = URI.recodePath(_path); + this._parts.path = _path; + this.build(!build); + return this; + }; + p.normalizePathname = p.normalizePath; + p.normalizeQuery = function(build) { + if (typeof this._parts.query === "string") { + if (!this._parts.query.length) { + this._parts.query = null; + } else { + this.query(URI.parseQuery(this._parts.query)); + } + this.build(!build); + } + return this; + }; + p.normalizeFragment = function(build) { + if (!this._parts.fragment) { + this._parts.fragment = null; + this.build(!build); + } + return this; + }; + p.normalizeSearch = p.normalizeQuery; + p.normalizeHash = p.normalizeFragment; + p.iso8859 = function() { + // expect unicode input, iso8859 output + var e = URI.encode; + var d = URI.decode; + URI.encode = escape; + URI.decode = decodeURIComponent; + this.normalize(); + URI.encode = e; + URI.decode = d; + return this; + }; + p.unicode = function() { + // expect iso8859 input, unicode output + var e = URI.encode; + var d = URI.decode; + URI.encode = strictEncodeURIComponent; + URI.decode = unescape; + this.normalize(); + URI.encode = e; + URI.decode = d; + return this; + }; + p.readable = function() { + var uri = this.clone(); + // removing username, password, because they shouldn't be displayed according to RFC 3986 + uri.username("").password("").normalize(); + var t = ''; + if (uri._parts.protocol) { + t += uri._parts.protocol + '://'; + } + if (uri._parts.hostname) { + if (uri.is('punycode') && punycode) { + t += punycode.toUnicode(uri._parts.hostname); + if (uri._parts.port) { + t += ":" + uri._parts.port; + } + } else { + t += uri.host(); + } + } + if (uri._parts.hostname && uri._parts.path && uri._parts.path[0] !== '/') { + t += '/'; + } + t += uri.path(true); + if (uri._parts.query) { + var q = ''; + for (var i = 0, qp = uri._parts.query.split('&'), l = qp.length; i < l; i++) { + var kv = (qp[i] || "").split('='); + q += '&' + URI.decodeQuery(kv[0]).replace(/&/g, '%26'); + if (kv[1] !== undefined) { + q += "=" + URI.decodeQuery(kv[1]).replace(/&/g, '%26'); + } + } + t += '?' + q.substring(1); + } + t += uri.hash(); + return t; + }; + // resolving relative and absolute URLs + p.absoluteTo = function(base) { + var resolved = this.clone(); + var properties = ['protocol', 'username', 'password', 'hostname', 'port']; + var basedir, i, p; + if (this._parts.urn) { + throw new Error('URNs do not have any generally defined hierachical components'); + } + if (this._parts.hostname) { + return resolved; + } + if (!(base instanceof URI)) { + base = new URI(base); + } + for (i = 0, p; p = properties[i]; i++) { + resolved._parts[p] = base._parts[p]; + } + properties = ['query', 'path']; + for (i = 0, p; p = properties[i]; i++) { + if (!resolved._parts[p] && base._parts[p]) { + resolved._parts[p] = base._parts[p]; + } + } + if (resolved.path()[0] !== '/') { + basedir = base.directory(); + resolved._parts.path = (basedir ? (basedir + '/') : '') + resolved._parts.path; + resolved.normalizePath(); + } + resolved.build(); + return resolved; + }; + p.relativeTo = function(base) { + var relative = this.clone(); + var properties = ['protocol', 'username', 'password', 'hostname', 'port']; + var common, _base, _this, _base_diff, _this_diff; + if (this._parts.urn) { + throw new Error('URNs do not have any generally defined hierachical components'); + } + if (!(base instanceof URI)) { + base = new URI(base); + } + if (this.path()[0] !== '/' || base.path()[0] !== '/') { + throw new Error('Cannot calculate common path from non-relative URLs'); + } + // determine common sub path + common = URI.commonPath(relative.path(), base.path()); + // no relation if there's nothing in common + if (!common || common === '/') { + return relative; + } + // relative paths don't have authority + for (var i = 0, p; p = properties[i]; i++) { + relative._parts[p] = null; + } + _base = base.directory(); + _this = this.directory(); + // base and this are on the same level + if (_base === _this) { + relative._parts.path = './' + relative.filename(); + return relative.build(); + } + _base_diff = _base.substring(common.length); + _this_diff = _this.substring(common.length); + // this is a descendant of base + if (_base + '/' === common) { + if (_this_diff) { + _this_diff += '/'; + } + relative._parts.path = './' + _this_diff + relative.filename(); + return relative.build(); + } + // this is a descendant of base + var parents = '../'; + var _common = new RegExp('^' + escapeRegEx(common)); + var _parents = _base.replace(_common, '/').match(/\//g).length - 1; + while (_parents--) { + parents += '../'; + } + relative._parts.path = relative._parts.path.replace(_common, parents); + return relative.build(); + }; + // comparing URIs + p.equals = function(uri) { + var one = this.clone(); + var two = new URI(uri); + var one_map = {}; + var two_map = {}; + var checked = {}; + var one_query, two_query, key; + one.normalize(); + two.normalize(); + // exact match + if (one.toString() === two.toString()) { + return true; + } + // extract query string + one_query = one.query(); + two_query = two.query(); + one.query(""); + two.query(""); + // definitely not equal if not even non-query parts match + if (one.toString() !== two.toString()) { + return false; + } + // query parameters have the same length, even if they're permutated + if (one_query.length !== two_query.length) { + return false; + } + one_map = URI.parseQuery(one_query); + two_map = URI.parseQuery(two_query); + for (key in one_map) { + if (hasOwn.call(one_map, key)) { + if (!isArray(one_map[key])) { + if (one_map[key] !== two_map[key]) { + return false; + } + } else { + if (!isArray(two_map[key])) { + return false; + } + // arrays can't be equal if they have different amount of content + if (one_map[key].length !== two_map[key].length) { + return false; + } + one_map[key].sort(); + two_map[key].sort(); + for (var i = 0, l = one_map[key].length; i < l; i++) { + if (one_map[key][i] !== two_map[key][i]) { + return false; + } + } + } + checked[key] = true; + } + } + for (key in two_map) { + if (hasOwn.call(two_map, key)) { + if (!checked[key]) { + // two contains a parameter not present in one + return false; + } + } + } + return true; + }; + // state + p.duplicateQueryParameters = function(v) { + this._parts.duplicateQueryParameters = !! v; + return this; + }; + return URI; +})); \ No newline at end of file diff --git a/documentation/scripts/bootstrap-dropdown.js b/documentation/scripts/bootstrap-dropdown.js new file mode 100644 index 0000000..d04da5d --- /dev/null +++ b/documentation/scripts/bootstrap-dropdown.js @@ -0,0 +1,169 @@ +/* ============================================================ + * bootstrap-dropdown.js v2.3.2 + * http://getbootstrap.com/2.3.2/javascript.html#dropdowns + * ============================================================ + * Copyright 2013 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* DROPDOWN CLASS DEFINITION + * ========================= */ + + var toggle = '[data-toggle=dropdown]' + , Dropdown = function (element) { + var $el = $(element).on('click.dropdown.data-api', this.toggle) + $('html').on('click.dropdown.data-api', function () { + $el.parent().removeClass('open') + }) + } + + Dropdown.prototype = { + + constructor: Dropdown + + , toggle: function (e) { + var $this = $(this) + , $parent + , isActive + + if ($this.is('.disabled, :disabled')) return + + $parent = getParent($this) + + isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + if ('ontouchstart' in document.documentElement) { + // if mobile we we use a backdrop because click events don't delegate + $('