Spaces:
Sleeping
Sleeping
| /** | |
| * URI.js | |
| * | |
| * @fileoverview An RFC 3986 compliant, scheme extendable URI parsing/validating/resolving library for JavaScript. | |
| * @author <a href="mailto:gary.court@gmail.com">Gary Court</a> | |
| * @version 1.3 | |
| * @see http://github.com/garycourt/uri-js | |
| * @license URI.js v1.3 (c) 2010 Gary Court. License: http://github.com/garycourt/uri-js | |
| */ | |
| /** | |
| * Copyright 2010 Gary Court. All rights reserved. | |
| * | |
| * Redistribution and use in source and binary forms, with or without modification, are | |
| * permitted provided that the following conditions are met: | |
| * | |
| * 1. Redistributions of source code must retain the above copyright notice, this list of | |
| * conditions and the following disclaimer. | |
| * | |
| * 2. Redistributions in binary form must reproduce the above copyright notice, this list | |
| * of conditions and the following disclaimer in the documentation and/or other materials | |
| * provided with the distribution. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY GARY COURT ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
| * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARY COURT OR | |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
| * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
| * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| * | |
| * The views and conclusions contained in the software and documentation are those of the | |
| * authors and should not be interpreted as representing official policies, either expressed | |
| * or implied, of Gary Court. | |
| */ | |
| /*jslint white: true, sub: true, onevar: true, undef: true, eqeqeq: true, newcap: true, immed: true, indent: 4 */ | |
| /*global exports:true, require:true */ | |
| if (typeof exports === "undefined") { | |
| exports = {}; | |
| } | |
| if (typeof require !== "function") { | |
| require = function (id) { | |
| return exports; | |
| }; | |
| } | |
| (function () { | |
| var | |
| /** | |
| * @param {...string} sets | |
| * @return {string} | |
| */ | |
| mergeSet = function (sets) { | |
| var set = arguments[0], | |
| x = 1, | |
| nextSet = arguments[x]; | |
| while (nextSet) { | |
| set = set.slice(0, -1) + nextSet.slice(1); | |
| nextSet = arguments[++x]; | |
| } | |
| return set; | |
| }, | |
| /** | |
| * @param {string} str | |
| * @return {string} | |
| */ | |
| subexp = function (str) { | |
| return "(?:" + str + ")"; | |
| }, | |
| ALPHA$$ = "[A-Za-z]", | |
| CR$ = "[\\x0D]", | |
| DIGIT$$ = "[0-9]", | |
| DQUOTE$$ = "[\\x22]", | |
| HEXDIG$$ = mergeSet(DIGIT$$, "[A-Fa-f]"), //case-insensitive | |
| LF$$ = "[\\x0A]", | |
| SP$$ = "[\\x20]", | |
| PCT_ENCODED$ = subexp("%" + HEXDIG$$ + HEXDIG$$), | |
| GEN_DELIMS$$ = "[\\:\\/\\?\\#\\[\\]\\@]", | |
| SUB_DELIMS$$ = "[\\!\\$\\&\\'\\(\\)\\*\\+\\,\\;\\=]", | |
| RESERVED$$ = mergeSet(GEN_DELIMS$$, SUB_DELIMS$$), | |
| UNRESERVED$$ = mergeSet(ALPHA$$, DIGIT$$, "[\\-\\.\\_\\~]"), | |
| SCHEME$ = subexp(ALPHA$$ + mergeSet(ALPHA$$, DIGIT$$, "[\\+\\-\\.]") + "*"), | |
| USERINFO$ = subexp(subexp(PCT_ENCODED$ + "|" + mergeSet(UNRESERVED$$, SUB_DELIMS$$, "[\\:]")) + "*"), | |
| DEC_OCTET$ = subexp(subexp("25[0-5]") + "|" + subexp("2[0-4]" + DIGIT$$) + "|" + subexp("1" + DIGIT$$ + DIGIT$$) + "|" + subexp("[1-9]" + DIGIT$$) + "|" + DIGIT$$), | |
| IPV4ADDRESS$ = subexp(DEC_OCTET$ + "\\." + DEC_OCTET$ + "\\." + DEC_OCTET$ + "\\." + DEC_OCTET$), | |
| H16$ = subexp(HEXDIG$$ + "{1,4}"), | |
| LS32$ = subexp(subexp(H16$ + "\\:" + H16$) + "|" + IPV4ADDRESS$), | |
| IPV6ADDRESS$ = subexp(mergeSet(UNRESERVED$$, SUB_DELIMS$$, "[\\:]") + "+"), //FIXME | |
| IPVFUTURE$ = subexp("v" + HEXDIG$$ + "+\\." + mergeSet(UNRESERVED$$, SUB_DELIMS$$, "[\\:]") + "+"), | |
| IP_LITERAL$ = subexp("\\[" + subexp(IPV6ADDRESS$ + "|" + IPVFUTURE$) + "\\]"), | |
| REG_NAME$ = subexp(subexp(PCT_ENCODED$ + "|" + mergeSet(UNRESERVED$$, SUB_DELIMS$$)) + "*"), | |
| HOST$ = subexp(IP_LITERAL$ + "|" + IPV4ADDRESS$ + "|" + REG_NAME$), | |
| PORT$ = subexp(DIGIT$$ + "*"), | |
| AUTHORITY$ = subexp(subexp(USERINFO$ + "@") + "?" + HOST$ + subexp("\\:" + PORT$) + "?"), | |
| PCHAR$ = subexp(PCT_ENCODED$ + "|" + mergeSet(UNRESERVED$$, SUB_DELIMS$$, "[\\:\\@]")), | |
| SEGMENT$ = subexp(PCHAR$ + "*"), | |
| SEGMENT_NZ$ = subexp(PCHAR$ + "+"), | |
| SEGMENT_NZ_NC$ = subexp(subexp(PCT_ENCODED$ + "|" + mergeSet(UNRESERVED$$, SUB_DELIMS$$, "[\\@]")) + "+"), | |
| PATH_ABEMPTY$ = subexp(subexp("\\/" + SEGMENT$) + "*"), | |
| PATH_ABSOLUTE$ = subexp("\\/" + subexp(SEGMENT_NZ$ + PATH_ABEMPTY$) + "?"), //simplified | |
| PATH_NOSCHEME$ = subexp(SEGMENT_NZ_NC$ + PATH_ABEMPTY$), //simplified | |
| PATH_ROOTLESS$ = subexp(SEGMENT_NZ$ + PATH_ABEMPTY$), //simplified | |
| PATH_EMPTY$ = subexp(""), //simplified | |
| PATH$ = subexp(PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_NOSCHEME$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$), | |
| QUERY$ = subexp(subexp(PCHAR$ + "|[\\/\\?]") + "*"), | |
| FRAGMENT$ = subexp(subexp(PCHAR$ + "|[\\/\\?]") + "*"), | |
| HIER_PART$ = subexp(subexp("\\/\\/" + AUTHORITY$ + PATH_ABEMPTY$) + "|" + PATH_ABSOLUTE$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$), | |
| URI$ = subexp(SCHEME$ + "\\:" + HIER_PART$ + subexp("\\?" + QUERY$) + "?" + subexp("\\#" + FRAGMENT$) + "?"), | |
| RELATIVE_PART$ = subexp(subexp("\\/\\/" + AUTHORITY$ + PATH_ABEMPTY$) + "|" + PATH_ABSOLUTE$ + "|" + PATH_NOSCHEME$ + "|" + PATH_EMPTY$), | |
| RELATIVE_REF$ = subexp(RELATIVE_PART$ + subexp("\\?" + QUERY$) + "?" + subexp("\\#" + FRAGMENT$) + "?"), | |
| URI_REFERENCE$ = subexp(URI$ + "|" + RELATIVE_REF$), | |
| ABSOLUTE_URI$ = subexp(SCHEME$ + "\\:" + HIER_PART$ + subexp("\\?" + QUERY$) + "?"), | |
| URI_REF = new RegExp("^" + subexp("(" + URI$ + ")|(" + RELATIVE_REF$ + ")") + "$"), | |
| GENERIC_REF = new RegExp("^(" + SCHEME$ + ")\\:" + subexp(subexp("\\/\\/(" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?)") + "?(" + PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$ + ")") + subexp("\\?(" + QUERY$ + ")") + "?" + subexp("\\#(" + FRAGMENT$ + ")") + "?$"), | |
| RELATIVE_REF = new RegExp("^(){0}" + subexp(subexp("\\/\\/(" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?)") + "?(" + PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_NOSCHEME$ + "|" + PATH_EMPTY$ + ")") + subexp("\\?(" + QUERY$ + ")") + "?" + subexp("\\#(" + FRAGMENT$ + ")") + "?$"), | |
| ABSOLUTE_REF = new RegExp("^(" + SCHEME$ + ")\\:" + subexp(subexp("\\/\\/(" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?)") + "?(" + PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$ + ")") + subexp("\\?(" + QUERY$ + ")") + "?$"), | |
| SAMEDOC_REF = new RegExp("^" + subexp("\\#(" + FRAGMENT$ + ")") + "?$"), | |
| AUTHORITY = new RegExp("^" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?$"), | |
| NOT_SCHEME = new RegExp(mergeSet("[^]", ALPHA$$, DIGIT$$, "[\\+\\-\\.]"), "g"), | |
| NOT_USERINFO = new RegExp(mergeSet("[^\\%\\:]", UNRESERVED$$, SUB_DELIMS$$), "g"), | |
| NOT_HOST = new RegExp(mergeSet("[^\\%]", UNRESERVED$$, SUB_DELIMS$$), "g"), | |
| NOT_PATH = new RegExp(mergeSet("[^\\%\\/\\:\\@]", UNRESERVED$$, SUB_DELIMS$$), "g"), | |
| NOT_PATH_NOSCHEME = new RegExp(mergeSet("[^\\%\\/\\@]", UNRESERVED$$, SUB_DELIMS$$), "g"), | |
| NOT_QUERY = new RegExp(mergeSet("[^\\%]", UNRESERVED$$, SUB_DELIMS$$, "[\\:\\@\\/\\?]"), "g"), | |
| NOT_FRAGMENT = NOT_QUERY, | |
| ESCAPE = new RegExp(mergeSet("[^]", UNRESERVED$$, SUB_DELIMS$$), "g"), | |
| UNRESERVED = new RegExp(UNRESERVED$$, "g"), | |
| OTHER_CHARS = new RegExp(mergeSet("[^\\%]", UNRESERVED$$, RESERVED$$), "g"), | |
| PCT_ENCODEDS = new RegExp(PCT_ENCODED$ + "+", "g"), | |
| URI_PARSE = /^(?:([^:\/?#]+):)?(?:\/\/((?:([^\/?#@]*)@)?([^\/?#:]*)(?:\:(\d*))?))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?/i, | |
| RDS1 = /^\.\.?\//, | |
| RDS2 = /^\/\.(\/|$)/, | |
| RDS3 = /^\/\.\.(\/|$)/, | |
| RDS4 = /^\.\.?$/, | |
| RDS5 = /^\/?.*?(?=\/|$)/, | |
| NO_MATCH_IS_UNDEFINED = ("").match(/(){0}/)[1] === undefined, | |
| /** | |
| * @param {string} chr | |
| * @return {string} | |
| */ | |
| pctEncChar = function (chr) { | |
| var c = chr.charCodeAt(0); | |
| if (c < 128) { | |
| return "%" + c.toString(16).toUpperCase(); | |
| } | |
| else if ((c > 127) && (c < 2048)) { | |
| return "%" + ((c >> 6) | 192).toString(16).toUpperCase() + "%" + ((c & 63) | 128).toString(16).toUpperCase(); | |
| } | |
| else { | |
| return "%" + ((c >> 12) | 224).toString(16).toUpperCase() + "%" + (((c >> 6) & 63) | 128).toString(16).toUpperCase() + "%" + ((c & 63) | 128).toString(16).toUpperCase(); | |
| } | |
| }, | |
| /** | |
| * @param {string} str | |
| * @return {string} | |
| */ | |
| pctDecUnreserved = function (str) { | |
| var newStr = "", | |
| i = 0, | |
| c, s; | |
| while (i < str.length) { | |
| c = parseInt(str.substr(i + 1, 2), 16); | |
| if (c < 128) { | |
| s = String.fromCharCode(c); | |
| if (s.match(UNRESERVED)) { | |
| newStr += s; | |
| } else { | |
| newStr += str.substr(i, 3); | |
| } | |
| i += 3; | |
| } | |
| else if ((c > 191) && (c < 224)) { | |
| newStr += str.substr(i, 6); | |
| i += 6; | |
| } | |
| else { | |
| newStr += str.substr(i, 9); | |
| i += 9; | |
| } | |
| } | |
| return newStr; | |
| }, | |
| /** | |
| * @param {string} str | |
| * @return {string} | |
| */ | |
| pctDecChars = function (str) { | |
| var newStr = "", | |
| i = 0, | |
| c, c2, c3; | |
| while (i < str.length) { | |
| c = parseInt(str.substr(i + 1, 2), 16); | |
| if (c < 128) { | |
| newStr += String.fromCharCode(c); | |
| i += 3; | |
| } | |
| else if ((c > 191) && (c < 224)) { | |
| c2 = parseInt(str.substr(i + 4, 2), 16); | |
| newStr += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); | |
| i += 6; | |
| } | |
| else { | |
| c2 = parseInt(str.substr(i + 4, 2), 16); | |
| c3 = parseInt(str.substr(i + 7, 2), 16); | |
| newStr += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); | |
| i += 9; | |
| } | |
| } | |
| return newStr; | |
| }, | |
| /** | |
| * @return {string} | |
| */ | |
| typeOf = function (o) { | |
| return o === undefined ? "undefined" : (o === null ? "null" : Object.prototype.toString.call(o).split(" ").pop().split("]").shift().toLowerCase()); | |
| }, | |
| /** | |
| * @constructor | |
| * @implements URIComponents | |
| */ | |
| Components = function () { | |
| this.errors = []; | |
| }, | |
| /** @namespace */ | |
| URI = exports; | |
| /** | |
| * Components | |
| */ | |
| Components.prototype = { | |
| /** | |
| * @type String | |
| */ | |
| scheme : undefined, | |
| /** | |
| * @type String | |
| */ | |
| authority : undefined, | |
| /** | |
| * @type String | |
| */ | |
| userinfo : undefined, | |
| /** | |
| * @type String | |
| */ | |
| host : undefined, | |
| /** | |
| * @type number | |
| */ | |
| port : undefined, | |
| /** | |
| * @type string | |
| */ | |
| path : undefined, | |
| /** | |
| * @type string | |
| */ | |
| query : undefined, | |
| /** | |
| * @type string | |
| */ | |
| fragment : undefined, | |
| /** | |
| * @type string | |
| * @values "uri", "absolute", "relative", "same-document" | |
| */ | |
| reference : undefined, | |
| /** | |
| * @type Array | |
| */ | |
| errors : undefined | |
| }; | |
| /** | |
| * URI | |
| */ | |
| /** | |
| * @namespace | |
| */ | |
| URI.SCHEMES = {}; | |
| /** | |
| * @param {string} uriString | |
| * @param {Options} [options] | |
| * @returns {URIComponents} | |
| */ | |
| URI.parse = function (uriString, options) { | |
| var matches, | |
| components = new Components(), | |
| schemeHandler; | |
| uriString = uriString ? uriString.toString() : ""; | |
| options = options || {}; | |
| if (options.reference === "suffix") { | |
| uriString = (options.scheme ? options.scheme + ":" : "") + "//" + uriString; | |
| } | |
| matches = uriString.match(URI_REF); | |
| if (matches) { | |
| if (matches[1]) { | |
| //generic URI | |
| matches = uriString.match(GENERIC_REF); | |
| } else { | |
| //relative URI | |
| matches = uriString.match(RELATIVE_REF); | |
| } | |
| } | |
| if (!matches) { | |
| if (!options.tolerant) { | |
| components.errors.push("URI is not strictly valid."); | |
| } | |
| matches = uriString.match(URI_PARSE); | |
| } | |
| if (matches) { | |
| if (NO_MATCH_IS_UNDEFINED) { | |
| //store each component | |
| components.scheme = matches[1]; | |
| components.authority = matches[2]; | |
| components.userinfo = matches[3]; | |
| components.host = matches[4]; | |
| components.port = parseInt(matches[5], 10); | |
| components.path = matches[6] || ""; | |
| components.query = matches[7]; | |
| components.fragment = matches[8]; | |
| //fix port number | |
| if (isNaN(components.port)) { | |
| components.port = matches[5]; | |
| } | |
| } else { //IE FIX for improper RegExp matching | |
| //store each component | |
| components.scheme = matches[1] || undefined; | |
| components.authority = (uriString.indexOf("//") !== -1 ? matches[2] : undefined); | |
| components.userinfo = (uriString.indexOf("@") !== -1 ? matches[3] : undefined); | |
| components.host = (uriString.indexOf("//") !== -1 ? matches[4] : undefined); | |
| components.port = parseInt(matches[5], 10); | |
| components.path = matches[6] || ""; | |
| components.query = (uriString.indexOf("?") !== -1 ? matches[7] : undefined); | |
| components.fragment = (uriString.indexOf("#") !== -1 ? matches[8] : undefined); | |
| //fix port number | |
| if (isNaN(components.port)) { | |
| components.port = (uriString.match(/\/\/.*\:(?:\/|\?|\#|$)/) ? matches[4] : undefined); | |
| } | |
| } | |
| //determine reference type | |
| if (!components.scheme && !components.authority && !components.path && !components.query) { | |
| components.reference = "same-document"; | |
| } else if (!components.scheme) { | |
| components.reference = "relative"; | |
| } else if (!components.fragment) { | |
| components.reference = "absolute"; | |
| } else { | |
| components.reference = "uri"; | |
| } | |
| //check for reference errors | |
| if (options.reference && options.reference !== "suffix" && options.reference !== components.reference) { | |
| components.errors.push("URI is not a " + options.reference + " reference."); | |
| } | |
| //check if a handler for the scheme exists | |
| schemeHandler = URI.SCHEMES[(components.scheme || options.scheme || "").toLowerCase()]; | |
| if (schemeHandler && schemeHandler.parse) { | |
| //perform extra parsing | |
| schemeHandler.parse(components, options); | |
| } | |
| } else { | |
| components.errors.push("URI can not be parsed."); | |
| } | |
| return components; | |
| }; | |
| /** | |
| * @private | |
| * @param {URIComponents} components | |
| * @returns {string|undefined} | |
| */ | |
| URI._recomposeAuthority = function (components) { | |
| var uriTokens = []; | |
| if (components.userinfo !== undefined || components.host !== undefined || typeof components.port === "number") { | |
| if (components.userinfo !== undefined) { | |
| uriTokens.push(components.userinfo.toString().replace(NOT_USERINFO, pctEncChar)); | |
| uriTokens.push("@"); | |
| } | |
| if (components.host !== undefined) { | |
| uriTokens.push(components.host.toString().toLowerCase().replace(NOT_HOST, pctEncChar)); | |
| } | |
| if (typeof components.port === "number") { | |
| uriTokens.push(":"); | |
| uriTokens.push(components.port.toString(10)); | |
| } | |
| } | |
| return uriTokens.length ? uriTokens.join("") : undefined; | |
| }; | |
| /** | |
| * @param {string} input | |
| * @returns {string} | |
| */ | |
| URI.removeDotSegments = function (input) { | |
| var output = [], s; | |
| while (input.length) { | |
| if (input.match(RDS1)) { | |
| input = input.replace(RDS1, ""); | |
| } else if (input.match(RDS2)) { | |
| input = input.replace(RDS2, "/"); | |
| } else if (input.match(RDS3)) { | |
| input = input.replace(RDS3, "/"); | |
| output.pop(); | |
| } else if (input === "." || input === "..") { | |
| input = ""; | |
| } else { | |
| s = input.match(RDS5)[0]; | |
| input = input.slice(s.length); | |
| output.push(s); | |
| } | |
| } | |
| return output.join(""); | |
| }; | |
| /** | |
| * @param {URIComponents} components | |
| * @param {Options} [options] | |
| * @returns {string} | |
| */ | |
| URI.serialize = function (components, options) { | |
| var uriTokens = [], | |
| schemeHandler, | |
| s; | |
| options = options || {}; | |
| //check if a handler for the scheme exists | |
| schemeHandler = URI.SCHEMES[components.scheme || options.scheme]; | |
| if (schemeHandler && schemeHandler.serialize) { | |
| //perform extra serialization | |
| schemeHandler.serialize(components, options); | |
| } | |
| if (options.reference !== "suffix" && components.scheme) { | |
| uriTokens.push(components.scheme.toString().toLowerCase().replace(NOT_SCHEME, "")); | |
| uriTokens.push(":"); | |
| } | |
| components.authority = URI._recomposeAuthority(components); | |
| if (components.authority !== undefined) { | |
| if (options.reference !== "suffix") { | |
| uriTokens.push("//"); | |
| } | |
| uriTokens.push(components.authority); | |
| if (components.path && components.path.charAt(0) !== "/") { | |
| uriTokens.push("/"); | |
| } | |
| } | |
| if (components.path) { | |
| s = URI.removeDotSegments(components.path.toString().replace(/%2E/ig, ".")); | |
| if (components.scheme) { | |
| s = s.replace(NOT_PATH, pctEncChar); | |
| } else { | |
| s = s.replace(NOT_PATH_NOSCHEME, pctEncChar); | |
| } | |
| if (components.authority === undefined) { | |
| s = s.replace(/^\/\//, "/%2F"); //don't allow the path to start with "//" | |
| } | |
| uriTokens.push(s); | |
| } | |
| if (components.query) { | |
| uriTokens.push("?"); | |
| uriTokens.push(components.query.toString().replace(NOT_QUERY, pctEncChar)); | |
| } | |
| if (components.fragment) { | |
| uriTokens.push("#"); | |
| uriTokens.push(components.fragment.toString().replace(NOT_FRAGMENT, pctEncChar)); | |
| } | |
| return uriTokens | |
| .join('') //merge tokens into a string | |
| .replace(PCT_ENCODEDS, pctDecUnreserved) //undecode unreserved characters | |
| //.replace(OTHER_CHARS, pctEncChar) //replace non-URI characters | |
| .replace(/%[0-9A-Fa-f]{2}/g, function (str) { //uppercase percent encoded characters | |
| return str.toUpperCase(); | |
| }) | |
| ; | |
| }; | |
| /** | |
| * @param {URIComponents} base | |
| * @param {URIComponents} relative | |
| * @param {Options} [options] | |
| * @param {boolean} [skipNormalization] | |
| * @returns {URIComponents} | |
| */ | |
| URI.resolveComponents = function (base, relative, options, skipNormalization) { | |
| var target = new Components(); | |
| if (!skipNormalization) { | |
| base = URI.parse(URI.serialize(base, options), options); //normalize base components | |
| relative = URI.parse(URI.serialize(relative, options), options); //normalize relative components | |
| } | |
| options = options || {}; | |
| if (!options.tolerant && relative.scheme) { | |
| target.scheme = relative.scheme; | |
| target.authority = relative.authority; | |
| target.userinfo = relative.userinfo; | |
| target.host = relative.host; | |
| target.port = relative.port; | |
| target.path = URI.removeDotSegments(relative.path); | |
| target.query = relative.query; | |
| } else { | |
| if (relative.authority !== undefined) { | |
| target.authority = relative.authority; | |
| target.userinfo = relative.userinfo; | |
| target.host = relative.host; | |
| target.port = relative.port; | |
| target.path = URI.removeDotSegments(relative.path); | |
| target.query = relative.query; | |
| } else { | |
| if (!relative.path) { | |
| target.path = base.path; | |
| if (relative.query !== undefined) { | |
| target.query = relative.query; | |
| } else { | |
| target.query = base.query; | |
| } | |
| } else { | |
| if (relative.path.charAt(0) === "/") { | |
| target.path = URI.removeDotSegments(relative.path); | |
| } else { | |
| if (base.authority !== undefined && !base.path) { | |
| target.path = "/" + relative.path; | |
| } else if (!base.path) { | |
| target.path = relative.path; | |
| } else { | |
| target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative.path; | |
| } | |
| target.path = URI.removeDotSegments(target.path); | |
| } | |
| target.query = relative.query; | |
| } | |
| target.authority = base.authority; | |
| target.userinfo = base.userinfo; | |
| target.host = base.host; | |
| target.port = base.port; | |
| } | |
| target.scheme = base.scheme; | |
| } | |
| target.fragment = relative.fragment; | |
| return target; | |
| }; | |
| /** | |
| * @param {string} baseURI | |
| * @param {string} relativeURI | |
| * @param {Options} [options] | |
| * @returns {string} | |
| */ | |
| URI.resolve = function (baseURI, relativeURI, options) { | |
| return URI.serialize(URI.resolveComponents(URI.parse(baseURI, options), URI.parse(relativeURI, options), options, true), options); | |
| }; | |
| /** | |
| * @param {string|URIComponents} uri | |
| * @param {Options} options | |
| * @returns {string|URIComponents} | |
| */ | |
| URI.normalize = function (uri, options) { | |
| if (typeof uri === "string") { | |
| return URI.serialize(URI.parse(uri, options), options); | |
| } else if (typeOf(uri) === "object") { | |
| return URI.parse(URI.serialize(uri, options), options); | |
| } | |
| return uri; | |
| }; | |
| /** | |
| * @param {string|URIComponents} uriA | |
| * @param {string|URIComponents} uriB | |
| * @param {Options} options | |
| */ | |
| URI.equal = function (uriA, uriB, options) { | |
| if (typeof uriA === "string") { | |
| uriA = URI.serialize(URI.parse(uriA, options), options); | |
| } else if (typeOf(uriA) === "object") { | |
| uriA = URI.serialize(uriA, options); | |
| } | |
| if (typeof uriB === "string") { | |
| uriB = URI.serialize(URI.parse(uriB, options), options); | |
| } else if (typeOf(uriB) === "object") { | |
| uriB = URI.serialize(uriB, options); | |
| } | |
| return uriA === uriB; | |
| }; | |
| /** | |
| * @param {string} str | |
| * @returns {string} | |
| */ | |
| URI.escapeComponent = function (str) { | |
| return str && str.toString().replace(ESCAPE, pctEncChar); | |
| }; | |
| /** | |
| * @param {string} str | |
| * @returns {string} | |
| */ | |
| URI.unescapeComponent = function (str) { | |
| return str && str.toString().replace(PCT_ENCODEDS, pctDecChars); | |
| }; | |
| //export API | |
| exports.pctEncChar = pctEncChar; | |
| exports.pctDecChars = pctDecChars; | |
| exports.Components = Components; | |
| exports.URI = URI; | |
| //name-safe export API | |
| exports["pctEncChar"] = pctEncChar; | |
| exports["pctDecChars"] = pctDecChars; | |
| exports["Components"] = Components; | |
| exports["URI"] = { | |
| "SCHEMES" : URI.SCHEMES, | |
| "parse" : URI.parse, | |
| "removeDotSegments" : URI.removeDotSegments, | |
| "serialize" : URI.serialize, | |
| "resolveComponents" : URI.resolveComponents, | |
| "resolve" : URI.resolve, | |
| "normalize" : URI.normalize, | |
| "equal" : URI.equal, | |
| "escapeComponent" : URI.escapeComponent, | |
| "unescapeComponent" : URI.unescapeComponent | |
| }; | |
| }()); |