stable-sort-domain.ts 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. // tldts-experimental is way faster than tldts, but very little bit inaccurate
  2. // (since it is hashes based). But the result is still deterministic, which is
  3. // enough when sorting.
  4. import { getDomain, getSubdomain } from 'tldts-experimental';
  5. import { sort } from './timsort';
  6. export const compare = (a: string, b: string) => {
  7. if (a === b) return 0;
  8. return (a.length - b.length) || a.localeCompare(b);
  9. };
  10. const tldtsOpt: Parameters<typeof getDomain>[1] = {
  11. allowPrivateDomains: false,
  12. extractHostname: false,
  13. validateHostname: false,
  14. detectIp: false,
  15. mixedInputs: false
  16. };
  17. export const sortDomains = (inputs: string[]) => {
  18. const domainMap = new Map<string, string>();
  19. const subdomainMap = new Map<string, string>();
  20. for (let i = 0, len = inputs.length; i < len; i++) {
  21. const cur = inputs[i];
  22. if (!domainMap.has(cur)) {
  23. const topD = getDomain(cur, tldtsOpt);
  24. domainMap.set(cur, topD ?? cur);
  25. }
  26. if (!subdomainMap.has(cur)) {
  27. const subD = getSubdomain(cur, tldtsOpt);
  28. subdomainMap.set(cur, subD ?? cur);
  29. }
  30. }
  31. const sorter = (a: string, b: string) => {
  32. if (a === b) return 0;
  33. const main_domain_a = domainMap.get(a)!;
  34. const main_domain_b = domainMap.get(b)!;
  35. let t = compare(
  36. main_domain_a,
  37. main_domain_b
  38. ) || compare(
  39. /** subdomain_a */ subdomainMap.get(a)!,
  40. /** subdomain_b */ subdomainMap.get(b)!
  41. );
  42. if (t !== 0) return t;
  43. if (a !== main_domain_a || b !== main_domain_b) {
  44. t = compare(a, b);
  45. }
  46. return t;
  47. };
  48. return sort(inputs, sorter);
  49. };