toad-uri-js
Version:
A modern RFC 3986/3987 compliant, scheme extendable URI/IRI parsing/normalizing/resolving/serializing library for JavaScript.
849 lines (835 loc) • 35.7 kB
JavaScript
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
// src/uri.ts
import punycode from "punycode/";
// src/util.ts
function merge(...sets) {
if (sets.length > 1) {
sets[0] = sets[0].slice(0, -1);
const xl = sets.length - 1;
for (let x = 1; x < xl; ++x) {
sets[x] = sets[x].slice(1, -1);
}
sets[xl] = sets[xl].slice(1);
return sets.join("");
} else {
return sets[0];
}
}
__name(merge, "merge");
function subexp(str) {
return "(?:" + str + ")";
}
__name(subexp, "subexp");
function typeOf(o) {
return o === void 0 ? "undefined" : o === null ? "null" : Object.prototype.toString.call(o).split(" ").pop().split("]").shift().toLowerCase();
}
__name(typeOf, "typeOf");
function toUpperCase(str) {
return str.toUpperCase();
}
__name(toUpperCase, "toUpperCase");
function toArray(obj) {
return obj !== void 0 && obj !== null ? Array.isArray(obj) ? obj : typeof obj.length !== "number" || obj.split || obj.setInterval || obj.call ? [obj] : Array.prototype.slice.call(obj) : [];
}
__name(toArray, "toArray");
function assign(target, source) {
const obj = target;
if (source) {
for (const key in source) {
obj[key] = source[key];
}
}
return obj;
}
__name(assign, "assign");
// src/regexps-uri.ts
function buildExps(isIRI2) {
const ALPHA$$ = "[A-Za-z]", CR$ = "[\\x0D]", DIGIT$$ = "[0-9]", DQUOTE$$ = "[\\x22]", HEXDIG$$2 = merge(DIGIT$$, "[A-Fa-f]"), LF$$ = "[\\x0A]", SP$$ = "[\\x20]", PCT_ENCODED$3 = subexp(
subexp("%[EFef]" + HEXDIG$$2 + "%" + HEXDIG$$2 + HEXDIG$$2 + "%" + HEXDIG$$2 + HEXDIG$$2) + "|" + subexp("%[89A-Fa-f]" + HEXDIG$$2 + "%" + HEXDIG$$2 + HEXDIG$$2) + "|" + subexp("%" + HEXDIG$$2 + HEXDIG$$2)
), GEN_DELIMS$$ = "[\\:\\/\\?\\#\\[\\]\\@]", SUB_DELIMS$$ = "[\\!\\$\\&\\'\\(\\)\\*\\+\\,\\;\\=]", RESERVED$$ = merge(GEN_DELIMS$$, SUB_DELIMS$$), UCSCHAR$$ = isIRI2 ? "[\\xA0-\\u200D\\u2010-\\u2029\\u202F-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]" : "[]", IPRIVATE$$ = isIRI2 ? "[\\uE000-\\uF8FF]" : "[]", UNRESERVED$$2 = merge(ALPHA$$, DIGIT$$, "[\\-\\.\\_\\~]", UCSCHAR$$), SCHEME$ = subexp(ALPHA$$ + merge(ALPHA$$, DIGIT$$, "[\\+\\-\\.]") + "*"), USERINFO$ = subexp(
subexp(PCT_ENCODED$3 + "|" + merge(UNRESERVED$$2, SUB_DELIMS$$, "[\\:]")) + "*"
), DEC_OCTET$ = subexp(
subexp("25[0-5]") + "|" + subexp("2[0-4]" + DIGIT$$) + "|" + subexp("1" + DIGIT$$ + DIGIT$$) + "|" + subexp("[1-9]" + DIGIT$$) + "|" + DIGIT$$
), DEC_OCTET_RELAXED$ = subexp(
subexp("25[0-5]") + "|" + subexp("2[0-4]" + DIGIT$$) + "|" + subexp("1" + DIGIT$$ + DIGIT$$) + "|" + subexp("0?[1-9]" + DIGIT$$) + "|0?0?" + DIGIT$$
), IPV4ADDRESS$ = subexp(
DEC_OCTET_RELAXED$ + "\\." + DEC_OCTET_RELAXED$ + "\\." + DEC_OCTET_RELAXED$ + "\\." + DEC_OCTET_RELAXED$
), H16$ = subexp(HEXDIG$$2 + "{1,4}"), LS32$ = subexp(subexp(H16$ + "\\:" + H16$) + "|" + IPV4ADDRESS$), IPV6ADDRESS1$ = subexp(subexp(H16$ + "\\:") + "{6}" + LS32$), IPV6ADDRESS2$ = subexp("\\:\\:" + subexp(H16$ + "\\:") + "{5}" + LS32$), IPV6ADDRESS3$ = subexp(subexp(H16$) + "?\\:\\:" + subexp(H16$ + "\\:") + "{4}" + LS32$), IPV6ADDRESS4$ = subexp(
subexp(subexp(H16$ + "\\:") + "{0,1}" + H16$) + "?\\:\\:" + subexp(H16$ + "\\:") + "{3}" + LS32$
), IPV6ADDRESS5$ = subexp(
subexp(subexp(H16$ + "\\:") + "{0,2}" + H16$) + "?\\:\\:" + subexp(H16$ + "\\:") + "{2}" + LS32$
), IPV6ADDRESS6$ = subexp(
subexp(subexp(H16$ + "\\:") + "{0,3}" + H16$) + "?\\:\\:" + H16$ + "\\:" + LS32$
), IPV6ADDRESS7$ = subexp(subexp(subexp(H16$ + "\\:") + "{0,4}" + H16$) + "?\\:\\:" + LS32$), IPV6ADDRESS8$ = subexp(subexp(subexp(H16$ + "\\:") + "{0,5}" + H16$) + "?\\:\\:" + H16$), IPV6ADDRESS9$ = subexp(subexp(subexp(H16$ + "\\:") + "{0,6}" + H16$) + "?\\:\\:"), IPV6ADDRESS$ = subexp(
[
IPV6ADDRESS1$,
IPV6ADDRESS2$,
IPV6ADDRESS3$,
IPV6ADDRESS4$,
IPV6ADDRESS5$,
IPV6ADDRESS6$,
IPV6ADDRESS7$,
IPV6ADDRESS8$,
IPV6ADDRESS9$
].join("|")
), ZONEID$ = subexp(subexp(UNRESERVED$$2 + "|" + PCT_ENCODED$3) + "+"), IPV6ADDRZ$ = subexp(IPV6ADDRESS$ + "\\%25" + ZONEID$), IPV6ADDRZ_RELAXED$ = subexp(
IPV6ADDRESS$ + subexp("\\%25|\\%(?!" + HEXDIG$$2 + "{2})") + ZONEID$
), IPVFUTURE$ = subexp(
"[vV]" + HEXDIG$$2 + "+\\." + merge(UNRESERVED$$2, SUB_DELIMS$$, "[\\:]") + "+"
), IP_LITERAL$ = subexp(
"\\[" + subexp(IPV6ADDRZ_RELAXED$ + "|" + IPV6ADDRESS$ + "|" + IPVFUTURE$) + "\\]"
), REG_NAME$ = subexp(subexp(PCT_ENCODED$3 + "|" + merge(UNRESERVED$$2, SUB_DELIMS$$)) + "*"), HOST$ = subexp(IP_LITERAL$ + "|" + IPV4ADDRESS$ + "(?!" + REG_NAME$ + ")|" + REG_NAME$), PORT$ = subexp(DIGIT$$ + "*"), AUTHORITY$ = subexp(subexp(USERINFO$ + "@") + "?" + HOST$ + subexp("\\:" + PORT$) + "?"), PCHAR$ = subexp(PCT_ENCODED$3 + "|" + merge(UNRESERVED$$2, SUB_DELIMS$$, "[\\:\\@]")), SEGMENT$ = subexp(PCHAR$ + "*"), SEGMENT_NZ$ = subexp(PCHAR$ + "+"), SEGMENT_NZ_NC$ = subexp(
subexp(PCT_ENCODED$3 + "|" + merge(UNRESERVED$$2, SUB_DELIMS$$, "[\\@]")) + "+"
), PATH_ABEMPTY$ = subexp(subexp("\\/" + SEGMENT$) + "*"), PATH_ABSOLUTE$ = subexp("\\/" + subexp(SEGMENT_NZ$ + PATH_ABEMPTY$) + "?"), PATH_NOSCHEME$ = subexp(SEGMENT_NZ_NC$ + PATH_ABEMPTY$), PATH_ROOTLESS$ = subexp(SEGMENT_NZ$ + PATH_ABEMPTY$), PATH_EMPTY$ = "(?!" + PCHAR$ + ")", PATH$ = subexp(
PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_NOSCHEME$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$
), QUERY$ = subexp(subexp(PCHAR$ + "|" + merge("[\\/\\?]", IPRIVATE$$)) + "*"), 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$ = subexp(
RELATIVE_PART$ + subexp("\\?" + QUERY$) + "?" + subexp("\\#" + FRAGMENT$) + "?"
), URI_REFERENCE$ = subexp(URI$ + "|" + RELATIVE$), ABSOLUTE_URI$ = subexp(SCHEME$ + "\\:" + HIER_PART$ + subexp("\\?" + QUERY$) + "?"), GENERIC_REF$ = "^(" + SCHEME$ + ")\\:" + subexp(
subexp(
"\\/\\/(" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?)"
) + "?(" + PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$ + ")"
) + subexp("\\?(" + QUERY$ + ")") + "?" + subexp("\\#(" + FRAGMENT$ + ")") + "?$", RELATIVE_REF$ = "^(){0}" + subexp(
subexp(
"\\/\\/(" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?)"
) + "?(" + PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_NOSCHEME$ + "|" + PATH_EMPTY$ + ")"
) + subexp("\\?(" + QUERY$ + ")") + "?" + subexp("\\#(" + FRAGMENT$ + ")") + "?$", ABSOLUTE_REF$ = "^(" + SCHEME$ + ")\\:" + subexp(
subexp(
"\\/\\/(" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?)"
) + "?(" + PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$ + ")"
) + subexp("\\?(" + QUERY$ + ")") + "?$", SAMEDOC_REF$ = "^" + subexp("\\#(" + FRAGMENT$ + ")") + "?$", AUTHORITY_REF$ = "^" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?$";
return {
NOT_SCHEME: new RegExp(merge("[^]", ALPHA$$, DIGIT$$, "[\\+\\-\\.]"), "g"),
NOT_USERINFO: new RegExp(merge("[^\\%\\:]", UNRESERVED$$2, SUB_DELIMS$$), "g"),
NOT_HOST: new RegExp(merge("[^\\%\\[\\]\\:]", UNRESERVED$$2, SUB_DELIMS$$), "g"),
NOT_PATH: new RegExp(merge("[^\\%\\/\\:\\@]", UNRESERVED$$2, SUB_DELIMS$$), "g"),
NOT_PATH_NOSCHEME: new RegExp(merge("[^\\%\\/\\@]", UNRESERVED$$2, SUB_DELIMS$$), "g"),
NOT_QUERY: new RegExp(
merge("[^\\%]", UNRESERVED$$2, SUB_DELIMS$$, "[\\:\\@\\/\\?]", IPRIVATE$$),
"g"
),
NOT_FRAGMENT: new RegExp(merge("[^\\%]", UNRESERVED$$2, SUB_DELIMS$$, "[\\:\\@\\/\\?]"), "g"),
ESCAPE: new RegExp(merge("[^]", UNRESERVED$$2, SUB_DELIMS$$), "g"),
UNRESERVED: new RegExp(UNRESERVED$$2, "g"),
OTHER_CHARS: new RegExp(merge("[^\\%]", UNRESERVED$$2, RESERVED$$), "g"),
PCT_ENCODED: new RegExp(PCT_ENCODED$3, "g"),
IPV4ADDRESS: new RegExp("^(" + IPV4ADDRESS$ + ")$"),
IPV6ADDRESS: new RegExp(
"^\\[?(" + IPV6ADDRESS$ + ")" + subexp(subexp("\\%25|\\%(?!" + HEXDIG$$2 + "{2})") + "(" + ZONEID$ + ")") + "?\\]?$"
)
//RFC 6874, with relaxed parsing rules
};
}
__name(buildExps, "buildExps");
var regexps_uri_default = buildExps(false);
// src/regexps-iri.ts
var regexps_iri_default = buildExps(true);
// src/uri.ts
var SCHEMES = {};
function pctEncChar(chr) {
const c = chr.charCodeAt(0);
let e;
if (c < 16)
e = "%0" + c.toString(16).toUpperCase();
else if (c < 128)
e = "%" + c.toString(16).toUpperCase();
else if (c < 2048)
e = "%" + (c >> 6 | 192).toString(16).toUpperCase() + "%" + (c & 63 | 128).toString(16).toUpperCase();
else
e = "%" + (c >> 12 | 224).toString(16).toUpperCase() + "%" + (c >> 6 & 63 | 128).toString(16).toUpperCase() + "%" + (c & 63 | 128).toString(16).toUpperCase();
return e;
}
__name(pctEncChar, "pctEncChar");
function pctDecChars(str) {
let newStr = "";
let i = 0;
const il = str.length;
while (i < il) {
const c = parseInt(str.substr(i + 1, 2), 16);
if (c < 128) {
newStr += String.fromCharCode(c);
i += 3;
} else if (c >= 194 && c < 224) {
if (il - i >= 6) {
const c2 = parseInt(str.substr(i + 4, 2), 16);
newStr += String.fromCharCode((c & 31) << 6 | c2 & 63);
} else {
newStr += str.substr(i, 6);
}
i += 6;
} else if (c >= 224) {
if (il - i >= 9) {
const c2 = parseInt(str.substr(i + 4, 2), 16);
const c3 = parseInt(str.substr(i + 7, 2), 16);
newStr += String.fromCharCode((c & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
} else {
newStr += str.substr(i, 9);
}
i += 9;
} else {
newStr += str.substr(i, 3);
i += 3;
}
}
return newStr;
}
__name(pctDecChars, "pctDecChars");
function _normalizeComponentEncoding(components, protocol) {
function decodeUnreserved2(str) {
const decStr = pctDecChars(str);
return !decStr.match(protocol.UNRESERVED) ? str : decStr;
}
__name(decodeUnreserved2, "decodeUnreserved");
if (components.scheme)
components.scheme = String(components.scheme).replace(protocol.PCT_ENCODED, decodeUnreserved2).toLowerCase().replace(protocol.NOT_SCHEME, "");
if (components.userinfo !== void 0)
components.userinfo = String(components.userinfo).replace(protocol.PCT_ENCODED, decodeUnreserved2).replace(protocol.NOT_USERINFO, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase);
if (components.host !== void 0)
components.host = String(components.host).replace(protocol.PCT_ENCODED, decodeUnreserved2).toLowerCase().replace(protocol.NOT_HOST, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase);
if (components.path !== void 0)
components.path = String(components.path).replace(protocol.PCT_ENCODED, decodeUnreserved2).replace(components.scheme ? protocol.NOT_PATH : protocol.NOT_PATH_NOSCHEME, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase);
if (components.query !== void 0)
components.query = String(components.query).replace(protocol.PCT_ENCODED, decodeUnreserved2).replace(protocol.NOT_QUERY, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase);
if (components.fragment !== void 0)
components.fragment = String(components.fragment).replace(protocol.PCT_ENCODED, decodeUnreserved2).replace(protocol.NOT_FRAGMENT, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase);
return components;
}
__name(_normalizeComponentEncoding, "_normalizeComponentEncoding");
function _stripLeadingZeros(str) {
return str.replace(/^0*(.*)/, "$1") || "0";
}
__name(_stripLeadingZeros, "_stripLeadingZeros");
function _normalizeIPv4(host, protocol) {
const matches = host.match(protocol.IPV4ADDRESS) || [];
const [, address] = matches;
if (address) {
return address.split(".").map(_stripLeadingZeros).join(".");
} else {
return host;
}
}
__name(_normalizeIPv4, "_normalizeIPv4");
function _normalizeIPv6(host, protocol) {
const matches = host.match(protocol.IPV6ADDRESS) || [];
const [, address, zone] = matches;
if (address) {
const [last, first] = address.toLowerCase().split("::").reverse();
const firstFields = first ? first.split(":").map(_stripLeadingZeros) : [];
const lastFields = last.split(":").map(_stripLeadingZeros);
const isLastFieldIPv4Address = protocol.IPV4ADDRESS.test(lastFields[lastFields.length - 1]);
const fieldCount = isLastFieldIPv4Address ? 7 : 8;
const lastFieldsStart = lastFields.length - fieldCount;
const fields = Array(fieldCount);
for (let x = 0; x < fieldCount; ++x) {
fields[x] = firstFields[x] || lastFields[lastFieldsStart + x] || "";
}
if (isLastFieldIPv4Address) {
fields[fieldCount - 1] = _normalizeIPv4(fields[fieldCount - 1], protocol);
}
const allZeroFields = fields.reduce(
(acc, field, index) => {
if (!field || field === "0") {
const lastLongest = acc[acc.length - 1];
if (lastLongest && lastLongest.index + lastLongest.length === index) {
lastLongest.length++;
} else {
acc.push({ index, length: 1 });
}
}
return acc;
},
[]
);
const longestZeroFields = allZeroFields.sort((a, b) => b.length - a.length)[0];
let newHost;
if (longestZeroFields && longestZeroFields.length > 1) {
const newFirst = fields.slice(0, longestZeroFields.index);
const newLast = fields.slice(longestZeroFields.index + longestZeroFields.length);
newHost = newFirst.join(":") + "::" + newLast.join(":");
} else {
newHost = fields.join(":");
}
if (zone) {
newHost += "%" + zone;
}
return newHost;
} else {
return host;
}
}
__name(_normalizeIPv6, "_normalizeIPv6");
var URI_PARSE = /^(?:([^:\/?#]+):)?(?:\/\/((?:([^\/?#@]*)@)?(\[[^\/?#\]]+\]|[^\/?#:]*)(?:\:(\d*))?))?([^?#]*)(?:\?([^#]*))?(?:#((?:.|\n|\r)*))?/i;
var NO_MATCH_IS_UNDEFINED = "".match(/(){0}/)[1] === void 0;
function parse(uriString, options = {}) {
const components = {};
const protocol = options.iri !== false ? regexps_iri_default : regexps_uri_default;
if (options.reference === "suffix")
uriString = (options.scheme ? options.scheme + ":" : "") + "//" + uriString;
const matches = uriString.match(URI_PARSE);
if (matches) {
if (NO_MATCH_IS_UNDEFINED) {
components.scheme = matches[1];
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];
if (isNaN(components.port)) {
components.port = matches[5];
}
} else {
components.scheme = matches[1] || void 0;
components.userinfo = uriString.indexOf("@") !== -1 ? matches[3] : void 0;
components.host = uriString.indexOf("//") !== -1 ? matches[4] : void 0;
components.port = parseInt(matches[5], 10);
components.path = matches[6] || "";
components.query = uriString.indexOf("?") !== -1 ? matches[7] : void 0;
components.fragment = uriString.indexOf("#") !== -1 ? matches[8] : void 0;
if (isNaN(components.port)) {
components.port = uriString.match(/\/\/(?:.|\n)*\:(?:\/|\?|\#|$)/) ? matches[4] : void 0;
}
}
if (components.host) {
components.host = _normalizeIPv6(_normalizeIPv4(components.host, protocol), protocol);
}
if (components.scheme === void 0 && components.userinfo === void 0 && components.host === void 0 && components.port === void 0 && !components.path && components.query === void 0) {
components.reference = "same-document";
} else if (components.scheme === void 0) {
components.reference = "relative";
} else if (components.fragment === void 0) {
components.reference = "absolute";
} else {
components.reference = "uri";
}
if (options.reference && options.reference !== "suffix" && options.reference !== components.reference) {
components.error = components.error || "URI is not a " + options.reference + " reference.";
}
const schemeHandler = SCHEMES[(options.scheme || components.scheme || "").toLowerCase()];
if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport)) {
if (components.host && (options.domainHost || schemeHandler && schemeHandler.domainHost)) {
try {
components.host = punycode.toASCII(
components.host.replace(protocol.PCT_ENCODED, pctDecChars).toLowerCase()
);
} catch (e) {
components.error = components.error || "Host's domain name can not be converted to ASCII via punycode: " + e;
}
}
_normalizeComponentEncoding(components, regexps_uri_default);
} else {
_normalizeComponentEncoding(components, protocol);
}
if (schemeHandler && schemeHandler.parse) {
schemeHandler.parse(components, options);
}
} else {
components.error = components.error || "URI can not be parsed.";
}
return components;
}
__name(parse, "parse");
function _recomposeAuthority(components, options) {
const protocol = options.iri !== false ? regexps_iri_default : regexps_uri_default;
const uriTokens = [];
if (components.userinfo !== void 0) {
uriTokens.push(components.userinfo);
uriTokens.push("@");
}
if (components.host !== void 0) {
uriTokens.push(
_normalizeIPv6(_normalizeIPv4(String(components.host), protocol), protocol).replace(
protocol.IPV6ADDRESS,
(_, $1, $2) => "[" + $1 + ($2 ? "%25" + $2 : "") + "]"
)
);
}
if (typeof components.port === "number" || typeof components.port === "string") {
uriTokens.push(":");
uriTokens.push(String(components.port));
}
return uriTokens.length ? uriTokens.join("") : void 0;
}
__name(_recomposeAuthority, "_recomposeAuthority");
var RDS1 = /^\.\.?\//;
var RDS2 = /^\/\.(\/|$)/;
var RDS3 = /^\/\.\.(\/|$)/;
var RDS5 = /^\/?(?:.|\n)*?(?=\/|$)/;
function removeDotSegments(input) {
const output = [];
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 {
const im = input.match(RDS5);
if (im) {
const s = im[0];
input = input.slice(s.length);
output.push(s);
} else {
throw new Error("Unexpected dot segment condition");
}
}
}
return output.join("");
}
__name(removeDotSegments, "removeDotSegments");
function serialize(components, options = {}) {
const protocol = options.iri ? regexps_iri_default : regexps_uri_default;
const uriTokens = [];
const schemeHandler = SCHEMES[(options.scheme || components.scheme || "").toLowerCase()];
if (schemeHandler && schemeHandler.serialize)
schemeHandler.serialize(components, options);
if (components.host) {
if (protocol.IPV6ADDRESS.test(components.host)) {
} else if (options.domainHost || schemeHandler && schemeHandler.domainHost) {
try {
components.host = !options.iri ? punycode.toASCII(
components.host.replace(protocol.PCT_ENCODED, pctDecChars).toLowerCase()
) : punycode.toUnicode(components.host);
} catch (e) {
components.error = components.error || "Host's domain name can not be converted to " + (!options.iri ? "ASCII" : "Unicode") + " via punycode: " + e;
}
}
}
_normalizeComponentEncoding(components, protocol);
if (options.reference !== "suffix" && components.scheme) {
uriTokens.push(components.scheme);
uriTokens.push(":");
}
const authority = _recomposeAuthority(components, options);
if (authority !== void 0) {
if (options.reference !== "suffix") {
uriTokens.push("//");
}
uriTokens.push(authority);
if (components.path && components.path.charAt(0) !== "/") {
uriTokens.push("/");
}
}
if (components.path !== void 0) {
let s = components.path;
if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
s = removeDotSegments(s);
}
if (authority === void 0) {
s = s.replace(/^\/\//, "/%2F");
}
uriTokens.push(s);
}
if (components.query !== void 0) {
uriTokens.push("?");
uriTokens.push(components.query);
}
if (components.fragment !== void 0) {
uriTokens.push("#");
uriTokens.push(components.fragment);
}
return uriTokens.join("");
}
__name(serialize, "serialize");
function resolveComponents(base, relative, options = {}, skipNormalization) {
const target = {};
if (!skipNormalization) {
base = parse(serialize(base, options), options);
relative = parse(serialize(relative, options), options);
}
options = options || {};
if (!options.tolerant && relative.scheme) {
target.scheme = relative.scheme;
target.userinfo = relative.userinfo;
target.host = relative.host;
target.port = relative.port;
target.path = removeDotSegments(relative.path || "");
target.query = relative.query;
} else {
if (relative.userinfo !== void 0 || relative.host !== void 0 || relative.port !== void 0) {
target.userinfo = relative.userinfo;
target.host = relative.host;
target.port = relative.port;
target.path = removeDotSegments(relative.path || "");
target.query = relative.query;
} else {
if (!relative.path) {
target.path = base.path;
if (relative.query !== void 0) {
target.query = relative.query;
} else {
target.query = base.query;
}
} else {
if (relative.path.charAt(0) === "/") {
target.path = removeDotSegments(relative.path);
} else {
if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !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 = removeDotSegments(target.path);
}
target.query = relative.query;
}
target.userinfo = base.userinfo;
target.host = base.host;
target.port = base.port;
}
target.scheme = base.scheme;
}
target.fragment = relative.fragment;
return target;
}
__name(resolveComponents, "resolveComponents");
function resolve(baseURI, relativeURI, options) {
const schemelessOptions = assign({ scheme: "null" }, options);
return serialize(
resolveComponents(
parse(baseURI, schemelessOptions),
parse(relativeURI, schemelessOptions),
schemelessOptions,
true
),
schemelessOptions
);
}
__name(resolve, "resolve");
function normalize(uri, options) {
if (typeof uri === "string") {
uri = serialize(parse(uri, options), options);
} else if (typeOf(uri) === "object") {
uri = parse(serialize(uri, options), options);
}
return uri;
}
__name(normalize, "normalize");
function equal(uriA, uriB, options) {
if (typeof uriA === "string") {
uriA = serialize(parse(uriA, options), options);
} else if (typeOf(uriA) === "object") {
uriA = serialize(uriA, options);
}
if (typeof uriB === "string") {
uriB = serialize(parse(uriB, options), options);
} else if (typeOf(uriB) === "object") {
uriB = serialize(uriB, options);
}
return uriA === uriB;
}
__name(equal, "equal");
function escapeComponent(str, options) {
return str && str.toString().replace(!options || !options.iri ? regexps_uri_default.ESCAPE : regexps_iri_default.ESCAPE, pctEncChar);
}
__name(escapeComponent, "escapeComponent");
function unescapeComponent(str, options) {
return str && str.toString().replace(
!options || !options.iri ? regexps_uri_default.PCT_ENCODED : regexps_iri_default.PCT_ENCODED,
pctDecChars
);
}
__name(unescapeComponent, "unescapeComponent");
// src/schemes/http.ts
var handler = {
scheme: "http",
domainHost: true,
parse: (components, options) => {
if (!components.host) {
components.error = components.error || "HTTP URIs must have a host.";
}
return components;
},
serialize: (components, options) => {
const secure = String(components.scheme).toLowerCase() === "https";
if (components.port === (secure ? 443 : 80) || components.port === "") {
components.port = void 0;
}
if (!components.path) {
components.path = "/";
}
return components;
}
};
var http_default = handler;
// src/schemes/https.ts
var handler2 = {
scheme: "https",
domainHost: http_default.domainHost,
parse: http_default.parse,
serialize: http_default.serialize
};
var https_default = handler2;
// src/schemes/ws.ts
function isSecure(wsComponents) {
return typeof wsComponents.secure === "boolean" ? wsComponents.secure : String(wsComponents.scheme).toLowerCase() === "wss";
}
__name(isSecure, "isSecure");
var handler3 = {
scheme: "ws",
domainHost: true,
parse: (components, options) => {
const wsComponents = components;
wsComponents.secure = isSecure(wsComponents);
wsComponents.resourceName = (wsComponents.path || "/") + (wsComponents.query ? "?" + wsComponents.query : "");
wsComponents.path = void 0;
wsComponents.query = void 0;
return wsComponents;
},
serialize: (wsComponents, options) => {
if (wsComponents.port === (isSecure(wsComponents) ? 443 : 80) || wsComponents.port === "") {
wsComponents.port = void 0;
}
if (typeof wsComponents.secure === "boolean") {
wsComponents.scheme = wsComponents.secure ? "wss" : "ws";
wsComponents.secure = void 0;
}
if (wsComponents.resourceName) {
const [path, query] = wsComponents.resourceName.split("?");
wsComponents.path = path && path !== "/" ? path : void 0;
wsComponents.query = query;
wsComponents.resourceName = void 0;
}
wsComponents.fragment = void 0;
return wsComponents;
}
};
var ws_default = handler3;
// src/schemes/wss.ts
var handler4 = {
scheme: "wss",
domainHost: ws_default.domainHost,
parse: ws_default.parse,
serialize: ws_default.serialize
};
var wss_default = handler4;
// src/schemes/mailto.ts
import punycode2 from "punycode/";
var O = {};
var isIRI = true;
var UNRESERVED$$ = "[A-Za-z0-9\\-\\.\\_\\~" + (isIRI ? "\\xA0-\\u200D\\u2010-\\u2029\\u202F-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF" : "") + "]";
var HEXDIG$$ = "[0-9A-Fa-f]";
var PCT_ENCODED$ = subexp(
subexp("%[EFef]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + subexp("%[89A-Fa-f]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + subexp("%" + HEXDIG$$ + HEXDIG$$)
);
var ATEXT$$ = "[A-Za-z0-9\\!\\$\\%\\'\\*\\+\\-\\^\\_\\`\\{\\|\\}\\~]";
var QTEXT$$ = "[\\!\\$\\%\\'\\(\\)\\*\\+\\,\\-\\.0-9\\<\\>A-Z\\x5E-\\x7E]";
var VCHAR$$ = merge(QTEXT$$, '[\\"\\\\]');
var DOT_ATOM_TEXT$ = subexp(ATEXT$$ + "+" + subexp("\\." + ATEXT$$ + "+") + "*");
var QUOTED_PAIR$ = subexp("\\\\" + VCHAR$$);
var QCONTENT$ = subexp(QTEXT$$ + "|" + QUOTED_PAIR$);
var QUOTED_STRING$ = subexp('\\"' + QCONTENT$ + '*\\"');
var DTEXT_NO_OBS$$ = "[\\x21-\\x5A\\x5E-\\x7E]";
var SOME_DELIMS$$ = "[\\!\\$\\'\\(\\)\\*\\+\\,\\;\\:\\@]";
var QCHAR$ = subexp(UNRESERVED$$ + "|" + PCT_ENCODED$ + "|" + SOME_DELIMS$$);
var DOMAIN$ = subexp(DOT_ATOM_TEXT$ + "|\\[" + DTEXT_NO_OBS$$ + "*\\]");
var LOCAL_PART$ = subexp(DOT_ATOM_TEXT$ + "|" + QUOTED_STRING$);
var ADDR_SPEC$ = subexp(LOCAL_PART$ + "\\@" + DOMAIN$);
var TO$ = subexp(ADDR_SPEC$ + subexp("\\," + ADDR_SPEC$) + "*");
var HFNAME$ = subexp(QCHAR$ + "*");
var HFVALUE$ = HFNAME$;
var HFIELD$ = subexp(HFNAME$ + "\\=" + HFVALUE$);
var HFIELDS2$ = subexp(HFIELD$ + subexp("\\&" + HFIELD$) + "*");
var HFIELDS$ = subexp("\\?" + HFIELDS2$);
var MAILTO_URI = new RegExp("^mailto\\:" + TO$ + "?" + HFIELDS$ + "?$");
var UNRESERVED = new RegExp(UNRESERVED$$, "g");
var PCT_ENCODED = new RegExp(PCT_ENCODED$, "g");
var NOT_LOCAL_PART = new RegExp(merge("[^]", ATEXT$$, "[\\.]", '[\\"]', VCHAR$$), "g");
var NOT_DOMAIN = new RegExp(merge("[^]", ATEXT$$, "[\\.]", "[\\[]", DTEXT_NO_OBS$$, "[\\]]"), "g");
var NOT_HFNAME = new RegExp(merge("[^]", UNRESERVED$$, SOME_DELIMS$$), "g");
var NOT_HFVALUE = NOT_HFNAME;
var TO = new RegExp("^" + TO$ + "$");
var HFIELDS = new RegExp("^" + HFIELDS2$ + "$");
function decodeUnreserved(str) {
const decStr = pctDecChars(str);
return !decStr.match(UNRESERVED) ? str : decStr;
}
__name(decodeUnreserved, "decodeUnreserved");
var handler5 = {
scheme: "mailto",
parse: (components, options) => {
const mailtoComponents = components;
const to = mailtoComponents.to = mailtoComponents.path ? mailtoComponents.path.split(",") : [];
mailtoComponents.path = void 0;
if (mailtoComponents.query) {
let unknownHeaders = false;
const headers = {};
const hfields = mailtoComponents.query.split("&");
for (let x = 0, xl = hfields.length; x < xl; ++x) {
const hfield = hfields[x].split("=");
switch (hfield[0]) {
case "to":
const toAddrs = hfield[1].split(",");
for (let x2 = 0, xl2 = toAddrs.length; x2 < xl2; ++x2) {
to.push(toAddrs[x2]);
}
break;
case "subject":
mailtoComponents.subject = unescapeComponent(hfield[1], options);
break;
case "body":
mailtoComponents.body = unescapeComponent(hfield[1], options);
break;
default:
unknownHeaders = true;
headers[unescapeComponent(hfield[0], options)] = unescapeComponent(hfield[1], options);
break;
}
}
if (unknownHeaders)
mailtoComponents.headers = headers;
}
mailtoComponents.query = void 0;
for (let x = 0, xl = to.length; x < xl; ++x) {
const addr = to[x].split("@");
addr[0] = unescapeComponent(addr[0]);
if (!options.unicodeSupport) {
try {
addr[1] = punycode2.toASCII(unescapeComponent(addr[1], options).toLowerCase());
} catch (e) {
mailtoComponents.error = mailtoComponents.error || "Email address's domain name can not be converted to ASCII via punycode: " + e;
}
} else {
addr[1] = unescapeComponent(addr[1], options).toLowerCase();
}
to[x] = addr.join("@");
}
return mailtoComponents;
},
serialize: (mailtoComponents, options) => {
const components = mailtoComponents;
const to = toArray(mailtoComponents.to);
if (to) {
for (let x = 0, xl = to.length; x < xl; ++x) {
const toAddr = String(to[x]);
const atIdx = toAddr.lastIndexOf("@");
const localPart = toAddr.slice(0, atIdx).replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, toUpperCase).replace(NOT_LOCAL_PART, pctEncChar);
let domain = toAddr.slice(atIdx + 1);
try {
domain = !options.iri ? punycode2.toASCII(unescapeComponent(domain, options).toLowerCase()) : punycode2.toUnicode(domain);
} catch (e) {
components.error = components.error || "Email address's domain name can not be converted to " + (!options.iri ? "ASCII" : "Unicode") + " via punycode: " + e;
}
to[x] = localPart + "@" + domain;
}
components.path = to.join(",");
}
const headers = mailtoComponents.headers = mailtoComponents.headers || {};
if (mailtoComponents.subject)
headers.subject = mailtoComponents.subject;
if (mailtoComponents.body)
headers.body = mailtoComponents.body;
const fields = [];
for (const name in headers) {
if (headers[name] !== O[name]) {
fields.push(
name.replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, toUpperCase).replace(NOT_HFNAME, pctEncChar) + "=" + headers[name].replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, toUpperCase).replace(NOT_HFVALUE, pctEncChar)
);
}
}
if (fields.length) {
components.query = fields.join("&");
}
return components;
}
};
var mailto_default = handler5;
// src/schemes/urn.ts
var NID$ = "(?:[0-9A-Za-z][0-9A-Za-z\\-]{1,31})";
var PCT_ENCODED$2 = "(?:\\%[0-9A-Fa-f]{2})";
var TRANS$$ = "[0-9A-Za-z\\(\\)\\+\\,\\-\\.\\:\\=\\@\\;\\$\\_\\!\\*\\'\\/\\?\\#]";
var NSS$ = "(?:(?:" + PCT_ENCODED$2 + "|" + TRANS$$ + ")+)";
var URN_SCHEME = new RegExp("^urn\\:(" + NID$ + ")$");
var URN_PATH = new RegExp("^(" + NID$ + ")\\:(" + NSS$ + ")$");
var URN_PARSE = /^([^\:]+)\:(.*)/;
var handler6 = {
scheme: "urn",
parse: (components, options) => {
const matches = components.path && components.path.match(URN_PARSE);
let urnComponents = components;
if (matches) {
const scheme = options.scheme || urnComponents.scheme || "urn";
const nid = matches[1].toLowerCase();
const nss = matches[2];
const urnScheme = `${scheme}:${options.nid || nid}`;
const schemeHandler = SCHEMES[urnScheme];
urnComponents.nid = nid;
urnComponents.nss = nss;
urnComponents.path = void 0;
if (schemeHandler) {
urnComponents = schemeHandler.parse(urnComponents, options);
}
} else {
urnComponents.error = urnComponents.error || "URN can not be parsed.";
}
return urnComponents;
},
serialize: (urnComponents, options) => {
const scheme = options.scheme || urnComponents.scheme || "urn";
const nid = urnComponents.nid;
const urnScheme = `${scheme}:${options.nid || nid}`;
const schemeHandler = SCHEMES[urnScheme];
if (schemeHandler) {
urnComponents = schemeHandler.serialize(urnComponents, options);
}
const uriComponents = urnComponents;
const nss = urnComponents.nss;
uriComponents.path = `${nid || options.nid}:${nss}`;
return uriComponents;
}
};
var urn_default = handler6;
// src/schemes/urn-uuid.ts
var UUID = /^[0-9A-Fa-f]{8}(?:\-[0-9A-Fa-f]{4}){3}\-[0-9A-Fa-f]{12}$/;
var handler7 = {
scheme: "urn:uuid",
parse: (urnComponents, options) => {
const uuidComponents = urnComponents;
uuidComponents.uuid = uuidComponents.nss;
uuidComponents.nss = void 0;
if (!options.tolerant && (!uuidComponents.uuid || !uuidComponents.uuid.match(UUID))) {
uuidComponents.error = uuidComponents.error || "UUID is not valid.";
}
return uuidComponents;
},
serialize: (uuidComponents, options) => {
const urnComponents = uuidComponents;
urnComponents.nss = (uuidComponents.uuid || "").toLowerCase();
return urnComponents;
}
};
var urn_uuid_default = handler7;
// src/index.ts
SCHEMES[http_default.scheme] = http_default;
SCHEMES[https_default.scheme] = https_default;
SCHEMES[ws_default.scheme] = ws_default;
SCHEMES[wss_default.scheme] = wss_default;
SCHEMES[mailto_default.scheme] = mailto_default;
SCHEMES[urn_default.scheme] = urn_default;
SCHEMES[urn_uuid_default.scheme] = urn_uuid_default;
export {
SCHEMES,
equal,
escapeComponent,
normalize,
parse,
pctDecChars,
pctEncChar,
removeDotSegments,
resolve,
resolveComponents,
serialize,
unescapeComponent
};