@coroboros/uri 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["ipv6Regexp"],"sources":["../src/config/index.ts","../src/helpers/object.ts","../src/checkers/chars.ts","../src/ip/index.ts","../src/punycode/index.ts","../src/domain/index.ts","../src/helpers/cast.ts","../src/helpers/error.ts","../src/parser/index.ts","../src/sitemap/index.ts","../src/checkers/index.ts","../src/decoders/index.ts","../src/encoders/index.ts","../src/resolver/index.ts"],"sourcesContent":["/**\n * config module\n */\n\nconst maxLengthURL = 2048;\nconst minPortInteger = 0;\nconst maxPortInteger = 65535;\n\nexport { maxLengthURL, maxPortInteger, minPortInteger };\n","/**\n * Internal type guards.\n *\n * - exists(thing) -> boolean\n * - is(Type, thing) -> boolean\n */\n\n/**\n * Whether the specified value is not null, undefined or NaN.\n */\nconst exists = function exists<T>(thing: T): thing is NonNullable<T> {\n return !(thing === undefined || thing === null || Number.isNaN(thing as number));\n};\n\ntype SupportedConstructor =\n | StringConstructor\n | NumberConstructor\n | BooleanConstructor\n | ArrayConstructor;\n\n/**\n * Whether the specified value is from the specified type regarding its whole prototype.\n */\nfunction is(Type: StringConstructor, thing: unknown): thing is string;\nfunction is(Type: NumberConstructor, thing: unknown): thing is number;\nfunction is(Type: BooleanConstructor, thing: unknown): thing is boolean;\nfunction is(Type: ArrayConstructor, thing: unknown): thing is unknown[];\nfunction is(Type: SupportedConstructor, thing: unknown): boolean {\n return (\n exists(Type) &&\n exists(thing) &&\n ((thing as { constructor?: unknown }).constructor === Type || thing instanceof Type)\n );\n}\n\nexport { exists, is };\n","/**\n * chars checkers\n *\n * - isSchemeChar(char, { start } = {}) -> Boolean\n * - isUserinfoChar(char, encode) -> Boolean\n * - isSitemapUserinfoChar(char, encode) -> Boolean\n * - isDomainChar(char, { start, end } = {}) -> Boolean\n * - isPathChar(char, encode) -> Boolean\n * - isSitemapPathChar(char, encode) -> Boolean\n * - isQueryOrFragmentChar(char, encode) -> Boolean\n * - isSitemapQueryOrFragmentChar(char, encode) -> Boolean\n * - isPercentEncodingChar(char) -> Boolean\n */\nimport { is } from '../helpers/object.js';\n\n/**\n * @func isSchemeChar\n *\n * Check scheme legal ascii codes according to\n * - RFC-3986 https://tools.ietf.org/html/rfc3986#section-3.1.\n *\n * Scheme must start with a letter and be followed by any combination of\n * letters, digits, plus (\"+\"), period (\".\"), or hyphen (\"-\").\n *\n * Letters must be in lowercase.\n *\n * 43 +\n * 45 -\n * 46 .\n * 48 to 57 0-9\n * 97 to 122 a-z\n */\nconst isSchemeChar = function isSchemeChar(\n char: string,\n { start }: { start?: boolean } = {},\n): boolean {\n if (!is(String, char)) {\n return false;\n }\n\n const code = char.charCodeAt(0);\n\n if (start) {\n return code >= 97 && code <= 122;\n }\n\n return (\n (code >= 48 && code <= 57) ||\n (code >= 97 && code <= 122) ||\n code === 43 ||\n code === 45 ||\n code === 46\n );\n};\n\n/**\n * @func isUserinfoChar\n *\n * Check userinfo legal ascii codes according to\n * - RFC-3986 https://tools.ietf.org/html/rfc3986#section-3.2.1.\n *\n * 33 !\n * 36 $\n * 37 % (not allowed when encoding)\n * 38 to 46 &'()*+,-.\n * 48 to 57 0-9\n * 58 :\n * 59 ;\n * 61 =\n * 65 to 90 A-Z\n * 95 _\n * 97 to 122 a-z\n * 126 ~\n */\nconst isUserinfoChar = function isUserinfoChar(char: string, encode?: boolean): boolean {\n if (!is(String, char)) {\n return false;\n }\n\n // false by default\n const encoding = encode === true;\n const code = char.charCodeAt(0);\n\n // % is not allowed when encoding\n if (code === 37) {\n return !encoding;\n }\n\n return (\n (code >= 38 && code <= 46) ||\n (code >= 48 && code <= 57) ||\n (code >= 65 && code <= 90) ||\n (code >= 97 && code <= 122) ||\n code === 33 ||\n code === 36 ||\n code === 58 ||\n code === 59 ||\n code === 61 ||\n code === 95 ||\n code === 126\n );\n};\n\n/**\n * @func isSitemapUserinfoChar\n *\n * Check sitemap userinfo legal ascii codes according to\n * - RFC-3986 https://tools.ietf.org/html/rfc3986#section-3.2.1;\n * - https://support.google.com/webmasters/answer/183668?hl=en&ref_topic=4581190.\n *\n * Removed AZ ' and *\n *\n * 33 !\n * 36 $\n * 37 % (not allowed when encoding)\n * 38 & (allowed but must be a proper escape code)\n * 40 to 41 ()\n * 43 to 46 +,-.\n * 48 to 57 0-9\n * 58 :\n * 59 ;\n * 61 =\n * 95 _\n * 97 to 122 a-z\n * 126 ~\n */\nconst isSitemapUserinfoChar = function isSitemapUserinfoChar(\n char: string,\n encode?: boolean,\n): boolean {\n if (!is(String, char)) {\n return false;\n }\n\n // false by default\n const encoding = encode === true;\n const code = char.charCodeAt(0);\n\n // % is not allowed when encoding\n if (code === 37) {\n return !encoding;\n }\n\n return (\n (code >= 40 && code <= 41) ||\n (code >= 43 && code <= 46) ||\n (code >= 48 && code <= 57) ||\n (code >= 97 && code <= 122) ||\n code === 33 ||\n code === 36 ||\n code === 38 ||\n code === 58 ||\n code === 59 ||\n code === 61 ||\n code === 95 ||\n code === 126\n );\n};\n\n/**\n * @func isDomainChar\n *\n * Check domain legal codes according to\n * - RFC-1034 https://www.ietf.org/rfc/rfc1034.txt.\n *\n * 45 -\n * 48 to 57 0-9\n * 97 to 122 a-z\n */\nconst isDomainChar = function isDomainChar(\n char: string,\n { start, end }: { start?: boolean; end?: boolean } = {},\n): boolean {\n if (!is(String, char)) {\n return false;\n }\n\n const code = char.charCodeAt(0);\n\n if ((start === true || end === true) && code === 45) {\n return false;\n }\n\n return (code >= 48 && code <= 57) || (code >= 97 && code <= 122) || code === 45;\n};\n\n/**\n * @func isPathChar\n *\n * Check path legal ascii codes according to\n * - RFC-3986 https://tools.ietf.org/html/rfc3986#section-3.3.\n *\n * 33 !\n * 36 to 59 $%&'()*+,-./0-9:;\n * 61 =\n * 64 to 90 @A-Z\n * 95 _\n * 97 to 122 a-z\n * 126 ~\n */\nconst isPathChar = function isPathChar(char: string, encode?: boolean): boolean {\n if (!is(String, char)) {\n return false;\n }\n\n // false by default\n const encoding = encode === true;\n const code = char.charCodeAt(0);\n\n // % is not allowed when encoding\n if (code === 37) {\n return !encoding;\n }\n\n return (\n (code >= 36 && code <= 59) ||\n (code >= 64 && code <= 90) ||\n (code >= 97 && code <= 122) ||\n code === 33 ||\n code === 61 ||\n code === 95 ||\n code === 126\n );\n};\n\n/**\n * @func isSitemapPathChar\n *\n * Check path legal ascii codes according to\n * - RFC-3986 https://tools.ietf.org/html/rfc3986#section-3.3.\n *\n * Removed AZ ' and *\n *\n * 33 !\n * 36 to 38 $%& (& allowed but must be a proper escape code)\n * 40 to 41 ()\n * 43 to 59 +,-./0-9:;\n * 61 =\n * 64 @\n * 95 _\n * 97 to 122 a-z\n * 126 ~\n */\nconst isSitemapPathChar = function isSitemapPathChar(char: string, encode?: boolean): boolean {\n if (!is(String, char)) {\n return false;\n }\n\n // false by default\n const encoding = encode === true;\n const code = char.charCodeAt(0);\n\n // % is not allowed when encoding\n if (code === 37) {\n return !encoding;\n }\n\n return (\n (code >= 36 && code <= 38) ||\n (code >= 40 && code <= 41) ||\n (code >= 43 && code <= 59) ||\n (code >= 97 && code <= 122) ||\n code === 33 ||\n code === 61 ||\n code === 64 ||\n code === 95 ||\n code === 126\n );\n};\n\n/**\n * @func isQueryOrFragmentChar\n *\n * Check query/fragment legal ascii codes according to\n * - RFC-3986 https://tools.ietf.org/html/rfc3986#section-3.4;\n * - RFC-3986 https://tools.ietf.org/html/rfc3986#section-3.5.\n *\n * path char\n * 63 ?\n */\nconst isQueryOrFragmentChar = function isQueryOrFragmentChar(\n char: string,\n encode?: boolean,\n): boolean {\n if (isPathChar(char, encode)) {\n return true;\n }\n\n return is(String, char) && char.charCodeAt(0) === 63;\n};\n\n/**\n * @func isSitemapQueryOrFragmentChar\n *\n * Check query/fragment legal ascii codes according to\n * - RFC-3986 https://tools.ietf.org/html/rfc3986#section-3.4;\n * - RFC-3986 https://tools.ietf.org/html/rfc3986#section-3.5.\n *\n * sitemap path char\n * 63 ?\n */\nconst isSitemapQueryOrFragmentChar = function isSitemapQueryOrFragmentChar(\n char: string,\n encode?: boolean,\n): boolean {\n if (isSitemapPathChar(char, encode)) {\n return true;\n }\n\n return is(String, char) && char.charCodeAt(0) === 63;\n};\n\n/**\n * @func isPercentEncodingChar\n *\n * Check percent encoding legal ascii codes according to RFC-3986 https://tools.ietf.org/html/rfc3986#section-2.1.\n *\n * HEXDIG is case-insensitive: %3a and %3A are equivalent\n * (RFC-3986 https://tools.ietf.org/html/rfc3986#section-6.2.2.1).\n *\n * 48 to 57 0-9\n * 65 to 70 A-F\n * 97 to 102 a-f\n */\nconst isPercentEncodingChar = function isPercentEncodingChar(char: string): boolean {\n if (!is(String, char)) {\n return false;\n }\n\n const code = char.charCodeAt(0);\n\n return (code >= 48 && code <= 57) || (code >= 65 && code <= 70) || (code >= 97 && code <= 102);\n};\n\nexport {\n isDomainChar,\n isPathChar,\n isPercentEncodingChar,\n isQueryOrFragmentChar,\n isSchemeChar,\n isSitemapPathChar,\n isSitemapQueryOrFragmentChar,\n isSitemapUserinfoChar,\n isUserinfoChar,\n};\n","/**\n * IP validator\n *\n * - isIP(ip) -> Boolean\n * - isIPv4(ip) -> Boolean\n * - isIPv6(ip) -> Boolean\n */\nimport { is } from '../helpers/object.js';\n\n// ip regexps, credits: https://github.com/sindresorhus/ip-regex/blob/master/index.js\nconst v4 =\n '(?:25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]\\\\d|\\\\d)(?:\\\\.(?:25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]\\\\d|\\\\d)){3}';\nconst v6seg = '[a-fA-F\\\\d]{1,4}';\nconst v6 = `\n(\n(?:${v6seg}:){7}(?:${v6seg}|:)| // 1:2:3:4:5:6:7:: 1:2:3:4:5:6:7:8\n(?:${v6seg}:){6}(?:${v4}|:${v6seg}|:)| // 1:2:3:4:5:6:: 1:2:3:4:5:6::8 1:2:3:4:5:6::8 1:2:3:4:5:6::1.2.3.4\n(?:${v6seg}:){5}(?::${v4}|(:${v6seg}){1,2}|:)| // 1:2:3:4:5:: 1:2:3:4:5::7:8 1:2:3:4:5::8 1:2:3:4:5::7:1.2.3.4\n(?:${v6seg}:){4}(?:(:${v6seg}){0,1}:${v4}|(:${v6seg}){1,3}|:)| // 1:2:3:4:: 1:2:3:4::6:7:8 1:2:3:4::8 1:2:3:4::6:7:1.2.3.4\n(?:${v6seg}:){3}(?:(:${v6seg}){0,2}:${v4}|(:${v6seg}){1,4}|:)| // 1:2:3:: 1:2:3::5:6:7:8 1:2:3::8 1:2:3::5:6:7:1.2.3.4\n(?:${v6seg}:){2}(?:(:${v6seg}){0,3}:${v4}|(:${v6seg}){1,5}|:)| // 1:2:: 1:2::4:5:6:7:8 1:2::8 1:2::4:5:6:7:1.2.3.4\n(?:${v6seg}:){1}(?:(:${v6seg}){0,4}:${v4}|(:${v6seg}){1,6}|:)| // 1:: 1::3:4:5:6:7:8 1::8 1::3:4:5:6:7:1.2.3.4\n(?::((?::${v6seg}){0,5}:${v4}|(?::${v6seg}){1,7}|:)) // ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::1.2.3.4\n)(%[0-9a-zA-Z]{1,})? // %eth0 %1\n`\n .replace(/\\s*\\/\\/.*$/gm, '')\n .replace(/\\n/g, '')\n .trim();\n\n// compiled once at module load — these patterns are stateless (no `g` flag)\nconst ipv4Regexp = new RegExp(`^${v4}$`);\nconst ipv6Regexp = new RegExp(`^${v6}$`);\nconst ipRegexp = new RegExp(`(?:^${v4}$)|(?:^${v6}$)`);\n\n/**\n * @func isIP\n *\n * Test a string is a valid IP.\n */\nconst isIP = function isIP(ip: string): boolean {\n if (!is(String, ip)) {\n return false;\n }\n\n return ipRegexp.test(ip);\n};\n\n/**\n * @func isIPv4\n *\n * Test a string is a valid IPv4.\n */\nconst isIPv4 = function isIPv4(ip: string): boolean {\n if (!is(String, ip)) {\n return false;\n }\n\n return ipv4Regexp.test(ip);\n};\n\n/**\n * @func isIPv6\n *\n * Test a string is a valid IPv6.\n */\nconst isIPv6 = function isIPv6(ip: string): boolean {\n if (!is(String, ip)) {\n return false;\n }\n\n return ipv6Regexp.test(ip);\n};\n\nexport { isIP, isIPv4, isIPv6 };\n","/**\n * punycode and punydecode\n *\n * - punycode(domain) -> String\n * - punydecode(domain) -> String\n */\nimport { domainToASCII, domainToUnicode } from 'node:url';\nimport { is } from '../helpers/object.js';\nimport { isIPv6 } from '../ip/index.js';\n\n/**\n * @func punycode\n *\n * Returns the Punycode ASCII serialization of the domain.\n * If domain is an invalid domain, the empty string is returned.\n *\n * Note:\n * - native function url.domainToASCII does not support IPv6 only IPv4;\n * - native function url.domainToASCII throws if no domain is provided or returns\n * `null`, `undefined`, `nan` for `null`, `undefined` or `NaN` values which is\n * not what to be expected.\n */\nconst punycode = function punycode(domain: string): string {\n if (isIPv6(domain)) {\n return domain;\n }\n\n return is(String, domain) ? domainToASCII(domain) : '';\n};\n\n/**\n * @func punydecode\n *\n * Returns the Unicode serialization of the domain.\n * If domain is an invalid domain, the empty string is returned.\n *\n * Note:\n * - native function url.domainToUnicode does not support IPv6 only IPv4;\n * - native function url.domainToUnicode throws if no domain is provided or returns\n * `null`, `undefined`, `nan` for `null`, `undefined` or `NaN` values which is\n * not what to be expected.\n */\nconst punydecode = function punydecode(domain: string): string {\n if (isIPv6(domain)) {\n return domain;\n }\n\n return is(String, domain) ? domainToUnicode(domain) : '';\n};\n\nexport { punycode, punydecode };\n","/**\n * domain\n *\n * - isDomainLabel(label) -> Boolean\n * - isDomain(name) -> Boolean\n */\nimport { isDomainChar } from '../checkers/chars.js';\nimport { is } from '../helpers/object.js';\nimport { punycode } from '../punycode/index.js';\n\n/**\n * @func isDomainLabel\n *\n * Test a label is a valid domain label according to RFC-1034.\n *\n * \"Note that while upper and lower case letters are allowed in domain names,\n * no significance is attached to the case. That is, two names with the same\n * spelling but different case are to be treated as if identical.\"\n *\n * By convention uppercased domain label will be considered invalid.\n *\n * Rules:\n * 1. \"Labels must be 63 characters or less.\";\n * 2. can be minimum one character;\n * 3. must only use lowercase letters, digits or hyphens;\n * 4. must not start or end with a hyphen;\n * 5. must not have consecutive hyphens;\n * 6. can start or end with a digit.\n *\n * Based on:\n * - RFC-1034 https://www.ietf.org/rfc/rfc1034.txt.\n */\nconst isDomainLabel = function isDomainLabel(label: string): boolean {\n // 1) and 2) rules\n if (!is(String, label)) {\n return false;\n }\n\n const len = label.length;\n\n if (len < 1 || len > 63) {\n return false;\n }\n\n // check each character\n for (let i = 0; i < len; i += 1) {\n if (!isDomainChar(label.charAt(i), { start: i === 0, end: i === len - 1 })) {\n return false;\n }\n\n // check consecutive hyphens\n if (label.charAt(i) === '-' && i + 1 < len && label.charAt(i + 1) === '-') {\n return false;\n }\n }\n\n return true;\n};\n\n/**\n * @func isDomain\n *\n * Test a name is a valid domain according to RFC-1034.\n *\n * Supports Fully-Qualified Domain Name (FQDN) and Internationalized Domain Name (IDN).\n *\n * Rules:\n * 1. labels rules apply;\n * 2. \"[...] the total number of octets that represent a domain name\n * (i.e., the sum of all label octets and label lengths) is limited to 255.\";\n * 3. labels are separated by dots (\".\");\n * 4. must have at least one extension label;\n * 5. must have labels different from each other;\n * 6. last label can be empty (root label \".\");\n * 7. labels can start with `xn--` for IDNs if the ASCII serialization is a valid Punycode;\n * 8. check also Punycodes as ॐ gives xn--'-6xd where ' is not valid.\n *\n * Based on:\n * - RFC-1034 https://www.ietf.org/rfc/rfc1034.txt.\n */\nconst isDomain = function isDomain(name: string): boolean {\n if (!is(String, name)) {\n return false;\n }\n\n // if a domain has an invalid label, its punycode value will be ''\n // eg. 'a.xn--hf.com'\n const domain = punycode(name);\n\n if (domain === 'localhost') {\n return true;\n }\n\n const len = domain.length;\n\n // \"To simplify implementations, the total number of octets that represent a\n // domain name (i.e., the sum of all label octets and label lengths) is\n // limited to 255.\"\n if (len <= 0 || len > 255) {\n return false;\n }\n\n // \"[...] the labels are separated by dots (\".\"). Since a complete\n // domain name ends with the root label, this leads to a printed form which\n // ends in a dot.\"\n // google.com./ is valid\n const labels = domain.split('.');\n const labelsLen = labels.length;\n\n // no label extension\n if (labelsLen <= 1) {\n return false;\n }\n\n // labels:\n // a) must be different from each other\n // b) last label can be empty (root label '.')\n // c) label can start with 'xn--' for IDNs if the Punycode is valid\n const occurences: Record<string, number> = {};\n\n for (const [i, current] of labels.entries()) {\n // ignore root label if ''\n if (!(i === labelsLen - 1 && current === '')) {\n const label = current.startsWith('xn--') ? current.slice(4) : current;\n\n // also check punycoded label as i.e. ॐ gives xn--'-6xd where ' is not valid\n if (!isDomainLabel(label)) {\n return false;\n }\n\n occurences[current] = (occurences[current] || 0) + 1;\n\n if (occurences[current] > 1) {\n return false;\n }\n }\n }\n\n return true;\n};\n\nexport { isDomain, isDomainLabel };\n","/**\n * Type casting helpers.\n *\n * Cast a value to a specific primitive type. If the value is\n * not of this type or can not be infer from this type, undefined is returned.\n *\n * undefined is an interesting value. When stringifying an object, an undefined property\n * disappears. Useful to respect data type schemas and where null values are not allowed.\n *\n * - num(thing, { le, ge } = {}) -> Number or undefined\n * - int(thing, { le, ge } = {}) -> Integer Number or undefined\n */\nimport { exists, is } from './object.js';\n\ntype Range = { ge?: unknown; le?: unknown };\n\n/**\n * @func number\n *\n * cast to primitive number if possible or returns undefined\n * because Number(null) returns 0 and Number(undefined|NaN) returns NaN\n * beware to call Number.isFinite only on number values\n * NOTE: only finite values\n */\nconst number = function number(thing: unknown): number | undefined {\n let castNum: number | undefined;\n\n if (exists(thing)) {\n const value = (thing as { valueOf(): unknown }).valueOf();\n\n if (is(Number, value)) {\n if (Number.isFinite(value)) {\n castNum = value;\n }\n } else if (is(String, value) || is(Boolean, value)) {\n const cast = Number(value);\n\n if (Number.isFinite(cast)) {\n castNum = cast;\n }\n }\n }\n\n return castNum;\n};\n\n/**\n * @func num\n *\n * cast to primitive number, with 'less or equal than'\n * or 'greater or equal than' options, or returns undefined\n * NOTE: based on \"number\" function\n */\nconst num = function num(thing: unknown, { ge, le }: Range = {}): number | undefined {\n let castNum = number(thing);\n\n if (castNum !== undefined) {\n const lessThan = number(le);\n const greaterThan = number(ge);\n\n if (lessThan !== undefined && greaterThan !== undefined) {\n if (castNum < greaterThan || castNum > lessThan) {\n castNum = undefined;\n }\n } else if (lessThan !== undefined && castNum > lessThan) {\n castNum = undefined;\n } else if (greaterThan !== undefined && castNum < greaterThan) {\n castNum = undefined;\n }\n }\n\n return castNum;\n};\n\n/**\n * @func integer\n *\n * cast to primitive integer number if possible or returns undefined\n * NOTE: based on \"number\" function, in base 10 only\n */\nconst integer = function integer(thing: unknown): number | undefined {\n // first cast to number to avoid some inconsistencies with hexa\n const castNum = number(thing);\n let castInt: number | undefined;\n\n if (castNum !== undefined) {\n const int = parseInt(String(castNum), 10);\n\n /* v8 ignore next -- unreachable: parseInt of a finite number's String is never NaN */\n if (!Number.isNaN(int)) {\n castInt = int;\n }\n }\n\n return castInt;\n};\n\n/**\n * @func int\n *\n * cast to primitive integer number, with 'less or equal than'\n * or 'greater or equal than' options, or returns undefined\n * NOTE: based on \"integer\" function, in base 10 only\n */\nconst int = function int(thing: unknown, { ge, le }: Range = {}): number | undefined {\n let castInt = integer(thing);\n\n if (castInt !== undefined) {\n const lessThan = integer(le);\n const greaterThan = integer(ge);\n\n if (lessThan !== undefined && greaterThan !== undefined) {\n if (castInt < greaterThan || castInt > lessThan) {\n castInt = undefined;\n }\n } else if (lessThan !== undefined && castInt > lessThan) {\n castInt = undefined;\n } else if (greaterThan !== undefined && castInt < greaterThan) {\n castInt = undefined;\n }\n }\n\n return castInt;\n};\n\n/**\n * @func isPort\n *\n * RFC-3986 §3.2.3: port = *DIGIT. True if the value is absent\n * (null/undefined) or a possibly empty string of ASCII digits.\n * The numeric range is validated separately by `int`.\n *\n * Rejects JS Number coercion artefacts (hex `0x1F`, scientific `1e3`,\n * whitespace) that `Number()` would otherwise accept.\n */\nconst isPort = function isPort(thing: unknown): boolean {\n return thing === null || thing === undefined || /^[0-9]*$/.test(String(thing));\n};\n\nexport { int, integer, isPort, num, number };\n","/**\n * error helper\n *\n * - fail(code, message) -> never (throws a coded URIError)\n */\n\ntype URIErrorWithCode = URIError & { code: string };\n\n/**\n * @func fail\n *\n * Throw a URIError carrying a stable `code` string. The thrown value is\n * always `instanceof URIError`.\n */\nconst fail = function fail(code: string, message: string): never {\n const error = new URIError(message) as URIErrorWithCode;\n\n error.code = code;\n\n throw error;\n};\n\nexport { fail, type URIErrorWithCode };\n","/**\n * parser\n *\n * - hostToURI(host) -> String\n * - recomposeURI({ scheme, userinfo, host port, path, query, fragment } = {}) -> String\n * - parseURI(uri) -> Object\n */\nimport { maxPortInteger, minPortInteger } from '../config/index.js';\nimport { int, isPort } from '../helpers/cast.js';\nimport { exists, is } from '../helpers/object.js';\nimport { isIPv6 } from '../ip/index.js';\nimport { punycode, punydecode } from '../punycode/index.js';\n\nexport interface ParsedURI {\n scheme: string | null;\n authority: string | null;\n authorityPunydecoded: string | null;\n userinfo: string | null;\n host: string | null;\n hostPunydecoded: string | null;\n port: number | string | null;\n path: string | null;\n pathqf: string | null;\n query: string | null;\n fragment: string | null;\n href: string | null;\n}\n\nexport interface URIComponents {\n scheme?: string | null;\n userinfo?: string | null;\n host?: string | null;\n port?: number | string | null;\n path?: string | null;\n query?: string | null;\n fragment?: string | null;\n}\n\n// regexp parsing uri from RFC-3986 https://tools.ietf.org/html/rfc3986#appendix-B\n// adding ?: to disable capturing some groups\nconst uriRegexp = /^(?:([^:/?#]+):)?(?:\\/\\/([^/?#]*))?([^?#]*)(?:\\?([^#]*))?(?:#(.*))?/;\n\n// detect IPv6 (regex based on RFC-3986 one): [ipv6]:port\nconst ipv6Regexp = /^(?:\\[([^\\]]+)\\]:?)([0-9]+)?$/;\n\n/**\n * @func hostToURI\n *\n * Format host with special [] for IPv6. The empty string is returned if host\n * is not a string.\n */\nconst hostToURI = function hostToURI(host: string): string {\n if (!is(String, host)) {\n return '';\n }\n\n return isIPv6(host) ? `[${host}]` : host;\n};\n\n/**\n * @func recomposeURI\n *\n * Recompose an URI from its components with basic URI checking.\n *\n * The empty string is returned if unable to recompose the URI.\n *\n * Rules:\n * 1. scheme is required and must be at least 1 character;\n * 2. path is required and can be empty;\n * 3. if host is present path must be empty or start with /;\n * 4. if host is not present path must not start with //;\n * 5. host, if any, must be at least 3 characters;\n * 6. userinfo will be ignored if empty;\n * 7. port will be ignored if empty or not an integer;\n * 8. query is emitted when defined (a string, including ''); a null\n * or undefined query is omitted (RFC-3986 §5.3);\n * 9. fragment is emitted when defined (a string, including ''); a null\n * or undefined fragment is omitted (RFC-3986 §5.3).\n *\n * Support:\n * - IPv4 and IPv6.\n *\n * Note:\n * / is added to any URI with a host and an empty path.\n *\n * Based on:\n * - RFC-3986 https://tools.ietf.org/html/rfc3986.\n */\nconst recomposeURI = function recomposeURI(components?: URIComponents): string {\n const cpts = components || {};\n const defaultReturnValue = '';\n const { scheme, userinfo, host, port, path, query, fragment } = cpts;\n\n if (!(is(String, scheme) && scheme.length > 0) || !is(String, path)) {\n return defaultReturnValue;\n }\n\n let uri = scheme;\n\n if (is(String, host)) {\n if (!(path === '' || path.startsWith('/'))) {\n return defaultReturnValue;\n }\n\n if (host.length <= 2) {\n return defaultReturnValue;\n }\n\n uri += '://';\n\n if (is(String, userinfo) && userinfo.length > 0) {\n uri += `${userinfo}@`;\n }\n\n uri += hostToURI(host);\n\n if (\n exists(port) &&\n isPort(port) &&\n int(port, { ge: minPortInteger, le: maxPortInteger }) !== undefined\n ) {\n uri += `:${port}`;\n }\n } else {\n if (path.startsWith('//')) {\n return defaultReturnValue;\n }\n\n uri += ':';\n }\n\n // add / if any host but path is empty and query/fragment is not\n if (path === '' && is(String, host)) {\n uri += '/';\n } else {\n uri += path;\n }\n\n // RFC-3986 §5.3: emit the delimiter whenever the component is defined,\n // including the empty string (a defined-empty query/fragment)\n if (is(String, query)) {\n uri += `?${query}`;\n }\n\n if (is(String, fragment)) {\n uri += `#${fragment}`;\n }\n\n return uri;\n};\n\n/**\n * @func parseURI\n *\n * Parse a string to get URI components.\n *\n * Support:\n * - IPv4 and IPv6 hosts;\n * - Internationalized Domain Name (IDN).\n *\n * Note:\n * - RegExp from RFC-3986 https://tools.ietf.org/html/rfc3986#appendix-B;\n * - scheme and host strings will always be put in lowercase once parsed,\n * as specified in RFC-3986;\n * - authority and its components will be put at null values if authority\n * parsed is missing or empty.\n *\n * Based on:\n * - RFC-3986 https://tools.ietf.org/html/rfc3986.\n */\nconst parseURI = function parseURI(uri: string): ParsedURI {\n const parsed: ParsedURI = {\n scheme: null,\n authority: null,\n authorityPunydecoded: null,\n userinfo: null,\n host: null,\n hostPunydecoded: null,\n port: null,\n path: null,\n pathqf: null,\n query: null,\n fragment: null,\n href: null,\n };\n\n // return an object with null attributes if uri is not a string or an empty string\n if (!(is(String, uri) && uri.length > 0)) {\n return parsed;\n }\n\n // extract uri components from RegExp\n /* v8 ignore next -- unreachable []: the all-optional Appendix-B regexp always matches a non-empty string */\n const [, scheme, authorityParsed, path, queryParsed, fragmentParsed] = uri.match(uriRegexp) ?? [];\n\n // scheme is required and must be a not empty string or this is not an uri\n if (!(is(String, scheme) && scheme.length > 0)) {\n return parsed;\n }\n\n let authority: string | null = null;\n let authorityPunydecoded: string | null = null;\n let userinfo: string | null = null;\n let host: string | null = null;\n let hostPunydecoded: string | null = null;\n let port: number | string | null = null;\n\n // parse authority components, if any\n if (is(String, authorityParsed)) {\n let hostAndPort: string | null = null;\n\n // RFC-3986 §3.2.1: userinfo is delimited by the last '@' before the host\n const userinfoEnd = authorityParsed.lastIndexOf('@');\n\n if (userinfoEnd === -1) {\n hostAndPort = authorityParsed;\n } else {\n userinfo = authorityParsed.slice(0, userinfoEnd);\n hostAndPort = authorityParsed.slice(userinfoEnd + 1);\n }\n\n // try to extract host and port only if any\n /* v8 ignore next -- unreachable false branch: hostAndPort is always an assigned string after the authority split */\n if (is(String, hostAndPort)) {\n // detect IPv6 here first\n const ipv6Match = hostAndPort.match(ipv6Regexp);\n let hostParsed: string | null = null;\n let portToCast: string | null = null;\n\n // if an array then it's constructed as an ipv6\n if (Array.isArray(ipv6Match)) {\n [, hostParsed = null, portToCast = null] = ipv6Match;\n } else {\n // not an ipv6 — RFC-3986 §3.2.2/§3.2.3: port follows the last ':'\n const portStart = hostAndPort.lastIndexOf(':');\n\n if (portStart === -1) {\n hostParsed = hostAndPort;\n } else {\n hostParsed = hostAndPort.slice(0, portStart);\n portToCast = hostAndPort.slice(portStart + 1);\n }\n }\n\n // hostPunydecoded should be the host in Unicode, host its Punycode value\n /* v8 ignore start -- unreachable null branch: the ipv6 regexp's required capture means hostParsed is always a string here */\n const hostLowerCase = is(String, hostParsed) ? hostParsed.toLowerCase() : null;\n const toASCII = punycode(hostLowerCase ?? '');\n const toUnicode = punydecode(hostLowerCase ?? '');\n /* v8 ignore stop */\n\n // host parsed was in Unicode\n if (hostLowerCase !== toASCII) {\n host = toASCII;\n hostPunydecoded = hostLowerCase;\n } else if (hostLowerCase !== toUnicode) {\n // host parsed was punycoded\n host = hostLowerCase;\n hostPunydecoded = toUnicode;\n } else {\n host = hostLowerCase;\n hostPunydecoded = hostLowerCase;\n }\n\n // we only keep original authority/host parsed so using parseURI allows to\n // see issues with provided host\n if (host === '' || hostPunydecoded === '') {\n host = null;\n }\n\n // necessary to handle possible port errors when checking uri\n // port is a valid integer or we keep its initial value to be aware of the error\n // here we also don't check wrong range for the same reason\n // RFC-3986 §3.2.3: a non-digit port (0x1F, 1e3, ...) is kept raw, not\n // coerced by Number(), so checkURI can flag it as URI_INVALID_PORT\n port =\n is(String, portToCast) && portToCast.length > 0 && !isPort(portToCast)\n ? portToCast\n : int(portToCast) || portToCast;\n\n // recompose authority with punycode ASCII and Unicode serialization of the host\n // userinfo@host:port\n // we still want to know the original host and authority provided\n // to check possible uri errors: a null host with a hostPunydecoded filled\n // means uri parsed had an invalid host name\n /* v8 ignore next -- unreachable false branch: hostPunydecoded is always an assigned string in this block */\n if (exists(hostPunydecoded)) {\n authorityPunydecoded = '';\n\n // recompose authorityPunydecoded, order matters\n if (exists(userinfo)) {\n authorityPunydecoded += `${userinfo}@`;\n }\n\n authorityPunydecoded += hostToURI(hostPunydecoded);\n\n if (exists(port)) {\n authorityPunydecoded += `:${port}`;\n }\n }\n\n // as punycode returns '' for invalid host, we already know if the host is basically valid\n // and there cannot be userinfo or a port with a null host parsed\n if (exists(host)) {\n authority = '';\n\n // recompose authority, order matters\n if (exists(userinfo)) {\n authority += `${userinfo}@`;\n }\n\n authority += hostToURI(host);\n\n if (exists(port)) {\n authority += `:${port}`;\n }\n } else {\n userinfo = null;\n port = null;\n }\n }\n }\n\n // format query and fragment\n // RFC-3986 §5.3: a present-but-empty query/fragment ('' from a bare '?'\n // or '#') is distinct from an absent one (null) and must round-trip\n const query = is(String, queryParsed) ? queryParsed : null;\n const fragment = is(String, fragmentParsed) ? fragmentParsed : null;\n\n // pathqf: recompose path + query + fragment if any\n // using valueOf to avoid potential String objects mutation with parsed.path\n /* v8 ignore next -- unreachable null branch: the Appendix-B regexp always captures a string path */\n parsed.pathqf = is(String, path) ? path.valueOf() : null;\n\n if (is(String, parsed.pathqf)) {\n if (is(String, query)) {\n parsed.pathqf += `?${query}`;\n }\n\n if (is(String, fragment)) {\n parsed.pathqf += `#${fragment}`;\n }\n }\n\n // we checked scheme is a string\n parsed.scheme = scheme.toLowerCase();\n parsed.authority = authority;\n parsed.authorityPunydecoded = authorityPunydecoded;\n parsed.userinfo = userinfo;\n parsed.host = host;\n parsed.hostPunydecoded = hostPunydecoded;\n parsed.port = port;\n /* v8 ignore next -- unreachable: the Appendix-B regexp always captures a string path */\n parsed.path = path ?? null;\n parsed.query = query;\n parsed.fragment = fragment;\n\n const recomposedURI = recomposeURI({\n scheme: parsed.scheme,\n userinfo: parsed.userinfo,\n host: parsed.host,\n port: parsed.port,\n path: parsed.path,\n query: parsed.query,\n fragment: parsed.fragment,\n });\n\n parsed.href = recomposedURI !== '' ? recomposedURI : null;\n\n return parsed;\n};\n\nexport { hostToURI, parseURI, recomposeURI };\n","/**\n * sitemap\n *\n * Percent encodings, entities and escape codes.\n *\n * - specialChars\n * - specialCharsKeys\n * - pencodings\n * - pencodingsKeys\n * - entities\n * - entitiesKeys\n * - escapeCodes\n * - escapeCodesKeys\n * - escapeCodesKeysLen\n */\n\n// special chars and their percent encodings\nconst specialChars: Record<string, string> = {\n '*': '%2A',\n};\n\n// special chars keys\nconst specialCharsKeys: string[] = Object.keys(specialChars);\n\n// inversed special chars (percent encodings)\nconst pencodings: Record<string, string> = {};\nspecialCharsKeys.forEach((char) => {\n pencodings[specialChars[char] as string] = char;\n});\n\nconst pencodingsKeys: string[] = Object.keys(pencodings);\n\n// sitemap entities to be escaped in URLs (sitemaps.org requires all five)\nconst entities: Record<string, string> = {\n '&': '&amp;',\n \"'\": '&apos;',\n '\"': '&quot;',\n '>': '&gt;',\n '<': '&lt;',\n};\n\n// entities keys\nconst entitiesKeys: string[] = Object.keys(entities);\n\n// inversed entities keys (escape codes)\nconst escapeCodes: Record<string, string> = {};\nentitiesKeys.forEach((entity) => {\n escapeCodes[entities[entity] as string] = entity;\n});\n\n// escape codes keys and length\nconst escapeCodesKeys: string[] = Object.keys(escapeCodes);\nconst escapeCodesKeysLen: number = escapeCodesKeys.length;\n\nexport {\n entities,\n entitiesKeys,\n escapeCodes,\n escapeCodesKeys,\n escapeCodesKeysLen,\n pencodings,\n pencodingsKeys,\n specialChars,\n specialCharsKeys,\n};\n","/**\n * checkers\n *\n * - checkPercentEncoding(string, index, stringLen) -> Number throws URIError\n * - checkSitemapEncoding(string, index, stringLen) -> Number throws URIError\n * - checkComponent({ type, string, sitemap } = {}) -> Boolean throws URIError\n * - checkSchemeChars(scheme, len) -> Boolean throws URIError\n * - checkLowercase(uri) -> Boolean throws URIError\n * - checkURISyntax(uri) -> Object throws URIError\n * - checkURI(uri, { sitemap } = {}) -> Object throws URIError\n * - checkHttpURL(uri, { https, web, sitemap } = {}) -> Object throws URIError\n * - checkHttpsURL(uri) -> Object throws URIError\n * - checkHttpSitemapURL(uri) -> Object throws URIError\n * - checkHttpsSitemapURL(uri) -> Object throws URIError\n * - checkWebURL(uri) -> Object throws URIError\n * - checkSitemapURL(uri) -> Object throws URIError\n */\nimport { maxLengthURL, maxPortInteger, minPortInteger } from '../config/index.js';\nimport { isDomain } from '../domain/index.js';\nimport { int, isPort } from '../helpers/cast.js';\nimport { fail } from '../helpers/error.js';\nimport { exists, is } from '../helpers/object.js';\nimport { isIP } from '../ip/index.js';\nimport { type ParsedURI, parseURI } from '../parser/index.js';\nimport { escapeCodesKeys, escapeCodesKeysLen } from '../sitemap/index.js';\nimport {\n isPathChar,\n isPercentEncodingChar,\n isQueryOrFragmentChar,\n isSchemeChar,\n isSitemapPathChar,\n isSitemapQueryOrFragmentChar,\n isSitemapUserinfoChar,\n isUserinfoChar,\n} from './chars.js';\n\nexport interface CheckedURI extends ParsedURI {\n valid: true;\n}\n\nexport interface CheckedURISyntax extends ParsedURI {\n schemeLen: number;\n valid: true;\n}\n\ntype CharChecker = (char: string, encode?: boolean) => boolean;\n\n// RFC 6874 §2: ZoneID = 1*( unreserved / pct-encoded ). Compiled once.\nconst ipv6ZoneIdRegexp = /^(?:[A-Za-z0-9._~-]|%[0-9A-Fa-f]{2})+$/;\n\n/**\n * @func checkPercentEncoding\n *\n * Check a % char found from a string at a specific index has a valid\n * percent encoding following this char.\n */\nconst checkPercentEncoding = function checkPercentEncoding(\n string: string,\n index: number,\n stringLen: number,\n): number {\n if (!is(String, string)) {\n fail('URI_INVALID_PERCENT_ENCODING', 'a string is required when checking for percent encoding');\n }\n\n const len = is(Number, stringLen) && stringLen >= 0 ? stringLen : string.length;\n const i = is(Number, index) && index < len ? index : 0;\n let offset = 0;\n\n if (len > 0 && string.charAt(i) === '%') {\n // should be %[A-F0-9]{2}(%[A-F0-9]{2}){0,1}\n // example: %20 or %C3%BC\n if (i + 2 < len) {\n if (!isPercentEncodingChar(string.charAt(i + 1))) {\n fail(\n 'URI_INVALID_PERCENT_ENCODING',\n `invalid percent encoding char '${string.charAt(i + 1)}'`,\n );\n } else if (!isPercentEncodingChar(string.charAt(i + 2))) {\n fail(\n 'URI_INVALID_PERCENT_ENCODING',\n `invalid percent encoding char '${string.charAt(i + 2)}'`,\n );\n } else {\n offset = 2;\n }\n } else {\n fail('URI_INVALID_PERCENT_ENCODING', 'incomplete percent encoding found');\n }\n }\n\n return offset;\n};\n\n/**\n * @func checkSitemapEncoding\n *\n * Check an entity in an URL at a specific index has a valid\n * sitemap escape encoding following this char.\n */\nconst checkSitemapEncoding = function checkSitemapEncoding(\n string: string,\n index: number,\n stringLen: number,\n): number {\n if (!is(String, string)) {\n fail('URI_INVALID_SITEMAP_ENCODING', 'a string is required when checking for sitemap encoding');\n }\n\n const len = is(Number, stringLen) && stringLen >= 0 ? stringLen : string.length;\n const i = is(Number, index) && index < len ? index : 0;\n let offset = 0;\n\n // check each &... is an expected escape code\n if (len > 0 && string.charAt(i) === '&') {\n let escapeOffset: number | undefined;\n\n for (let j = 0; j < escapeCodesKeysLen; j += 1) {\n const code = escapeCodesKeys[j];\n\n /* v8 ignore next 3 -- unreachable: j is bounded by escapeCodesKeys.length so the index is always defined */\n if (code === undefined) {\n break;\n }\n\n const codeLen = code.length;\n\n if (i + codeLen <= len && code === string.substring(i, i + codeLen)) {\n escapeOffset = codeLen - 1;\n break;\n }\n }\n\n if (!exists(escapeOffset)) {\n fail('URI_INVALID_SITEMAP_ENCODING', `entity '${string.charAt(i)}' is not properly escaped`);\n } else {\n offset = escapeOffset;\n }\n }\n\n return offset;\n};\n\n/**\n * @func checkComponent\n *\n * Check a string has valid characters regarding userinfo, path, query,\n * or fragment URI component type.\n *\n * NOTE:\n * - check only if string is present as these components are not required;\n * - path is required but is at least empty,\n * regexp assures that and checkURISyntax verifies that too.\n */\nconst checkComponent = function checkComponent({\n type,\n string,\n sitemap,\n}: {\n type?: string | undefined;\n string?: string | null | undefined;\n sitemap?: boolean | undefined;\n} = {}): boolean {\n if (!['userinfo', 'path', 'query', 'fragment'].includes(type as string)) {\n fail(\n 'URI_INVALID_CHECKING_COMPONENT',\n `unable to check pathqf, got '${type}' component to check`,\n );\n }\n\n // path is always at least empty here, userinfo, query and fragment are not required\n if ((type === 'path' && (!exists(string) || string === '')) || !exists(string)) {\n return true;\n }\n\n const len = string.length;\n const checkSitemap = sitemap === true;\n let checkCharFunc!: CharChecker;\n\n switch (type) {\n case 'userinfo':\n checkCharFunc = checkSitemap ? isSitemapUserinfoChar : isUserinfoChar;\n break;\n case 'path':\n checkCharFunc = checkSitemap ? isSitemapPathChar : isPathChar;\n break;\n case 'query':\n case 'fragment':\n checkCharFunc = checkSitemap ? isSitemapQueryOrFragmentChar : isQueryOrFragmentChar;\n break;\n /* v8 ignore next -- unreachable: type is validated to one of the four cases before the switch */\n default:\n }\n\n for (let i = 0; i < len; i += 1) {\n // check character is valid\n if (!checkCharFunc(string.charAt(i))) {\n fail(\n `URI_INVALID_${(type as string).toUpperCase()}_CHAR`,\n `invalid ${type} char '${string.charAt(i)}'`,\n );\n }\n\n // check percent encodings\n // increase i if a percent encoding has been found (0 if not)\n i += checkPercentEncoding(string, i, len);\n\n // check sitemap encodings\n if (checkSitemap) {\n // increase i if a sitemap encoding has been found (0 if not)\n i += checkSitemapEncoding(string, i, len);\n }\n }\n\n return true;\n};\n\n/**\n * @func checkSchemeChars\n *\n * Check scheme characters are valid.\n *\n * Based on:\n * - RFC-3986 https://tools.ietf.org/html/rfc3986#section-3.1.\n */\nconst checkSchemeChars = function checkSchemeChars(scheme: string, len?: number): boolean {\n if (!is(String, scheme)) {\n fail('URI_INVALID_SCHEME', 'scheme must be a string');\n }\n\n const schemeLen = is(Number, len) && len > 0 ? len : scheme.length;\n\n if (schemeLen <= 0) {\n fail('URI_INVALID_SCHEME', 'scheme cannot be empty');\n }\n\n for (let i = 0; i < schemeLen; i += 1) {\n if (!isSchemeChar(scheme.charAt(i), { start: i === 0 })) {\n fail('URI_INVALID_SCHEME_CHAR', `invalid scheme char '${scheme.charAt(i)}'`);\n }\n }\n\n return true;\n};\n\n/**\n * @func checkLowercase\n *\n * Check a string has not any uppercase characters.\n */\nconst checkLowercase = function checkLowercase(uri: string): boolean {\n if (!is(String, uri)) {\n fail('URI_INVALID_TYPE', 'uri must be a string');\n }\n\n if (uri.toLowerCase() !== uri) {\n fail('URI_INVALID_CHAR', 'uri cannot contain any uppercase characters');\n }\n\n return true;\n};\n\n/**\n * @func checkURISyntax\n *\n * Check an URI syntax is valid according to RFC-3986.\n *\n * Beware this function does not fully check if an URI is valid.\n * Rules:\n * 1. scheme is required and cannot be empty;\n * 2. path is required and can be empty;\n * 3. if authority is present path must be empty or start with /;\n * 4. if authority is not present path must not start with //;\n * 5. check for inconsistent authority (original vs parsed)\n * which would mean host parsed was actually wrong.\n */\nconst checkURISyntax = function checkURISyntax(uri: string): CheckedURISyntax {\n if (!is(String, uri)) {\n fail('URI_INVALID_TYPE', 'uri must be a string');\n }\n\n // parse uri and check scheme, authority, pathname and slashes\n // NOTE: parseURI automatically convert host to punycode\n // example:\n const {\n scheme,\n authority,\n authorityPunydecoded,\n userinfo,\n host,\n hostPunydecoded,\n port,\n path,\n pathqf,\n query,\n fragment,\n href,\n } = parseURI(uri);\n const schemeLen = is(String, scheme) ? scheme.length : 0;\n\n // scheme (required)\n if (!is(String, scheme)) {\n fail('URI_MISSING_SCHEME', 'uri scheme is required');\n /* v8 ignore start -- unreachable: parseURI yields a null or non-empty scheme, never an empty string */\n } else if (schemeLen <= 0) {\n fail('URI_EMPTY_SCHEME', 'uri scheme must not be empty');\n }\n /* v8 ignore stop */\n\n // path (required), can be an empty string\n /* v8 ignore next 3 -- unreachable: the Appendix-B regexp always captures a string path */\n if (!is(String, path)) {\n fail('URI_MISSING_PATH', 'uri path is required');\n }\n\n // path: if authority is present path must be empty or start with /\n if (is(String, authority) && authority.length > 0) {\n /* v8 ignore next 3 -- unreachable: when authority is present the Appendix-B regexp makes path empty or '/'-prefixed */\n if (!(path === '' || (path as string).startsWith('/'))) {\n fail('URI_INVALID_PATH', \"path must be empty or start with '/' when authority is present\");\n }\n } else if ((path as string).startsWith('//')) {\n // if authority is not present path must not start with //\n fail('URI_INVALID_PATH', \"path must not start with '//' when authority is not present\");\n }\n\n // check for inconsistent authority (original vs parsed) which means\n // host parsed was actually wrong\n if (!exists(authority) && exists(authorityPunydecoded)) {\n fail('URI_INVALID_HOST', `host must be a valid ip or domain name, got '${hostPunydecoded}'`);\n }\n\n // RFC 6874: an IPv6 zone identifier in a URI MUST use the percent-encoded\n // \"%25\" delimiter and the ZoneID must be a non-empty 1*( unreserved / pct-encoded )\n if (is(String, host) && host.includes(':')) {\n const zoneAt = host.indexOf('%');\n\n if (zoneAt !== -1) {\n const zoneId = host.slice(zoneAt + 3);\n\n if (host.slice(zoneAt, zoneAt + 3) !== '%25') {\n fail(\n 'URI_INVALID_HOST',\n `IPv6 zone identifier must use the '%25' delimiter, got '${host}'`,\n );\n }\n\n if (zoneId === '' || !ipv6ZoneIdRegexp.test(zoneId)) {\n fail(\n 'URI_INVALID_HOST',\n `IPv6 zone identifier must be a non-empty RFC 6874 ZoneID, got '${host}'`,\n );\n }\n }\n }\n\n return {\n scheme,\n authority,\n authorityPunydecoded,\n userinfo,\n host,\n hostPunydecoded,\n port,\n path,\n pathqf,\n query,\n fragment,\n href,\n schemeLen,\n valid: true,\n };\n};\n\n/**\n * @func checkURI\n *\n * Check an URI is valid according to RFC-3986.\n *\n * Rules:\n * 1. scheme is required and cannot be empty;\n * 2. path is required and can be empty;\n * 3. if authority is present path must be empty or start with /;\n * 4. if authority is not present path must not start with //;\n * 5. scheme can only have specific characters:\n * https://tools.ietf.org/html/rfc3986#section-3.1;\n * 6. if authority is present:\n * 1. host must be a valid IP or domain name;\n * 2. userinfo, if any, can only have specific characters:\n * https://tools.ietf.org/html/rfc3986#section-3.2.1;\n * 3. port, if any, must be an integer in a specific range.\n * 7. path, query and fragment can only have specific characters:\n * https://tools.ietf.org/html/rfc3986#section-3.3.\n */\nconst checkURI = function checkURI(\n uri: string,\n { sitemap }: { sitemap?: boolean | undefined } = {},\n): CheckedURI {\n // check uri type and syntax\n const {\n scheme,\n authority,\n authorityPunydecoded,\n userinfo,\n host,\n hostPunydecoded,\n port,\n path,\n pathqf,\n query,\n fragment,\n href,\n schemeLen,\n } = checkURISyntax(uri);\n\n // check scheme characters\n checkSchemeChars(scheme as string, schemeLen);\n\n // authority (not required)\n if (exists(authority)) {\n // check userinfo\n checkComponent({ sitemap, type: 'userinfo', string: userinfo });\n\n // check host is a valid ip first (RFC-3986) or a domain name\n if (!isIP(host as string) && !isDomain(host as string)) {\n fail('URI_INVALID_HOST', `host must be a valid ip or domain name, got '${host}'`);\n }\n\n // check port is a valid RFC-3986 *DIGIT and in range if any\n if (\n exists(port) &&\n (!isPort(port) || int(port, { ge: minPortInteger, le: maxPortInteger }) === undefined)\n ) {\n fail(\n 'URI_INVALID_PORT',\n `port must be an integer between ${minPortInteger}-${maxPortInteger}, got '${port}'`,\n );\n }\n }\n\n // check path, query and fragment\n checkComponent({ sitemap, type: 'path', string: path });\n checkComponent({ sitemap, type: 'query', string: query });\n checkComponent({ sitemap, type: 'fragment', string: fragment });\n\n return {\n scheme,\n authority,\n authorityPunydecoded,\n userinfo,\n host,\n hostPunydecoded,\n port,\n path,\n pathqf,\n query,\n fragment,\n href,\n valid: true,\n };\n};\n\n/**\n * @func checkHttpURL\n *\n * Check an URI is a valid HTTP URL (sitemap URLs supported to create aliases).\n *\n * This function uses checkURI to check URI provided is valid.\n *\n * Rules:\n * 1. scheme must be http or HTTP;\n * 2. authority is required;\n * 3. URL must be less than max length.\n *\n * Based on:\n * - RFC-3986 https://tools.ietf.org/html/rfc3986;\n * - https://support.google.com/webmasters/answer/183668?hl=en&ref_topic=4581190.\n */\nconst checkHttpURL = function checkHttpURL(\n uri: string,\n {\n https,\n web,\n sitemap,\n }: { https?: boolean | undefined; web?: boolean | undefined; sitemap?: boolean | undefined } = {},\n): CheckedURI {\n // precheck case for sitemap only\n if (sitemap === true) {\n checkLowercase(uri);\n }\n\n const schemesToCheck: string[] = [];\n\n if (https === true) {\n schemesToCheck.push('https');\n } else if (web === true) {\n schemesToCheck.push('http', 'https');\n } else {\n schemesToCheck.push('http');\n }\n\n const {\n scheme,\n authority,\n authorityPunydecoded,\n userinfo,\n host,\n hostPunydecoded,\n port,\n path,\n pathqf,\n query,\n fragment,\n href,\n } = checkURI(uri, { sitemap });\n\n // scheme\n if (!schemesToCheck.includes(scheme as string)) {\n fail('URI_INVALID_SCHEME', `scheme must be ${schemesToCheck.join(' or ')}, got '${scheme}'`);\n }\n\n // authority\n if (!is(String, authority)) {\n fail('URI_MISSING_AUTHORITY', 'authority is required');\n }\n\n // max length\n // sitemaps.org: a URL must be strictly less than 2,048 characters\n if (is(String, href) && href.length >= maxLengthURL) {\n fail('URI_MAX_LENGTH_URL', `max URL length of ${maxLengthURL} reached: ${href.length}`);\n }\n\n return {\n scheme,\n authority,\n authorityPunydecoded,\n userinfo,\n host,\n hostPunydecoded,\n port,\n path,\n pathqf,\n query,\n fragment,\n href,\n valid: true,\n };\n};\n\n/**\n * @func checkHttpsURL\n *\n * Check an URI is a valid HTTPS URL.\n *\n * Same behavior than checkHttpURL except scheme must be https or HTTPS.\n */\nconst checkHttpsURL = function checkHttpsURL(uri: string): CheckedURI {\n return checkHttpURL(uri, { https: true });\n};\n\n/**\n * @func checkHttpSitemapURL\n *\n * Check an URI is a valid HTTP URL to be used in an XML sitemap file.\n *\n * This function uses checkHttpURL to check URI provided is a valid HTTP URL.\n *\n * Rules:\n * 1. scheme must be http;\n * 2. authority is required;\n * 3. specific characters must be escaped;\n * 4. can only contain lowercase characters;\n * 5. URL must be less than max length.\n *\n * Based on:\n * - RFC-3986 https://tools.ietf.org/html/rfc3986;\n * - https://support.google.com/webmasters/answer/183668?hl=en&ref_topic=4581190.\n */\nconst checkHttpSitemapURL = function checkHttpSitemapURL(uri: string): CheckedURI {\n return checkHttpURL(uri, { sitemap: true });\n};\n\n/**\n * @func checkHttpsSitemapURL\n *\n * Check an URI is a valid HTTPS URL to be used in an XML sitemap file.\n * Same behavior than checkHttpSitemapURL except scheme must be https.\n */\nconst checkHttpsSitemapURL = function checkHttpsSitemapURL(uri: string): CheckedURI {\n return checkHttpURL(uri, { https: true, sitemap: true });\n};\n\n/**\n * @func checkWebURL\n *\n * Check an URI is a valid HTTP or HTTPS URL.\n *\n * Same behavior than checkHttpURL except scheme can be http/HTTP or https/HTTPS.\n */\nconst checkWebURL = function checkWebURL(uri: string): CheckedURI {\n return checkHttpURL(uri, { web: true });\n};\n\n/**\n * @func checkSitemapURL\n *\n * Check an URI is a valid HTTP or HTTPS URL to be used in an XML sitemap file.\n *\n * Same behavior than checkHttpSitemapURL except scheme can be http or https.\n */\nconst checkSitemapURL = function checkSitemapURL(uri: string): CheckedURI {\n return checkHttpURL(uri, { web: true, sitemap: true });\n};\n\nexport {\n checkComponent,\n checkHttpSitemapURL,\n checkHttpsSitemapURL,\n checkHttpsURL,\n checkHttpURL,\n checkLowercase,\n checkPercentEncoding,\n checkSchemeChars,\n checkSitemapEncoding,\n checkSitemapURL,\n checkURI,\n checkURISyntax,\n checkWebURL,\n};\n","/**\n * decoders\n *\n * - decodeURIComponentString(component, { sitemap, lowercase } = {}) -> String\n * - decodeURIString(uri, { sitemap, lowercase } = {}) -> String throws URIError\n * - decodeWebURL(uri, { lowercase } = {}) -> String\n * - decodeSitemapURL(uri, { lowercase } = {}) -> String\n */\nimport { checkSchemeChars, checkURISyntax } from '../checkers/index.js';\nimport { maxLengthURL, maxPortInteger, minPortInteger } from '../config/index.js';\nimport { isDomain } from '../domain/index.js';\nimport { int, isPort } from '../helpers/cast.js';\nimport { fail } from '../helpers/error.js';\nimport { exists, is } from '../helpers/object.js';\nimport { isIP } from '../ip/index.js';\nimport { recomposeURI } from '../parser/index.js';\nimport { escapeCodes, escapeCodesKeys, pencodings, pencodingsKeys } from '../sitemap/index.js';\n\n// compiled once at module load — used only via String.prototype.replace,\n// which resets lastIndex per spec, so reusing the global regexp is safe\nconst sitemapDecodeRegexp = new RegExp(escapeCodesKeys.concat(pencodingsKeys).join('|'), 'g');\n\n/**\n * @func decodeURIComponentString\n *\n * Decode an URI component string with Sitemap's escape codes support.\n *\n * Native function decodeURIComponent could throw and to be consistent with\n * encodeURIComponentString the empty string is returned if unable to decode.\n *\n * Based on:\n * - RFC-3986 https://tools.ietf.org/html/rfc3986;\n * - https://support.google.com/webmasters/answer/183668?hl=en&ref_topic=4581190.\n */\nconst decodeURIComponentString = function decodeURIComponentString(\n component: string,\n { sitemap, lowercase }: { sitemap?: boolean | undefined; lowercase?: boolean | undefined } = {},\n): string {\n if (!is(String, component)) {\n return '';\n }\n\n const componentToDecode = lowercase === true ? component.toLowerCase() : component;\n\n if (sitemap === true) {\n const uriToDecode = componentToDecode.replace(\n sitemapDecodeRegexp,\n /* v8 ignore next -- unreachable '': the regexp is built from these keys so every match resolves */\n (match) => escapeCodes[match] || pencodings[match] || '',\n );\n\n try {\n return decodeURIComponent(uriToDecode);\n } catch {\n return '';\n }\n }\n\n try {\n return decodeURIComponent(componentToDecode);\n } catch {\n return '';\n }\n};\n\n/**\n * @func decodeURIString\n *\n * Decode an URI string according to RFC-3986 with basic checking.\n *\n * Checked:\n * - scheme is required;\n * - path is required, can be empty;\n * - port, if any, must be an integer in a specific range;\n * - host must be a valid ip or domain name;\n * - maximum size once encoded for URLs.\n *\n * Support:\n * - IDNs: returns URI with its Punydecoded host (Unicode serialization of the domain), if any;\n * - lower and upper case.\n *\n * Note:\n * - if one of userinfo, path, query or fragment component cannot be decoded, it will be ignored;\n * - native function decodeURI does not support IDNs and cannot properly work\n * with encodeURI since the function is based on an outdated standard;\n * - to stay fully RFC-3986 compliant, scheme and host are put in lowercase;\n * - to only use with encodeURIString.\n *\n * Based on:\n * - RFC-3986 https://tools.ietf.org/html/rfc3986;\n * - https://support.google.com/webmasters/answer/183668?hl=en&ref_topic=4581190.\n */\nconst decodeURIString = function decodeURIString(\n uri: string,\n {\n web,\n sitemap,\n lowercase,\n }: {\n web?: boolean | undefined;\n sitemap?: boolean | undefined;\n lowercase?: boolean | undefined;\n } = {},\n): string {\n const uriToDecode = is(String, uri) && lowercase === true ? uri.toLowerCase() : uri;\n const webURL = web === true || sitemap === true;\n\n // check uri type and syntax\n const {\n scheme,\n authority,\n userinfo,\n host,\n hostPunydecoded,\n port,\n path,\n query,\n fragment,\n schemeLen,\n } = checkURISyntax(uriToDecode);\n\n // scheme must be http or https for web/sitemap or with valid chars, always in lowercase\n if (webURL) {\n if (scheme !== 'http' && scheme !== 'https') {\n fail('URI_INVALID_SCHEME', `scheme must be http or https, got '${scheme}'`);\n }\n } else {\n // check scheme characters, it is not intended to decode a scheme\n checkSchemeChars(scheme as string, schemeLen);\n }\n\n // authority is required and must be a valid host for web/sitemap\n if (webURL && !is(String, authority)) {\n fail('URI_MISSING_AUTHORITY', 'authority is required');\n }\n\n // check host is a valid ip first (RFC-3986) or a domain name\n if (exists(host) && !isIP(host) && !isDomain(host)) {\n fail('URI_INVALID_HOST', `host must be a valid ip or domain name, got '${host}'`);\n }\n\n // check port is a valid RFC-3986 *DIGIT and in range if any\n if (\n exists(port) &&\n (!isPort(port) || int(port, { ge: minPortInteger, le: maxPortInteger }) === undefined)\n ) {\n fail(\n 'URI_INVALID_PORT',\n `port must be an integer between ${minPortInteger}-${maxPortInteger}, got '${port}'`,\n );\n }\n\n // userinfo\n // pass lowercase to false option since whole uri has been lowercased if true\n const userinfoDecoded = decodeURIComponentString(userinfo ?? '', { sitemap, lowercase: false });\n\n // path\n /* v8 ignore next -- unreachable '': checkURISyntax always yields a string path */\n const pathDecoded = decodeURIComponentString(path ?? '', { sitemap, lowercase: false });\n\n // RFC-3986 §5.3: an absent query/fragment (null) stays absent and a\n // present-empty one ('') round-trips with its '?'/'#'. A non-empty\n // component that fails to decode is ignored (mapped to null), per the\n // documented decode contract.\n const decodeComponent = (value: string | null): string | null => {\n if (!is(String, value) || value === '') {\n return value;\n }\n\n return decodeURIComponentString(value, { sitemap, lowercase: false }) || null;\n };\n\n const queryDecoded = decodeComponent(query);\n const fragmentDecoded = decodeComponent(fragment);\n\n const uridecoded = recomposeURI({\n scheme,\n port,\n host: hostPunydecoded,\n userinfo: userinfoDecoded,\n path: pathDecoded,\n query: queryDecoded,\n fragment: fragmentDecoded,\n });\n\n // sitemaps.org: a URL must be strictly less than 2,048 characters\n if (webURL && uridecoded.length >= maxLengthURL) {\n fail('URI_MAX_LENGTH_URL', `max URL length of ${maxLengthURL} reached: ${uridecoded.length}`);\n }\n\n return uridecoded;\n};\n\n/**\n * @func decodeWebURL\n *\n * Decode an URI string with basic checking based on RFC-3986 standard applied\n * to HTTP and HTTPS URLs.\n *\n * Uses a fixed decodeURI function to be RFC-3986 compliant.\n *\n * Checked:\n * - scheme must be http/HTTP or https/HTTPS;\n * - path is required, can be empty;\n * - authority is required;\n * - port, if any, must be an integer in a specific range;\n * - parseURI prechecked host, will be null if invalid and so does authority.\n *\n * Support:\n * - IDNs: returns URI with its Punydecoded host\n * (Unicode serialization of the domain), if any;\n * - lower and upper case.\n *\n * Note:\n * - native function decodeURI does not support IDNs and cannot properly work\n * with encodeURI since the function is based on an outdated standard;\n * - to stay fully RFC-3986 compliant, scheme and host are put in lowercase;\n * - to use only with encodeWebURL.\n */\nconst decodeWebURL = function decodeWebURL(\n uri: string,\n { lowercase }: { lowercase?: boolean | undefined } = {},\n): string {\n return decodeURIString(uri, { lowercase, web: true });\n};\n\n/**\n * @func decodeSitemapURL\n *\n * Decode an URI string with basic checking based on RFC-3986 standard applied\n * to HTTP and HTTPS URLs and sitemap requirements regarding escape codes to decode.\n *\n * Checked:\n * - scheme must be http/HTTP or https/HTTPS;\n * - path is required, can be empty;\n * - authority is required;\n * - port, if any, must be an integer in a specific range;\n * - parseURI prechecked host, will be null if invalid and so does authority.\n *\n * Support:\n * - Sitemap's escape codes;\n * - IDNs: returns URI with its Punydecoded host\n * (Unicode serialization of the domain), if any;\n * - lower and upper case.\n *\n * Note:\n * - native function decodeURI does not support IDNs and cannot properly work\n * with encodeURI since the function is based on an outdated standard;\n * - to stay fully RFC-3986 compliant, scheme and host are put in lowercase;\n * - to use only with encodeSitemapURL.\n *\n * Based on:\n * - RFC-3986 https://tools.ietf.org/html/rfc3986;\n * - https://support.google.com/webmasters/answer/183668?hl=en&ref_topic=4581190.\n */\nconst decodeSitemapURL = function decodeSitemapURL(\n uri: string,\n { lowercase }: { lowercase?: boolean | undefined } = {},\n): string {\n return decodeURIString(uri, { lowercase, sitemap: true });\n};\n\nexport { decodeSitemapURL, decodeURIComponentString, decodeURIString, decodeWebURL };\n","/**\n * encoders\n *\n * - encodeURIComponentString(uri, { sitemap, lowercase } = {}) -> String\n * - encodeURIString(uri, { web, sitemap, lowercase } = {}) -> String throws URIError\n * - encodeWebURL(uri, { lowercase } = {}) -> String\n * - encodeSitemapURL(uri, { lowercase } = {}) -> String\n */\n\nimport {\n isPathChar,\n isQueryOrFragmentChar,\n isSitemapPathChar,\n isSitemapQueryOrFragmentChar,\n isSitemapUserinfoChar,\n isUserinfoChar,\n} from '../checkers/chars.js';\nimport { checkSchemeChars, checkURISyntax } from '../checkers/index.js';\nimport { maxLengthURL, maxPortInteger, minPortInteger } from '../config/index.js';\nimport { isDomain } from '../domain/index.js';\nimport { int, isPort } from '../helpers/cast.js';\nimport { fail } from '../helpers/error.js';\nimport { exists, is } from '../helpers/object.js';\nimport { isIP } from '../ip/index.js';\nimport { recomposeURI } from '../parser/index.js';\nimport { entities, specialChars } from '../sitemap/index.js';\n\n/**\n * @func encodeURIComponentString\n *\n * Encode an URI component according to RFC-3986 with Sitemap entities support.\n *\n * Support:\n * - Sitemap's special characters;\n * - lower and upper case.\n *\n * Note:\n * - only userinfo, path, query and fragment components can be encoded;\n * - scheme and authority host+port can never have percent encoded characters;\n * - the empty string is returned if unable to encode;\n * - sitemap characters must be in lowercase and escaped for XML sitemap.\n *\n * Based on:\n * - RFC-3986 https://tools.ietf.org/html/rfc3986;\n * - https://support.google.com/webmasters/answer/183668?hl=en&ref_topic=4581190.\n */\nconst encodeURIComponentString = function encodeURIComponentString(\n component: string,\n {\n type,\n sitemap,\n lowercase,\n }: {\n type?: string | undefined;\n sitemap?: boolean | undefined;\n lowercase?: boolean | undefined;\n } = {},\n): string {\n if (!is(String, component)) {\n return '';\n }\n\n const componentToEncode =\n lowercase === true || sitemap === true ? component.toLowerCase() : component;\n const componentToEncodeLen = componentToEncode.length;\n let uricomponent = '';\n\n for (let i = 0; i < componentToEncodeLen; i += 1) {\n const char = componentToEncode.charAt(i);\n let encoded = false;\n\n // escape entity or special chars if any FIRST\n if (sitemap === true) {\n const entity = entities[char];\n const special = specialChars[char];\n\n if (exists(entity)) {\n uricomponent += entity;\n encoded = true;\n } else if (exists(special)) {\n uricomponent += special;\n encoded = true;\n }\n }\n\n if (!encoded) {\n let isChar: boolean;\n\n switch (type) {\n case 'userinfo':\n isChar =\n (sitemap === true && isSitemapUserinfoChar(char, true)) || isUserinfoChar(char, true);\n break;\n case 'path':\n isChar = (sitemap === true && isSitemapPathChar(char, true)) || isPathChar(char, true);\n break;\n case 'query':\n case 'fragment':\n isChar =\n (sitemap === true && isSitemapQueryOrFragmentChar(char, true)) ||\n isQueryOrFragmentChar(char, true);\n break;\n default:\n isChar = false;\n }\n\n uricomponent += !isChar ? encodeURIComponent(char) : char;\n }\n }\n\n return uricomponent;\n};\n\n/**\n * @func encodeURIString\n *\n * Encode an URI string according to RFC-3986 with basic checking.\n *\n * Checked:\n * - scheme is required;\n * - path is required, can be empty;\n * - port, if any, must be an integer in a specific range;\n * - host must be a valid ip or domain name;\n * - maximum size once encoded for URLs.\n *\n * Support:\n * - IDNs: returns URI with its Punycode host, if any;\n * - lower and upper case.\n *\n * Note:\n * - only userinfo, path, query and fragment can be percent encoded;\n * - native function encodeURI encodes string according to RFC-2396 which is outdated;\n * - native function encodeURI also encodes scheme and host that cannot have\n * percend-encoded characters;\n * - characters that should not be percent-encoded in RFC-3986 are [] to represent IPv6 host;\n * - to stay fully RFC-3986 compliant, scheme and host are put in lowercase.\n *\n * Based on:\n * - RFC-3986 https://tools.ietf.org/html/rfc3986;\n * - https://support.google.com/webmasters/answer/183668?hl=en&ref_topic=4581190.\n */\nconst encodeURIString = function encodeURIString(\n uri: string,\n {\n web,\n sitemap,\n lowercase,\n }: {\n web?: boolean | undefined;\n sitemap?: boolean | undefined;\n lowercase?: boolean | undefined;\n } = {},\n): string {\n const uriToEncode = is(String, uri) && lowercase === true ? uri.toLowerCase() : uri;\n const webURL = web === true || sitemap === true;\n\n // check uri type and syntax\n const { scheme, authority, userinfo, host, port, path, query, fragment, schemeLen } =\n checkURISyntax(uriToEncode);\n\n // scheme must be http or https for web/sitemap or with valid chars, always in lowercase\n if (webURL) {\n if (scheme !== 'http' && scheme !== 'https') {\n fail('URI_INVALID_SCHEME', `scheme must be http or https, got '${scheme}'`);\n }\n } else {\n // check scheme characters, it is not intended to encode a scheme\n checkSchemeChars(scheme as string, schemeLen);\n }\n\n // authority is required and must be a valid host for web/sitemap\n if (webURL && !is(String, authority)) {\n fail('URI_MISSING_AUTHORITY', 'authority is required');\n }\n\n // check host is a valid ip first (RFC-3986) or a domain name\n if (exists(host) && !isIP(host) && !isDomain(host)) {\n fail('URI_INVALID_HOST', `host must be a valid ip or domain name, got '${host}'`);\n }\n\n // check port is a valid RFC-3986 *DIGIT and in range if any\n if (\n exists(port) &&\n (!isPort(port) || int(port, { ge: minPortInteger, le: maxPortInteger }) === undefined)\n ) {\n fail(\n 'URI_INVALID_PORT',\n `port must be an integer between ${minPortInteger}-${maxPortInteger}, got '${port}'`,\n );\n }\n\n // userinfo\n // pass lowercase to false option since whole uri has been lowercased if true\n const userinfoEncoded = encodeURIComponentString(userinfo ?? '', {\n sitemap,\n type: 'userinfo',\n lowercase: false,\n });\n\n // path\n /* v8 ignore next -- unreachable '': checkURISyntax always yields a string path */\n const pathEncoded = encodeURIComponentString(path ?? '', {\n sitemap,\n type: 'path',\n lowercase: false,\n });\n\n // query — RFC-3986 §5.3: keep an absent query (null) absent; only a\n // present query (including '') is encoded and re-emitted with '?'\n const queryEncoded = is(String, query)\n ? encodeURIComponentString(query, { sitemap, type: 'query', lowercase: false })\n : query;\n\n // fragment — same defined/absent distinction (RFC-3986 §5.3)\n const fragmentEncoded = is(String, fragment)\n ? encodeURIComponentString(fragment, { sitemap, type: 'fragment', lowercase: false })\n : fragment;\n\n const uriencoded = recomposeURI({\n scheme,\n host,\n port,\n userinfo: userinfoEncoded,\n path: pathEncoded,\n query: queryEncoded,\n fragment: fragmentEncoded,\n });\n\n // sitemaps.org: a URL must be strictly less than 2,048 characters\n if (webURL && uriencoded.length >= maxLengthURL) {\n fail('URI_MAX_LENGTH_URL', `max URL length of ${maxLengthURL} reached: ${uriencoded.length}`);\n }\n\n return uriencoded;\n};\n\n/**\n * @func encodeWebURL\n *\n * Encode an URI string with basic checking based on RFC-3986 standard applied\n * to HTTP and HTTPS URLs.\n *\n * Uses a fixed encodeURI function to be RFC-3986 compliant.\n *\n * Checked:\n * - scheme must be http/HTTP or https/HTTPS;\n * - path is required, can be empty;\n * - authority is required;\n * - port, if any, must be an integer in a specific range;\n * - host must be a valid IP or domain name;\n * - maximum size once encoded.\n *\n * Support:\n * - IDNs: returns URL with its Punycode host, if any;\n * - lower and upper case.\n *\n * Note:\n * - only userinfo, path, query and fragment can be percent encoded;\n * - native function encodeURI encodes string according to RFC-2396 which is outdated;\n * - native function encodes also scheme and host that cannot have percend encoded characters;\n * - characters that should not be percent-encoded in RFC-3986 are [] to represent IPv6 host;\n * - to stay fully RFC-3986 compliant, scheme and host are put in lowercase.\n *\n * Based on:\n * - RFC-3986 https://tools.ietf.org/html/rfc3986.\n */\nconst encodeWebURL = function encodeWebURL(\n uri: string,\n { lowercase }: { lowercase?: boolean | undefined } = {},\n): string {\n return encodeURIString(uri, { lowercase, web: true });\n};\n\n/**\n * @func encodeSitemapURL\n *\n * Encode an URI string with basic checking based on RFC-3986 standard applied\n * to HTTP and HTTPS URLs and sitemap requirements regarding special entities to escape.\n *\n * Checked:\n * - scheme must be http/HTTP or https/HTTPS;\n * - path is required, can be empty;\n * - authority is required;\n * - port, if any, must be an integer in a specific range;\n * - host must be a valid IP or domain name;\n * - maximum size once encoded.\n *\n * Support:\n * - Sitemap's special characters;\n * - IDNs: returns URI with its Punycode host, if any;\n * - lower case only.\n *\n * Note:\n * - only userinfo, path, query and fragment can be percent encoded;\n * - native function encodeURI encodes string according to RFC-2396 which is outdated;\n * - native function encodes also scheme and host that cannot have percend encoded characters;\n * - characters that should not be percent-encoded in RFC-3986 are [] to represent IPv6 host;\n * - to stay fully RFC-3986 compliant, scheme and host are put in lowercase.\n *\n * Based on:\n * - RFC-3986 https://tools.ietf.org/html/rfc3986;\n * - https://support.google.com/webmasters/answer/183668?hl=en&ref_topic=4581190.\n */\nconst encodeSitemapURL = function encodeSitemapURL(uri: string): string {\n return encodeURIString(uri, { lowercase: true, sitemap: true });\n};\n\nexport { encodeSitemapURL, encodeURIComponentString, encodeURIString, encodeWebURL };\n","/**\n * reference resolution\n *\n * - removeDotSegments(path) -> String\n * - resolveURI(base, reference) -> String\n *\n * Based on:\n * - RFC-3986 https://tools.ietf.org/html/rfc3986#section-5.\n */\nimport { is } from '../helpers/object.js';\n\n// RFC-3986 Appendix B reference-parsing regexp. Unlike parseURI this keeps\n// relative references (no scheme / no authority) so §5.2.2 can resolve them.\nconst referenceRegexp = /^(?:([^:/?#]+):)?(?:\\/\\/([^/?#]*))?([^?#]*)(?:\\?([^#]*))?(?:#(.*))?/;\n\ninterface Reference {\n scheme: string | null;\n authority: string | null;\n path: string;\n query: string | null;\n fragment: string | null;\n}\n\n/**\n * @func parseReference\n *\n * Split a URI-reference into its five RFC-3986 components. A component is\n * null when the delimiter is absent and '' when present but empty, so the\n * defined/undefined distinction §5.2.2 relies on is preserved.\n */\nconst parseReference = function parseReference(reference: string): Reference {\n /* v8 ignore next -- unreachable []: the Appendix-B regexp is all-optional and matches any string */\n const [, scheme, authority, path, query, fragment] = reference.match(referenceRegexp) ?? [];\n\n return {\n scheme: scheme ?? null,\n authority: authority ?? null,\n /* v8 ignore next -- unreachable '': the path group [^?#]* always captures a string */\n path: path ?? '',\n query: query ?? null,\n fragment: fragment ?? null,\n };\n};\n\n/**\n * @func removeDotSegments\n *\n * Remove the special \".\" and \"..\" complete path segments from a path,\n * implementing the RFC-3986 §5.2.4 ordered loop verbatim.\n *\n * Based on:\n * - RFC-3986 https://tools.ietf.org/html/rfc3986#section-5.2.4.\n */\nconst removeDotSegments = function removeDotSegments(path: string): string {\n if (!is(String, path)) {\n return '';\n }\n\n let input = path;\n let output = '';\n\n while (input.length > 0) {\n // 2A\n if (input.startsWith('../')) {\n input = input.slice(3);\n } else if (input.startsWith('./')) {\n input = input.slice(2);\n // 2B\n } else if (input.startsWith('/./')) {\n input = `/${input.slice(3)}`;\n } else if (input === '/.') {\n input = '/';\n // 2C\n } else if (input.startsWith('/../')) {\n input = `/${input.slice(4)}`;\n output = output.slice(0, Math.max(0, output.lastIndexOf('/')));\n } else if (input === '/..') {\n input = '/';\n output = output.slice(0, Math.max(0, output.lastIndexOf('/')));\n // 2D\n } else if (input === '.' || input === '..') {\n input = '';\n // 2E\n } else {\n const start = input.startsWith('/') ? 1 : 0;\n const next = input.indexOf('/', start);\n\n if (next === -1) {\n output += input;\n input = '';\n } else {\n output += input.slice(0, next);\n input = input.slice(next);\n }\n }\n }\n\n return output;\n};\n\n/**\n * @func merge\n *\n * Merge a relative reference's path with the base path, per RFC-3986 §5.2.3.\n */\nconst merge = function merge(base: Reference, refPath: string): string {\n if (is(String, base.authority) && base.path === '') {\n return `/${refPath}`;\n }\n\n const lastSlash = base.path.lastIndexOf('/');\n\n return lastSlash === -1 ? refPath : base.path.slice(0, lastSlash + 1) + refPath;\n};\n\n/**\n * @func recompose\n *\n * Recompose a resolved target from its components, per RFC-3986 §5.3.\n * A component is emitted whenever it is defined (non-null), including ''.\n */\nconst recompose = function recompose(target: Reference): string {\n let result = '';\n\n /* v8 ignore next -- unreachable false branch: a resolved target always has a scheme (the base is absolute) */\n if (is(String, target.scheme)) {\n result += `${target.scheme}:`;\n }\n\n if (is(String, target.authority)) {\n result += `//${target.authority}`;\n }\n\n result += target.path;\n\n if (is(String, target.query)) {\n result += `?${target.query}`;\n }\n\n if (is(String, target.fragment)) {\n result += `#${target.fragment}`;\n }\n\n return result;\n};\n\n/**\n * @func resolveURI\n *\n * Resolve a URI reference against a base URI, implementing the RFC-3986\n * §5.2.2 strict transform (with §5.2.3 merge and §5.2.4 remove_dot_segments)\n * and recomposing per §5.3.\n *\n * The base must be an absolute URI (a scheme is required, RFC-3986 §5.2.1);\n * a fragment on the base is ignored (RFC-3986 §5.1: the base is used\n * stripped of any fragment); the empty string is returned if base or\n * reference is invalid.\n *\n * Based on:\n * - RFC-3986 https://tools.ietf.org/html/rfc3986#section-5.2.\n */\nconst resolveURI = function resolveURI(base: string, reference: string): string {\n if (!(is(String, base) && is(String, reference))) {\n return '';\n }\n\n const baseRef = parseReference(base);\n\n // RFC-3986 §5.2.1: the base URI MUST be an absolute URI\n if (!is(String, baseRef.scheme)) {\n return '';\n }\n\n const r = parseReference(reference);\n const t: Reference = {\n scheme: null,\n authority: null,\n path: '',\n query: null,\n fragment: null,\n };\n\n // RFC-3986 §5.2.2 (strict mode)\n if (is(String, r.scheme)) {\n t.scheme = r.scheme;\n t.authority = r.authority;\n t.path = removeDotSegments(r.path);\n t.query = r.query;\n } else {\n if (is(String, r.authority)) {\n t.authority = r.authority;\n t.path = removeDotSegments(r.path);\n t.query = r.query;\n } else {\n if (r.path === '') {\n t.path = baseRef.path;\n t.query = is(String, r.query) ? r.query : baseRef.query;\n } else {\n t.path = r.path.startsWith('/')\n ? removeDotSegments(r.path)\n : removeDotSegments(merge(baseRef, r.path));\n t.query = r.query;\n }\n\n t.authority = baseRef.authority;\n }\n\n t.scheme = baseRef.scheme;\n }\n\n t.fragment = r.fragment;\n\n return recompose(t);\n};\n\nexport { removeDotSegments, resolveURI };\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,93 @@
1
+ {
2
+ "name": "@coroboros/uri",
3
+ "version": "1.0.0",
4
+ "description": "RFC-3986 URI toolkit for Node.js. IDN (RFC-3987), IPv6 zone identifiers (RFC 6874), Sitemap protocol. Zero dependencies.",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "main": "./dist/index.cjs",
8
+ "module": "./dist/index.mjs",
9
+ "types": "./dist/index.d.cts",
10
+ "exports": {
11
+ ".": {
12
+ "import": {
13
+ "types": "./dist/index.d.mts",
14
+ "default": "./dist/index.mjs"
15
+ },
16
+ "require": {
17
+ "types": "./dist/index.d.cts",
18
+ "default": "./dist/index.cjs"
19
+ }
20
+ },
21
+ "./package.json": "./package.json"
22
+ },
23
+ "files": [
24
+ "dist",
25
+ "README.md",
26
+ "LICENSE.md",
27
+ "CHANGELOG.md"
28
+ ],
29
+ "scripts": {
30
+ "build": "tsdown",
31
+ "dev": "tsdown --watch",
32
+ "lint": "biome check .",
33
+ "lint:fix": "biome check --write .",
34
+ "typecheck": "tsc --noEmit",
35
+ "test": "vitest run",
36
+ "test:watch": "vitest",
37
+ "test:coverage": "vitest run --coverage",
38
+ "bench": "pnpm build && node bench/uri.bench.mjs",
39
+ "prepublishOnly": "pnpm lint && pnpm typecheck && pnpm test && pnpm build"
40
+ },
41
+ "keywords": [
42
+ "coroboros",
43
+ "uri",
44
+ "url",
45
+ "rfc-3986",
46
+ "rfc-3987",
47
+ "rfc-6874",
48
+ "rfc-1034",
49
+ "rfc-1123",
50
+ "idn",
51
+ "punycode",
52
+ "parse",
53
+ "encode",
54
+ "decode",
55
+ "sitemap",
56
+ "sitemap-protocol",
57
+ "ip",
58
+ "domain",
59
+ "typescript",
60
+ "nodejs",
61
+ "zero-dependency"
62
+ ],
63
+ "author": "Coroboros <ob@coroboros.com> (https://github.com/coroboros)",
64
+ "license": "MIT",
65
+ "repository": {
66
+ "type": "git",
67
+ "url": "git+https://github.com/coroboros/uri.git"
68
+ },
69
+ "bugs": {
70
+ "url": "https://github.com/coroboros/uri/issues"
71
+ },
72
+ "homepage": "https://github.com/coroboros/uri#readme",
73
+ "engines": {
74
+ "node": ">=22"
75
+ },
76
+ "packageManager": "pnpm@11.1.3",
77
+ "publishConfig": {
78
+ "access": "public"
79
+ },
80
+ "private": false,
81
+ "preferGlobal": false,
82
+ "analyze": false,
83
+ "devDependencies": {
84
+ "@biomejs/biome": "^2.4.15",
85
+ "@types/node": "^22.0.0",
86
+ "@vitest/coverage-v8": "^4.1.6",
87
+ "fast-check": "^4.8.0",
88
+ "mitata": "^1.0.34",
89
+ "tsdown": "^0.22.0",
90
+ "typescript": "^6.0.3",
91
+ "vitest": "^4.1.6"
92
+ }
93
+ }