[SNOLAB] NPM Typescript Flag

Show "Dt" and "Ts" Icon on npm package search result.

目前为 2023-11-11 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name [SNOLAB] NPM Typescript Flag
  3. // @namespace https://userscript.snomiao.com/
  4. // @version 0.1.7
  5. // @description Show "Dt" and "Ts" Icon on npm package search result.
  6. // @author snomiao@gmail.com
  7. // @match *://www.npmjs.com/search*
  8. // @match *://npmjs.com/search*
  9. // @grant none
  10. // @contributionURL https://snomiao.com/donate
  11. // @supportURL https://github.com/snomiao/userscript.js/issues
  12. // ==/UserScript==
  13.  
  14. console.log("[SNOLAB] NPM Typescript Flag v0.1.5");
  15. let lastFetch = 0;
  16. let fails = 0;
  17.  
  18. const observer = new IntersectionObserver((entries) =>
  19. entries.forEach(async (entry) => {
  20. if (!entry.isIntersecting) return;
  21. while (!(await markPackage(entry.target)));
  22. })
  23. );
  24.  
  25. async function markPackage(h3) {
  26. if (h3.ariaChecked) return true;
  27. // back-off retry
  28. const interval = 200;
  29. const wait = interval * 2 ** fails;
  30. const until = lastFetch + wait;
  31. while (+new Date() < until)
  32. await new Promise((r) => setTimeout(r, (until - +new Date()) / 2));
  33. lastFetch = +new Date();
  34. //
  35. const pathname = h3.parentElement.pathname;
  36. const response = await fetch(pathname, { cache: "force-cache" });
  37. if (response.status !== 200) {
  38. fails++;
  39. return false; // will try again later
  40. }
  41. fails /= 2; // find a balanced request rate
  42.  
  43. const content = await response.text();
  44. const hasDt =
  45. content.match(
  46. '(?<="flex">)<img.*?This package has TypeScript declarations provided by.*?/>'
  47. )?.[0] ?? "";
  48. const hasTs =
  49. content.match(
  50. '(?<="true">)<img.*?This package contains built-in TypeScript declarations.*?/>'
  51. )?.[0] ?? "";
  52. h3.innerHTML = h3.innerText + " / " + hasDt + hasTs;
  53. console.log({ pathname, hasDt, hasTs });
  54. h3.ariaChecked = true;
  55. return true;
  56. }
  57.  
  58. function $$(sel, el = document) {
  59. return [...el.querySelectorAll(sel)];
  60. }
  61.  
  62. $$("a>h3").forEach(async (h3) => observer.observe(h3));