Greasy Fork 支持简体中文。

GitHub Commit Compare

Add controls to compare commits.

目前為 2024-02-01 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name GitHub Commit Compare
  3. // @namespace https://github.com/jerone/UserScripts
  4. // @description Add controls to compare commits.
  5. // @author jerone
  6. // @contributor darkred
  7. // @copyright 2017+, jerone (https://github.com/jerone)
  8. // @license CC-BY-NC-SA-4.0; https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
  9. // @license GPL-3.0-or-later; http://www.gnu.org/licenses/gpl-3.0.txt
  10. // @homepage https://github.com/jerone/UserScripts/tree/master/GitHub_Commit_Compare
  11. // @homepageURL https://github.com/jerone/UserScripts/tree/master/GitHub_Commit_Compare
  12. // @supportURL https://github.com/jerone/UserScripts/issues
  13. // @contributionURL https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=VCYMHWQ7ZMBKW
  14. // @icon https://github.githubassets.com/pinned-octocat.svg
  15. // @include https://github.com/*/*/commits
  16. // @include https://github.com/*/*/commits/*
  17. // @exclude https://github.com/*/*.diff
  18. // @exclude https://github.com/*/*.patch
  19. // @version 0.0.3
  20. // @grant none
  21. // ==/UserScript==
  22.  
  23. (function () {
  24.  
  25. function addButton() {
  26. var nav;
  27. if ((nav = document.querySelector('.file-navigation'))) {
  28.  
  29. // Check if our group of buttons are already attached.
  30. // Remove it, as the 'old' buttons don't have events anymore.
  31. const e = document.getElementById('GitHubCommitCompareGroup');
  32. if (e) {
  33. e.parentElement.removeChild(e);
  34. }
  35. Array.from(document.querySelectorAll('.GitHubCommitCompareButtonAB')).forEach(function (b) {
  36. b.parentElement.removeChild(b);
  37. });
  38.  
  39. const c = document.createElement('input');
  40. c.type = 'checkbox';
  41. c.addEventListener('change',
  42. function () {
  43. const bb = document.querySelectorAll('.GitHubCommitCompareButtonAB');
  44. if (this.checked) {
  45. if (bb.length === 0) {
  46. addCompareButtons();
  47. } else {
  48. Array.from(bb).forEach(function (b) {
  49. b.classList.remove('d-none');
  50. });
  51. }
  52. } else {
  53. Array.from(bb).forEach(function (b) {
  54. b.classList.add('d-none');
  55. });
  56. }
  57. const bbb = document.getElementById('GitHubCommitCompareButton');
  58. if (bbb) bbb.classList.remove('disabled');
  59. });
  60.  
  61. const l = document.createElement('label');
  62. l.classList.add('tooltipped', 'tooltipped-n');
  63. l.setAttribute('aria-label', 'Show commit compare buttons');
  64. l.style.cssText = `
  65. float: left;
  66. padding: 3px 10px;
  67. font-size: 12px;
  68. font-weight: 600;
  69. line-height: 20px;
  70. color: #24292e;
  71. vertical-align: middle;
  72. background-color: #fff;
  73. border: 1px solid rgba(27,31,35,0.2);
  74. border-right: 0;
  75. border-top-left-radius: 3px;
  76. border-bottom-left-radius: 3px;
  77. `;
  78. l.appendChild(c);
  79.  
  80. const p = document.createElementNS('http://www.w3.org/2000/svg', 'path');
  81. p.setAttributeNS(null,
  82. 'd',
  83. 'M5 12H4c-.27-.02-.48-.11-.69-.31-.21-.2-.3-.42-.31-.69V4.72A1.993 1.993 0 0 0 2 1a1.993 1.993 0 0 0-1 3.72V11c.03.78.34 1.47.94 2.06.6.59 1.28.91 2.06.94h1v2l3-3-3-3v2zM2 1.8c.66 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2C1.35 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2zm11 9.48V5c-.03-.78-.34-1.47-.94-2.06-.6-.59-1.28-.91-2.06-.94H9V0L6 3l3 3V4h1c.27.02.48.11.69.31.21.2.3.42.31.69v6.28A1.993 1.993 0 0 0 12 15a1.993 1.993 0 0 0 1-3.72zm-1 2.92c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z');
  84.  
  85. const s = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  86. s.classList.add('octicon', 'octicon-diff');
  87. s.setAttributeNS(null, 'height', 16);
  88. s.setAttributeNS(null, 'width', 14);
  89. s.setAttributeNS(null, 'viewBox', '0 0 14 16');
  90. s.appendChild(p);
  91.  
  92. const a = document.createElement('a');
  93. a.id = 'GitHubCommitCompareButton';
  94. a.classList.add('btn', 'btn-sm', 'tooltipped', 'tooltipped-n', 'disabled');
  95. a.setAttribute('href', '#');
  96. a.setAttribute('rel', 'nofollow');
  97. a.setAttribute('aria-label', 'Compare these commits');
  98. a.style.cssText = `
  99. border-top-left-radius: 0;
  100. border-bottom-left-radius: 0;
  101. font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
  102. `;
  103. a.appendChild(s);
  104. a.appendChild(document.createElement("span"));
  105.  
  106. const g = document.createElement('div');
  107. g.id = 'GitHubCommitCompareGroup';
  108. g.classList.add('float-right');
  109. g.appendChild(l);
  110. g.appendChild(a);
  111.  
  112. nav.appendChild(g);
  113. }
  114. }
  115.  
  116. function updateRadioButtons() {
  117. var compareAdisabled = true;
  118. var compareBdisabled = false;
  119.  
  120. const compares = document.querySelectorAll('.GitHubCommitCompareButtonAB');
  121. Array.from(compares).forEach(function (compare) {
  122. const compareA = compare.querySelector('[name="GitHubCommitCompareButtonA"]');
  123. const compareB = compare.querySelector('[name="GitHubCommitCompareButtonB"]');
  124.  
  125. compareA.disabled = compareAdisabled;
  126. compareA.parentNode.classList.toggle('disabled', compareAdisabled);
  127.  
  128. if (compareA.checked) {
  129. compareBdisabled = true;
  130. }
  131. if (compareB.checked) {
  132. compareAdisabled = false;
  133. }
  134.  
  135. compareB.disabled = compareBdisabled;
  136. compareB.parentNode.classList.toggle('disabled', compareBdisabled);
  137. });
  138.  
  139. updateCompareButton();
  140. }
  141.  
  142. function updateCompareButton() {
  143. const repo = document.querySelector('meta[property="og:url"]').content;
  144.  
  145. const compareA = document.querySelector('.GitHubCommitCompareButtonAB [name="GitHubCommitCompareButtonA"]:checked');
  146. const hashA = compareA.parentNode.parentNode.parentNode.querySelector('clipboard-copy').value;
  147. const compareB = document.querySelector('.GitHubCommitCompareButtonAB [name="GitHubCommitCompareButtonB"]:checked');
  148. const hashB = compareB.parentNode.parentNode.parentNode.querySelector('clipboard-copy').value;
  149.  
  150. const a = document.getElementById('GitHubCommitCompareButton');
  151. a.setAttribute('href', `${repo}/compare/${hashA}...${hashB}`);
  152. a.querySelector('span').textContent = ` ${hashA.substring(0, 7)}...${hashB.substring(0, 7)}`;
  153.  
  154. //localStorage.setItem('GitHubCommitCompareButtonHashA', hashA);
  155. //localStorage.setItem('GitHubCommitCompareButtonHashB', hashB);
  156. }
  157.  
  158. function addCompareButtons() {
  159. const commits = document.querySelectorAll('.commits-list-item .commit-links-cell');
  160. Array.from(commits).forEach(function (item, index) {
  161. const c1 = document.createElement('input');
  162. c1.name = 'GitHubCommitCompareButtonA';
  163. c1.type = 'radio';
  164. c1.addEventListener('change', updateRadioButtons);
  165. if (index === 1) c1.checked = true;
  166.  
  167. const l1 = document.createElement('label');
  168. l1.classList.add('btn', 'btn-outline', 'BtnGroup-item', 'tooltipped', 'tooltipped-s');
  169. l1.setAttribute('aria-label', 'Choose a base commit');
  170. l1.appendChild(c1);
  171.  
  172. const c2 = document.createElement('input');
  173. c2.name = 'GitHubCommitCompareButtonB';
  174. c2.type = 'radio';
  175. c2.addEventListener('change', updateRadioButtons);
  176. if (index === 0) c2.checked = true;
  177.  
  178. const l2 = document.createElement('label');
  179. l2.classList.add('btn', 'btn-outline', 'BtnGroup-item', 'tooltipped', 'tooltipped-s');
  180. l2.setAttribute('aria-label', 'Choose a head commit');
  181. l2.appendChild(c2);
  182.  
  183. // const p3 = document.createElementNS('http://www.w3.org/2000/svg', 'path');
  184. // p3.setAttributeNS(null,
  185. //'d',
  186. //'M5 12H4c-.27-.02-.48-.11-.69-.31-.21-.2-.3-.42-.31-.69V4.72A1.993 1.993 0 0 0 2 1a1.993 1.993 0 0 0-1 3.72V11c.03.78.34 1.47.94 2.06.6.59 1.28.91 2.06.94h1v2l3-3-3-3v2zM2 1.8c.66 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2C1.35 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2zm11 9.48V5c-.03-.78-.34-1.47-.94-2.06-.6-.59-1.28-.91-2.06-.94H9V0L6 3l3 3V4h1c.27.02.48.11.69.31.21.2.3.42.31.69v6.28A1.993 1.993 0 0 0 12 15a1.993 1.993 0 0 0 1-3.72zm-1 2.92c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z');
  187.  
  188. // const s3 = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  189. // s3.classList.add('octicon', 'octicon-diff');
  190. // s3.setAttributeNS(null, 'height', 16);
  191. // s3.setAttributeNS(null, 'width', 14);
  192. // s3.setAttributeNS(null, 'viewBox', '0 0 14 16');
  193. // s3.appendChild(p3);
  194.  
  195. // const l3 = document.createElement('a');
  196. // l3.classList.add('btn', 'btn-outline', 'BtnGroup-item', 'tooltipped', 'tooltipped-sw');
  197. // l3.setAttribute('aria-label', 'TODO');
  198. // l3.appendChild(s3);
  199.  
  200. const gg = document.createElement('div');
  201. gg.classList.add('GitHubCommitCompareButtonAB', 'commit-links-group', 'BtnGroup');
  202. gg.appendChild(l1);
  203. gg.appendChild(l2);
  204. //gg.appendChild(l3);
  205.  
  206. //item.style.width = '350px';
  207. if (item.querySelector('.muted-link')) { // Insert after number of comments button.
  208. item.insertBefore(gg, item.querySelector('.muted-link').nextSibling);
  209. } else {
  210. item.insertBefore(gg, item.firstChild);
  211. }
  212. });
  213.  
  214. updateRadioButtons(); // Update radio buttons.
  215. }
  216.  
  217. // Init.
  218. addButton();
  219.  
  220. // Pjax.
  221. document.addEventListener('pjax:end', addButton);
  222.  
  223. })();