Greasy Fork 还支持 简体中文。

GitHub Remark

GitHub remark

目前為 2022-04-23 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name GitHub Remark
  3. // @namespace https://greasyfork.org/zh-CN/scripts/443857-github-remark
  4. // @version 0.1.0
  5. // @description GitHub remark
  6. // @author Dorad
  7. // @license MIT License
  8. // @match https://github.com/*
  9. // @require https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.slim.min.js
  10. // @grant GM_downlaod
  11. // @grant GM_xmlhttpRequest
  12. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAC5klEQVRYR+2Xu49NURTGjZEomdC7iNZby8XUjKg9ghoRrQRRegStx4yaQSdB0CIepUe4/ANoROn7TfaSdfbZj3vGTCFxki/3zN5r7f2t95mRBfnnvbaWC/eEy8Lbgmxqa6kWdwnHhI3CAeFWLDiSObSn9Q/CIrd/U+8nhCXC+oBY/Y0WwDrhorDaCVzX+5FhCfQl+KSjxTXxxxIY/2cIEIKPwmjNrA77nUJADF9GOdDhrqToN62SjAO/m0tCKmDN396Y0G/lQYrAfilOzcPlduSGUCkzf6cI3Nb63nkkcEFnn7TzUwReaHNzRIC43Re+J4it0NqXDOF9Wl8V7TXCkCLwSwqLnZI1oNTlwzjqmoQOO8EqAZ+An50F5MbpgFZLdRdQQTeCVw4Frz3X75YgUyXwSII7g7D1757+9q15LBMO1B4K1vGYA1cEn9hVAt5l26X8NDqAS5KDJZD2IbTL+tqz1l5NQs92Qook326BqWiPrbulP681AkcledWkU0nIGMXdjGJj69dIxpWFEHgPmqe8UegOSgTYY45jMZdRRvySXHuEu0Lp2wCyWPlD4DuCx0q7NQ9yrRil8wLz/7VAUs62DE9J92w4Z0d8TokAJLYJlBRZT3uerFgfDJ75wYvHBRL5UiDRMiImANuF4SLf3SByUKCPEwq+enIeoTMS52cC4SKUuU7ZmgUcTufrBeapWCNDeS3z5rp3q/3MdnO5VAVfJZqK/TCjupHpJSa5HLDEeSVl2imewLX0A+JJmOwZhD1/VqPWZ0PA131KnxnxKXiIJHsgMMAoMwYPBpwbJgalKiDW00I8TjmXHOAhRJ4AHZKkmxMCZsBWvZD9PBAmBDkCkKHnzykB78l+uOA/gTvyBIka54CFoDFyS8lYa8Wxrk06yoySjAlQ//xDQ+fbJFTnRxcCWMVwmhTOCO+EnwKXQowvaapgbZCjTCFRfLoQwOVmEZOSzy7mPU2KPQhCwFq0l8+S+A28A6wh+zYOCgAAAABJRU5ErkJggg==
  13. // ==/UserScript==
  14.  
  15. const key = 'GithubRemark-cache';
  16. const defaultRemark = 'unset';
  17.  
  18. /**
  19. * API for cache data.
  20. */
  21.  
  22. function updateRemark(userToken, username, remark) {
  23. let cache = JSON.parse(localStorage.getItem(key));
  24. if(!cache){
  25. cache=[];
  26. }
  27. const matchedItemIdx = cache.findIndex(e => e.username==username && e.userToken==userToken)
  28. if(matchedItemIdx>-1){
  29. // 已存在
  30. cache[matchedItemIdx].remark = remark;
  31. cache[matchedItemIdx].updatedAt = new Date().getTime() / 1000
  32. }else{
  33. const item={
  34. userToken:userToken,
  35. username:username,
  36. remark:remark,
  37. updatedAt: new Date().getTime() / 1000
  38. }
  39. cache.push(item);
  40. }
  41. console.log(cache);
  42. localStorage.setItem(key, JSON.stringify(cache));
  43. // showRemarks(userToken);
  44. }
  45.  
  46. function getRemark(userToken, username, callback) {
  47. let cache = JSON.parse(localStorage.getItem(key));
  48. if(!cache){
  49. callback(defaultRemark);
  50. return
  51. }
  52. const item = cache.find(e => e.username==username && e.userToken==userToken)
  53. if(item){
  54. callback(item.remark);
  55. }else{
  56. callback(defaultRemark);
  57. }
  58. }
  59.  
  60. /**
  61. *
  62. * page functions
  63. */
  64.  
  65. function getGithubLoginUsername() {
  66. var doc = document.querySelector("head > meta[name*='login']");
  67. return doc == null ? null : doc.content;
  68. }
  69.  
  70. function hasLoginFrame() {
  71. var loginBtn = document.querySelector('div.HeaderMenu a[href*=login]');
  72. return loginBtn != null;
  73. }
  74.  
  75. function getMasterOfPage(url) {
  76. var master = /github.com\/([^\/|^\?]+)/.exec(url);
  77. if (master !== null)
  78. master = master[1];
  79. return master;
  80. }
  81.  
  82. function getCurrentTab() {
  83. var homepage = /github.com\/$/.exec(location.href);
  84. if (homepage !== null)
  85. return 'homepage';
  86. var tab = /[\?|\&]tab=([^\&]+)/.exec(location.href);
  87. if (tab !== null)
  88. tab = tab[1];
  89. if(/https:\/\/github.com\/orgs\/([\S\s]+)\/people/.exec(location.href))
  90. tab = 'orgs-people';
  91. if(/https:\/\/github.com\/orgs\/([\S\s]+)\/members/.exec(location.href))
  92. tab = 'orgs-members';
  93. return tab;
  94. }
  95.  
  96. function insertAfter(newEl, targetEl) {
  97. var parentEl = targetEl.parentNode;
  98. if (parentEl.lastChild == targetEl) {
  99. parentEl.appendChild(newEl);
  100. } else {
  101. parentEl.insertBefore(newEl, targetEl.nextSibling);
  102. }
  103. }
  104.  
  105. function generateRemarkSpan(className, userToken, username, remark){
  106. var span = document.createElement('span');
  107. span.className = className;
  108. span.textContent = '('+remark+')';
  109. span.title = '('+remark+')';
  110. span.addEventListener('dblclick', function (event) {
  111. console.log(event);
  112. const newRemark = changeRemarks(userToken, username, remark);
  113. if(newRemark!==remark){
  114. span.replaceWith(generateRemarkSpan(
  115. className,userToken, username,newRemark
  116. ));
  117. }
  118. }, false);
  119. return span;
  120. }
  121.  
  122. function clearRemarkOfCurrentNode(div){
  123. if (!!div.querySelector('span.github-remarks'))
  124. div.removeChild(div.querySelector('span.github-remarks'));
  125. }
  126.  
  127. /**
  128. *
  129. * Show remark functions, adapted for each page
  130. */
  131.  
  132. function showRemarkInHomepage(userToken) {
  133. var news = document.querySelector("#dashboard > div.news");
  134. var userCount = document.querySelectorAll("div.flex-items-baseline > div > a[data-hovercard-type=user]").length;
  135. var observer = new MutationObserver(function (mutations, self) {
  136. var users = document.querySelectorAll("div.flex-items-baseline > div > a[data-hovercard-type=user]");
  137. if (userCount != users.length) {
  138. userCount = users.length
  139. users.forEach(function (element) {
  140. clearRemarkOfCurrentNode(element.parentNode);
  141. var username = getMasterOfPage(element.href);
  142. getRemark(userToken, username, function (remark) {
  143. var remarkEl = generateRemarkSpan('link-gray pl-1 github-remarks', userToken, username, remark);
  144. insertAfter(remarkEl, element);
  145. });
  146. }, this);
  147. }
  148. });
  149. observer.observe(news, { childList: true, subtree: true });
  150. }
  151.  
  152. function showRemarkInLeftPannel(userToken) {
  153. var vcard = document.querySelector('h1.vcard-names');//author in home page
  154. if (!!vcard) {
  155. if (vcard.childElementCount > 2)
  156. vcard.removeChild(vcard.querySelector('span.github-remarks'));
  157. var username = getMasterOfPage(location.href);
  158. getRemark(userToken, username, function (remark) {
  159. vcard.appendChild(generateRemarkSpan('vcard-username d-block github-remarks', userToken, username, remark));
  160. });
  161. }
  162. }
  163.  
  164. function showRemarkInStarsTab(userToken) {
  165. var stars = document.querySelectorAll('div > h3 > a');//in star page
  166. if (stars !== null) {
  167. stars.forEach(function (element) {
  168. clearRemarkOfCurrentNode(element.parentNode);
  169. if (!!element.querySelector('span.text-normal')) {
  170. var text = element.querySelector('span.text-normal').textContent;
  171. var username = text.substring(0, text.indexOf(' /'));
  172. getRemark(userToken, username, function (remark) {
  173. insertAfter(generateRemarkSpan('link-gray pl-1 github-remarks', userToken, username, remark), element);
  174. });
  175. }
  176. }, this);
  177. }
  178. }
  179.  
  180. function showRemarkInFollowersTab(userToken) {
  181. var followers = document.querySelectorAll('div.d-table > div:nth-child(2) > a');//in followers/following page
  182. if (!!followers) {
  183. followers.forEach(function (element) {
  184. clearRemarkOfCurrentNode(element.parentNode);
  185. var username = element.querySelector('span:last-child').textContent;
  186. getRemark(userToken, username, function (remark) {
  187. insertAfter(generateRemarkSpan('link-gray pl-1 github-remarks', userToken, username, remark), element);
  188. });
  189. }, this);
  190. }
  191. }
  192.  
  193. function showRemarkInRepoStargazersPage(userToken) {
  194. var stargazers = document.querySelectorAll('div > h3 > span');
  195. if (!!stargazers) {
  196. stargazers.forEach(function (element) {
  197. clearRemarkOfCurrentNode(element.parentNode);
  198. var a = element.querySelector('a');
  199. var username = getMasterOfPage(a.href);
  200. getRemark(userToken, username, function (remark) {
  201. var remarkEl = generateRemarkSpan('link-gray pl-1 github-remarks', userToken, username, remark)
  202. insertAfter(remarkEl, a);
  203. //如果username太长,截断显示,为remark留点位置
  204. if (a.offsetWidth > element.clientWidth * 4 / 5) {
  205. a.style.width = element.clientWidth * 4 / 5 + 'px';
  206. a.className += 'css-truncate-target';
  207. remarkEl.style.width = element.clientWidth * 1 / 5 + 'px';
  208. remarkEl.className += 'css-truncate-target';
  209. }
  210. });
  211. }, this);
  212. }
  213. }
  214.  
  215. function showRemarkInRepoDetailPage(userToken) {
  216. var author = document.querySelector('span.author > a');//in a repo page
  217. if (!!author) {
  218. var username = getMasterOfPage(location.href);
  219. getRemark(userToken, username, function (remark) {
  220. author.textContent = username + '(' + remark + ')';
  221. });
  222. }
  223. var repoDetail = /\/(stargazers|watchers)(\/you_know)?$/.exec(location.href);
  224. if (repoDetail !== null) {
  225. switch (repoDetail[1]) {
  226. case 'watchers':
  227. case 'stargazers':
  228. showRemarkInRepoStargazersPage(userToken);
  229. break;
  230. }
  231. }
  232. }
  233.  
  234. function showRemarkInOrgPeople(userToken){
  235. var users = document.querySelectorAll('a[data-hovercard-type=user][id]');
  236. if(!!users){
  237. users.forEach(function (element) {
  238. clearRemarkOfCurrentNode(element.parentNode);
  239. var username = getMasterOfPage(element.href);
  240. if(element.href.indexOf('orgs')>-1){
  241. username = /https:\/\/github.com\/orgs\/([\S\s]+)\/people\/([\s\S]+)$/.exec(element.href)[2];
  242. }
  243. getRemark(userToken, username, function (remark) {
  244. insertAfter(generateRemarkSpan('link-gray pl-1 github-remarks', userToken, username, remark), element);
  245. });
  246. }, this)
  247. }
  248. }
  249.  
  250. function showRemarkInOrgMembers(userToken){
  251. var users = document.querySelectorAll('ul.member-listing > li > div > a[data-hovercard-type=user]');
  252. if(!!users){
  253. users.forEach(function (element) {
  254. clearRemarkOfCurrentNode(element.parentNode);
  255. var username = /https:\/\/github.com\/orgs\/([\S\s]+)\/people\/([\s\S]+)$/.exec(element.href)[2];
  256. getRemark(userToken, username, function (remark) {
  257. insertAfter(generateRemarkSpan('link-gray pl-1 github-remarks', userToken, username, remark), element);
  258. });
  259. }, this)
  260. }
  261. }
  262.  
  263. function changeRemarks(userToken, username, oldValue) {
  264. var newValue = window.prompt("请输入新备注 (Please input new remark):", oldValue);
  265. if (newValue !== null && newValue !== oldValue) {
  266. updateRemark(userToken, username, newValue);
  267. return newValue;
  268. }
  269. return oldValue;
  270. }
  271.  
  272. function showRemarks(userToken) {
  273. showRemarkInLeftPannel(userToken);
  274. var tab = getCurrentTab();
  275. switch (tab) {
  276. case 'homepage':
  277. showRemarkInHomepage(userToken);
  278. break;
  279. case 'repositories':
  280. break;
  281. case 'stars':
  282. showRemarkInStarsTab(userToken);
  283. break;
  284. case 'following':
  285. case 'followers':
  286. showRemarkInFollowersTab(userToken);
  287. break;
  288. case 'orgs-members':
  289. showRemarkInOrgMembers(userToken);
  290. break;
  291. case 'orgs-people':
  292. showRemarkInOrgPeople(userToken);
  293. break;
  294. default:
  295. showRemarkInRepoDetailPage(userToken);
  296. break;
  297. }
  298. console.log(tab,'Show remarks')
  299. }
  300.  
  301. (function () {
  302. console.log('GithubRemark-Dorad');
  303. var username = getGithubLoginUsername();
  304. if (username !== null && username != '') {
  305. showRemarks(username);
  306. } else if (hasLoginFrame()) {
  307. alert('你还未登陆github,请先登录你的github账户!\r\nYou have not log in to Github!\r\nPlease log in first.');
  308. }
  309. }());
  310.