stable-sort-domain.ts 1.7 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 * as tldts from 'tldts-experimental';
  5. import { looseTldtsOpt } from '../constants/loose-tldts-opt';
  6. export function compare(a: string, b: string) {
  7. if (a === b) return 0;
  8. return (a.length - b.length) || a.localeCompare(b);
  9. }
  10. export function buildParseDomainMap(inputs: string[]) {
  11. const domainMap = new Map<string, string>();
  12. const subdomainMap = new Map<string, string>();
  13. for (let i = 0, len = inputs.length; i < len; i++) {
  14. const cur = inputs[i];
  15. if (!domainMap.has(cur)) {
  16. const parsed = tldts.parse(cur, looseTldtsOpt);
  17. domainMap.set(cur, parsed.domain ?? cur);
  18. // if (!subdomainMap.has(cur)) {
  19. subdomainMap.set(cur, parsed.subdomain ?? cur);
  20. }
  21. }
  22. return { domainMap, subdomainMap };
  23. }
  24. export function sortDomains(inputs: string[],
  25. domainMap?: Map<string, string> | null,
  26. subdomainMap?: Map<string, string> | null) {
  27. if (!domainMap || !subdomainMap) {
  28. const { domainMap: dm, subdomainMap: sm } = buildParseDomainMap(inputs);
  29. domainMap = dm;
  30. subdomainMap = sm;
  31. }
  32. const sorter = (a: string, b: string) => {
  33. if (a === b) return 0;
  34. const main_domain_a = domainMap.get(a)!;
  35. const main_domain_b = domainMap.get(b)!;
  36. let t = compare(main_domain_a, main_domain_b)
  37. || compare(
  38. /** subdomain_a */ subdomainMap.get(a)!,
  39. /** subdomain_b */ subdomainMap.get(b)!
  40. );
  41. if (t !== 0) return t;
  42. if (a !== main_domain_a || b !== main_domain_b) {
  43. t = compare(a, b);
  44. }
  45. return t;
  46. };
  47. return inputs.sort(sorter);
  48. }