{"version":3,"file":"common-validation-rule.min.cjs","sources":["../src/rules/alpha-number.js","../src/rules/bool.js","../src/rules/impl/china-identity-card-validator.js","../src/rules/china-identity-card.js","../src/rules/china-mobile.js","../src/rules/china-officer-card.js","../src/rules/china-passport.js","../src/rules/china-phone.js","../node_modules/email-validator/index.js","../src/rules/email.js","../src/rules/integer.js","../src/rules/local-date.js","../src/rules/local-date-time.js","../src/rules/local-time.js","../src/rules/number.js","../src/rules/numeric.js","../src/rules/other-credential.js","../src/rules/password.js","../src/rules/person-name.js","../src/rules/timestamp.js","../src/rules/uppercase-alpha-number.js","../node_modules/node-uri/src/helpers/object.js","../node_modules/node-uri/src/helpers/cast.js","../node_modules/node-uri/src/helpers/index.js","../node_modules/node-uri/src/ip/index.js","../node_modules/node-uri/src/punycode/index.js","../node_modules/node-uri/src/config/index.js","../node_modules/node-uri/src/parser/index.js","../node_modules/node-uri/src/checkers/chars.js","../node_modules/node-uri/src/domain/index.js","../node_modules/node-uri/src/sitemap/index.js","../node_modules/node-uri/src/checkers/index.js","../node_modules/node-uri/src/encoders/index.js","../node_modules/node-uri/src/decoders/index.js","../node_modules/node-uri/src/index.js","../src/rules/url.js","../src/rules/username.js","../src/validation-result.js","../src/rules/verify-code.js"],"sourcesContent":["////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n/**\n * 验证字符串是否是数字和字母组合成字符串的正则表达式。\n *\n * 这类字符串通常可以用来表示证件编号、发票号等数据。\n *\n * @author 胡海星\n * @private\n */\nconst ALPHA_NUMBER_REGEXP = /^\\s*[0-9a-zA-Z]+\\s*$/;\n\n/**\n * 数字和字母组合字符串的验证规则。\n *\n * @type {object}\n * @namespace\n * @author 胡海星\n */\nconst AlphaNumberRule = {\n\n  /**\n   * 测试一个值是否是数字和字母组合成字符串。\n   *\n   * 这类字符串通常可以用来表示证件编号、发票号等数据。\n   *\n   * @param {any} value\n   *    待测试的值，前后允许有空白字符。\n   * @return {boolean}\n   *    若该字符串是数字和字母组合成字符串则返回true；否则返回false。\n   * @author 胡海星\n   */\n  isValid(value) {\n    if ((typeof value === 'string') || (value instanceof String)) {\n      return ALPHA_NUMBER_REGEXP.test(value);\n    } else {\n      return false;\n    }\n  },\n};\n\nexport default AlphaNumberRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2024.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * 布尔值验证规则。\n *\n * @type {object}\n * @namespace\n * @author 胡海星\n */\nconst BoolRule = {\n  /**\n   * 测试一个值是否是一个布尔值或表示合法布尔值的字符串。\n   *\n   * 测试时忽略大小写。\n   *\n   * @param {any} value\n   *    待测试的值，前后允许有空白字符。\n   * @return {boolean}\n   *    若该值是一个布尔值或表示合法布尔值的字符串，则返回true；否则返回false。\n   * @author 胡海星\n   */\n  isValid(value) {\n    const type = typeof value;\n    if ((type === 'boolean') || (value instanceof Boolean)) {\n      return true;\n    } else if ((type === 'string') || (value instanceof String)) {\n      const val = value.trim().toLowerCase();\n      return (val === 'true' || val === 'false');\n    } else {\n      return false;\n    }\n  },\n};\n\nexport default BoolRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\nimport AREA_CODES from './china-area-codes';\n\nconst NUMBER_LENGTH = 18;\nconst YEAR_INDEX = 6;\nconst YEAR_LENGTH = 4;\nconst MONTH_INDEX = 10;\nconst MONTH_LENGTH = 2;\nconst DAY_INDEX = 12;\nconst DAY_LENGTH = 2;\nconst AREA_INDEX = 0;\nconst AREA_LENGTH = 6;\nconst GENDER_INDEX = 16;\nconst DECIMAL_BASE = 10;\nconst ASCII_0_CHAR_CODE = 48;\nconst ASCII_9_CHAR_CODE = 57;\nconst RATIO = [\n  7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2,\n];\nconst LAST_CHAR = [\n  '1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2',\n];\n\n/**\n * 将给定的身份证号码给定的片段解析为整数。\n *\n * @param {string} number\n *     给定的身份证号码。\n * @param {Number} start\n *     起始位置。\n * @param {Number} end\n *     结束位置（不包含在内）。\n * @return\n *     若给定的号码的起始位置到结束位置（不包含）的片段可以解析为一个整数，则返\n *     回解析后的整数；否则返回null。\n * @author 胡海星\n * @private\n */\nfunction parseNumber(number, start, end) {\n  let result = 0;\n  for (let i = start; i < end; ++i) {\n    const ch = number.charCodeAt(i);\n    if (ch < ASCII_0_CHAR_CODE || ch > ASCII_9_CHAR_CODE) {\n      return null;\n    }\n    result *= DECIMAL_BASE;\n    result += (ch - ASCII_0_CHAR_CODE);\n  }\n  return result;\n}\n\n/**\n * 判定给定的身份证号码的生日字段是否合法。\n *\n * 身份证号码第7~12为日期码，表示该居民的出生年月日。格式为YYYYMMDD，如19491001。\n * 出生日期码是按GB/T 7408的规定执行的。\n *\n * 注意：对于身份证号码中编码的出生日期，此函数不仅验证该日期是否存在，也会验证\n * 出生日期是否是个合法的日期，同时也会验证该日期是否超过今天的日期（不应该超过\n * 今天的日期）。\n *\n * @param {string} number\n *     给定的身份证号码。\n * @return {Boolean}\n *     若给定的身份证号码的生日字段合法，则返回true；否则返回false。\n * @author 胡海星\n * @private\n */\nexport function isIdCardBirthdayValid(number) {\n  if ((typeof number === 'string') || (number instanceof String)) {\n    number = number.trim();\n    if (number.length !== NUMBER_LENGTH) {\n      return false;\n    }\n    const year = parseNumber(number, YEAR_INDEX, YEAR_INDEX + YEAR_LENGTH);\n    const month = parseNumber(number, MONTH_INDEX, MONTH_INDEX + MONTH_LENGTH);\n    const day = parseNumber(number, DAY_INDEX, DAY_INDEX + DAY_LENGTH);\n    if (year == null || month == null || day == null) {\n      return false;\n    }\n    const birthday = new Date(year, month - 1, day);  // 注意月份从0开始计算\n    // 判定解析出来的年、月、日是否是合法的年、月、日\n    if (birthday.getFullYear() !== year\n      || birthday.getMonth() !== month - 1\n      || birthday.getDate() !== day) {\n      return false;\n    }\n    // 判定解析出来的日期是否超过今天，合法的身份证的日期不应该超过今天\n    const now = new Date();\n    if (birthday.getTime() > now.getTime()) {\n      return false;\n    }\n    return true;\n  }\n  return false;\n}\n\n/**\n * 判定给定的身份证号码的地址区县字段是否合法。\n *\n * 身份证号码第1~6位为地址码，表示登记户口时所在地的行政区划代码（省、市、县）。\n * 其中1-2位省、自治区、直辖市代码；3-4位地级市、盟、自治州代码；5-6位县、县级市、\n * 区代码。如果行政区划进行了重新划分，同一个地方进行户口登记的可能存在地址码不\n * 一致的情况。行政区划代码按GB/T2260的规定执行。\n *\n * @param {string} number\n *     给定的身份证号码。\n * @return {Boolean}\n *     若给定的身份证号码的地址区县字段合法，则返回true；否则返回false。\n * @author 胡海星\n * @private\n */\nexport function isIdCardAreaValid(number) {\n  if ((typeof number === 'string') || (number instanceof String)) {\n    number = number.trim();\n    if (number.length !== NUMBER_LENGTH) {\n      return false;\n    }\n    const code = number.substring(AREA_INDEX, AREA_INDEX + AREA_LENGTH);\n    return AREA_CODES.has(code);\n  } else {\n    return false;\n  }\n}\n\n/**\n * 判定给定的身份证号码是否合法。\n *\n * 身份证号码第1~6位为地址码，表示登记户口时所在地的行政区划代码（省、市、县）。\n * 其中1-2位省、自治区、直辖市代码；3-4位地级市、盟、自治州代码；5-6位县、县级市、\n * 区代码。如果行政区划进行了重新划分，同一个地方进行户口登记的可能存在地址码不\n * 一致的情况。行政区划代码按GB/T2260的规定执行。\n *\n * 身份证号码第7~12为日期码，表示该居民的出生年月日。格式为YYYYMMDD，如19491001。\n * 出生日期码是按GB/T 7408的规定执行的。\n *\n * 身份证号码第15~17为顺序码，表示同一地址码区域内，同年、同月、同日生的人所编订\n * 的顺序号，根据自己身份证的顺序码就可以知道：与我们同年同月同日生的同性至少有\n * 多少个，且在我们之前登记户籍的有多少人。身份证顺序码的奇数分配给男性，偶数分\n * 配给女性。因此身份证号码倒数第2位是奇数则为男性，偶数则为女性。\n *\n * 身份证中第十八位数字的计算方法如下：\n * - 将前面的身份证号码17位数分别乘以不同的系数，从第一位到第十七位的系数分别\n *   为：7、9、10、5、8、4、2、1、6、3、7、9、10、5、8、4、2；\n * - 将这17位数字和系数相乘的结果相加；\n * - 用加出来和除以11，看余数是多少；\n * - 余数只可能有0 、1、 2、 3、 4、 5、 6、 7、 8、 9、 10这11个数字；\n * - 其分别对应的最后一位身份证的号码为1、0、X、9、8、7、6、5、4、3、2；\n *\n * 通过上面得知如果余数是2，就会在身份证的第18位数字上出现罗马数字的Ⅹ。\n * 如果余数是10，身份证的最后一位号码就是2。\n *\n * @param {string} number\n *     给定的身份证号码，前后允许有空白字符。\n * @return {Boolean}\n *     若给定的身份证号码合法，则返回true；否则返回false。\n * @author 胡海星\n * @private\n */\nexport function isIdCardNumberValid(number) {\n  if ((typeof number === 'string') || (number instanceof String)) {\n    number = number.trim();\n    if (number.length !== NUMBER_LENGTH) {\n      return false;\n    }\n    // 验证奇偶校验码是否合法\n    let sum = 0;\n    for (let i = 0; i < NUMBER_LENGTH - 1; ++i) {\n      const ch = number.charCodeAt(i);\n      if (ch < ASCII_0_CHAR_CODE || ch > ASCII_9_CHAR_CODE) {\n        return false;\n      }\n      sum += (ch - ASCII_0_CHAR_CODE) * RATIO[i];\n    }\n    const lastChar = LAST_CHAR[sum % LAST_CHAR.length];\n    if (number.charAt(NUMBER_LENGTH - 1).toUpperCase() !== lastChar) {\n      return false;\n    }\n    // 验证出生日期是否合法\n    if (!isIdCardBirthdayValid(number)) {\n      return false;\n    }\n    // 验证地址区县是否合法\n    // 暂时屏蔽区号验证\n    // if (!isIdCardAreaValid(number)) {\n    //   return false;\n    // }\n    return true;\n  } else {\n    return false;\n  }\n}\n\n/**\n * 从给定的身份证号码中提取出生日期。\n *\n * 身份证号码第7~12为日期码，表示该居民的出生年月日。格式为YYYYMMDD，如19491001。\n * 出生日期码是按GB/T 7408的规定执行的。\n *\n * 注意此函数不验证给定的身份证号码是否合法，也不验证提取出的出生日期是否合法。\n *\n * @param {string} number\n *     给定的身份证号码。\n * @return {string|null}\n *     从给定的身份证号码中提取出的出生日期，表示为'YYYY-MM-DD'格式的字符串。如\n *     果无法提取，则返回`null`。\n * @author 胡海星\n * @private\n */\nexport function getIdCardBirthday(number) {\n  if ((typeof number === 'string') || (number instanceof String)) {\n    number = number.trim();\n    if (number.length !== NUMBER_LENGTH) {\n      return null;\n    }\n    const year = number.substring(YEAR_INDEX, YEAR_INDEX + YEAR_LENGTH);\n    const month = number.substring(MONTH_INDEX, MONTH_INDEX + MONTH_LENGTH);\n    const day = number.substring(DAY_INDEX, DAY_INDEX + DAY_LENGTH);\n    return `${year}-${month}-${day}`;\n  } else {\n    return null;\n  }\n}\n\n/**\n * 从给定的身份证号码中提取性别。\n *\n * 注意此函数不验证给定的身份证号码是否合法。\n *\n * @param {string} number\n *     给定的身份证号码。\n * @return {string|null}\n *     从给定的身份证号码中提取出的性别，表示为字符串`'MALE'`或`'FEMALE'`。如果无法提取，则\n *     返回`null`。\n * @author 胡海星\n * @private\n */\nexport function getIdCardGender(number) {\n  if ((typeof number === 'string') || (number instanceof String)) {\n    number = number.trim();\n    if (number.length !== NUMBER_LENGTH) {\n      return null;\n    }\n    const digit = number.charCodeAt(GENDER_INDEX) - ASCII_0_CHAR_CODE;\n    return (digit % 2 === 1 ? 'MALE' : 'FEMALE');\n  } else {\n    return null;\n  }\n}\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\nimport {\n  isIdCardNumberValid, getIdCardBirthday, getIdCardGender,\n} from './impl/china-identity-card-validator';\n\n/**\n * 中华人民共和国大陆身份证号码验证规则。\n *\n * 身份证号码第1~6位为地址码，表示登记户口时所在地的行政区划代码（省、市、县）。\n * 其中1-2位省、自治区、直辖市代码；3-4位地级市、盟、自治州代码；5-6位县、县级市、\n * 区代码。如果行政区划进行了重新划分，同一个地方进行户口登记的可能存在地址码不\n * 一致的情况。行政区划代码按GB/T2260的规定执行。\n *\n * 身份证号码第7~12为日期码，表示该居民的出生年月日。格式为YYYYMMDD，如19491001。\n * 出生日期码是按GB/T 7408的规定执行的。\n *\n * 身份证号码第15~17为顺序码，表示同一地址码区域内，同年、同月、同日生的人所编订\n * 的顺序号，根据自己身份证的顺序码就可以知道：与我们同年同月同日生的同 性至少有\n * 多少个，且在我们之前登记户籍的有多少人。身份证顺序码的奇数分配给男性，偶数分\n * 配给女性。因此身份证号码倒数第2位是奇数则为男性，偶数则为女性。\n *\n * 身份证中第十八位数字的计算方法如下：\n * - 将前面的身份证号码17位数分别乘以不同的系数，从第一位到第十七位的系数分别\n *   为：7、9、10、5、8、4、2、1、6、3、7、9、10、5、8、4、2；\n * - 将这17位数字和系数相乘的结果相加；\n * - 用加出来和除以11，看余数是多少；\n * - 余数只可能有0 、1、 2、 3、 4、 5、 6、 7、 8、 9、 10这11个数字；\n * - 其分别对应的最后一位身份证的号码为1、0、X、9、8、7、6、5、4、3、2；\n *\n * 通过上面得知如果余数是2，就会在身份证的第18位数字上出现罗马数字的Ⅹ。\n * 如果余数是10，身份证的最后一位号码就是2。\n *\n * 注意：对于身份证号码中编码的出生日期，此验证规则只验证该日期是否存在，没有验\n * 证出生日期的范围是否合法。\n *\n * @type {object}\n * @namespace\n * @author 胡海星\n */\nconst ChinaIdentityCardRule = {\n  /**\n   * 表示身份证的证件类型的字符串。\n   *\n   * @author 胡海星\n   */\n  type: 'IDENTITY_CARD',\n\n  /**\n   * 身份证的证件名称。\n   *\n   * @author 胡海星\n   */\n  name: '身份证',\n\n  /**\n   * 检查身份证号码是否合法\n   *\n   * @param {any} number\n   *    身份证号码，前后允许有空白字符。\n   * @return {boolean}\n   *    若该身份证号码合法，返回true；否则返回false\n   * @author 胡海星\n   */\n  isValid(number) {\n    return isIdCardNumberValid(number);\n  },\n\n  /**\n   * 根据身份证号码计算性别。\n   *\n   * 注意此函数不验证给定的身份证号码是否合法。\n   *\n   * @param {any} number\n   *    身份证号码，前后允许有空白字符。\n   * @return {string|null}\n   *     从给定的身份证号码中提取出的性别，表示为字符串`'MALE'`或`'FEMALE'`。如果无法提取，\n   *     则返回`null`。\n   * @author 胡海星\n   */\n  getGender(number) {\n    return getIdCardGender(number);\n  },\n\n  /**\n   * 根据身份证号码计算出生日期。\n   *\n   * 注意此函数不验证给定的身份证号码是否合法，也不验证提取出的出生日期是否合法。\n   *\n   * @param {any} number\n   *    身份证号码，前后允许有空白字符。\n   * @return {string|null}\n   *    返回该身份证号码对应的出生日期，以字符串形式表示，格式为'YYYY-MM-DD'；\n   *    如身份证号码长度不对，则返回`null`。\n   * @author 胡海星\n   */\n  getBirthday(number) {\n    return getIdCardBirthday(number);\n  },\n};\n\nexport default ChinaIdentityCardRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * 验证中国手机号码的正则表达式\n *\n * - 手机号码可以以 \"0\", \"86\", \"17951\" 开头\n * - 手机号码一共11位数字\n * - 各运营商手机号码开头3位数字为\n *     - 移动：134 135 136 137 138 139 147 148 150 151 152 157 158 159 165 172 178\n *            182 183 184 187 188 198\n *     - 联通：130 131 132 145 146 155 156 166 171 175 176 185 186\n *     - 电信：133 149 153 173 174 177 180 181 189 191 199\n *     - 虚拟运营商：170\n *\n * 参考资料：\n * 1. https://blog.csdn.net/fengshi_sh/article/details/12085307\n * 2. http://www.cnblogs.com/zengxiangzhan/p/phone.html\n *\n * TODO：增加手机号码归属地计算\n *\n * @author 胡海星\n * @private\n */\nconst MOBILE_REGEXP = /^\\s*(0|86|17951)?(13[0-9]|14[5-9]|15[0-35-9]|16[5-6]|17[0-8]|18[0-9]|19[1589])[0-9]{8}\\s*$/;\n\n/**\n * 中国手机号码验证规则。\n *\n * @type {object}\n * @namespace\n * @author 胡海星\n */\nconst ChinaMobileRule = {\n  /**\n   * 测试中国手机号码是否合法\n   *\n   * @param {any} mobile\n   *    待测试的手机号码，前后允许有空白字符。\n   * @return {boolean}\n   *    若手机号码合法则返回true；否则返回false。\n   * @author 胡海星\n   */\n  isValid(mobile) {\n    return ((typeof mobile === 'string') || (mobile instanceof String))\n        && (mobile.length !== 0)\n        && MOBILE_REGEXP.test(mobile);\n  },\n};\n\nexport default ChinaMobileRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * 验证中华人民共和国军官证号码合法性的正则表达式。\n *\n * 合法的军官证号码由6~8位字母、数字或句点组成。\n *\n * @author 胡海星\n * @private\n */\nconst NUMBER_REGEXP = /^\\s*[a-zA-Z0-9.]{6,8}\\s*$/;\n\n/**\n * 中华人民共和国军官证号码验证规则。\n *\n * @type {object}\n * @namespace\n * @author 胡海星\n */\nconst ChinaOfficerCardRule = {\n  /**\n   * 表示军官证的证件类型的字符串。\n   *\n   * @type string\n   * @author 胡海星\n   */\n  type: 'OFFICER_CARD',\n\n  /**\n   * 军官证的证件名称。\n   *\n   * @type string\n   * @author 胡海星\n   */\n  name: '中国人民解放军军官证',\n\n  /**\n   * 检查军官证号码是否合法\n   *\n   * @param {any} number\n   *    军官证号码，前后允许有空白字符。\n   * @return {boolean}\n   *    若该军官证号码合法，返回true；否则返回false\n   * @author 胡海星\n   */\n  isValid(number) {\n    if ((typeof number === 'string') || (number instanceof String)) {\n      return NUMBER_REGEXP.test(number);\n    } else {\n      return false;\n    }\n  },\n};\n\nexport default ChinaOfficerCardRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * 验证中华人民共和国护照号码合法性的正则表达式。\n *\n * 中国于2012年5月起正式签发普通电子护照。\n *\n * 普通电子护照颁发给因定居、探亲、学习、就业、旅行、从事商务活动等非公务原因出\n * 国的中国公民，护照号码格式市：E+8 位数字编号 或 E+字母+7位数字编号。\n *\n * 公务护照又分为因公普通护照、公务护照和外交护照三个类别\n * 1. 因公普通护照：PE+7 位数字编码\n * 2. 公务护照：SE+7 位数字编码\n * 3. 外交护照：DE+7 位数字编码\n *\n * 发给有澳门特区永久性居民身份证的中国公民，护照号码格式是：MA+7 位编号。\n *\n * 发给有香港永久性居民身份证，并享有香港特别行政区居留权的中国公民，护照号格\n * 式是：K+8 位编号。\n *\n * 旧版护照号码格式如下：\n *\n * 1. 因私普通护照号码格式：14 + 7位数字， 15 + 7位数字， G + 8位数字；\n * 2. 因公普通护照号码格式：P + 7位数；\n * 3. 公务护照号码格式：S + 7位数 或  S + 8位数；\n * 4. 外交护照号码格式：D + 8为数字；\n *\n * @author 胡海星\n * @private\n */\nconst NUMBER_REGEXP = /^\\s*(E[A-Z0-9][0-9]{7}|[SDP]E[0-9]{7}|MA[0-9]{7}|K[0-9]{8}|1[45][0-9]{7}|G[0-9]{8}|P[0-9]{7}|S[0-9]{7,8}|D[0-9]{8})\\s*$/;\n\n/**\n * 中华人民共和国护照号码验证规则。\n *\n * @type {object}\n * @namespace\n * @author 胡海星\n */\nconst ChinaPassportRule = {\n\n  /**\n   * 表示护照的证件类型的字符串。\n   *\n   * @author 胡海星\n   */\n  type: 'PASSPORT',\n\n  /**\n   * 护照的证件名称。\n   *\n   * @author 胡海星\n   */\n  name: '护照',\n\n  /**\n   * 检查护照号码是否合法\n   *\n   * @param {any} number\n   *    护照号码，前后允许有空白字符。\n   * @return {boolean}\n   *    若该护照号码合法，返回true；否则返回false\n   * @author 胡海星\n   */\n  isValid(number) {\n    if ((typeof number === 'string') || (number instanceof String)) {\n      return NUMBER_REGEXP.test(number);\n    } else {\n      return false;\n    }\n  },\n};\n\nexport default ChinaPassportRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n/**\n * 验证中国固定电话号码的正则表达式\n *\n * - 国内固定电话和传真的格式基本都是带有0的区号+连接符“-”＋电话号码；\n * - 另外还有可能有分机号\n * - 区号有3位、4位，电话号码有7位和8位的\n * - 其它格式的有前面不带0的，或者不带连接符的\n * - 或者分机号前面使用#号的，或者前面加“+86”的等等；\n *\n * 参考资料：\n * 1. https://blog.csdn.net/lyhjava/article/details/52316438\n *\n * FIXME：验证此规则正确性，并重构规则\n *\n * @author 胡海星\n * @private\n */\nconst PHONE_REGEXP = /^\\s*(\\+?\\d{2,4}[-_－—]?\\d{3,8}([-_－—]?\\d{1,8}){0,2}|0?1[35]\\d{9})\\s*$/;\n\n/**\n * 中国固定电话号码验证规则。\n *\n * @type {object}\n * @namespace\n * @author 胡海星\n */\nconst ChinaPhoneRule = {\n  /**\n   * 测试中国固定电话号码是否合法\n   *\n   * @param {any} phone\n   *    待测试的固定电话号码，前后允许有空白字符。\n   * @return {boolean}\n   *    若固定电话号码合法则返回true；否则返回false。\n   * @author 胡海星\n   */\n  isValid(phone) {\n    return ((typeof phone === 'string') || (phone instanceof String))\n        && (phone.length !== 0)\n        && PHONE_REGEXP.test(phone);\n  },\n};\n\nexport default ChinaPhoneRule;\n","\"use strict\";\r\n\r\nvar tester = /^[-!#$%&'*+\\/0-9=?A-Z^_a-z{|}~](\\.?[-!#$%&'*+\\/0-9=?A-Z^_a-z`{|}~])*@[a-zA-Z0-9](-*\\.?[a-zA-Z0-9])*\\.[a-zA-Z](-?[a-zA-Z0-9])+$/;\r\n// Thanks to:\r\n// http://fightingforalostcause.net/misc/2006/compare-email-regex.php\r\n// http://thedailywtf.com/Articles/Validating_Email_Addresses.aspx\r\n// http://stackoverflow.com/questions/201323/what-is-the-best-regular-expression-for-validating-email-addresses/201378#201378\r\nexports.validate = function(email)\r\n{\r\n\tif (!email)\r\n\t\treturn false;\r\n\t\t\r\n\tif(email.length>254)\r\n\t\treturn false;\r\n\r\n\tvar valid = tester.test(email);\r\n\tif(!valid)\r\n\t\treturn false;\r\n\r\n\t// Further checking of some things regex can't handle\r\n\tvar parts = email.split(\"@\");\r\n\tif(parts[0].length>64)\r\n\t\treturn false;\r\n\r\n\tvar domainParts = parts[1].split(\".\");\r\n\tif(domainParts.some(function(part) { return part.length>63; }))\r\n\t\treturn false;\r\n\r\n\treturn true;\r\n}","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\nimport EmailValidator from 'email-validator';\n\n/**\n * 电子邮件地址验证规则。\n *\n * @type {object}\n * @namespace\n * @author 胡海星\n */\nconst EmailRule = {\n  /**\n   * 测试电子邮件地址是否合法。\n   *\n   * @param {any} email\n   *    待测试的电子邮件地址，前后允许有空白字符。\n   * @return {boolean}\n   *    若电子邮件地址合法则返回true；否则返回false。\n   * @author 胡海星\n   */\n  isValid(email) {\n    return ((typeof email === 'string') || (email instanceof String))\n        && EmailValidator.validate(email.trim());\n  },\n};\n\nexport default EmailRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n/**\n * 验证字符串是否表示合法的整数的正则表达式。\n *\n * 整数可以是正数或者负数，只考虑十进制。\n *\n * @author 胡海星\n * @private\n */\nconst INTEGER_REGEXP = /^\\s*[+-]?\\d+\\s*$/;\n\n/**\n * 整数验证规则。\n *\n * @type {object}\n * @namespace\n * @author 胡海星\n */\nconst IntegerRule = {\n  /**\n   * 测试一个值是否表示一个合法的整数。\n   *\n   * 整数可以是正数或者负数，只考虑十进制。\n   *\n   * 注意此函数允许字符串首位出现空格。\n   *\n   * @param {any} value\n   *    待测试的值，前后允许有空白字符。\n   * @return {boolean}\n   *    若该值是一个表示整数的`number`，`Number`或`bigint`，或表示整数的字符串，则返回true；\n   *    否则返回false。\n   * @author 胡海星\n   */\n  isValid(value) {\n    const type = typeof value;\n    if (type === 'bigint') {\n      return true;\n    } else if (type === 'number') {\n      return Number.isInteger(value);\n    } else if (value instanceof Number) {\n      return Number.isInteger(Number(value));   // should convert value to primitive number\n    } else if ((type === 'string') || (value instanceof String)) {\n      return INTEGER_REGEXP.test(value);\n    } else {\n      return false;\n    }\n  },\n};\n\nexport default IntegerRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * The regular expression of a valid local date.\n *\n * @author Haixing Hu\n * @private\n */\nconst DATE_REGEXP = /^\\s*[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}\\s*$/;\n\n/**\n * The validation rule of local date values.\n *\n * @type {object}\n * @namespace\n * @author Haixing Hu\n */\nconst LocalDateRule = {\n  /**\n   * Tests whether a value represents a valid local date.\n   *\n   * The value could be a string representing a valid local date, or a built-in\n   * `Date` object.\n   *\n   * If the value is a string, it will be trimmed before testing.\n   *\n   * Note that this function only tests the format of the date, but not its\n   * logical value (e.g. whether a month exceeds 31 days).\n   *\n   * @param {any} value\n   *    The value to be tested. It could be a string primitive, a built-in\n   *    `String` object, or a built-in `Date` object. The leading or trailing\n   *    white spaces of the string will be trimmed before testing.\n   * @return {boolean}\n   *    `true` if the value represents a valid local date; `false` otherwise.\n   * @author Haixing Hu\n   */\n  isValid(value) {\n    if (value instanceof Date) {\n      return true;\n    } else if ((typeof value === 'string') || (value instanceof String)) {\n      return DATE_REGEXP.test(value.trim());\n    } else {\n      return false;\n    }\n  },\n};\n\nexport default LocalDateRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * 验证字符串是否表示合法的本地日期时间的正则表达式。\n *\n * @author 胡海星\n * @private\n */\nconst DATETIME_REGEXP = /^\\s*[0-9]{4}-(0?[1-9]|1[0-2])-(0?[1-9]|[12][0-9]|3[01]) (0?[0-9]|1[0-9]|2[0-3]):(0?[0-9]|[1-5][0-9])(:(0?[0-9]|[1-5][0-9]))?\\s*$/;\n\n/**\n * 本地日期时间验证规则。\n *\n * @type {object}\n * @namespace\n * @author 胡海星\n */\nconst LocalDateTimeRule = {\n  /**\n   * 测试一个字符串是否表示一个合法的本地日期时间。\n   *\n   * 一个合法的本地日期时间字符串应该符合以下格式：\n   *\n   * ```\n   * yyyy-MM-dd' 'HH:mm:ss\n   * ```\n   *\n   * 注意此函数允许字符串首位出现空格。\n   *\n   * 注意，此函数只考虑日期时间格式是否正确，不考虑日期时间的逻辑合理性（比如某个月超过了31天）。\n   *\n   * @param {any} datetime\n   *    待测试的字符串，前后允许有空白字符。\n   * @return {boolean}\n   *    若该字符串表示一个合法的日期时间则返回true；否则返回false。\n   * @author 胡海星\n   */\n  isValid(datetime) {\n    if (((typeof datetime === 'string') || (datetime instanceof String))) {\n      return DATETIME_REGEXP.test(datetime);\n    } else {\n      return false;\n    }\n  },\n};\n\nexport default LocalDateTimeRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * The regular expression of a valid local date.\n *\n * @author Haixing Hu\n * @private\n */\nconst TIME_REGEXP = /^\\s*(0?[0-9]|1[0-9]|2[0-3]):(0?[0-9]|[0-5][0-9])(:(0?[0-9]|[0-5][0-9]))?\\s*$/;\n\n/**\n * The validation rule of local time values.\n *\n * @type {object}\n * @namespace\n * @author Haixing Hu\n */\nconst LocalTimeRule = {\n  /**\n   * Tests whether a value represents a valid local time.\n   *\n   * If the value is a string, it will be trimmed before testing.\n   *\n   * A valid local time string should be in the following format:\n   * ```\n   * [H]H:[m]m[:[s]s]\n   * ```\n   *\n   * For example, `12:34`, `23:59:59`, `02:32:9`, `1:2:3`, etc.\n   *\n   * Note that this function only tests the format of the time, as well as its\n   * logical value (e.g. whether a second exceeds 60).\n   *\n   * @param {any} value\n   *    The value to be tested. It could be a string primitive, a built-in\n   *    `String` object, or other type. The leading and trailing whitespaces\n   *    of a string will be trimmed before testing.\n   * @return {boolean}\n   *    `true` if the value represents a valid local date; `false` otherwise.\n   * @author Haixing Hu\n   */\n  isValid(value) {\n    if ((typeof value === 'string') || (value instanceof String)) {\n      return TIME_REGEXP.test(value);\n    } else {\n      return false;\n    }\n  },\n};\n\nexport default LocalTimeRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * 验证字符串是否表示合法的数字的正则表达式。\n *\n * 数字可以是正数或者负数，可以是科学计数法，并且只考虑十进制。\n *\n * 注意，此正则表达式不考虑 `NaN` 和 `Infinity`.\n *\n * @author 胡海星\n * @private\n */\nconst NUMBER_REGEXP = /^\\s*[+-]?(?:\\d+\\.?|\\d*\\.\\d+)(?:[E|e][+|-]?\\d+)?\\s*$/;\n\n/**\n * 用于测试一个值是否表示合法的数字的规则对象。\n *\n * 数字包括整数和浮点数（`number`, `Number`对象），但**不包括**大整数（`bigint`）。\n *\n * 表示一个合法数字的字符串（`string`或`String`对象），也被看作是一个合法的数字。\n *\n * 数字可以是正数或者负数，可以是科学计数法，并且只考虑十进制。\n *\n * **注意：** 和 `NumericRule` 对象不同，`bigint` 值不被看作是一个合法的数字。\n *\n * @type {object}\n * @namespace\n * @see NumericRule\n * @author 胡海星\n */\nconst NumberRule = {\n\n  /**\n   * 默认的测试选项。\n   */\n  DEFAULT_OPTION: {\n    allowNaN: false,\n    allowInfinity: false,\n  },\n\n  /**\n   * 测试一个值是否表示一个合法的数字。\n   *\n   * 数字包括整数和浮点数（`number`, `Number`对象），但**不包括**大整数（`bigint`）。\n   *\n   * 表示一个合法数字的字符串（`string`或`String`对象），也被看作是一个合法的数字。\n   *\n   * 数字可以是正数或者负数，可以用科学计数法，并且只考虑十进制。\n   *\n   * 注意此函数允许字符串首位出现空格。\n   *\n   * **注意：** 和 `NumericRule.isValid()` 不同，`bigint` 值不被看作是一个合法的数字。\n   *\n   * @param {any} value\n   *    待测试的值，前后允许有空白字符。\n   * @param {object} option\n   *    测试选项，表示是否将 ‘NaN’ 或 ‘Infinity’ 也看做是合法的数字字符串表示。\n   *    此选项对象可以包含下列属性：\n   *    - allowNaN: 是否将字符串 'NaN' 也看做是一个表示浮点数的合法字符串；默认值为`false`。\n   *    - allowInfinity: 是否将字符串 'Infinity' （注意大小写）也看做是一个表示浮点数的合法字符串；默认值为`false`。\n   * @return {boolean}\n   *    若该值是一个合法数字，或时一个表示合法数字的字符串则返回true；否则返回false。\n   * @author 胡海星\n   */\n  isValid(value, option = this.DEFAULT_OPTION) {\n    const type = typeof value;\n    if ((type === 'number') || (value instanceof Number)) {\n      const val = Number(value);  // should convert value to primitive number\n      if (Number.isNaN(val)) {\n        return (option.allowNaN === true);\n      } else if (!Number.isFinite(val)) {\n        return (option.allowInfinity === true);\n      }\n      return true;\n    } else if ((type === 'string') || (value instanceof String)) {\n      value = value.trim();\n      if (value.length === 0) {\n        return false;\n      }\n      if (NUMBER_REGEXP.test(value)) {\n        return true;\n      }\n      if (option.allowNaN && value.trim() === 'NaN') {\n        return true;\n      }\n      if (option.allowInfinity && value.trim() === 'Infinity') {\n        return true;\n      }\n    }\n    return false;\n  },\n};\n\nexport default NumberRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\nimport NumberRule from './number';\n\n/**\n * 用于测试一个值是否表示合法的数值的规则对象。\n *\n * 数值包括整数和浮点数（`number`, `Number`对象），和大整数（`bigint`）。\n *\n * 表示一个合法数字的字符串（`string`或`String`对象），也被看作是一个合法的数值。\n *\n * **注意：** 和 `NumberRule` 对象不同，`bigint` 值也被看作是一个合法的数值。\n *\n * @type {object}\n * @namespace\n * @see NumberRule\n * @author 胡海星\n */\nconst NumericRule = {\n  /**\n   * 测试一个值是否表示一个合法的数值。\n   *\n   * 数值包括整数和浮点数（`number`, `Number`对象），和大整数（`bigint`）。\n   *\n   * 表示一个合法数字的字符串（`string`或`String`对象），也被看作是一个合法的数值。\n   *\n   * 注意此函数允许字符串首位出现空格。\n   *\n   * **注意：** 和 `NumberRule.isValid()` 不同，`bigint` 值也被看作是一个合法的数值。\n   *\n   * @param {any} value\n   *    待测试的值，前后允许有空白字符。\n   * @param {object} option\n   *    测试选项，表示是否将 ‘NaN’ 或 ‘Infinity’ 也看做是合法的浮点数字符串表示。\n   *    此选项对象可以包含下列属性：\n   *    - allowNaN: 是否将字符串 'NaN' 也看做是一个表示浮点数的合法字符串；默认值为`false`。\n   *    - allowInfinity: 是否将字符串 'Infinity' （注意大小写）也看做是一个表示浮点数的合法字符串；默认值为`false`。\n   * @return {boolean}\n   *    若该值是一个合法浮点数，或时一个表示合法浮点数的字符串则返回true；否则返回false。\n   * @author 胡海星\n   */\n  isValid(value, option = NumberRule.DEFAULT_OPTION) {\n    if (typeof value === 'bigint') {\n      return true;\n    }\n    return NumberRule.isValid(value, option);\n  },\n};\n\nexport default NumericRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * 验证其他证件号码合法性的正则表达式。\n *\n * 合法的证件号码由2~60位字母、数字或句点组成。\n *\n * @author 胡海星\n * @private\n */\nconst NUMBER_REGEXP = /^\\s*[a-zA-Z0-9.]{2,60}\\s*$/;\n\n/**\n * 其他证件号码验证规则。\n *\n * @type {object}\n * @namespace\n * @author 胡海星\n */\nconst OtherCredentialRule = {\n  /**\n   * 检查其他证件号码是否合法\n   *\n   * @param {any} number\n   *    证件号码，前后允许有空白字符。\n   * @return {boolean}\n   *    若该证件号码合法，返回true；否则返回false\n   * @author 胡海星\n   */\n  isValid(number) {\n    if ((typeof number === 'string') || (number instanceof String)) {\n      return NUMBER_REGEXP.test(number);\n    } else {\n      return false;\n    }\n  },\n};\n\nexport default OtherCredentialRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2024.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * 验证字符串是否是合法的密码的正则表达式。\n *\n * 密码的规则如下：\n *\n * - 最少6个字符；\n * - 最多32个字符；\n * - 可以包含字母、数字；\n * - 可以包含下列特殊字符：`~!@#$%^&*()_=+{}[]|\\:;'\",./?<>`；\n *\n * @author 胡海星\n * @private\n */\nconst PASSWORD_REGEXP = /^[-a-zA-Z0-9`~!@#$%^&*()_=+{}[\\]|\\\\:;'\",./?<>]+$/;\n\n/**\n * 密码的验证规则。\n *\n * @type {object}\n * @namespace\n * @author 胡海星\n */\nconst PasswordRule = {\n  /**\n   * 密码的最小长度。\n   */\n  minLength: 6,\n\n  /**\n   * 密码的最大长度。\n   */\n  maxLength: 32,\n\n  /**\n   * 测试一个值是否是合法的密码。\n   *\n   * 密码的规则如下：\n   *\n   * - 最少6个字符；\n   * - 最多32个字符；\n   * - 可以包含字母、数字；\n   * - 可以包含下列特殊字符：`~!@#$%^&*()_=+{}[]|\\:;'\",./?<>`；\n   *\n   * @param {any} value\n   *    待测试的值，前后不允许有空白字符。\n   * @return {boolean}\n   *    若该字符串是一个表示合法密码的字符串则返回`true`；否则返回`false`。\n   * @author 胡海星\n   */\n  isValid(value) {\n    if ((typeof value === 'string') || (value instanceof String)) {\n      return (value.length >= this.minLength)\n        && (value.length <= this.maxLength)\n        && PASSWORD_REGEXP.test(value);\n    } else {\n      return false;\n    }\n  },\n};\n\nexport default PasswordRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * 验证中文姓名的正则表达式\n *\n * 中文名称允许出现下述 Unicode 字符集\n * - CJK Unified Ideographs (U+4E00..U+9FEF)\n * - CJK Unified Ideographs Extension A (U+3400..U+4DBF)\n * - CJK Unified Ideographs Extension B (U+20000..U+2A6D6)\n * - CJK Unified Ideographs Extension C (U+2A700..U+2B734)\n * - CJK Unified Ideographs Extension D (U+2B740..U+2B81D)\n * - CJK Unified Ideographs Extension E (U+2B820..U+2CEA1)\n * - CJK Unified Ideographs Extension F (U+2CEB0..U+2EBE0)\n * - CJK Compatibility Ideographs (U+F900..U+FAD9)\n * - CJK Compatibility Ideographs Supplement (U+2F800..U+2FA1F)\n *\n *\n * 同时允许出现少数民族名中的点，包含[.·]等。\n *\n * 最小长度为２个字符，最大为30个字符。名字中间不允许出现空格。\n *\n * 参考链接：\n * 1. https://en.wikipedia.org/wiki/CJK_Unified_Ideographs\n * 2. https://en.wikipedia.org/wiki/CJK_Compatibility_Ideographs\n * 3. https://en.wikipedia.org/wiki/CJK_Compatibility_Ideographs_Supplement\n *\n * @author 胡海星\n * @private\n */\nconst CHINESE_NAME_REGEXP = /^\\s*[\\u{4E00}-\\u{9FEF}\\u{3400}-\\u{4DBF}\\u{20000}-\\u{2A6D6}\\u{2A700}-\\u{2B734}\\u{2B740}-\\u{2B81D}\\u{2B820}-\\u{2CEA1}\\u{2CEB0}-\\u{2EBE0}\\u{F900}-\\u{FAD9}\\u{2F800}-\\u{2FA1F}][\\u{4E00}-\\u{9FEF}\\u{3400}-\\u{4DBF}\\u{20000}-\\u{2A6D6}\\u{2A700}-\\u{2B734}\\u{2B740}-\\u{2B81D}\\u{2B820}-\\u{2CEA1}\\u{2CEB0}-\\u{2EBE0}\\u{F900}-\\u{FAD9}\\u{2F800}-\\u{2FA1F}·.]{0,28}[\\u{4E00}-\\u{9FEF}\\u{3400}-\\u{4DBF}\\u{20000}-\\u{2A6D6}\\u{2A700}-\\u{2B734}\\u{2B740}-\\u{2B81D}\\u{2B820}-\\u{2CEA1}\\u{2CEB0}-\\u{2EBE0}\\u{F900}-\\u{FAD9}\\u{2F800}-\\u{2FA1F}]\\s*$/u;\n\n/**\n * 验证英文姓名或汉语拼音名字的正则表达式\n *\n * 英文姓名或汉语拼音姓名允许大小写英文字母，半角空格，半角句点。\n *\n * 最短需要有2个字符，最长不超过60个字符。\n *\n * @author 胡海星\n * @private\n */\nconst ENGLISH_NAME_REGEXP = /^\\s*[a-zA-Z][a-zA-Z .]{0,58}[a-zA-Z]\\s*$/;\n\n/**\n * 中英文姓名验证规则。\n *\n * @type {object}\n * @namespace\n * @author 胡海星\n */\nconst PersonNameRule = {\n  /**\n   * 测试中英文姓名是否合法\n   *\n   * @param {any} name\n   *    待测试的姓名，前后允许有空白字符。\n   * @return {boolean}\n   *    若姓名合法则返回true；否则返回false。\n   * @author 胡海星\n   */\n  isValid(name) {\n    return ((typeof name === 'string') || (name instanceof String))\n        && (name.length !== 0)\n        && (CHINESE_NAME_REGEXP.test(name) || ENGLISH_NAME_REGEXP.test(name));\n  },\n};\n\nexport default PersonNameRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * 验证字符串是否表示合法的时间戳的正则表达式。\n *\n * @author 胡海星\n * @private\n */\nconst TIMESTAMP_REGEXP = /^\\s*[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}([ ]?T?[0-2]?[0-9]:[0-5]?[0-9](:[0-5]?[0-9](\\.[0-9]{1,3})?)?)?([ ]*[Zz])?\\s*$/;\n\n/**\n * 时间戳验证规则。\n *\n * @type {object}\n * @namespace\n * @author 胡海星\n */\nconst TimestampRule = {\n  /**\n   * 测试一个字符串是否表示一个合法的时间戳。\n   *\n   * 一个合法的时间戳字符串应该符合以下格式：\n   *\n   * ```\n   * yyyy-MM-dd[ ][T][HH:mm[:ss[.S[S[S]]]]][ ][Z|z]\n   * ```\n   *\n   * 注意此函数允许字符串首位出现空格。\n   *\n   * 注意，此函数只考虑时间戳格式是否正确，不考虑时间戳的逻辑合理性（比如某个月超过了31天）。\n   *\n   * @param {any} timestamp\n   *    待测试的字符串，前后允许有空白字符。\n   * @return {boolean}\n   *    若该字符串表示一个合法的时间戳则返回true；否则返回false。\n   * @author 胡海星\n   */\n  isValid(timestamp) {\n    if (((typeof timestamp === 'string') || (timestamp instanceof String))) {\n      return TIMESTAMP_REGEXP.test(timestamp);\n    } else {\n      return false;\n    }\n  },\n};\n\nexport default TimestampRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * 验证字符串是否是数字和大写字母组合成字符串。\n *\n * 这类字符串通常可以用来表示证件编号、发票号等数据。\n *\n * @author 胡海星\n * @private\n */\nconst UPPERCASE_ALPHA_NUMBER_REGEXP = /^\\s*[0-9A-Z]+\\s*$/;\n\n/**\n * 数字和大写字母组合字符串验证规则。\n *\n * @type {object}\n * @namespace\n * @author 胡海星\n */\nconst UppercaseAlphaNumberRule = {\n  /**\n   * 测试一个字符串是否是数字和大写字母组合成字符串。\n   *\n   * 这类字符串通常可以用来表示证件编号、发票号等数据。\n   *\n   * @param {any} str\n   *    待测试的字符串，前后允许有空白字符。\n   * @return {boolean}\n   *    若该字符串是数字和大写字母组合成字符串则返回true；否则返回false。\n   * @author 胡海星\n   */\n  isValid(str) {\n    if ((typeof str === 'string') || (str instanceof String)) {\n      return UPPERCASE_ALPHA_NUMBER_REGEXP.test(str);\n    } else {\n      return false;\n    }\n  },\n};\n\nexport default UppercaseAlphaNumberRule;\n","/**\n * Object helper from consis (https://github.com/elysiumphase/consis).\n *\n *    - exists(thing) -> Boolean\n *    - is(Type, thing) -> Boolean\n */\n\n/**\n * @func exists\n *\n * whether the specified value is not null, undefined or NaN\n * @param  {Any} thing\n * @return {Boolean}\n */\nconst exists = function exists(thing) {\n  return !(thing === undefined || thing === null || Number.isNaN(thing));\n};\n\n/**\n * @func is\n *\n * whether the specified value is from the specified type regarding its whole prototype\n * @param  {Function} Type a type function\n * @param  {Any} thing\n * @return {Boolean}\n */\nconst is = function is(Type, thing) {\n  return exists(Type)\n  && exists(thing)\n  && (thing.constructor === Type\n  || thing instanceof Type);\n};\n\nmodule.exports = Object.freeze({\n  exists,\n  is,\n});\n","/**\n * Type casting helper from consis (https://github.com/elysiumphase/consis).\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 */\nconst { is, exists } = require('./object');\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 *\n * @param  {Any} thing a value to cast to primitive number\n * @return {Number|undefined}\n */\nconst number = function number(thing) {\n  let castNum;\n\n  if (exists(thing)) {\n    const value = thing.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 *\n * @param  {Any} thing a value to cast to primitive number\n * @return {Number|undefined}\n */\nconst num = function num(thing, { ge, le } = {}) {\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 *\n * @param  {Any} thing a value to cast to primitive integer number\n * @return {Integer Number|undefined}\n */\nconst integer = function integer(thing) {\n  // first cast to number to avoid some inconsistencies with hexa\n  const castNum = number(thing);\n  let castInt;\n\n  if (castNum !== undefined) {\n    const int = parseInt(castNum, 10);\n\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 *\n * @param  {Any} thing a value to cast to primitive integer number\n * @return {Integer Number|undefined}\n */\nconst int = function int(thing, { le, ge } = {}) {\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// exports\nmodule.exports = Object.freeze({\n  number,\n  num,\n  int,\n  integer,\n});\n","const cast = require('./cast');\nconst object = require('./object');\n\nmodule.exports = Object.freeze({\n  cast,\n  object,\n});\n","/**\n * IP validator\n *\n * - isIP(ip) -> Boolean\n * - isIPv4(ip) -> Boolean\n * - isIPv6(ip) -> Boolean\n */\nconst { object: { is } } = require('../helpers');\n\n// ip regexps, credits: https://github.com/sindresorhus/ip-regex/blob/master/index.js\nconst v4 = '(?: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`.replace(/\\s*\\/\\/.*$/gm, '').replace(/\\n/g, '').trim();\n\n/**\n * @func isIP\n *\n * Test a string is a valid IP.\n *\n * @param  {String} ip\n * @return {Boolean}\n */\nconst isIP = function isIP(ip) {\n  if (!is(String, ip)) {\n    return false;\n  }\n\n  return new RegExp(`(?:^${v4}$)|(?:^${v6}$)`).test(ip);\n};\n\n/**\n * @func isIPv4\n *\n * Test a string is a valid IPv4.\n *\n * @param  {String} ip\n * @return {Boolean}\n */\nconst isIPv4 = function isIPv4(ip) {\n  if (!is(String, ip)) {\n    return false;\n  }\n\n  return new RegExp(`^${v4}$`).test(ip);\n};\n\n/**\n * @func isIPv6\n *\n * Test a string is a valid IPv6.\n *\n * @param  {String} ip\n * @return {Boolean}\n */\nconst isIPv6 = function isIPv6(ip) {\n  if (!is(String, ip)) {\n    return false;\n  }\n\n  return new RegExp(`^${v6}$`).test(ip);\n};\n\nmodule.exports = Object.freeze({\n  isIP,\n  isIPv4,\n  isIPv6,\n});\n","/**\n * punycode and punydecode\n *\n * - punycode(domain) -> String\n * - punydecode(domain) -> String\n */\nconst { domainToASCII, domainToUnicode } = require('url');\nconst { isIPv6 } = require('../ip');\nconst { object: { is } } = require('../helpers');\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 *\n * @param  {String} domain\n * @return {String}\n */\nconst punycode = function punycode(domain) {\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 *\n * @param  {String} domain\n * @return {String}\n */\nconst punydecode = function punydecode(domain) {\n  if (isIPv6(domain)) {\n    return domain;\n  }\n\n  return is(String, domain) ? domainToUnicode(domain) : '';\n};\n\nmodule.exports = Object.freeze({\n  punycode,\n  punydecode,\n});\n","/**\n * config module\n */\n\nconst maxLengthURL = 2048;\nconst minPortInteger = 0;\nconst maxPortInteger = 65535;\n\nmodule.exports = Object.freeze({\n  maxLengthURL,\n  minPortInteger,\n  maxPortInteger,\n});\n","/**\n * parser\n *\n * - hostToURI(host) -> String\n * - recomposeURI({ scheme, userinfo, host port, path, query, fragment } = {}) -> String\n * - parseURI(uri) -> Object\n */\nconst { punycode, punydecode } = require('../punycode');\nconst { isIPv6 } = require('../ip');\nconst { cast: { int }, object: { exists, is } } = require('../helpers');\nconst { minPortInteger, maxPortInteger } = require('../config');\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 *\n * @param  {String} host\n * @return {String}\n */\nconst hostToURI = function hostToURI(host) {\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 will be ignored if empty;\n * 9. fragment will be ignored if empty.\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 *\n * @param {Object} components:\n * @param {String} scheme\n * @param {String} userinfo\n * @param {String} host\n * @param {Integer} port\n * @param {String} path\n * @param {String} query\n * @param {String} fragment\n * @return {String}\n */\nconst recomposeURI = function recomposeURI(components) {\n  const cpts = components || {};\n  const defaultReturnValue = '';\n\n  if (!(is(String, cpts.scheme) && cpts.scheme.length > 0) || !is(String, cpts.path)) {\n    return defaultReturnValue;\n  }\n\n  let uri = cpts.scheme;\n\n  if (is(String, cpts.host)) {\n    if (!(cpts.path === '' || cpts.path.startsWith('/'))) {\n      return defaultReturnValue;\n    }\n\n    if (cpts.host.length <= 2) {\n      return defaultReturnValue;\n    }\n\n    uri += '://';\n\n    if (is(String, cpts.userinfo) && cpts.userinfo.length > 0) {\n      uri += `${cpts.userinfo}@`;\n    }\n\n    uri += hostToURI(cpts.host);\n\n    if (exists(cpts.port)\n      && int(cpts.port, { ge: minPortInteger, le: maxPortInteger }) !== undefined) {\n      uri += `:${cpts.port}`;\n    }\n  } else {\n    if (cpts.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 (cpts.path === '' && is(String, cpts.host)) {\n    uri += '/';\n  } else {\n    uri += cpts.path;\n  }\n\n  if (is(String, cpts.query) && cpts.query.length > 0) {\n    uri += `?${cpts.query}`;\n  }\n\n  if (is(String, cpts.fragment) && cpts.fragment.length > 0) {\n    uri += `#${cpts.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 *\n * @param  {String} uri\n * @return {Object}\n */\nconst parseURI = function parseURI(uri) {\n  const parsed = {\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  const [,\n    scheme,\n    authorityParsed,\n    path,\n    queryParsed,\n    fragmentParsed,\n  ] = 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 = null;\n  let authorityPunydecoded = null;\n  let userinfo = null;\n  let host = null;\n  let hostPunydecoded = null;\n  let port = null;\n\n  // parse authority components, if any\n  if (is(String, authorityParsed)) {\n    let hostAndPort = null;\n\n    [userinfo = null, hostAndPort = null] = authorityParsed.split('@');\n\n    // authority had no '@' and no userinfo can be extracted\n    if (!exists(hostAndPort) && exists(userinfo)) {\n      hostAndPort = userinfo;\n      userinfo = null;\n    }\n\n    // try to extract host and port only if any\n    if (is(String, hostAndPort)) {\n      // detect IPv6 here first\n      const ipv6Match = hostAndPort.match(ipv6Regexp);\n      let hostParsed;\n      let portToCast;\n\n      // if an array then it's constructed as an ipv6\n      if (is(Array, ipv6Match)) {\n        [, hostParsed = null, portToCast = null] = ipv6Match;\n      } else {\n        // not an ipv6\n        [hostParsed = null, portToCast = null] = hostAndPort.split(':');\n      }\n\n      // hostPunydecoded should be the host in Unicode, host its Punycode value\n      const hostLowerCase = is(String, hostParsed) ? hostParsed.toLowerCase() : null;\n      const toASCII = punycode(hostLowerCase);\n      const toUnicode = punydecode(hostLowerCase);\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      port = 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      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  const query = is(String, queryParsed) && queryParsed.length > 0 ? queryParsed : null;\n  const fragment = is(String, fragmentParsed) && fragmentParsed.length > 0 ? fragmentParsed : null;\n\n  // pathqf: recompose path + query + fragment if any\n  // using valueOf to avoid potential String objects mutation with parsed.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  parsed.path = path;\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\nmodule.exports = Object.freeze({\n  hostToURI,\n  recomposeURI,\n  parseURI,\n});\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 */\nconst { object: { is } } = require('../helpers');\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 *\n * @param  {String} char\n * @return {Boolean}\n */\nconst isSchemeChar = function isSchemeChar(char, { start } = {}) {\n  if (!is(String, char)) {\n    return false;\n  }\n\n  const code = char.charCodeAt();\n\n  if (start) {\n    return code >= 97 && code <= 122;\n  }\n\n  return (code >= 48 && code <= 57)\n    || (code >= 97 && code <= 122)\n    || code === 43\n    || code === 45\n    || code === 46;\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 *\n * @param  {String} char\n * @return {Boolean}\n */\nconst isUserinfoChar = function isUserinfoChar(char, encode) {\n  if (!is(String, char)) {\n    return false;\n  }\n\n  // false by default\n  const encoding = encode === true;\n  const code = char.charCodeAt();\n\n  // % is not allowed when encoding\n  if (code === 37) {\n    return !encoding;\n  }\n\n  return (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 * @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 *\n * @param  {String} char\n * @return {Boolean}\n */\nconst isSitemapUserinfoChar = function isSitemapUserinfoChar(char, encode) {\n  if (!is(String, char)) {\n    return false;\n  }\n\n  // false by default\n  const encoding = encode === true;\n  const code = char.charCodeAt();\n\n  // % is not allowed when encoding\n  if (code === 37) {\n    return !encoding;\n  }\n\n  return (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 * @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 *\n * @param  {String} char\n * @return {Boolean}\n */\nconst isDomainChar = function isDomainChar(char, { start, end } = {}) {\n  if (!is(String, char)) {\n    return false;\n  }\n\n  const code = char.charCodeAt();\n\n  if ((start === true || end === true) && code === 45) {\n    return false;\n  }\n\n  return (code >= 48 && code <= 57)\n    || (code >= 97 && code <= 122)\n    || 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 *\n * @param  {String} char\n * @return {Boolean}\n */\nconst isPathChar = function isPathChar(char, encode) {\n  if (!is(String, char)) {\n    return false;\n  }\n\n  // false by default\n  const encoding = encode === true;\n  const code = char.charCodeAt();\n\n  // % is not allowed when encoding\n  if (code === 37) {\n    return !encoding;\n  }\n\n  return (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 * @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 *\n * @param  {String} char\n * @return {Boolean}\n */\nconst isSitemapPathChar = function isSitemapPathChar(char, encode) {\n  if (!is(String, char)) {\n    return false;\n  }\n\n  // false by default\n  const encoding = encode === true;\n  const code = char.charCodeAt();\n\n  // % is not allowed when encoding\n  if (code === 37) {\n    return !encoding;\n  }\n\n  return (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 * @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 *\n * @param  {String} char\n * @return {Boolean}\n */\nconst isQueryOrFragmentChar = function isQueryOrFragmentChar(char, encode) {\n  if (isPathChar(char, encode)) {\n    return true;\n  }\n\n  return is(String, char) && char.charCodeAt() === 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 *\n * @param  {String} char\n * @return {Boolean}\n */\nconst isSitemapQueryOrFragmentChar = function isSitemapQueryOrFragmentChar(char, encode) {\n  if (isSitemapPathChar(char, encode)) {\n    return true;\n  }\n\n  return is(String, char) && char.charCodeAt() === 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 * 48 to 57       0-9\n * 65 to 70       A-F\n *\n * @param  {String} char\n * @return {Boolean}\n */\nconst isPercentEncodingChar = function isPercentEncodingChar(char) {\n  if (!is(String, char)) {\n    return false;\n  }\n\n  const code = char.charCodeAt();\n\n  return (code >= 48 && code <= 57)\n    || (code >= 65 && code <= 70);\n};\n\nmodule.exports = Object.freeze({\n  isSchemeChar,\n  isUserinfoChar,\n  isSitemapUserinfoChar,\n  isDomainChar,\n  isPathChar,\n  isSitemapPathChar,\n  isQueryOrFragmentChar,\n  isSitemapQueryOrFragmentChar,\n  isPercentEncodingChar,\n});\n","/**\n * domain\n *\n * - isDomainLabel(label) -> Boolean\n * - isDomain(name) -> Boolean\n */\nconst { punycode } = require('../punycode');\nconst { isDomainChar } = require('../checkers/chars');\nconst { object: { is } } = require('../helpers');\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 *\n * @param  {String} label\n * @return {Boolean}\n */\nconst isDomainLabel = function isDomainLabel(label) {\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[i], { start: (i === 0), end: (i === len - 1) })) {\n      return false;\n    }\n\n    // check consecutive hyphens\n    if (label[i] === '-' && (i + 1) < len && label[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 *\n * @param  {String} name\n * @return {Boolean}\n */\nconst isDomain = function isDomain(name) {\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 = {};\n\n  for (let i = 0; i < labelsLen; i += 1) {\n    // ignore root label if ''\n    if (!(i === labelsLen - 1 && labels[i] === '')) {\n      const label = labels[i].startsWith('xn--') ? labels[i].slice(4) : labels[i];\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[labels[i]] = (occurences[labels[i]] || 0) + 1;\n\n      if (occurences[labels[i]] > 1) {\n        return false;\n      }\n    }\n  }\n\n  return true;\n};\n\nmodule.exports = Object.freeze({\n  isDomainLabel,\n  isDomain,\n});\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 = {\n  '*': '%2A',\n};\n\n// special chars keys\nconst specialCharsKeys = Object.keys(specialChars);\n\n// inversed special chars (percent encodings)\nconst pencodings = {};\nspecialCharsKeys.forEach((char) => {\n  pencodings[specialChars[char]] = char;\n});\n\nconst pencodingsKeys = Object.keys(pencodings);\n\n// sitemap entities to be escaped in URLs\nconst entities = {\n  '&': '&amp;',\n  '\\'': '&apos;',\n};\n\n// entities keys\nconst entitiesKeys = Object.keys(entities);\n\n// inversed entities keys (escape codes)\nconst escapeCodes = {};\nentitiesKeys.forEach((entity) => {\n  escapeCodes[entities[entity]] = entity;\n});\n\n// escape codes keys and length\nconst escapeCodesKeys = Object.keys(escapeCodes);\nconst escapeCodesKeysLen = escapeCodesKeys.length;\n\nmodule.exports = Object.freeze({\n  specialChars,\n  specialCharsKeys,\n  pencodings,\n  pencodingsKeys,\n  entities,\n  entitiesKeys,\n  escapeCodes,\n  escapeCodesKeys,\n  escapeCodesKeysLen,\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 */\nconst { maxLengthURL, minPortInteger, maxPortInteger } = require('../config');\nconst { parseURI } = require('../parser');\nconst { isDomain } = require('../domain');\nconst { cast: { int }, object: { exists, is } } = require('../helpers');\nconst { isIP } = require('../ip');\nconst {\n  escapeCodesKeys,\n  escapeCodesKeysLen,\n} = require('../sitemap');\nconst {\n  isSchemeChar,\n  isUserinfoChar,\n  isPathChar,\n  isQueryOrFragmentChar,\n  isSitemapUserinfoChar,\n  isSitemapPathChar,\n  isSitemapQueryOrFragmentChar,\n  isPercentEncodingChar,\n} = require('./chars');\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 *\n * @param  {String} string\n * @param  {Number} index\n * @param  {Number} stringLen\n * @return {Number} the offset where to check next\n * @throws {URIError}\n */\nconst checkPercentEncoding = function checkPercentEncoding(string, index, stringLen) {\n  if (!is(String, string)) {\n    const error = new URIError('a string is required when checking for percent encoding');\n    error.code = 'URI_INVALID_PERCENT_ENCODING';\n    throw error;\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[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[i + 1])) {\n        const error = new URIError(`invalid percent encoding char '${string[i + 1]}'`);\n        error.code = 'URI_INVALID_PERCENT_ENCODING';\n        throw error;\n      } else if (!isPercentEncodingChar(string[i + 2])) {\n        const error = new URIError(`invalid percent encoding char '${string[i + 2]}'`);\n        error.code = 'URI_INVALID_PERCENT_ENCODING';\n        throw error;\n      } else {\n        offset = 2;\n      }\n    } else {\n      const error = new URIError('incomplete percent encoding found');\n      error.code = 'URI_INVALID_PERCENT_ENCODING';\n      throw error;\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 *\n * @param  {String} string\n * @param  {Number} index\n * @param  {Number} stringLen\n * @return {Number} the offset where to check next\n * @throws {URIError}\n */\nconst checkSitemapEncoding = function checkSitemapEncoding(string, index, stringLen) {\n  if (!is(String, string)) {\n    const error = new URIError('a string is required when checking for sitemap encoding');\n    error.code = 'URI_INVALID_SITEMAP_ENCODING';\n    throw error;\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[i] === '&') {\n    let escapeOffset;\n\n    for (let j = 0; j < escapeCodesKeysLen; j += 1) {\n      const code = escapeCodesKeys[j];\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      const error = new URIError(`entity '${string[i]}' is not properly escaped`);\n      error.code = 'URI_INVALID_SITEMAP_ENCODING';\n      throw error;\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 *\n * @param  {String} type\n * @param  {String} string\n * @param  {Boolean} sitemap\n * @return {Boolean}\n * @throws {URIError}\n */\nconst checkComponent = function checkComponent({ type, string, sitemap } = {}) {\n  if (!['userinfo', 'path', 'query', 'fragment'].includes(type)) {\n    const error = new URIError(`unable to check pathqf, got '${type}' component to check`);\n    error.code = 'URI_INVALID_CHECKING_COMPONENT';\n    throw error;\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;\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    default:\n  }\n\n  for (let i = 0; i < len; i += 1) {\n    // check character is valid\n    if (!checkCharFunc(string[i])) {\n      const error = new URIError(`invalid ${type} char '${string[i]}'`);\n      error.code = `URI_INVALID_${type.toUpperCase()}_CHAR`;\n      throw error;\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 *\n * @param {String} scheme\n * @return {Boolean}\n */\nconst checkSchemeChars = function checkSchemeChars(scheme, len) {\n  if (!is(String, scheme)) {\n    const error = new URIError('scheme must be a string');\n    error.code = 'URI_INVALID_SCHEME';\n    throw error;\n  }\n\n  const schemeLen = is(Number, len) && len > 0 ? len : scheme.length;\n\n  if (schemeLen <= 0) {\n    const error = new URIError('scheme cannot be empty');\n    error.code = 'URI_INVALID_SCHEME';\n    throw error;\n  }\n\n  for (let i = 0; i < schemeLen; i += 1) {\n    if (!isSchemeChar(scheme[i], { start: (i === 0) })) {\n      const error = new URIError(`invalid scheme char '${scheme[i]}'`);\n      error.code = 'URI_INVALID_SCHEME_CHAR';\n      throw error;\n    }\n  }\n\n  return true;\n};\n\n/**\n * @func checkLowercase\n *\n * Check a string has not any uppercase characters.\n *\n * @param  {String} uri\n * @return {Boolean}\n * @throws {URIError}\n */\nconst checkLowercase = function checkLowercase(uri) {\n  if (!is(String, uri)) {\n    const error = new URIError('uri must be a string');\n    error.code = 'URI_INVALID_TYPE';\n    throw error;\n  }\n\n  if (uri.toLowerCase() !== uri) {\n    const error = new URIError('uri cannot contain any uppercase characters');\n    error.code = 'URI_INVALID_CHAR';\n    throw error;\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 *\n * @param  {String} uri\n * @return {Object}\n * @throws {URIError}\n */\nconst checkURISyntax = function checkURISyntax(uri) {\n  if (!is(String, uri)) {\n    const error = new URIError('uri must be a string');\n    error.code = 'URI_INVALID_TYPE';\n    throw error;\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    const error = new URIError('uri scheme is required');\n    error.code = 'URI_MISSING_SCHEME';\n    throw error;\n  } else if (schemeLen <= 0) {\n    const error = new URIError('uri scheme must not be empty');\n    error.code = 'URI_EMPTY_SCHEME';\n    throw error;\n  }\n\n  // path (required), can be an empty string\n  if (!is(String, path)) {\n    const error = new URIError('uri path is required');\n    error.code = 'URI_MISSING_PATH';\n    throw error;\n  }\n\n  // path: if authority is present path must be empty or start with /\n  if (is(String, authority) && authority.length > 0) {\n    if (!(path === '' || path.startsWith('/'))) {\n      const error = new URIError('path must be empty or start with \\'/\\' when authority is present');\n      error.code = 'URI_INVALID_PATH';\n      throw error;\n    }\n  } else if (path.startsWith('//')) {\n    // if authority is not present path must not start with //\n    const error = new URIError('path must not start with \\'//\\' when authority is not present');\n    error.code = 'URI_INVALID_PATH';\n    throw error;\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    const error = new URIError(`host must be a valid ip or domain name, got '${hostPunydecoded}'`);\n    error.code = 'URI_INVALID_HOST';\n    throw error;\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 *\n * @param  {String} uri\n * @param  {Boolean} sitemap\n * @return {Object}\n * @throws {URIError}\n */\nconst checkURI = function checkURI(uri, { sitemap } = {}) {\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, 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) && !isDomain(host)) {\n      const error = new URIError(`host must be a valid ip or domain name, got '${host}'`);\n      error.code = 'URI_INVALID_HOST';\n      throw error;\n    }\n\n    // check port is a number if any\n    if (exists(port) && int(port, { ge: minPortInteger, le: maxPortInteger }) === undefined) {\n      const error = new URIError(`port must be an integer between ${minPortInteger}-${maxPortInteger}, got '${port}'`);\n      error.code = 'URI_INVALID_PORT';\n      throw error;\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 *\n * @param  {String} uri\n * @param  {Boolean} https\n * @param  {Boolean} web whether to check both http and https\n * @param  {Boolean} sitemap\n * @return {Object}\n * @throws {URIError}\n */\nconst checkHttpURL = function checkHttpURL(uri, { https, web, sitemap } = {}) {\n  // precheck case for sitemap only\n  if (sitemap === true) {\n    checkLowercase(uri);\n  }\n\n  const schemesToCheck = [];\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)) {\n    const error = new URIError(`scheme must be ${schemesToCheck.join(' or ')}, got '${scheme}'`);\n    error.code = 'URI_INVALID_SCHEME';\n    throw error;\n  }\n\n  // authority\n  if (!is(String, authority)) {\n    const error = new URIError('authority is required');\n    error.code = 'URI_MISSING_AUTHORITY';\n    throw error;\n  }\n\n  // max length\n  if (is(String, href) && href.length > maxLengthURL) {\n    const error = new URIError(`max URL length of ${maxLengthURL} reached: ${href.length}`);\n    error.code = 'URI_MAX_LENGTH_URL';\n    throw error;\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 *\n * @param  {String} uri\n * @return {Object}\n * @throws {URIError}\n */\nconst checkHttpsURL = function checkHttpsURL(uri) {\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 *\n * @param  {String} uri\n * @return {Object}\n * @throws {URIError}\n */\nconst checkHttpSitemapURL = function checkHttpSitemapURL(uri) {\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 *\n * @param  {String} uri\n * @return {Object}\n * @throws {URIError}\n */\nconst checkHttpsSitemapURL = function checkHttpsSitemapURL(uri) {\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 *\n * @param  {String} uri\n * @return {Object}\n * @throws {URIError}\n */\nconst checkWebURL = function checkWebURL(uri) {\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 *\n * @param  {String} uri\n * @return {Object}\n * @throws {URIError}\n */\nconst checkSitemapURL = function checkSitemapURL(uri) {\n  return checkHttpURL(uri, { web: true, sitemap: true });\n};\n\nmodule.exports = Object.freeze({\n  checkPercentEncoding,\n  checkSitemapEncoding,\n  checkComponent,\n  checkSchemeChars,\n  checkLowercase,\n  checkURISyntax,\n  checkURI,\n  checkHttpURL,\n  checkHttpsURL,\n  checkHttpSitemapURL,\n  checkHttpsSitemapURL,\n  checkWebURL,\n  checkSitemapURL,\n});\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 */\nconst { maxLengthURL, minPortInteger, maxPortInteger } = require('../config');\nconst { checkURISyntax, checkSchemeChars } = require('../checkers');\nconst {\n  isUserinfoChar,\n  isPathChar,\n  isQueryOrFragmentChar,\n  isSitemapUserinfoChar,\n  isSitemapPathChar,\n  isSitemapQueryOrFragmentChar,\n} = require('../checkers/chars');\nconst { recomposeURI } = require('../parser');\nconst { entities, specialChars } = require('../sitemap');\nconst { isDomain } = require('../domain');\nconst { isIP } = require('../ip');\nconst { cast: { int }, object: { exists, is } } = require('../helpers');\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 *\n * @param  {String} component\n * @param  {String} type\n * @param  {Boolean} sitemap\n * @param  {Boolean} lowercase\n * @return {String}\n */\nconst encodeURIComponentString = function encodeURIComponentString(\n  component,\n  { type, sitemap, lowercase } = {},\n) {\n  if (!is(String, component)) {\n    return '';\n  }\n\n  const componentToEncode = lowercase === true || sitemap === true\n    ? component.toLowerCase()\n    : component;\n  const componentToEncodeLen = componentToEncode.length;\n  let uricomponent = '';\n\n  for (let i = 0; i < componentToEncodeLen; i += 1) {\n    let encoded = false;\n\n    // escape entity or special chars if any FIRST\n    if (sitemap === true) {\n      if (exists(entities[componentToEncode[i]])) {\n        uricomponent += entities[componentToEncode[i]];\n        encoded = true;\n      } else if (exists(specialChars[componentToEncode[i]])) {\n        uricomponent += specialChars[componentToEncode[i]];\n        encoded = true;\n      }\n    }\n\n    if (!encoded) {\n      let isChar;\n\n      switch (type) {\n        case 'userinfo':\n          isChar = (sitemap && isSitemapUserinfoChar(componentToEncode[i], true))\n            || isUserinfoChar(componentToEncode[i], true);\n          break;\n        case 'path':\n          isChar = (sitemap && isSitemapPathChar(componentToEncode[i], true))\n            || isPathChar(componentToEncode[i], true);\n          break;\n        case 'query':\n        case 'fragment':\n          isChar = (sitemap && isSitemapQueryOrFragmentChar(componentToEncode[i], true))\n            || isQueryOrFragmentChar(componentToEncode[i], true);\n          break;\n        default:\n          isChar = false;\n      }\n\n      uricomponent += !isChar\n        ? encodeURIComponent(componentToEncode[i])\n        : componentToEncode[i];\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 *\n * @param  {String} uri\n * @param  {Boolean} web\n * @param  {Boolean} sitemap\n * @param  {Boolean} lowercase\n * @return {String}\n * @throws {URIError}\n */\nconst encodeURIString = function encodeURIString(uri, { web, sitemap, lowercase } = {}) {\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 {\n    scheme,\n    authority,\n    userinfo,\n    host,\n    port,\n    path,\n    query,\n    fragment,\n    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      const error = new URIError(`scheme must be http or https, got '${scheme}'`);\n      error.code = 'URI_INVALID_SCHEME';\n      throw error;\n    }\n  } else {\n    // check scheme characters, it is not intended to encode a scheme\n    checkSchemeChars(scheme, schemeLen);\n  }\n\n  // authority is required and must be a valid host for web/sitemap\n  if (webURL && !is(String, authority)) {\n    const error = new URIError('authority is required');\n    error.code = 'URI_MISSING_AUTHORITY';\n    throw error;\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    const error = new URIError(`host must be a valid ip or domain name, got '${host}'`);\n    error.code = 'URI_INVALID_HOST';\n    throw error;\n  }\n\n  // check port is a number if any\n  if (exists(port) && int(port, { ge: minPortInteger, le: maxPortInteger }) === undefined) {\n    const error = new URIError(`port must be an integer between ${minPortInteger}-${maxPortInteger}, got '${port}'`);\n    error.code = 'URI_INVALID_PORT';\n    throw error;\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  const pathEncoded = encodeURIComponentString(path, {\n    sitemap,\n    type: 'path',\n    lowercase: false,\n  });\n\n  // query\n  const queryEncoded = encodeURIComponentString(query, {\n    sitemap,\n    type: 'query',\n    lowercase: false,\n  });\n\n  // fragment\n  const fragmentEncoded = encodeURIComponentString(fragment, {\n    sitemap,\n    type: 'fragment',\n    lowercase: false,\n  });\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  if (webURL && uriencoded.length > maxLengthURL) {\n    const error = new URIError(`max URL length of ${maxLengthURL} reached: ${uriencoded.length}`);\n    error.code = 'URI_MAX_LENGTH_URL';\n    throw error;\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 *\n *\n * @param {String} uri\n * @param  {Boolean} lowercase\n * @return {String}\n * @throws {URIError}\n */\nconst encodeWebURL = function encodeWebURL(uri, { lowercase } = {}) {\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 *\n * @param  {String} uri\n * @return {String}\n * @throws {URIError}\n */\nconst encodeSitemapURL = function encodeSitemapURL(uri) {\n  return encodeURIString(uri, { lowercase: true, sitemap: true });\n};\n\nmodule.exports = Object.freeze({\n  encodeURIComponentString,\n  encodeURIString,\n  encodeWebURL,\n  encodeSitemapURL,\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 */\nconst { maxLengthURL, minPortInteger, maxPortInteger } = require('../config');\nconst { checkURISyntax, checkSchemeChars } = require('../checkers');\nconst { cast: { int }, object: { exists, is } } = require('../helpers');\nconst { recomposeURI } = require('../parser');\nconst { isDomain } = require('../domain');\nconst { isIP } = require('../ip');\nconst {\n  escapeCodes,\n  escapeCodesKeys,\n  pencodings,\n  pencodingsKeys,\n} = require('../sitemap');\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 *\n * @param  {String} uri\n * @param  {Boolean} sitemap\n * @param  {Boolean} lowercase\n * @return {String}\n */\nconst decodeURIComponentString = function decodeURIComponentString(\n  component,\n  { sitemap, lowercase } = {},\n) {\n  if (!is(String, component)) {\n    return '';\n  }\n\n  const componentToDecode = lowercase === true ? component.toLowerCase() : component;\n\n  if (sitemap === true) {\n    const regexp = new RegExp(escapeCodesKeys.concat(pencodingsKeys).join('|'), 'g');\n    const uriToDecode = componentToDecode.replace(\n      regexp,\n      (match) => escapeCodes[match] || pencodings[match],\n    );\n\n    try {\n      return decodeURIComponent(uriToDecode);\n    } catch (e) {\n      return '';\n    }\n  }\n\n  try {\n    return decodeURIComponent(componentToDecode);\n  } catch (e) {\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 *\n * @param  {String} uri\n * @param  {Boolean} sitemap\n * @param  {Boolean} lowercase\n * @return {String}\n * @throws {URIError}\n */\nconst decodeURIString = function decodeURIString(uri, { web, sitemap, lowercase } = {}) {\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      const error = new URIError(`scheme must be http or https, got '${scheme}'`);\n      error.code = 'URI_INVALID_SCHEME';\n      throw error;\n    }\n  } else {\n    // check scheme characters, it is not intended to decode a scheme\n    checkSchemeChars(scheme, schemeLen);\n  }\n\n  // authority is required and must be a valid host for web/sitemap\n  if (webURL && !is(String, authority)) {\n    const error = new URIError('authority is required');\n    error.code = 'URI_MISSING_AUTHORITY';\n    throw error;\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    const error = new URIError(`host must be a valid ip or domain name, got '${host}'`);\n    error.code = 'URI_INVALID_HOST';\n    throw error;\n  }\n\n  // check port is a number if any\n  if (exists(port) && int(port, { ge: minPortInteger, le: maxPortInteger }) === undefined) {\n    const error = new URIError(`port must be an integer between ${minPortInteger}-${maxPortInteger}, got '${port}'`);\n    error.code = 'URI_INVALID_PORT';\n    throw error;\n  }\n\n  // userinfo\n  // pass lowercase to false option since whole uri has been lowercased if true\n  const userinfoDecoded = decodeURIComponentString(\n    userinfo,\n    { sitemap, lowercase: false },\n  );\n\n  // path\n  const pathDecoded = decodeURIComponentString(\n    path,\n    { sitemap, lowercase: false },\n  );\n\n  // query\n  const queryDecoded = decodeURIComponentString(\n    query,\n    { sitemap, lowercase: false },\n  );\n\n  // fragment\n  const fragmentDecoded = decodeURIComponentString(\n    fragment,\n    { sitemap, lowercase: false },\n  );\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  if (webURL && uridecoded.length > maxLengthURL) {\n    const error = new URIError(`max URL length of ${maxLengthURL} reached: ${uridecoded.length}`);\n    error.code = 'URI_MAX_LENGTH_URL';\n    throw error;\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 *\n * @param  {String} uri\n * @param  {Boolean} lowercase\n * @return {String}\n * @throws {URIError}\n */\nconst decodeWebURL = function decodeWebURL(uri, { lowercase } = {}) {\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 *\n * @param  {String} uri\n * @param  {Boolean} lowercase\n * @return {String}\n * @throws {URIError}\n */\nconst decodeSitemapURL = function decodeSitemapURL(uri, { lowercase } = {}) {\n  return decodeURIString(uri, { lowercase, sitemap: true });\n};\n\nmodule.exports = Object.freeze({\n  decodeURIComponentString,\n  decodeURIString,\n  decodeWebURL,\n  decodeSitemapURL,\n});\n","/**\n * node-uri\n */\nconst { punycode, punydecode } = require('./punycode');\nconst { parseURI, recomposeURI } = require('./parser');\nconst { isDomainLabel, isDomain } = require('./domain');\nconst { isIP, isIPv4, isIPv6 } = require('./ip');\nconst {\n  checkURI,\n  checkHttpURL,\n  checkHttpsURL,\n  checkHttpSitemapURL,\n  checkHttpsSitemapURL,\n  checkWebURL,\n  checkSitemapURL,\n} = require('./checkers');\nconst {\n  encodeURIComponentString,\n  encodeURIString,\n  encodeWebURL,\n  encodeSitemapURL,\n} = require('./encoders');\nconst {\n  decodeURIComponentString,\n  decodeURIString,\n  decodeWebURL,\n  decodeSitemapURL,\n} = require('./decoders');\n\nmodule.exports = Object.freeze({\n  punycode,\n  punydecode,\n  parseURI,\n  recomposeURI,\n  isDomainLabel,\n  isDomain,\n  isIP,\n  isIPv4,\n  isIPv6,\n  checkURI,\n  checkHttpURL,\n  checkHttpsURL,\n  checkHttpSitemapURL,\n  checkHttpsSitemapURL,\n  checkWebURL,\n  checkSitemapURL,\n  encodeURIComponentString,\n  encodeURIString,\n  encodeWebURL,\n  encodeSitemapURL,\n  decodeURIComponentString,\n  decodeURIString,\n  decodeWebURL,\n  decodeSitemapURL,\n});\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\nimport uri from 'node-uri';\n\n/**\n * URL地址验证规则。\n *\n * @type {object}\n * @namespace\n * @author 胡海星\n */\nconst UrlRule = {\n  /**\n   * 测试URL是否是合法的网址。\n   *\n   * 合法的网址的schema必须是HTTP或HTTPS协议。\n   *\n   * @param {String} url\n   *    待测试的URL，前后允许有空白字符。\n   * @return {Boolean}\n   *    若URL合法则返回true；否则返回false。\n   * @author 胡海星\n   */\n  isValid(url) {\n    if ((typeof url === 'string') || (url instanceof String)) {\n      const u = url.trim();\n      if (u.length === 0) {\n        return false;\n      }\n      try {\n        uri.checkWebURL(u);\n        return true;\n      } catch (URIError) {\n        return false;\n      }\n    } else {\n      return false;\n    }\n  },\n};\n\nexport default UrlRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2024.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n/**\n * 验证字符串是否是合法的用户名的正则表达式。\n *\n * 用户名的规则如下：\n *\n * - 必须以字母或数字开头；\n * - 只能包含字母、数字、下划线、连字符、点号、@符号；\n * - 长度为4到32个字符。\n *\n * @author 胡海星\n * @private\n */\nconst USERNAME_REGEXP = /^[a-zA-Z0-9][a-zA-Z0-9@\\\\._-]*$/;\n\n/**\n * 用户名的验证规则。\n *\n * @type {object}\n * @namespace\n * @author 胡海星\n */\nconst UsernameRule = {\n  /**\n   * 用户名的最小长度。\n   */\n  minLength: 4,\n\n  /**\n   * 用户名的最大长度。\n   */\n  maxLength: 32,\n\n  /**\n   * 测试一个值是否是合法的用户名。\n   *\n   * 用户名的规则如下：\n   *\n   * - 必须以字母或数字开头；\n   * - 只能包含字母、数字、下划线、连字符、点号、@符号；\n   * - 长度为4到32个字符。\n   *\n   * @param {any} value\n   *    待测试的值，前后不允许有空白字符。\n   * @return {boolean}\n   *    若该字符串是一个表示合法用户名的字符串则返回`true`；否则返回`false`。\n   * @author 胡海星\n   */\n  isValid(value) {\n    if ((typeof value === 'string') || (value instanceof String)) {\n      return (value.length >= this.minLength)\n        && (value.length <= this.maxLength)\n        && USERNAME_REGEXP.test(value);\n    } else {\n      return false;\n    }\n  },\n};\n\nexport default UsernameRule;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * The class of validation result.\n *\n * @author Haixing Hu\n */\nclass ValidationResult {\n  /**\n   * Indicates whether the validation is successful.\n   *\n   * @type {boolean}\n   */\n  success = true;\n\n  /**\n   * The description of the validation result.\n   *\n   * @type {string}\n   */\n  description = '';\n\n  /**\n   * Next validation result.\n   *\n   * If the validation has multiple failed results, the next failed result will\n   * be chained to this field.\n   *\n   * @type {ValidationResult | null}\n   */\n  next = null;\n\n  /**\n   * Create a new {@link ValidationResult} object.\n   *\n   * @param {boolean} success\n   *     The validation correctness flag of the new object. If not provided, the\n   *     default value `true` is used.\n   * @param {string} description\n   *     Description of the validation result of the new object. If not provided,\n   *     the default value is an empty string.\n   */\n  constructor(success = true, description = '') {\n    this.success = success ?? true;\n    this.description = description ?? '';\n    this.next = null;\n  }\n\n  /**\n   * Merge multiple {@link ValidationResult} objects.\n   *\n   * If all {@link ValidationResult} objects to be merged are successful,\n   * the merging result is a single successful {@link ValidationResult} object;\n   * otherwise, the merging result is the chain of all failed\n   * {@link ValidationResult} objects.\n   *\n   * @param  {Array} results\n   *     An array of multiple {@link ValidationResult} objects.\n   * @return {ValidationResult}\n   *     Returns the result of merging all objects in the specified\n   *     {@link ValidationResult} object array as a new {@link ValidationResult}\n   *     object.\n   */\n  static merge(results) {\n    if (Array.isArray(results) && (results.length > 0)) {\n      const first = new ValidationResult(true);\n      let last = first;\n      for (let i = 0; i < results.length; ++i) {\n        const result = results[i];\n        if (result && !result.success) {\n          last.next = result;\n          last = result;\n        }\n      }\n      last.next = null;\n      if (first.next) {\n        last = first.next;\n        first.next = null;\n        return last;\n      } else {\n        return first;\n      }\n    } else {\n      return new ValidationResult(true);\n    }\n  }\n}\n\nexport default ValidationResult;\n","////////////////////////////////////////////////////////////////////////////////\n//\n//    Copyright (c) 2022 - 2023.\n//    Haixing Hu, Qubit Co. Ltd.\n//\n//    All rights reserved.\n//\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * The default length of the verify code.\n *\n * @type {number}\n * @private\n */\nconst DEFAULT_VERIFY_CODE_LENGTH = 6;\n\n/**\n * The validation rule of verify codes.\n *\n * @type {object}\n * @namespace\n * @author Haixing Hu\n */\nconst VerifyCodeRule = {\n  /**\n   * Tests whether a string is a valid verify code.\n   *\n   * A valid verify code is a string which contains only digits and has the\n   * specified length\n   *\n   * @param {string} code\n   *     The string to be tested. The leading and trailing spaces are ignored.\n   * @param {number} length\n   *     The optional length of the verify code. The default value is 6.\n   * @return\n   *     true if the string is a valid verify code; false otherwise\n   * @author Haixing Hu\n   */\n  isValid(code, length = DEFAULT_VERIFY_CODE_LENGTH) {\n    if ((typeof code === 'string') || (code instanceof String)) {\n      code = code.trim();\n      const n = code.length;\n      if (n !== length) {\n        return false;\n      }\n      for (let i = 0; i < n; ++i) {\n        if ((code.charCodeAt(i) < 48)     // 48 is the ASCII code of '0'\n          || (code.charCodeAt(i) > 57)) { // 57 is the ASCII code of '9'\n          return false;\n        }\n      }\n      return true;\n    }\n    return false;\n  },\n};\n\nexport default VerifyCodeRule;\n"],"names":["_typeof","require","require$$0","_classCallCheck","_createClass","_defineProperty","ALPHA_NUMBER_REGEXP","AlphaNumberRule","isValid","value","String","test","BoolRule","type","Boolean","val","trim","toLowerCase","NUMBER_LENGTH","YEAR_INDEX","YEAR_LENGTH","MONTH_INDEX","MONTH_LENGTH","DAY_INDEX","DAY_LENGTH","DECIMAL_BASE","ASCII_0_CHAR_CODE","ASCII_9_CHAR_CODE","RATIO","LAST_CHAR","parseNumber","number","start","end","result","i","ch","charCodeAt","isIdCardNumberValid","length","sum","lastChar","charAt","toUpperCase","isIdCardBirthdayValid","year","month","day","birthday","Date","getFullYear","getMonth","getDate","now","getTime","ChinaIdentityCardRule","name","getGender","getIdCardGender","getBirthday","getIdCardBirthday","substring","concat","MOBILE_REGEXP","ChinaMobileRule","mobile","NUMBER_REGEXP","ChinaOfficerCardRule","ChinaPassportRule","PHONE_REGEXP","ChinaPhoneRule","phone","getDefaultExportFromCjs","x","tester","emailValidator","validate","email","parts","split","some","part","EmailRule","EmailValidator","INTEGER_REGEXP","IntegerRule","Number","isInteger","DATE_REGEXP","LocalDateRule","DATETIME_REGEXP","LocalDateTimeRule","datetime","TIME_REGEXP","LocalTimeRule","NumberRule","DEFAULT_OPTION","allowNaN","allowInfinity","option","arguments","undefined","this","isNaN","isFinite","NumericRule","OtherCredentialRule","PASSWORD_REGEXP","PasswordRule","minLength","maxLength","CHINESE_NAME_REGEXP","ENGLISH_NAME_REGEXP","PersonNameRule","TIMESTAMP_REGEXP","TimestampRule","timestamp","UPPERCASE_ALPHA_NUMBER_REGEXP","UppercaseAlphaNumberRule","str","exists","thing","object","Object","freeze","is","Type","constructor","castNum","valueOf","cast","integer","castInt","int","parseInt","num","ge","le","lessThan","greaterThan","require$$1","helpers","v4","v6seg","v6","replace","ip","isIP","RegExp","isIPv4","isIPv6","domainToASCII","domainToUnicode","require$$2","punycode_1","punycode","domain","punydecode","config","maxLengthURL","minPortInteger","maxPortInteger","require$$3","uriRegexp","ipv6Regexp","hostToURI","host","recomposeURI","components","cpts","scheme","path","uri","startsWith","userinfo","port","query","fragment","parser","parseURI","parsed","authority","authorityPunydecoded","hostPunydecoded","pathqf","href","authorityParsed","queryParsed","fragmentParsed","match","hostAndPort","ipv6Match","hostParsed","portToCast","Array","hostLowerCase","toASCII","toUnicode","recomposedURI","isPathChar","char","encode","encoding","code","isSitemapPathChar","chars","isSchemeChar","isUserinfoChar","isSitemapUserinfoChar","isDomainChar","isQueryOrFragmentChar","isSitemapQueryOrFragmentChar","isPercentEncodingChar","isDomainLabel","label","len","isDomain","labels","labelsLen","occurences","slice","specialChars","specialCharsKeys","keys","pencodings","forEach","pencodingsKeys","entities","entitiesKeys","escapeCodes","entity","escapeCodesKeys","escapeCodesKeysLen","sitemap","require$$4","require$$5","require$$6","checkPercentEncoding","string","index","stringLen","error","URIError","offset","checkSitemapEncoding","escapeOffset","j","codeLen","checkComponent","includes","checkSitemap","checkCharFunc","checkSchemeChars","schemeLen","checkLowercase","checkURISyntax","valid","checkURI","checkHttpURL","https","web","schemesToCheck","push","join","checkers","checkHttpsURL","checkHttpSitemapURL","checkHttpsSitemapURL","checkWebURL","checkSitemapURL","require$$7","encodeURIComponentString","component","lowercase","componentToEncode","componentToEncodeLen","uricomponent","encoded","isChar","encodeURIComponent","encodeURIString","uriToEncode","webURL","userinfoEncoded","pathEncoded","queryEncoded","fragmentEncoded","uriencoded","encoders","encodeWebURL","encodeSitemapURL","decodeURIComponentString","componentToDecode","regexp","uriToDecode","decodeURIComponent","e","decodeURIString","userinfoDecoded","pathDecoded","queryDecoded","fragmentDecoded","uridecoded","decoders","decodeWebURL","decodeSitemapURL","UrlRule","url","u","USERNAME_REGEXP","UsernameRule","ValidationResult","success","description","next","key","merge","results","isArray","first","last","VerifyCodeRule","n","exports"],"mappings":"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","x_google_ignoreList":[8,21,22,23,24,25,26,27,28,29,30,31,32,33,34]}