GitHub Network Shortcut

Adds a shortcut to the network graph on the repository's main page

  1. // ==UserScript==
  2. // @name GitHub Network Shortcut
  3. // @namespace https://mkps.app/
  4. // @version 0.1.1
  5. // @description Adds a shortcut to the network graph on the repository's main page
  6. // @author MK
  7. // @match *://github.com/*
  8. // @icon https://github.com/favicon.ico
  9. // ==/UserScript==
  10.  
  11. (() => {
  12. "use strict";
  13.  
  14. const ELEMENT_CLASS = "MK_userscript_ghNetworkShortcut_element";
  15. const CONTAINER_SELECTOR_LG = `#repo-content-turbo-frame .Layout-sidebar .about-margin > div.BorderGrid-row > div.BorderGrid-cell > div.hide-sm.hide-md`;
  16. const CONTAINER_SELECTOR_SM = `#responsive-meta-container ul[aria-label="Repository details"]`;
  17.  
  18. function main() {
  19. forMatchingElementsForever(CONTAINER_SELECTOR_LG, (element) => {
  20. if (element.querySelector(`.${ELEMENT_CLASS}`)) {return;}
  21. for (const child of element.children) {
  22. if (child.children[0]?.getAttribute("href")?.endsWith("/forks")) {
  23. child.insertAdjacentElement("afterend", createShortcutLg());
  24. break;
  25. }
  26. }
  27. });
  28. forMatchingElementsForever(CONTAINER_SELECTOR_SM, (element) => {
  29. if (element.querySelector(`.${ELEMENT_CLASS}`)) {return;}
  30. for (const child of element.children) {
  31. if (child.getAttribute("href")?.endsWith("/activity")) {
  32. child.insertAdjacentElement("afterend", createShortcutSm());
  33. break;
  34. }
  35. }
  36. });
  37. }
  38.  
  39. function getNetworkUrl() {
  40. const terms = [...location.pathname.split("/").slice(1, 3), "network"];
  41. return `/${terms.join("/")}`;
  42. }
  43.  
  44. function createShortcutLg() {
  45. const div = document.createElement("div");
  46. div.classList.add(ELEMENT_CLASS);
  47. div.classList.add("mt-2");
  48. const a = document.createElement("a");
  49. a.setAttribute("href", getNetworkUrl());
  50. a.setAttribute("data-view-component", "true");
  51. a.classList.add("Link", "Link--muted");
  52. a.appendChild(createCommitIcon("mr-2"));
  53. a.appendChild(document.createTextNode(" "));
  54. const span = document.createElement("span");
  55. span.classList.add("color-fg-muted");
  56. span.textContent = "Network";
  57. a.appendChild(span);
  58. div.appendChild(a);
  59. return div;
  60. }
  61.  
  62. function createShortcutSm() {
  63. const a = document.createElement("a");
  64. a.classList.add(ELEMENT_CLASS, "Link--secondary", "no-underline", "d-block", "mr-2");
  65. a.setAttribute("role", "listitem");
  66. a.setAttribute("href", getNetworkUrl());
  67. a.appendChild(createCommitIcon("mr-1"));
  68. a.appendChild(document.createTextNode(" "));
  69. const span = document.createElement("span");
  70. span.textContent = "Network";
  71. a.appendChild(span);
  72. return a;
  73. }
  74.  
  75. function createCommitIcon(marginClass) {
  76. const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
  77. svg.setAttribute("version", "1.1");
  78. svg.setAttribute("width", "16");
  79. svg.setAttribute("height", "16");
  80. svg.setAttribute("viewBox", "0 0 16 16");
  81. svg.setAttribute("aria-hidden", "true");
  82. svg.setAttribute("data-view-component", "true");
  83. svg.classList.add("octicon", "octicon-commit", marginClass);
  84. svg.innerHTML = `<path d="M11.93 8.5a4.002 4.002 0 0 1-7.86 0H.75a.75.75 0 0 1 0-1.5h3.32a4.002 4.002 0 0 1 7.86 0h3.32a.75.75 0 0 1 0 1.5Zm-1.43-.75a2.5 2.5 0 1 0-5 0 2.5 2.5 0 0 0 5 0Z"></path>`;
  85. return svg;
  86. }
  87.  
  88. function forMatchingElementsForever(selector, fn) {
  89. const observer = new MutationObserver((list, observer) => {
  90. for (const mutation of list) {
  91. for (const addedNode of mutation.addedNodes) {
  92. if (addedNode.nodeType !== Node.ELEMENT_NODE) {continue;}
  93. for (const newNode of addedNode.querySelectorAll(selector)) {
  94. fn(newNode);
  95. }
  96. }
  97. }
  98. });
  99. observer.observe(document.body, {childList: true, subtree: true});
  100.  
  101. for (const element of document.querySelectorAll(selector)) {
  102. fn(element);
  103. }
  104. }
  105.  
  106. main();
  107. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址