json-schema-library
Version:
Customizable and hackable json-validator and json-schema utilities for traversal, data generation and validation
1 lines • 79.8 kB
Source Map (JSON)
{"version":3,"file":"formats.mjs","names":["alpha","hexdig","atom","localPart","letDig","ldhStr","subDomain","domain","decOctet","ipv4Address","h16","ls32","mailbox","domain","ucschar","alpha","hexdig","decOctet","h16","ls32","decOctet","ipV4Address","hexdig","decOctet","ipV4Address","h16","ls32","hexdig","pctEncoded","iprivate","isUri","isUriReference","isIri","isIriReference","Hyperjump.isUri","Hyperjump.isUriReference","Hyperjump.isIri","Hyperjump.isIriReference","jsonPointer"],"sources":["../node_modules/.pnpm/@hyperjump+json-schema-formats@1.0.1/node_modules/@hyperjump/json-schema-formats/src/rfc3339.js","../node_modules/.pnpm/@hyperjump+json-schema-formats@1.0.1/node_modules/@hyperjump/json-schema-formats/src/rfc5321.js","../node_modules/.pnpm/punycode@2.3.1/node_modules/punycode/punycode.js","../node_modules/.pnpm/idn-hostname@15.1.8/node_modules/idn-hostname/idnaMappingTableCompact.json","../node_modules/.pnpm/idn-hostname@15.1.8/node_modules/idn-hostname/index.js","../node_modules/.pnpm/@hyperjump+json-schema-formats@1.0.1/node_modules/@hyperjump/json-schema-formats/src/rfc1123.js","../node_modules/.pnpm/@hyperjump+json-schema-formats@1.0.1/node_modules/@hyperjump/json-schema-formats/src/uts46.js","../node_modules/.pnpm/@hyperjump+json-schema-formats@1.0.1/node_modules/@hyperjump/json-schema-formats/src/rfc6531.js","../node_modules/.pnpm/@hyperjump+json-schema-formats@1.0.1/node_modules/@hyperjump/json-schema-formats/src/rfc2673.js","../node_modules/.pnpm/@hyperjump+json-schema-formats@1.0.1/node_modules/@hyperjump/json-schema-formats/src/rfc4291.js","../node_modules/.pnpm/@hyperjump+uri@1.3.3/node_modules/@hyperjump/uri/lib/index.js","../node_modules/.pnpm/@hyperjump+json-schema-formats@1.0.1/node_modules/@hyperjump/json-schema-formats/src/rfc3986.js","../node_modules/.pnpm/@hyperjump+json-schema-formats@1.0.1/node_modules/@hyperjump/json-schema-formats/src/rfc3987.js","../node_modules/.pnpm/@hyperjump+json-schema-formats@1.0.1/node_modules/@hyperjump/json-schema-formats/src/rfc4122.js","../node_modules/.pnpm/@hyperjump+json-schema-formats@1.0.1/node_modules/@hyperjump/json-schema-formats/src/rfc6570.js","../node_modules/.pnpm/@hyperjump+json-schema-formats@1.0.1/node_modules/@hyperjump/json-schema-formats/src/rfc6901.js","../node_modules/.pnpm/@hyperjump+json-schema-formats@1.0.1/node_modules/@hyperjump/json-schema-formats/src/draft-bhutton-relative-json-pointer-00.js","../src/formats/additionalFormats.ts"],"sourcesContent":["import { daysInMonth, hasLeapSecond } from \"./date-math.js\";\n\n/**\n * @import * as API from \"./index.d.ts\"\n */\n\nconst dateFullyear = `\\\\d{4}`;\nconst dateMonth = `(?:0[1-9]|1[0-2])`; // 01-12\nconst dateMday = `(?:0[1-9]|[12][0-9]|3[01])`; // 01-28, 01-29, 01-30, 01-31 based on month/year\nconst fullDate = `(?<year>${dateFullyear})-(?<month>${dateMonth})-(?<day>${dateMday})`;\n\nconst datePattern = new RegExp(`^${fullDate}$`);\n\n/** @type API.isDate */\nexport const isDate = (date) => {\n const parsedDate = datePattern.exec(date)?.groups;\n if (!parsedDate) {\n return false;\n }\n\n const day = Number.parseInt(parsedDate.day, 10);\n const year = Number.parseInt(parsedDate.year, 10);\n\n return day <= daysInMonth(parsedDate.month, year);\n};\n\nconst timeHour = `(?:[01]\\\\d|2[0-3])`; // 00-23\nconst timeMinute = `[0-5]\\\\d`; // 00-59\nconst timeSecond = `[0-5]\\\\d`; // 00-59\nconst timeSecondAllowLeapSeconds = `(?<seconds>[0-5]\\\\d|60)`; // 00-58, 00-59, 00-60 based on leap second rules\nconst timeSecfrac = `\\\\.\\\\d+`;\nconst timeNumoffset = `[+-]${timeHour}:${timeMinute}`;\nconst timeOffset = `(?:[zZ]|${timeNumoffset})`;\nconst partialTime = `${timeHour}:${timeMinute}:${timeSecond}(?:${timeSecfrac})?`;\nconst fullTime = `${partialTime}${timeOffset}`;\n\n/**\n * @type API.isTime\n * @function\n */\nexport const isTime = RegExp.prototype.test.bind(new RegExp(`^${fullTime}$`));\n\nconst timePattern = new RegExp(`^${timeHour}:${timeMinute}:${timeSecondAllowLeapSeconds}(?:${timeSecfrac})?${timeOffset}$`);\n\n/** @type (time: string) => { seconds: string } | undefined */\nconst parseTime = (time) => {\n return /** @type {{ seconds: string } | undefined} */ (timePattern.exec(time)?.groups);\n};\n\n/** @type API.isDateTime */\nexport const isDateTime = (dateTime) => {\n const date = dateTime.substring(0, 10);\n const t = dateTime[10];\n const time = dateTime.substring(11);\n const seconds = parseTime(time)?.seconds;\n\n return isDate(date)\n && /^t$/i.test(t)\n && !!seconds\n && (seconds !== \"60\" || hasLeapSecond(new Date(`${date}T${time.replace(\"60\", \"59\")}`)));\n};\n\nconst durSecond = `\\\\d+S`;\nconst durMinute = `\\\\d+M(?:${durSecond})?`;\nconst durHour = `\\\\d+H(?:${durMinute})?`;\nconst durTime = `T(?:${durHour}|${durMinute}|${durSecond})`;\nconst durDay = `\\\\d+D`;\nconst durWeek = `\\\\d+W`;\nconst durMonth = `\\\\d+M(?:${durDay})?`;\nconst durYear = `\\\\d+Y(?:${durMonth})?`;\nconst durDate = `(?:${durDay}|${durMonth}|${durYear})(?:${durTime})?`;\nconst duration = `P(?:${durDate}|${durTime}|${durWeek})`;\n\n/**\n * @type API.isDuration\n * @function\n */\nexport const isDuration = RegExp.prototype.test.bind(new RegExp(`^${duration}$`));\n","/**\n * @import * as API from \"./index.d.ts\"\n */\n\nconst alpha = `[a-zA-Z]`;\nconst hexdig = `[\\\\da-fA-F]`;\n\n// Printable US-ASCII characters not including specials.\nconst atext = `[\\\\w!#$%&'*+\\\\-/=?^\\`{|}~]`;\nconst atom = `${atext}+`;\nconst dotString = `${atom}(?:\\\\.${atom})*`;\n\n// Any ASCII graphic or space without blackslash-quoting except double-quote and the backslash itself.\nconst qtextSMTP = `[\\\\x20-\\\\x21\\\\x23-\\\\x5B\\\\x5D-\\\\x7E]`;\n// backslash followed by any ASCII graphic or space\nconst quotedPairSMTP = `\\\\\\\\[\\\\x20-\\\\x7E]`;\nconst qcontentSMTP = `(?:${qtextSMTP}|${quotedPairSMTP})`;\nconst quotedString = `\"${qcontentSMTP}*\"`;\n\nconst localPart = `(?:${dotString}|${quotedString})`; // MAY be case-sensitive\n\nconst letDig = `(?:${alpha}|\\\\d)`;\nconst ldhStr = `(?:${letDig}|-)*${letDig}`;\nconst subDomain = `${letDig}${ldhStr}?`;\nconst domain = `${subDomain}(?:\\\\.${subDomain})*`;\n\nconst decOctet = `(?:\\\\d|[1-9]\\\\d|1\\\\d\\\\d|2[0-4]\\\\d|25[0-5])`;\nconst ipv4Address = `${decOctet}\\\\.${decOctet}\\\\.${decOctet}\\\\.${decOctet}`;\n\nconst h16 = `${hexdig}{1,4}`;\nconst ls32 = `(?:${h16}:${h16}|${ipv4Address})`;\nconst ipv6Address = `(?:(?:${h16}:){6}${ls32}|::(?:${h16}:){5}${ls32}|(?:${h16})?::(?:${h16}:){4}${ls32}|(?:(?:${h16}:){0,1}${h16})?::(?:${h16}:){3}${ls32}|(?:(?:${h16}:){0,2}${h16})?::(?:${h16}:){2}${ls32}|(?:(?:${h16}:){0,3}${h16})?::(?:${h16}:){1}${ls32}|(?:(?:${h16}:){0,4}${h16})?::${ls32}|(?:(?:${h16}:){0,5}${h16})?::${h16}|(?:(?:${h16}:){0,6}${h16})?::)`;\nconst ipv6AddressLiteral = `IPv6:${ipv6Address}`;\n\nconst dcontent = `[\\\\x21-\\\\x5A\\\\x5E-\\\\x7E]`; // Printable US-ASCII excluding \"[\", \"\\\", \"]\"\nconst generalAddressLiteral = `${ldhStr}:${dcontent}+`;\n\nconst addressLiteral = `\\\\[(?:${ipv4Address}|${ipv6AddressLiteral}|${generalAddressLiteral})]`;\n\nconst mailbox = `${localPart}@(?:${domain}|${addressLiteral})`;\n\n/**\n * @type API.isEmail\n * @function\n */\nexport const isEmail = RegExp.prototype.test.bind(new RegExp(`^${mailbox}$`));\n","'use strict';\n\n/** Highest positive signed 32-bit float value */\nconst maxInt = 2147483647; // aka. 0x7FFFFFFF or 2^31-1\n\n/** Bootstring parameters */\nconst base = 36;\nconst tMin = 1;\nconst tMax = 26;\nconst skew = 38;\nconst damp = 700;\nconst initialBias = 72;\nconst initialN = 128; // 0x80\nconst delimiter = '-'; // '\\x2D'\n\n/** Regular expressions */\nconst regexPunycode = /^xn--/;\nconst regexNonASCII = /[^\\0-\\x7F]/; // Note: U+007F DEL is excluded too.\nconst regexSeparators = /[\\x2E\\u3002\\uFF0E\\uFF61]/g; // RFC 3490 separators\n\n/** Error messages */\nconst errors = {\n\t'overflow': 'Overflow: input needs wider integers to process',\n\t'not-basic': 'Illegal input >= 0x80 (not a basic code point)',\n\t'invalid-input': 'Invalid input'\n};\n\n/** Convenience shortcuts */\nconst baseMinusTMin = base - tMin;\nconst floor = Math.floor;\nconst stringFromCharCode = String.fromCharCode;\n\n/*--------------------------------------------------------------------------*/\n\n/**\n * A generic error utility function.\n * @private\n * @param {String} type The error type.\n * @returns {Error} Throws a `RangeError` with the applicable error message.\n */\nfunction error(type) {\n\tthrow new RangeError(errors[type]);\n}\n\n/**\n * A generic `Array#map` utility function.\n * @private\n * @param {Array} array The array to iterate over.\n * @param {Function} callback The function that gets called for every array\n * item.\n * @returns {Array} A new array of values returned by the callback function.\n */\nfunction map(array, callback) {\n\tconst result = [];\n\tlet length = array.length;\n\twhile (length--) {\n\t\tresult[length] = callback(array[length]);\n\t}\n\treturn result;\n}\n\n/**\n * A simple `Array#map`-like wrapper to work with domain name strings or email\n * addresses.\n * @private\n * @param {String} domain The domain name or email address.\n * @param {Function} callback The function that gets called for every\n * character.\n * @returns {String} A new string of characters returned by the callback\n * function.\n */\nfunction mapDomain(domain, callback) {\n\tconst parts = domain.split('@');\n\tlet result = '';\n\tif (parts.length > 1) {\n\t\t// In email addresses, only the domain name should be punycoded. Leave\n\t\t// the local part (i.e. everything up to `@`) intact.\n\t\tresult = parts[0] + '@';\n\t\tdomain = parts[1];\n\t}\n\t// Avoid `split(regex)` for IE8 compatibility. See #17.\n\tdomain = domain.replace(regexSeparators, '\\x2E');\n\tconst labels = domain.split('.');\n\tconst encoded = map(labels, callback).join('.');\n\treturn result + encoded;\n}\n\n/**\n * Creates an array containing the numeric code points of each Unicode\n * character in the string. While JavaScript uses UCS-2 internally,\n * this function will convert a pair of surrogate halves (each of which\n * UCS-2 exposes as separate characters) into a single code point,\n * matching UTF-16.\n * @see `punycode.ucs2.encode`\n * @see <https://mathiasbynens.be/notes/javascript-encoding>\n * @memberOf punycode.ucs2\n * @name decode\n * @param {String} string The Unicode input string (UCS-2).\n * @returns {Array} The new array of code points.\n */\nfunction ucs2decode(string) {\n\tconst output = [];\n\tlet counter = 0;\n\tconst length = string.length;\n\twhile (counter < length) {\n\t\tconst value = string.charCodeAt(counter++);\n\t\tif (value >= 0xD800 && value <= 0xDBFF && counter < length) {\n\t\t\t// It's a high surrogate, and there is a next character.\n\t\t\tconst extra = string.charCodeAt(counter++);\n\t\t\tif ((extra & 0xFC00) == 0xDC00) { // Low surrogate.\n\t\t\t\toutput.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);\n\t\t\t} else {\n\t\t\t\t// It's an unmatched surrogate; only append this code unit, in case the\n\t\t\t\t// next code unit is the high surrogate of a surrogate pair.\n\t\t\t\toutput.push(value);\n\t\t\t\tcounter--;\n\t\t\t}\n\t\t} else {\n\t\t\toutput.push(value);\n\t\t}\n\t}\n\treturn output;\n}\n\n/**\n * Creates a string based on an array of numeric code points.\n * @see `punycode.ucs2.decode`\n * @memberOf punycode.ucs2\n * @name encode\n * @param {Array} codePoints The array of numeric code points.\n * @returns {String} The new Unicode string (UCS-2).\n */\nconst ucs2encode = codePoints => String.fromCodePoint(...codePoints);\n\n/**\n * Converts a basic code point into a digit/integer.\n * @see `digitToBasic()`\n * @private\n * @param {Number} codePoint The basic numeric code point value.\n * @returns {Number} The numeric value of a basic code point (for use in\n * representing integers) in the range `0` to `base - 1`, or `base` if\n * the code point does not represent a value.\n */\nconst basicToDigit = function(codePoint) {\n\tif (codePoint >= 0x30 && codePoint < 0x3A) {\n\t\treturn 26 + (codePoint - 0x30);\n\t}\n\tif (codePoint >= 0x41 && codePoint < 0x5B) {\n\t\treturn codePoint - 0x41;\n\t}\n\tif (codePoint >= 0x61 && codePoint < 0x7B) {\n\t\treturn codePoint - 0x61;\n\t}\n\treturn base;\n};\n\n/**\n * Converts a digit/integer into a basic code point.\n * @see `basicToDigit()`\n * @private\n * @param {Number} digit The numeric value of a basic code point.\n * @returns {Number} The basic code point whose value (when used for\n * representing integers) is `digit`, which needs to be in the range\n * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is\n * used; else, the lowercase form is used. The behavior is undefined\n * if `flag` is non-zero and `digit` has no uppercase form.\n */\nconst digitToBasic = function(digit, flag) {\n\t// 0..25 map to ASCII a..z or A..Z\n\t// 26..35 map to ASCII 0..9\n\treturn digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);\n};\n\n/**\n * Bias adaptation function as per section 3.4 of RFC 3492.\n * https://tools.ietf.org/html/rfc3492#section-3.4\n * @private\n */\nconst adapt = function(delta, numPoints, firstTime) {\n\tlet k = 0;\n\tdelta = firstTime ? floor(delta / damp) : delta >> 1;\n\tdelta += floor(delta / numPoints);\n\tfor (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {\n\t\tdelta = floor(delta / baseMinusTMin);\n\t}\n\treturn floor(k + (baseMinusTMin + 1) * delta / (delta + skew));\n};\n\n/**\n * Converts a Punycode string of ASCII-only symbols to a string of Unicode\n * symbols.\n * @memberOf punycode\n * @param {String} input The Punycode string of ASCII-only symbols.\n * @returns {String} The resulting string of Unicode symbols.\n */\nconst decode = function(input) {\n\t// Don't use UCS-2.\n\tconst output = [];\n\tconst inputLength = input.length;\n\tlet i = 0;\n\tlet n = initialN;\n\tlet bias = initialBias;\n\n\t// Handle the basic code points: let `basic` be the number of input code\n\t// points before the last delimiter, or `0` if there is none, then copy\n\t// the first basic code points to the output.\n\n\tlet basic = input.lastIndexOf(delimiter);\n\tif (basic < 0) {\n\t\tbasic = 0;\n\t}\n\n\tfor (let j = 0; j < basic; ++j) {\n\t\t// if it's not a basic code point\n\t\tif (input.charCodeAt(j) >= 0x80) {\n\t\t\terror('not-basic');\n\t\t}\n\t\toutput.push(input.charCodeAt(j));\n\t}\n\n\t// Main decoding loop: start just after the last delimiter if any basic code\n\t// points were copied; start at the beginning otherwise.\n\n\tfor (let index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {\n\n\t\t// `index` is the index of the next character to be consumed.\n\t\t// Decode a generalized variable-length integer into `delta`,\n\t\t// which gets added to `i`. The overflow checking is easier\n\t\t// if we increase `i` as we go, then subtract off its starting\n\t\t// value at the end to obtain `delta`.\n\t\tconst oldi = i;\n\t\tfor (let w = 1, k = base; /* no condition */; k += base) {\n\n\t\t\tif (index >= inputLength) {\n\t\t\t\terror('invalid-input');\n\t\t\t}\n\n\t\t\tconst digit = basicToDigit(input.charCodeAt(index++));\n\n\t\t\tif (digit >= base) {\n\t\t\t\terror('invalid-input');\n\t\t\t}\n\t\t\tif (digit > floor((maxInt - i) / w)) {\n\t\t\t\terror('overflow');\n\t\t\t}\n\n\t\t\ti += digit * w;\n\t\t\tconst t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);\n\n\t\t\tif (digit < t) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tconst baseMinusT = base - t;\n\t\t\tif (w > floor(maxInt / baseMinusT)) {\n\t\t\t\terror('overflow');\n\t\t\t}\n\n\t\t\tw *= baseMinusT;\n\n\t\t}\n\n\t\tconst out = output.length + 1;\n\t\tbias = adapt(i - oldi, out, oldi == 0);\n\n\t\t// `i` was supposed to wrap around from `out` to `0`,\n\t\t// incrementing `n` each time, so we'll fix that now:\n\t\tif (floor(i / out) > maxInt - n) {\n\t\t\terror('overflow');\n\t\t}\n\n\t\tn += floor(i / out);\n\t\ti %= out;\n\n\t\t// Insert `n` at position `i` of the output.\n\t\toutput.splice(i++, 0, n);\n\n\t}\n\n\treturn String.fromCodePoint(...output);\n};\n\n/**\n * Converts a string of Unicode symbols (e.g. a domain name label) to a\n * Punycode string of ASCII-only symbols.\n * @memberOf punycode\n * @param {String} input The string of Unicode symbols.\n * @returns {String} The resulting Punycode string of ASCII-only symbols.\n */\nconst encode = function(input) {\n\tconst output = [];\n\n\t// Convert the input in UCS-2 to an array of Unicode code points.\n\tinput = ucs2decode(input);\n\n\t// Cache the length.\n\tconst inputLength = input.length;\n\n\t// Initialize the state.\n\tlet n = initialN;\n\tlet delta = 0;\n\tlet bias = initialBias;\n\n\t// Handle the basic code points.\n\tfor (const currentValue of input) {\n\t\tif (currentValue < 0x80) {\n\t\t\toutput.push(stringFromCharCode(currentValue));\n\t\t}\n\t}\n\n\tconst basicLength = output.length;\n\tlet handledCPCount = basicLength;\n\n\t// `handledCPCount` is the number of code points that have been handled;\n\t// `basicLength` is the number of basic code points.\n\n\t// Finish the basic string with a delimiter unless it's empty.\n\tif (basicLength) {\n\t\toutput.push(delimiter);\n\t}\n\n\t// Main encoding loop:\n\twhile (handledCPCount < inputLength) {\n\n\t\t// All non-basic code points < n have been handled already. Find the next\n\t\t// larger one:\n\t\tlet m = maxInt;\n\t\tfor (const currentValue of input) {\n\t\t\tif (currentValue >= n && currentValue < m) {\n\t\t\t\tm = currentValue;\n\t\t\t}\n\t\t}\n\n\t\t// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,\n\t\t// but guard against overflow.\n\t\tconst handledCPCountPlusOne = handledCPCount + 1;\n\t\tif (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {\n\t\t\terror('overflow');\n\t\t}\n\n\t\tdelta += (m - n) * handledCPCountPlusOne;\n\t\tn = m;\n\n\t\tfor (const currentValue of input) {\n\t\t\tif (currentValue < n && ++delta > maxInt) {\n\t\t\t\terror('overflow');\n\t\t\t}\n\t\t\tif (currentValue === n) {\n\t\t\t\t// Represent delta as a generalized variable-length integer.\n\t\t\t\tlet q = delta;\n\t\t\t\tfor (let k = base; /* no condition */; k += base) {\n\t\t\t\t\tconst t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);\n\t\t\t\t\tif (q < t) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tconst qMinusT = q - t;\n\t\t\t\t\tconst baseMinusT = base - t;\n\t\t\t\t\toutput.push(\n\t\t\t\t\t\tstringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))\n\t\t\t\t\t);\n\t\t\t\t\tq = floor(qMinusT / baseMinusT);\n\t\t\t\t}\n\n\t\t\t\toutput.push(stringFromCharCode(digitToBasic(q, 0)));\n\t\t\t\tbias = adapt(delta, handledCPCountPlusOne, handledCPCount === basicLength);\n\t\t\t\tdelta = 0;\n\t\t\t\t++handledCPCount;\n\t\t\t}\n\t\t}\n\n\t\t++delta;\n\t\t++n;\n\n\t}\n\treturn output.join('');\n};\n\n/**\n * Converts a Punycode string representing a domain name or an email address\n * to Unicode. Only the Punycoded parts of the input will be converted, i.e.\n * it doesn't matter if you call it on a string that has already been\n * converted to Unicode.\n * @memberOf punycode\n * @param {String} input The Punycoded domain name or email address to\n * convert to Unicode.\n * @returns {String} The Unicode representation of the given Punycode\n * string.\n */\nconst toUnicode = function(input) {\n\treturn mapDomain(input, function(string) {\n\t\treturn regexPunycode.test(string)\n\t\t\t? decode(string.slice(4).toLowerCase())\n\t\t\t: string;\n\t});\n};\n\n/**\n * Converts a Unicode string representing a domain name or an email address to\n * Punycode. Only the non-ASCII parts of the domain name will be converted,\n * i.e. it doesn't matter if you call it with a domain that's already in\n * ASCII.\n * @memberOf punycode\n * @param {String} input The domain name or email address to convert, as a\n * Unicode string.\n * @returns {String} The Punycode representation of the given domain name or\n * email address.\n */\nconst toASCII = function(input) {\n\treturn mapDomain(input, function(string) {\n\t\treturn regexNonASCII.test(string)\n\t\t\t? 'xn--' + encode(string)\n\t\t\t: string;\n\t});\n};\n\n/*--------------------------------------------------------------------------*/\n\n/** Define the public API */\nconst punycode = {\n\t/**\n\t * A string representing the current Punycode.js version number.\n\t * @memberOf punycode\n\t * @type String\n\t */\n\t'version': '2.3.1',\n\t/**\n\t * An object of methods to convert from JavaScript's internal character\n\t * representation (UCS-2) to Unicode code points, and back.\n\t * @see <https://mathiasbynens.be/notes/javascript-encoding>\n\t * @memberOf punycode\n\t * @type Object\n\t */\n\t'ucs2': {\n\t\t'decode': ucs2decode,\n\t\t'encode': ucs2encode\n\t},\n\t'decode': decode,\n\t'encode': encode,\n\t'toASCII': toASCII,\n\t'toUnicode': toUnicode\n};\n\nmodule.exports = punycode;\n","","'use strict';\r\n// IDNA2008 validator using idnaMappingTableCompact.json\r\nconst punycode = require('punycode/');\r\nconst { props, viramas, ranges, mappings, bidi_ranges, joining_type_ranges } = require('./idnaMappingTableCompact.json');\r\n// --- Error classes (short messages; RFC refs included in message) ---\r\nconst throwIdnaContextJError = (msg) => { throw Object.assign(new SyntaxError(msg), { name: \"IdnaContextJError\" }); };\r\nconst throwIdnaContextOError = (msg) => { throw Object.assign(new SyntaxError(msg), { name: \"IdnaContextOError\" }); };\r\nconst throwIdnaUnicodeError = (msg) => { throw Object.assign(new SyntaxError(msg), { name: \"IdnaUnicodeError\" }); };\r\nconst throwIdnaLengthError = (msg) => { throw Object.assign(new SyntaxError(msg), { name: \"IdnaLengthError\" }); };\r\nconst throwIdnaSyntaxError = (msg) => { throw Object.assign(new SyntaxError(msg), { name: \"IdnaSyntaxError\" }); };\r\nconst throwPunycodeError = (msg) => { throw Object.assign(new SyntaxError(msg), { name: \"PunycodeError\" }); };\r\nconst throwIdnaBidiError = (msg) => { throw Object.assign(new SyntaxError(msg), { name: \"IdnaBidiError\" }); };\r\n// --- constants ---\r\nconst ZWNJ = 0x200c;\r\nconst ZWJ = 0x200d;\r\nconst MIDDLE_DOT = 0x00b7;\r\nconst GREEK_KERAIA = 0x0375;\r\nconst KATAKANA_MIDDLE_DOT = 0x30fb;\r\nconst HEBREW_GERESH = 0x05f3;\r\nconst HEBREW_GERSHAYIM = 0x05f4;\r\n// Viramas (used for special ZWJ/ZWNJ acceptance)\r\nconst VIRAMAS = new Set(viramas);\r\n// binary range lookup\r\nfunction getRange(range, key) {\r\n if (!Array.isArray(range) || range.length === 0) return null;\r\n let lb = 0;\r\n let ub = range.length - 1;\r\n while (lb <= ub) {\r\n const mid = (lb + ub) >> 1;\r\n const r = range[mid];\r\n if (key < r[0]) ub = mid - 1;\r\n else if (key > r[1]) lb = mid + 1;\r\n else return r[2];\r\n }\r\n return null;\r\n}\r\n// mapping label (disallowed chars were removed from ranges, so undefined means disallowed or unassigned)\r\nfunction uts46map(label) {\r\n const mappedCps = [];\r\n for (let i = 0; i < label.length; ) {\r\n const cp = label.codePointAt(i);\r\n const prop = props[getRange(ranges, cp)];\r\n const maps = mappings[String(cp)];\r\n // mapping cases\r\n if (prop === 'mapped' && Array.isArray(maps) && maps.length) {\r\n for (const mcp of maps) mappedCps.push(mcp);\r\n } else if (prop === 'valid' || prop === 'deviation') {\r\n mappedCps.push(cp);\r\n } else if (prop === 'ignored') {\r\n // drop\r\n } else {\r\n throwIdnaUnicodeError(`${cpHex(cp)} is disallowed in hostname (RFC 5892, UTS #46).`);\r\n }\r\n i += cp > 0xffff ? 2 : 1;\r\n }\r\n // mapped → label\r\n return String.fromCodePoint(...mappedCps);\r\n}\r\n// --- helpers ---\r\nfunction cpHex(cp) {\r\n return `char '${String.fromCodePoint(cp)}' ` + JSON.stringify('(U+' + cp.toString(16).toUpperCase().padStart(4, '0') + ')');\r\n}\r\n// main validator\r\nfunction isIdnHostname(hostname) {\r\n // basic hostname checks\r\n if (typeof hostname !== 'string') throwIdnaSyntaxError('Label must be a string (RFC 5890 §2.3.2.3).');\r\n // split hostname in labels by the separators defined in uts#46 §2.3\r\n const rawLabels = hostname.split(/[\\x2E\\uFF0E\\u3002\\uFF61]/);\r\n if (rawLabels.some((label) => label.length === 0)) throwIdnaLengthError('Label cannot be empty (consecutive or leading/trailing dot) (RFC 5890 §2.3.2.3).');\r\n // checks per label (IDNA is defined for labels, not for parts of them and not for complete domain names. RFC 5890 §2.3.2.1)\r\n let aceHostnameLength = 0;\r\n for (const rawLabel of rawLabels) {\r\n // ACE label (xn--) validation: decode and re-encode must match\r\n let label = rawLabel;\r\n if (/^xn--/i.test(rawLabel)) {\r\n if (/[^\\p{ASCII}]/u.test(rawLabel)) throwIdnaSyntaxError(`A-label '${rawLabel}' cannot contain non-ASCII character(s) (RFC 5890 §2.3.2.1).`);\r\n const aceBody = rawLabel.slice(4);\r\n try {\r\n label = punycode.decode(aceBody);\r\n } catch (e) {\r\n throwPunycodeError(`Invalid ASCII Compatible Encoding (ACE) of label '${rawLabel}' (RFC 5891 §4.4 → RFC 3492).`);\r\n }\r\n if (!/[^\\p{ASCII}]/u.test(label)) throwIdnaSyntaxError(`decoded A-label '${rawLabel}' result U-label '${label}' cannot be empty or all-ASCII character(s) (RFC 5890 §2.3.2.1).`);\r\n if (punycode.encode(label) !== aceBody) throwPunycodeError(`Re-encode mismatch for ASCII Compatible Encoding (ACE) label '${rawLabel}' (RFC 5891 §4.4 → RFC 3492).`);\r\n }\r\n // mapping phase (here because decoded A-label may contain disallowed chars)\r\n label = uts46map(label).normalize('NFC');\r\n // final ACE label lenght accounting\r\n let aceLabel;\r\n try {\r\n aceLabel = /[^\\p{ASCII}]/u.test(label) ? punycode.toASCII(label) : label;\r\n } catch (e) {\r\n throwPunycodeError(`ASCII conversion failed for '${label}' (RFC 3492).`);\r\n }\r\n if (aceLabel.length > 63) throwIdnaLengthError('Final ASCII Compatible Encoding (ACE) label cannot exceed 63 bytes (RFC 5890 §2.3.2.1).');\r\n aceHostnameLength += aceLabel.length + 1;\r\n // hyphen rules (the other one is covered by bidi)\r\n if (/^-|-$/.test(label)) throwIdnaSyntaxError('Label cannot begin or end with hyphen-minus (RFC 5891 §4.2.3.1).');\r\n if (label.indexOf('--') === 2) throwIdnaSyntaxError('Label cannot contain consecutive hyphen-minus in the 3rd and 4th positions (RFC 5891 §4.2.3.1).');\r\n // leading combining marks check (some are not covered by bidi)\r\n if (/^\\p{M}$/u.test(String.fromCodePoint(label.codePointAt(0)))) throwIdnaSyntaxError(`Label cannot begin with combining/enclosing mark ${cpHex(label.codePointAt(0))} (RFC 5891 §4.2.3.2).`);\r\n // spread cps for context and bidi checks\r\n const cps = Array.from(label).map((char) => char.codePointAt(0));\r\n let joinTypes = '';\r\n let digits = '';\r\n let bidiClasses = [];\r\n // per-codepoint contextual checks\r\n for (let j = 0; j < cps.length; j++) {\r\n const cp = cps[j];\r\n // check ContextJ ZWNJ (uses joining types and virama rule)\r\n if (cps.includes(ZWNJ)) {\r\n joinTypes += VIRAMAS.has(cp) ? 'V' : cp === ZWNJ ? 'Z' : getRange(joining_type_ranges, cp) || 'U';\r\n if (j === cps.length - 1 && /(?![LD][T]*)(?<!V)Z(?![T]*[RD])/.test(joinTypes)) throwIdnaContextJError(`char ${JSON.stringify('U+200C')} (ZWNJ) has invalid join context: '${joinTypes}' (RFC 5892 Appendix A.1).`);\r\n }\r\n // check ContextJ ZWJ (must be preceded by virama)\r\n if (cp === ZWJ) {\r\n if (j === 0 || !VIRAMAS.has(cps[j - 1])) {\r\n throwIdnaContextJError(`${cpHex(cp)} cannot appear at start or without a Virama before (RFC 5892 Appendix A.2).`);\r\n }\r\n }\r\n // check ContextO MIDDLE_DOT\r\n if (cp === MIDDLE_DOT) {\r\n if (j === 0 || j === cps.length - 1 || !(cps[j - 1] === 0x6c && cps[j + 1] === 0x6c)) throwIdnaContextOError(`${cpHex(cp)} must be between two ASCII 'l' characters (RFC 5892 A.3).`);\r\n }\r\n // check ContextO GREEK_KERAIA, must be followed by a Greek character (next non-spacing mark)\r\n if (cp === GREEK_KERAIA) {\r\n if (!/^\\p{Mn}*\\p{sc=Greek}$/u.test(String.fromCodePoint(...cps.slice(j + 1)))) throwIdnaContextOError(`${cpHex(cp)} must be followed by Greek script (RFC 5892 A.4).`);\r\n }\r\n // check ContextO HEBREW_GERESH and HEBREW_GERSHAYIM\r\n if (cp === HEBREW_GERESH || cp === HEBREW_GERSHAYIM) {\r\n if (j === 0 || !/^\\p{sc=Hebrew}$/u.test(String.fromCodePoint(cps[j - 1]))) throwIdnaContextOError(`${cpHex(cp)} must be preceded by Hebrew script (RFC 5892 A.5/A.6).`);\r\n }\r\n // check ContextO KATAKANA_MIDDLE_DOT, allowed only if label contains at least one Hiragana / Katakana / Han character\r\n if (cp === KATAKANA_MIDDLE_DOT) {\r\n if (!/[\\p{sc=Hiragana}\\p{sc=Katakana}\\p{sc=Han}]/u.test(String.fromCodePoint(...cps))) {\r\n throwIdnaContextOError(`${cpHex(cp)} requires at least one Hiragana/Katakana/Han in the label (RFC 5892 Appendix A.7).`);\r\n }\r\n }\r\n // check mixed digit sets\r\n if ((cp >= 0x0660 && cp <= 0x0669) || (cp >= 0x06f0 && cp <= 0x06f9)) digits += (cp < 0x06f0 ? 'a' : 'e' );\r\n if (j === cps.length - 1 && /^(?=.*a)(?=.*e).*$/.test(digits)) throwIdnaContextOError('Arabic-Indic digits cannot be mixed with Extended Arabic-Indic digits (RFC 5892 Appendix A.8/A.9).');\r\n // validate bidi\r\n bidiClasses.push(getRange(bidi_ranges, cp));\r\n if (j === cps.length - 1 && (bidiClasses.includes('R') || bidiClasses.includes('AL'))) {\r\n // order of chars in label (RFC 5890 §2.3.3)\r\n if (bidiClasses[0] === 'R' || bidiClasses[0] === 'AL') {\r\n for (let cls of bidiClasses) if (!['R', 'AL', 'AN', 'EN', 'ET', 'ES', 'CS', 'ON', 'BN', 'NSM'].includes(cls)) throwIdnaBidiError(`'${label}' breaks rule #2: Only R, AL, AN, EN, ET, ES, CS, ON, BN, NSM allowed in label (RFC 5893 §2.2)`);\r\n if (!/(R|AL|EN|AN)(NSM)*$/.test(bidiClasses.join(''))) throwIdnaBidiError(`'${label}' breaks rule #3: label must end with R, AL, EN, or AN, followed by zero or more NSM (RFC 5893 §2.3)`);\r\n if (bidiClasses.includes('EN') && bidiClasses.includes('AN')) throwIdnaBidiError(`'${label}' breaks rule #4: EN and AN cannot be mixed in the same label (RFC 5893 §2.4)`);\r\n } else if (bidiClasses[0] === 'L') {\r\n for (let cls of bidiClasses) if (!['L', 'EN', 'ET', 'ES', 'CS', 'ON', 'BN', 'NSM'].includes(cls)) throwIdnaBidiError(`'${label}' breaks rule #5: Only L, EN, ET, ES, CS, ON, BN, NSM allowed in label (RFC 5893 §2.5)`);\r\n if (!/(L|EN)(NSM)*$/.test(bidiClasses.join(''))) throwIdnaBidiError(`'${label}' breaks rule #6: label must end with L or EN, followed by zero or more NSM (RFC 5893 §2.6)`);\r\n } else {\r\n throwIdnaBidiError(`'${label}' breaks rule #1: label must start with L or R or AL (RFC 5893 §2.1)`);\r\n }\r\n }\r\n }\r\n }\r\n if (aceHostnameLength - 1 > 253) throwIdnaLengthError('Final ASCII Compatible Encoding (ACE) hostname cannot exceed 253 bytes (RFC 5890 → RFC 1034 §3.1).');\r\n return true;\r\n}\r\n// return ACE hostname if valid\r\nconst idnHostname = (string) =>\r\n isIdnHostname(string) &&\r\n punycode.toASCII(\r\n string\r\n .split('.')\r\n .map((label) => uts46map(label).normalize('NFC'))\r\n .join('.')\r\n );\r\n// export\r\nmodule.exports = { isIdnHostname, idnHostname, uts46map, punycode };\r\n","/**\n * @import * as API from \"./index.d.ts\"\n */\n\nconst label = `(?!-)[A-Za-z0-9-]{1,63}(?<!-)`;\nconst domain = `${label}(?:\\\\.${label})*`;\n\nconst domainPattern = new RegExp(`^${domain}$`);\n\n/** @type API.isHostname */\nexport const isHostname = (hostname) => {\n return domainPattern.test(hostname) && hostname.length < 256;\n};\n","import { isIdnHostname } from \"idn-hostname\";\nimport { isHostname } from \"./rfc1123.js\";\n\n/**\n * @import * as API from \"./index.d.ts\"\n */\n\n/** @type API.isAsciiIdn */\nexport const isAsciiIdn = (hostname) => {\n return isHostname(hostname) && isIdn(hostname);\n};\n\n/** @type API.isIdn */\nexport const isIdn = (hostname) => {\n try {\n return isIdnHostname(hostname);\n } catch (_error) {\n return false;\n }\n};\n","import { isIdn } from \"./uts46.js\";\n\n/**\n * @import * as API from \"./index.d.ts\"\n */\n\nconst ucschar = `[\\\\u{A0}-\\\\u{D7FF}\\\\u{F900}-\\\\u{FDCF}\\\\u{FDF0}-\\\\u{FFEF}\\\\u{10000}-\\\\u{1FFFD}\\\\u{20000}-\\\\u{2FFFD}\\\\u{30000}-\\\\u{3FFFD}\\\\u{40000}-\\\\u{4FFFD}\\\\u{50000}-\\\\u{5FFFD}\\\\u{60000}-\\\\u{6FFFD}\\\\u{70000}-\\\\u{7FFFD}\\\\u{80000}-\\\\u{8FFFD}\\\\u{90000}-\\\\u{9FFFD}\\\\u{A0000}-\\\\u{AFFFD}\\\\u{B0000}-\\\\u{BFFFD}\\\\u{C0000}-\\\\u{CFFFD}\\\\u{D0000}-\\\\u{DFFFD}\\\\u{E1000}-\\\\u{EFFFD}]`;\n\nconst alpha = `[a-zA-Z]`;\nconst hexdig = `[\\\\da-fA-F]`;\n\n// Printable US-ASCII characters not including specials.\nconst atext = `(?:[\\\\w!#$%&'*+\\\\-/=?^\\`{|}~]|${ucschar})`;\nconst atom = `${atext}+`;\nconst dotString = `${atom}(?:\\\\.${atom})*`;\n\n// Any ASCII graphic or space without blackslash-quoting except double-quote and the backslash itself.\nconst qtextSMTP = `(?:[\\\\x20-\\\\x21\\\\x23-\\\\x5B\\\\x5D-\\\\x7E]|${ucschar})`;\n// backslash followed by any ASCII graphic or space\nconst quotedPairSMTP = `\\\\\\\\[\\\\x20-\\\\x7E]`;\nconst qcontentSMTP = `(?:${qtextSMTP}|${quotedPairSMTP})`;\nconst quotedString = `\"${qcontentSMTP}*\"`;\n\nconst localPart = `(?:${dotString}|${quotedString})`; // MAY be case-sensitive\n\nconst letDig = `(?:${alpha}|\\\\d)`;\nconst ldhStr = `(?:${letDig}|-)*${letDig}`;\nconst letDigUcs = `(?:${alpha}|\\\\d|${ucschar})`;\nconst ldhStrUcs = `(?:${letDigUcs}|-)*${letDigUcs}`;\nconst subDomain = `${letDigUcs}${ldhStrUcs}?`;\nconst domain = `${subDomain}(?:\\\\.${subDomain})*`;\n\nconst decOctet = `(?:\\\\d|[1-9]\\\\d|1\\\\d\\\\d|2[0-4]\\\\d|25[0-5])`;\nconst ipv4Address = `${decOctet}\\\\.${decOctet}\\\\.${decOctet}\\\\.${decOctet}`;\n\nconst h16 = `${hexdig}{1,4}`;\nconst ls32 = `(?:${h16}:${h16}|${ipv4Address})`;\nconst ipv6Address = `(?:(?:${h16}:){6}${ls32}|::(?:${h16}:){5}${ls32}|(?:${h16})?::(?:${h16}:){4}${ls32}|(?:(?:${h16}:){0,1}${h16})?::(?:${h16}:){3}${ls32}|(?:(?:${h16}:){0,2}${h16})?::(?:${h16}:){2}${ls32}|(?:(?:${h16}:){0,3}${h16})?::(?:${h16}:){1}${ls32}|(?:(?:${h16}:){0,4}${h16})?::${ls32}|(?:(?:${h16}:){0,5}${h16})?::${h16}|(?:(?:${h16}:){0,6}${h16})?::)`;\nconst ipv6AddressLiteral = `IPv6:${ipv6Address}`;\n\nconst dcontent = `[\\\\x21-\\\\x5A\\\\x5E-\\\\x7E]`; // Printable US-ASCII excluding \"[\", \"\\\", \"]\"\nconst generalAddressLiteral = `${ldhStr}:${dcontent}+`;\n\nconst addressLiteral = `\\\\[(?:${ipv4Address}|${ipv6AddressLiteral}|${generalAddressLiteral})\\\\]`;\n\nconst mailbox = `(?<localPart>${localPart})@(?:(?<ip>${addressLiteral})|(?<domain>${domain}))`;\n\nconst mailboxPattern = new RegExp(`^${mailbox}$`, \"u\");\n\n/** @type API.isIdnEmail */\nexport const isIdnEmail = (email) => {\n const parsedEmail = mailboxPattern.exec(email)?.groups;\n\n return !!parsedEmail && (!parsedEmail.domain || isIdn(parsedEmail.domain));\n};\n","/**\n * @import * as API from \"./index.d.ts\"\n */\n\nconst decOctet = `(?:\\\\d|[1-9]\\\\d|1\\\\d\\\\d|2[0-4]\\\\d|25[0-5])`;\nconst ipV4Address = `${decOctet}\\\\.${decOctet}\\\\.${decOctet}\\\\.${decOctet}`;\n\n/**\n * @type API.isIPv4\n * @function\n */\nexport const isIPv4 = RegExp.prototype.test.bind(new RegExp(`^${ipV4Address}$`));\n","/**\n * @import * as API from \"./index.d.ts\"\n */\n\nconst hexdig = `[a-fA-F0-9]`;\n\nconst decOctet = `(?:\\\\d|[1-9]\\\\d|1\\\\d\\\\d|2[0-4]\\\\d|25[0-5])`;\nconst ipV4Address = `${decOctet}\\\\.${decOctet}\\\\.${decOctet}\\\\.${decOctet}`;\n\nconst h16 = `${hexdig}{1,4}`;\nconst ls32 = `(?:${h16}:${h16}|${ipV4Address})`;\nconst ipV6Address = `(?:(?:${h16}:){6}${ls32}|::(?:${h16}:){5}${ls32}|(?:${h16})?::(?:${h16}:){4}${ls32}|(?:(?:${h16}:){0,1}${h16})?::(?:${h16}:){3}${ls32}|(?:(?:${h16}:){0,2}${h16})?::(?:${h16}:){2}${ls32}|(?:(?:${h16}:){0,3}${h16})?::(?:${h16}:){1}${ls32}|(?:(?:${h16}:){0,4}${h16})?::${ls32}|(?:(?:${h16}:){0,5}${h16})?::${h16}|(?:(?:${h16}:){0,6}${h16})?::)`;\n\n/**\n * @type API.isIPv6\n * @function\n */\nexport const isIPv6 = RegExp.prototype.test.bind(new RegExp(`^${ipV6Address}$`));\n","/**\n * @import * as API from \"./index.d.ts\"\n */\n\n/**\n * @template A\n * @typedef {(value: string) => A} Parser\n */\n\n/**\n * @typedef {(value: string) => string} Normalizer\n */\n\n/**\n * @typedef {{\n * parseAbsolute: Parser<API.AbsoluteIdentifierComponents>;\n * parseReference: Parser<API.RelativeIdentifierComponents>;\n * parse: Parser<API.IdentifierComponents>;\n * normalizePath: Normalizer;\n * normalizeQuery: Normalizer;\n * normalizeFragment: Normalizer;\n * }} Strategy\n */\n\n// Common\nconst hexdig = `[a-fA-F0-9]`;\nconst unreserved = `[a-zA-Z0-9-._~]`;\nconst subDelims = `[!$&'()*+,;=]`;\nconst pctEncoded = `%${hexdig}${hexdig}`;\n\nconst decOctet = `(?:\\\\d|[1-9]\\\\d|1\\\\d\\\\d|2[0-4]\\\\d|25[0-5])`;\nconst ipV4Address = `${decOctet}\\\\.${decOctet}\\\\.${decOctet}\\\\.${decOctet}`;\nconst h16 = `${hexdig}{1,4}`;\nconst ls32 = `(?:${h16}:${h16}|${ipV4Address})`;\nconst ipV6Address = `(?:(?:${h16}:){6}${ls32}|::(?:${h16}:){5}${ls32}|(?:${h16})?::(?:${h16}:){4}${ls32}|(?:(?:${h16}:){0,1}${h16})?::(?:${h16}:){3}${ls32}|(?:(?:${h16}:){0,2}${h16})?::(?:${h16}:){2}${ls32}|(?:(?:${h16}:){0,3}${h16})?::(?:${h16}:){1}${ls32}|(?:(?:${h16}:){0,4}${h16})?::${ls32}|(?:(?:${h16}:){0,5}${h16})?::${h16}|(?:(?:${h16}:){0,6}${h16})?::)`;\nconst ipVFuture = `v${hexdig}+\\\\.(?:${unreserved}|${subDelims}|:)+`;\nconst ipLiteral = `\\\\[(?:${ipV6Address}|${ipVFuture})\\\\]`;\nconst scheme = `(?<scheme>[a-zA-Z][a-zA-Z0-9-+.]*)`;\nconst port = `:(?<port>\\\\d*)`;\n\n// URI\nconst regName = `(?:${unreserved}|${pctEncoded}|${subDelims})*?`;\nconst host = `(?<host>${ipLiteral}|${ipV4Address}|${regName})`;\nconst userinfo = `(?<userinfo>(?:${unreserved}|${pctEncoded}|${subDelims}|:)*)`;\nconst pchar = `(?:${unreserved}|${pctEncoded}|${subDelims}|:|@)`;\nconst segment = `${pchar}*?`;\nconst pathAbEmpty = `(?:/${segment})*`;\n\nconst authority = `(?<authority>(?:${userinfo}@)?${host}(?:${port})?)`;\nconst path = `(?<path>${pathAbEmpty})`;\nconst pathWithoutAuthority = `(?<path2>(?!//)${segment}${pathAbEmpty})`;\nconst query = `(?:\\\\?(?<query>(?:${pchar}|/|\\\\?)*))?`;\nconst fragment = `(?:#(?<fragment>(?:${pchar}|/|\\\\?)*))?`;\n\nconst uri = `^${scheme}:(?://${authority}${path}|${pathWithoutAuthority})${query}${fragment}$`;\nconst uriReference = `^(?:${scheme}:|)(?://${authority}${path}|${pathWithoutAuthority})${query}${fragment}$`;\nconst absoluteUri = `^${scheme}:(?://${authority}${path}|${pathWithoutAuthority})${query}$`;\n\n// IRI\nconst iunreserved = `[a-zA-Z0-9\\\\-._~\\\\u{A0}-\\\\u{D7FF}\\\\u{F900}-\\\\u{FDCF}\\\\u{FDF0}-\\\\u{FFEF}\\\\u{10000}-\\\\u{1FFFD}\\\\u{20000}-\\\\u{2FFFD}\\\\u{30000}-\\\\u{3FFFD}\\\\u{40000}-\\\\u{4FFFD}\\\\u{50000}-\\\\u{5FFFD}\\\\u{60000}-\\\\u{6FFFD}\\\\u{70000}-\\\\u{7FFFD}\\\\u{80000}-\\\\u{8FFFD}\\\\u{90000}-\\\\u{9FFFD}\\\\u{A0000}-\\\\u{AFFFD}\\\\u{B0000}-\\\\u{BFFFD}\\\\u{C0000}-\\\\u{CFFFD}\\\\u{D0000}-\\\\u{DFFFD}\\\\u{E1000}-\\\\u{EFFFD}]`;\nconst iprivate = `[\\\\u{E000}-\\\\u{F8FF}\\\\u{F0000}-\\\\u{FFFFD}\\\\u{100000}-\\\\u{10FFFD}]`;\n\nconst iregName = `(?:${iunreserved}|${pctEncoded}|${subDelims})*?`;\nconst ihost = `(?<host>${ipLiteral}|${ipV4Address}|${iregName})`;\nconst iuserinfo = `(?<userinfo>(?:${iunreserved}|${pctEncoded}|${subDelims}|:)*)`;\nconst ipchar = `(?:${iunreserved}|${pctEncoded}|${subDelims}|:|@)`;\nconst isegment = `${ipchar}*?`;\nconst ipathAbEmpty = `(?:/${isegment})*`;\n\nconst iauthority = `(?<authority>(?:${iuserinfo}@)?${ihost}(?:${port})?)`;\nconst ipath = `(?<path>${ipathAbEmpty})`;\nconst ipathWithoutAuthority = `(?<path2>(?!//)${isegment}${ipathAbEmpty})`;\nconst iquery = `(?:\\\\?(?<query>(?:${ipchar}|${iprivate}|/|\\\\?)*))?`;\nconst ifragment = `(?:#(?<fragment>(?:${ipchar}|/|\\\\?)*))?`;\n\nconst iri = `^${scheme}:(?://${iauthority}${ipath}|${ipathWithoutAuthority})${iquery}${ifragment}$`;\nconst iriReference = `^(?:${scheme}:|)(?://${iauthority}${ipath}|${ipathWithoutAuthority})${iquery}${ifragment}$`;\nconst absoluteIri = `^${scheme}:(?://${iauthority}${ipath}|${ipathWithoutAuthority})${iquery}$`;\n\n// Components\n/** @type (strategy: Strategy) => (reference: string, base: string) => string */\nconst resolveReference = (strategy) => (reference, base) => {\n const resolvedComponents = /** @type API.IdentifierComponents */ (strategy.parseReference(reference));\n\n if (resolvedComponents.scheme === undefined) {\n const baseComponents = strategy.parseAbsolute(base);\n resolvedComponents.scheme = baseComponents.scheme;\n\n if (resolvedComponents.authority === undefined) {\n resolvedComponents.authority = baseComponents.authority;\n resolvedComponents.userinfo = baseComponents.userinfo;\n resolvedComponents.host = baseComponents.host;\n resolvedComponents.port = baseComponents.port;\n\n if (resolvedComponents.path === \"\") {\n resolvedComponents.path = baseComponents.path;\n\n resolvedComponents.query ??= baseComponents.query;\n } else if (!resolvedComponents.path.startsWith(\"/\")) {\n resolvedComponents.path = mergePaths(resolvedComponents.path, baseComponents);\n }\n }\n }\n\n return composeIdentifier(strategy, resolvedComponents);\n};\n\n/** @type (path: string, base: API.IdentifierComponents) => string */\nconst mergePaths = (path, base) => {\n if (base.authority && base.path === \"\") {\n return \"/\" + path;\n } else {\n const position = base.path.lastIndexOf(\"/\");\n return position === -1 ? path : base.path.slice(0, position + 1) + path;\n }\n};\n\nconst isNoOpSegment = /^\\.?\\.\\/|^\\.\\.?$/;\nconst isSlashDotSegment = /^\\/\\.(?:\\/|$)/;\nconst isUpSegment = /^\\/\\.\\.(?:\\/|$)/;\n\n/** @type (path: string) => string */\nconst removeDotSegments = (path) => {\n let output = \"\";\n\n while (path.length > 0) {\n if (isNoOpSegment.test(path)) {\n path = removeSegment(path);\n } else if (isSlashDotSegment.test(path)) {\n path = replaceSegmentWithSlash(path);\n } else if (isUpSegment.test(path)) {\n path = replaceSegmentWithSlash(path);\n output = removeLastSegment(output);\n } else {\n const segment = getSegment(path);\n path = removeSegment(path);\n output += segment;\n }\n }\n\n return output;\n};\n\n/** @type (path: string) => string */\nconst removeSegment = (path) => {\n const position = path.indexOf(\"/\", 1);\n return position === -1 ? \"\" : \"/\" + path.slice(position + 1);\n};\n\n/** @type (path: string) => string */\nconst replaceSegmentWithSlash = (path) => {\n const position = path.indexOf(\"/\", 1);\n return position === -1 ? \"/\" : \"/\" + path.slice(position + 1);\n};\n\n/** @type (path: string) => string */\nconst removeLastSegment = (path) => {\n const position = path.lastIndexOf(\"/\");\n return position === -1 ? path : path.slice(0, position);\n};\n\n/** @type (path: string) => string */\nconst getSegment = (path) => {\n const position = path.indexOf(\"/\", 1);\n return position === -1 ? path : path.slice(0, position);\n};\n\n/** @type (strategy: Strategy, components: API.IdentifierComponents) => string */\nconst composeIdentifier = (strategy, components) => {\n let resolved = components.scheme.toLowerCase() + \":\";\n resolved += components.authority === undefined ? \"\" : \"//\"\n + (components.userinfo === undefined ? \"\" : components.userinfo + \"@\")\n + components.host.toLowerCase()\n + (components.port === undefined ? \"\" : \":\" + components.port);\n resolved += strategy.normalizePath(components.path);\n resolved += components.query === undefined ? \"\" : \"?\" + strategy.normalizeQuery(components.query);\n resolved += components.fragment === undefined ? \"\" : \"#\" + strategy.normalizeFragment(components.fragment);\n\n return resolved;\n};\n\nconst percentEncoded = new RegExp(pctEncoded, \"g\");\n\n/** @type (isAllowed: (value: string) => boolean) => (match: string) => string */\nconst percentEncodedToChar = (isAllowed) => (match) => {\n const charCode = parseInt(match.slice(1), 16);\n const char = String.fromCharCode(charCode);\n\n return isAllowed(char) ? char : match.toUpperCase();\n};\n\nconst isAllowedUnescapedInPath = RegExp.prototype.test.bind(new RegExp(`${unreserved}|${subDelims}|[:@]`));\nconst isAllowedUnescapedInIPath = RegExp.prototype.test.bind(new RegExp(`${iunreserved}|${subDelims}|[:@]`, \"u\"));\n\n/** @type (isAllowed: (value: string) => boolean) => (segment: string) => string */\nconst normalizePath = (isAllowed) => (segment) => removeDotSegments(segment).replaceAll(percentEncoded, percentEncodedToChar(isAllowed));\n\nconst isAllowedUnescapedInQuery = RegExp.prototype.test.bind(new RegExp(`${unreserved}|${subDelims}|[:@/?]`));\nconst isAllowedUnescapedInIQuery = RegExp.prototype.test.bind(new RegExp(`${iunreserved}|${subDelims}|[:@/?]`, \"u\"));\n\n/** @type (isAllowed: (value: string) => boolean) => (segment: string) => string */\nconst normalizeQuery = (isAllowed) => (query) => query.replaceAll(percentEncoded, percentEncodedToChar(isAllowed));\n\n// API\n/** @type API.isUri */\nexport const isUri = RegExp.prototype.test.bind(new RegExp(uri));\n/** @type API.isUriReference */\nexport const isUriReference = RegExp.prototype.test.bind(new RegExp(uriReference));\n/** @type API.isAbsoluteUri */\nexport const isAbsoluteUri = RegExp.prototype.test.bind(new RegExp(absoluteUri));\n\n/** @type API.isIri */\nexport const isIri = RegExp.prototype.test.bind(new RegExp(iri, \"u\"));\n/** @type API.isIriReference */\nexport const isIriReference = RegExp.prototype.test.bind(new RegExp(iriReference, \"u\"));\n/** @type API.isAbsoluteIri */\nexport const isAbsoluteIri = RegExp.prototype.test.bind(new RegExp(absoluteIri, \"u\"));\n\n/**\n * @type (pattern: RegExp, type: string) => (value: string) => any\n */\nconst createParser = (pattern, type) => (value) => {\n const match = pattern.exec(value);\n if (match === null) {\n throw Error(`Invalid ${type}: ${value}`);\n }\n const groups = /** @type Record<string, string> */ (match.groups);\n if (groups.authority === undefined) {\n groups.path = groups.path2;\n }\n delete groups.path2;\n\n return groups;\n};\n\n/** @type API.parseUri */\nexport const parseUri = createParser(new RegExp(uri), \"URI\");\n/** @type API.parseUriReference */\nexport const parseUriReference = createParser(new RegExp(uriReference), \"URI-reference\");\n/** @type API.parseAbsoluteUri */\nexport const parseAbsoluteUri = createParser(new RegExp(absoluteUri), \"absolute-URI\");\n\n/** @type API.parseIri */\nexport const parseIri = createParser(new RegExp(iri, \"u\"), \"IRI\");\n/** @type API.parseIriReference */\nexport const parseIriReference = createParser(new RegExp(iriReference, \"u\"), \"IRI-reference\");\n/** @type API.parseAbsoluteIri */\nexport const parseAbsoluteIri = createParser(new RegExp(absoluteIri, \"u\"), \"absolute-IRI\");\n\n/** @type Record<string, Strategy> */\nconst strategies = {\n uri: {\n parseAbsolute: parseAbsoluteUri,\n parseReference: parseUriReference,\n parse: parseUri,\n normalizePath: normalizePath(isAllowedUnescapedInPath),\n normalizeQuery: normalizeQuery(isAllowedUnescapedInQuery),\n normalizeFragment: normalizeQuery(isAllowedUnescapedInQuery)\n },\n iri: {\n parseAbsolute: parseAbsoluteIri,\n parseReference: parseIriReference,\n parse: parseIri,\n normalizePath: normalizePath(isAllowedUnescapedInIPath),\n normalizeQuery: normalizeQuery(isAllowedUnescapedInIQuery),\n normalizeFragment: normalizeQuery(isAllowedUnescapedInIQuery)\n }\n};\n\n/** @type (strategy: Strategy) => (identifier: string) => string */\nconst toAbsolute = (strategy) => (identifier) => {\n const components = strategy.parse(identifier);\n delete components.fragment;\n return composeIdentifier(strategy, components);\n};\n\n/** @type API.toAbsoluteUri */\nexport const toAbsoluteUri = toAbsolute(strategies.uri);\n/** @type API.toAbsoluteIri */\nexport const toAbsoluteIri = toAbsolute(strategies.iri);\n\n/** @type (strategy: Strategy) => (identifier: string) => string */\nconst normalize = (strategy) => (identifier) => {\n const components = strategy.parse(identifier);\n return composeIdentifier(strategy, components);\n};\n\n/** @type API.normalizeUri */\nexport const normalizeUri = normalize(strategies.uri);\n/** @type API.normalizeIri */\nexport const normalizeIri = normalize(strategies.iri);\n\n/** @type API.resolveUri */\nexport const resolveUri = resolveReference(strategies.uri);\n/** @type API.resolveIri */\nexport const resolveIri = resolveReference(strategies.iri);\n\n/** @type (strategy: Strategy) => (uri: string, relativeTo: string) => string */\nconst toRelative = (strategy) => (uri, relativeTo) => {\n const fromUri = strategy.parseAbsolute(uri);\n const toUri = strategy.parse(relativeTo);\n\n if (toUri.scheme !== fromUri.scheme) {\n return relativeTo;\n }\n\n