index.ts 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // @ts-nocheck
  2. /**
  3. * 域名验证配置选项
  4. */
  5. export type IsValidDomainOptions = {
  6. /**
  7. * 是否要求必须包含顶级域名(TLD)
  8. * @default true
  9. * @example
  10. * true -> "example.com" 有效
  11. * false -> "localhost" 有效
  12. */
  13. requireTld : boolean;
  14. /**
  15. * 是否允许域名部分包含下划线(_)
  16. * @default false
  17. * @example
  18. * true -> "my_site.com" 有效
  19. * false -> "my_site.com" 无效
  20. */
  21. allowUnderscore : boolean;
  22. /**
  23. * 是否允许域名以点号(.)结尾
  24. * @default false
  25. * @example
  26. * true -> "example.com." 有效
  27. * false -> "example.com." 无效
  28. */
  29. allowTrailingDot : boolean;
  30. }
  31. /**
  32. * 验证字符串是否为合法域名
  33. * @param str 要验证的字符串
  34. * @param options 配置选项,默认 {
  35. * requireTld: true, // 需要顶级域名
  36. * allowUnderscore: false,// 允许下划线
  37. * allowTrailingDot: false// 允许结尾点号
  38. * }
  39. * @returns 验证结果
  40. *
  41. * 示例:
  42. * isValidDomain("example.com") // true
  43. * isValidDomain("my_site.com", { allowUnderscore: true }) // true
  44. */
  45. export function isValidDomain(
  46. str : string,
  47. options : IsValidDomainOptions = {
  48. requireTld: true,
  49. allowUnderscore: false,
  50. allowTrailingDot: false
  51. }
  52. ) : boolean {
  53. // 预处理字符串
  54. let domain = str;
  55. // 处理结尾点号
  56. if (options.allowTrailingDot && domain.endsWith('.')) {
  57. domain = domain.slice(0, -1);
  58. }
  59. // 分割域名部分
  60. const parts = domain.split('.');
  61. if (parts.length == 1 && options.requireTld) return false;
  62. // 验证顶级域名
  63. const tld = parts[parts.length - 1];
  64. if (options.requireTld) {
  65. if (!/^[a-z\u00A1-\uFFFF]{2,}$/i.test(tld) || /\s/.test(tld)) {
  66. return false;
  67. }
  68. }
  69. // 验证每个部分
  70. const domainRegex = options.allowUnderscore
  71. ? /^[a-z0-9\u00A1-\uFFFF](?:[a-z0-9-\u00A1-\uFFFF_]*[a-z0-9\u00A1-\uFFFF])?$/i
  72. : /^[a-z0-9\u00A1-\uFFFF](?:[a-z0-9-\u00A1-\uFFFF]*[a-z0-9\u00A1-\uFFFF])?$/i;
  73. return parts.every(part => {
  74. // 长度校验
  75. if (part.length > 63) return false;
  76. // 格式校验
  77. if (!domainRegex.test(part)) return false;
  78. // 禁止开头/结尾连字符
  79. return !(part.startsWith('-') || part.endsWith('-'));
  80. });
  81. }