GitHub Mentioned Links

A userscript adds all mentioned links in the side bar

  1. // ==UserScript==
  2. // @name GitHub Mentioned Links
  3. // @version 0.1.3
  4. // @description A userscript adds all mentioned links in the side bar
  5. // @license MIT
  6. // @author Rob Garrison
  7. // @namespace https://github.com/Mottie
  8. // @include https://github.com/*
  9. // @run-at document-idle
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // @require https://gf.qytechs.cn/scripts/28721-mutations/code/mutations.js?version=1108163
  13. // @require https://gf.qytechs.cn/scripts/398877-utils-js/code/utilsjs.js?version=1079637
  14. // @icon https://github.githubassets.com/pinned-octocat.svg
  15. // @supportURL https://github.com/Mottie/GitHub-userscripts/issues
  16. // ==/UserScript==
  17. /* global $ $$ on */
  18. (() => {
  19. "use strict";
  20.  
  21. // GitHub loves to change class names
  22. const selectors = {
  23. // Insert entry after milestone in the sidebar
  24. sidebar: ".discussion-sidebar-item.sidebar-progress-bar",
  25. // Load more comments button (2 buttons; either works)
  26. loadMore: "form[action*='more_items'] button",
  27. // Issue/PR timeline element with anchor id
  28. timelineGroup: ".timeline-comment-group",
  29. // All links within a timeline comment
  30. links: ".comment-body a:not(.user-mention)"
  31. };
  32.  
  33. const internalLinkIcon = `
  34. <svg aria-hidden="true" class="octicon octicon-internal-link" viewBox="0 0 12 16" height="12">
  35. <path d="M11 10h1v3c0 .6-.4 1-1 1H1c-.6 0-1-.4-1-1V3c0-.5.4-1 1-1h3v1H1v10h10v-3z"/>
  36. <path d="M11 9L8.8 6.7 12 3.5 10.5 2 7.3 5.2 5 3v6z"/>
  37. </svg>`
  38.  
  39. // Sidebar item
  40. const item = document.createElement("details");
  41. item.id = "ghml-wrapper";
  42. item.className = "discussion-sidebar-item sidebar-mentioned-links";
  43. item.open = GM_getValue("mentionedOpened", false);
  44. item.onclick = event => {
  45. // Set as opposite makes it work?! DOM update delay, maybe?
  46. GM_setValue("mentionedOpened", !event.target.parentElement.open);
  47. };
  48.  
  49. // Load more button
  50. const loadMoreButton = document.createElement("button");
  51. loadMoreButton.className = "btn btn-block btn-sm width-auto ml-2 py-0 px-1 text-normal";
  52. loadMoreButton.style.fontSize = "10px";
  53. loadMoreButton.title = "Each click loads up to 60 items";
  54.  
  55. function getLinks() {
  56. const list = new Set();
  57. const links = [];
  58. $$(selectors.timelineGroup).forEach(body => {
  59. $$(selectors.links, body).forEach(link => {
  60. if (!list.has(link.href) && !$("img", link)) {
  61. list.add(link.href);
  62. links.push(
  63. `<li class="css-truncate css-truncate-overflow">
  64. <a href="#${body.id}" class="link-gray" title="Internal link">
  65. ${internalLinkIcon}
  66. </a>
  67. ${link.outerHTML}
  68. </li>`
  69. );
  70. }
  71. });
  72. });
  73. list.clear();
  74. buildLinks(links);
  75. }
  76.  
  77. function addLoadMoreButton() {
  78. const formButton = $(selectors.loadMore);
  79. if (formButton) {
  80. const more = loadMoreButton.cloneNode(true);
  81. more.textContent = formButton.textContent;
  82. more.onclick = event => {
  83. const target = event.target;
  84. target.textContent = "Loading…";
  85. formButton.click();
  86. };
  87. $("#ghml-wrapper summary").append(more);
  88. }
  89. }
  90.  
  91. function buildLinks(links) {
  92. const entry = $("#ghml-wrapper") || item.cloneNode(true);
  93. const hasLinks = links.length;
  94. entry.innerHTML = `
  95. <summary class="discussion-sidebar-heading text-bold d-flex flex-items-center">
  96. Mentioned Links ${hasLinks ? `(${links.length})` : ""}
  97. </summary>
  98. <ul class="list-style-none">
  99. ${hasLinks ? links.join("") : "No links found"}
  100. </ul>`;
  101. $(selectors.sidebar).after(entry);
  102. addLoadMoreButton();
  103. }
  104.  
  105. function init() {
  106. if ($("#discussion_bucket") && $(selectors.sidebar)) {
  107. getLinks();
  108. }
  109. }
  110.  
  111. on(document, "ghmo:container ghmo:comments", init);
  112. init();
  113.  
  114. })();

QingJ © 2025

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