stable-sort-domain.js 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. // @ts-check
  2. const tldts = require('tldts');
  3. const cache1 = Object.create(null);
  4. /**
  5. * @param {string} url
  6. * @returns {ReturnType<typeof tldts.parse>}
  7. */
  8. // eslint-disable-next-line no-return-assign -- cache
  9. const parse = (url) => (cache1[url] ||= tldts.parse(url, { allowPrivateDomains: true }));
  10. /**
  11. * @param {string | null} a
  12. * @param {string | null} b
  13. * @returns {0 | 1 | -1}
  14. */
  15. const compare = (a, b) => {
  16. if (a === b) return 0;
  17. if (b == null) {
  18. return 1;
  19. }
  20. if (a == null) {
  21. return -1;
  22. }
  23. if (a.length !== b.length) {
  24. const r = a.length - b.length;
  25. if (r > 0) {
  26. return 1;
  27. }
  28. if (r < 0) {
  29. return -1;
  30. }
  31. return 0;
  32. }
  33. for (let i = 0; i < a.length; i++) {
  34. if (b[i] == null) {
  35. return 1;
  36. }
  37. if (a[i] < b[i]) {
  38. return -1;
  39. }
  40. if (a[i] > b[i]) {
  41. return 1;
  42. }
  43. }
  44. return 0;
  45. };
  46. /**
  47. * @param {string} a
  48. * @param {string} b
  49. * @returns {0 | 1 | -1}
  50. */
  51. const domainSorter = (a, b) => {
  52. if (a === b) return 0;
  53. const aParsed = parse(a[0] === '.' ? a.slice(1) : a);
  54. const bParsed = parse(b[0] === '.' ? b.slice(1) : b);
  55. const resultDomainWithoutSuffix = compare(aParsed.domainWithoutSuffix, bParsed.domainWithoutSuffix);
  56. if (resultDomainWithoutSuffix !== 0) {
  57. return resultDomainWithoutSuffix;
  58. }
  59. const resultSuffix = compare(aParsed.publicSuffix, bParsed.publicSuffix);
  60. if (resultSuffix !== 0) {
  61. return resultSuffix;
  62. }
  63. const resultSubdomain = compare(aParsed.subdomain, bParsed.subdomain);
  64. if (resultSubdomain !== 0) {
  65. return resultSubdomain;
  66. }
  67. return 0;
  68. };
  69. module.exports = domainSorter;