GitHub First Commit

Add a link to a GitHub repo's first commit

2024-11-21 يوللانغان نەشرى. ئەڭ يېڭى نەشرىنى كۆرۈش.

  1. // ==UserScript==
  2. // @name GitHub First Commit
  3. // @description Add a link to a GitHub repo's first commit
  4. // @author chocolateboy
  5. // @copyright chocolateboy
  6. // @version 4.0.2
  7. // @namespace https://github.com/chocolateboy/userscripts
  8. // @license GPL
  9. // @include https://github.com/
  10. // @include https://github.com/*
  11. // @grant GM_log
  12. // @noframes
  13. // ==/UserScript==
  14.  
  15. // NOTE This file is generated from src/github-first-commit.user.ts and should not be edited directly.
  16.  
  17. "use strict";
  18. (() => {
  19. // src/lib/util.ts
  20. var constant = (value) => (..._args) => value;
  21.  
  22. // src/lib/observer.ts
  23. var INIT = { childList: true, subtree: true };
  24. var done = constant(true);
  25. var resume = constant(false);
  26. var observe = (target, ...args) => {
  27. const [init, callback] = args.length === 1 ? [INIT, args[0]] : args;
  28. const $callback = (mutations, observer2) => {
  29. observer2.disconnect();
  30. const done2 = callback({ mutations, observer: observer2, target, init });
  31. if (!done2) {
  32. observer2.observe(target, init);
  33. }
  34. };
  35. const observer = new MutationObserver($callback);
  36. queueMicrotask(() => $callback([], observer));
  37. return observer;
  38. };
  39.  
  40. // src/github-first-commit.user.ts
  41. // @license GPL
  42. var ID = "first-commit";
  43. var PATH = 'meta[name="analytics-location"][content]';
  44. var REPO_PAGE = "/<user-name>/<repo-name>";
  45. var USER_REPO = 'meta[name="octolytics-dimension-repository_network_root_nwo"][content]';
  46. var $ = document;
  47. var openFirstCommit = (user, repo) => {
  48. return fetch(`https://api.github.com/repos/${user}/${repo}/commits`).then((res) => Promise.all([res.headers.get("link"), res.json()])).then(([link, commits]) => {
  49. if (!link) {
  50. return commits;
  51. }
  52. const lastPage = link.match(/^.+?<([^>]+)>;/)[1];
  53. return fetch(lastPage).then((res) => res.json());
  54. }).then((commits) => {
  55. if (Array.isArray(commits)) {
  56. location.href = commits.at(-1).html_url;
  57. } else {
  58. console.error(commits);
  59. }
  60. });
  61. };
  62. observe($.body, () => {
  63. const path = $.querySelector(PATH)?.content;
  64. if (path !== REPO_PAGE) {
  65. return;
  66. }
  67. if ($.getElementById(ID)) {
  68. return;
  69. }
  70. const commitHistory = $.querySelector("div svg.octicon-history")?.closest("div");
  71. if (!commitHistory) {
  72. return;
  73. }
  74. const firstCommit = commitHistory.cloneNode(true);
  75. const label = firstCommit.querySelector(':scope [data-component="text"] > *');
  76. const header = firstCommit.querySelector(":scope h2");
  77. const link = firstCommit.querySelector(":scope a[href]");
  78. const [user, repo] = $.querySelector(USER_REPO).getAttribute("content").split("/");
  79. firstCommit.id = ID;
  80. header.textContent = label.textContent = "1st Commit";
  81. link.removeAttribute("href");
  82. link.setAttribute("aria-label", "First commit");
  83. const onClick = (e) => {
  84. e.preventDefault();
  85. e.stopPropagation();
  86. label.textContent = "Loading...";
  87. openFirstCommit(user, repo);
  88. };
  89. firstCommit.addEventListener("click", onClick, { once: true });
  90. commitHistory.after(firstCommit);
  91. });
  92. })();