Github Find Active Forks [Embeded Edition]

Find most active fork of a github repository.

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
  1. // ==UserScript==
  2. // @name Github Find Active Forks [Embeded Edition]
  3. // @version 1.4.1
  4. // @description Find most active fork of a github repository.
  5. // @description:de Finden Sie die aktivsten Forks eines Github-Repositorys.
  6. // @description:fr Trouver les forks les plus actifs d'un dépôt github.
  7. // @description:it Trova i fork più attivi di un repository github.
  8. // @author J.H
  9. // @match *://github.com/*
  10. // @icon https://github.githubassets.com/favicons/favicon-dark.png
  11.  
  12. // @grant GM_getResourceText
  13. // @grant GM_addStyle
  14. // @grant GM_xmlhttpRequest
  15. // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js
  16. // @require https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js
  17. // @require https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js
  18. // @require https://cdnjs.cloudflare.com/ajax/libs/jquery-footable/3.1.6/footable.min.js
  19.  
  20. // @resource footable.bootstrap.min.css https://cdnjs.cloudflare.com/ajax/libs/jquery-footable/3.1.6/footable.bootstrap.min.css
  21. // @resource custom.css https://pastebin.com/raw/ReyeKaAm
  22. // @run-at document-end
  23. // @license MIT
  24. // @namespace https://greatest.deepsurf.us/users/448067
  25. // ==/UserScript==
  26.  
  27. GM_addStyle(GM_getResourceText("footable.bootstrap.min.css"));
  28. GM_addStyle(GM_getResourceText("custom.css"));
  29.  
  30. const customInnerHTML = '<table class="table" data-paging="true" data-sorting="true"></table>';
  31. const SIZE_KILO = 1024;
  32. const UNITS = [
  33. 'Bytes',
  34. 'KB',
  35. 'MB',
  36. 'GB',
  37. 'TB',
  38. 'PB'
  39. ];
  40.  
  41. const httpFetch = function (url, func) {
  42. GM_xmlhttpRequest({
  43. method: "GET",
  44. url: url,
  45. onload: function (response) {
  46. func(response);
  47. },
  48. });
  49. }
  50.  
  51. const restInit = function (user, repo) {
  52. httpFetch(
  53. "https://api.github.com/repos/" + user + "/" + repo,
  54. function (resp) {
  55. const json1 = JSON.parse(resp.responseText);
  56. httpFetch(
  57. "https://api.github.com/repos/" +
  58. user +
  59. "/" +
  60. repo +
  61. "/forks?sort=newest&per_page=100",
  62. function (resp) {
  63. const json2 = JSON.parse(resp.responseText);
  64. createTable(json2, json1);
  65. }
  66. );
  67. }
  68. );
  69. }
  70.  
  71. const getHumanFileSize = function(size){
  72. if (size === 0) {
  73. return {
  74. size: '0',
  75. unit: UNITS[0],
  76. }
  77. } else if (size === -1) {
  78. return {
  79. size: '-1',
  80. unit: UNITS[0],
  81. }
  82. }
  83. size = size * SIZE_KILO;
  84. const order = Math.floor(Math.log(size) / Math.log(SIZE_KILO));
  85. return {
  86. size: (size / Math.pow(SIZE_KILO, order)).toFixed(2),
  87. unit: UNITS[order],
  88. }
  89. }
  90.  
  91. const createTable = function (rJson, cJson) {
  92. const humanSize = getHumanFileSize(cJson?.size ?? -1);
  93. const rowsData = [];
  94. const ev = {};
  95. ev.repoName =
  96. '<img id="1337" src="' +
  97. cJson.owner.avatar_url +
  98. '&amp;s=48" width="24" height="24" class="avatar rounded-1 avatar-user" title="" style="margin-right: .5rem!important;"><a href="' +
  99. cJson.html_url +
  100. '">' +
  101. cJson.full_name +
  102. "</a>";
  103. ev.repoStars = cJson?.stargazers_count ?? -1;
  104. ev.repoForks = cJson?.forks_count ?? -1;
  105. ev.repoOpenIssue = cJson?.open_issues_count ?? -1;
  106. ev.repoSize = humanSize;
  107. ev.repoModified = Number(moment(cJson?.pushed_at ?? "NULL").format("x"));
  108. rowsData.push(ev);
  109.  
  110. for (const [_, v] of Object.entries(rJson)) {
  111. const humanSize = getHumanFileSize(v?.size ?? -1);
  112. const ec = {};
  113. ec.repoName =
  114. '<img src="' +
  115. v.owner.avatar_url +
  116. '&amp;s=48" width="24" height="24" class="avatar rounded-1 avatar-user" title="" style="margin-right: .5rem!important;"><a href="' +
  117. v.html_url +
  118. '">' +
  119. v.full_name +
  120. "</a>";
  121. ec.repoStars = v?.stargazers_count ?? -1;
  122. ec.repoForks = v?.forks_count ?? -1;
  123. ec.repoOpenIssue = v?.open_issues_count ?? -1;
  124. ec.repoSize = humanSize;
  125. ec.repoModified = Number(moment(v?.pushed_at ?? "NULL").format("x"));
  126.  
  127. rowsData.push(ec);
  128. }
  129. jQuery(function ($) {
  130. $(".table").footable({
  131. columns: [
  132. { name: "repoName", title: "Repo" },
  133. {
  134. name: "repoStars",
  135. title: "Stars",
  136. breakpoints: "xs",
  137. type: "number",
  138. },
  139. {
  140. name: "repoForks",
  141. title: "Forks",
  142. breakpoints: "xs",
  143. type: "number",
  144. },
  145. {
  146. name: "repoOpenIssue",
  147. title: "Open Issues",
  148. breakpoints: "xs",
  149. type: "number",
  150. },
  151. {
  152. name: "repoSize",
  153. title: "Size",
  154. breakpoints: "xs",
  155. type: "object",
  156. direction: "DESC",
  157. formatter: function(value){
  158. if (value){
  159. return value.size + value.unit;
  160. }
  161. return -1;
  162. },
  163. sortValue: function(value){
  164. if (value){
  165. // return value by it's UNIT value (PB, TB, GB, MB, KB, Bytes) in order to sort it
  166. return value.size * Math.pow(SIZE_KILO, UNITS.indexOf(value.unit)); // in test..
  167. // return UNITS.indexOf(value.unit) + Number(value.size); // should be OK
  168. }
  169. return null
  170. }
  171. },
  172. {
  173. name: "repoModified",
  174. title: "Last Push",
  175. type: "date",
  176. breakpoints: "xs sm md",
  177. formatter: function (value) {
  178. return moment().to(moment(value, "YYYYMMDD"));
  179. },
  180. },
  181. ],
  182. rows: rowsData,
  183. });
  184. });
  185. document.querySelector(
  186. 'img[id="1337"]'
  187. ).parentElement.parentElement.style.backgroundImage =
  188. "linear-gradient(var(--color-checks-logline-warning-bg),var(--color-checks-logline-warning-bg))";
  189. document.querySelector(
  190. 'img[id="1337"]'
  191. ).parentElement.lastElementChild.style.color = "var(--color-checks-logline-warning-num-text)";
  192. }
  193.  
  194. // loadMain function is called when the page is loaded, and it is the main function of the script
  195. const loadMain = function () {
  196. const pathComponents = window.location.pathname.split("/");
  197. if (pathComponents.length >= 3) {
  198. const user = pathComponents[1],
  199. repo = pathComponents[2];
  200. const divForks = document.querySelector('div[id="network"]');
  201. divForks.innerHTML = customInnerHTML;
  202. restInit(user, repo);
  203. }
  204. }
  205.  
  206. // use turbo to loadMain when the page is loaded via ajax request
  207. document.addEventListener('turbo:render', function () {
  208. if (location.pathname.endsWith("/network/members")) {
  209. loadMain();
  210. }
  211. });
  212.  
  213. // loadMain when url ends with /network/members
  214. if (location.pathname.endsWith("/network/members")) {
  215. loadMain();
  216. }