stable-sort-domain.ts 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. import * as tldts from 'tldts';
  2. import { sort } from './timsort';
  3. export const compare = (a: string, b: string) => {
  4. if (a === b) return 0;
  5. return (a.length - b.length) || a.localeCompare(b);
  6. };
  7. const tldtsOpt = {
  8. extractHostname: false,
  9. allowPrivateDomains: false,
  10. detectIp: false,
  11. validateHostname: false,
  12. mixedInputs: false
  13. };
  14. export const sortDomains = (inputs: string[]) => {
  15. const domainMap = new Map<string, string>();
  16. const subdomainMap = new Map<string, string>();
  17. for (let i = 0, len = inputs.length; i < len; i++) {
  18. const cur = inputs[i];
  19. if (!domainMap.has(cur)) {
  20. const topD = tldts.getDomain(cur, tldtsOpt);
  21. domainMap.set(cur, topD ?? cur);
  22. }
  23. if (!subdomainMap.has(cur)) {
  24. const subD = tldts.getSubdomain(cur, tldtsOpt);
  25. subdomainMap.set(cur, subD ?? cur);
  26. }
  27. }
  28. const sorter = (a: string, b: string) => {
  29. if (a === b) return 0;
  30. const main_domain_a = domainMap.get(a)!;
  31. const main_domain_b = domainMap.get(b)!;
  32. let t = compare(main_domain_a, main_domain_b);
  33. if (t === 0) {
  34. const subdomain_a = subdomainMap.get(a)!;
  35. const subdomain_b = subdomainMap.get(b)!;
  36. t = compare(subdomain_a, subdomain_b);
  37. }
  38. if (t === 0 && (a !== main_domain_a || b !== main_domain_b)) {
  39. t = compare(a, b);
  40. }
  41. return t;
  42. };
  43. return sort(inputs, sorter);
  44. };