GitWeb: copy commit reference

Adds a "Copy commit reference" button to every commit page on GitWeb websites.

安装此脚本
作者推荐脚本

您可能也喜欢Sourcehut: copy commit reference

安装此脚本
  1. // ==UserScript==
  2. // @name GitWeb: copy commit reference
  3. // @namespace https://andrybak.dev
  4. // @version 5
  5. // @license AGPL-3.0-only
  6. // @author Andrei Rybak
  7. // @description Adds a "Copy commit reference" button to every commit page on GitWeb websites.
  8. // @icon https://repo.or.cz/git-favicon.png
  9. // @homepageURL https://github.com/rybak/copy-commit-reference-userscript
  10. // @supportURL https://github.com/rybak/copy-commit-reference-userscript/issues
  11. // @match https://repo.or.cz/*/commit/*
  12. // @match https://git.savannah.gnu.org/gitweb/*a=commit*
  13. // @match https://git.ffmpeg.org/gitweb/*/commit/*
  14. // @match http://localhost:1234/*a=commit*
  15. // @require https://cdn.jsdelivr.net/gh/rybak/userscript-libs@e86c722f2c9cc2a96298c8511028f15c45180185/waitForElement.js
  16. // @require https://cdn.jsdelivr.net/gh/rybak/copy-commit-reference-userscript@1306877cef88bb8792c0851e31454d9b7a82b262/copy-commit-reference-lib.js
  17. // @grant none
  18. // ==/UserScript==
  19.  
  20. /*
  21. * Copyright (C) 2023-2025 Andrei Rybak
  22. *
  23. * This program is free software: you can redistribute it and/or modify
  24. * it under the terms of the GNU Affero General Public License as published
  25. * by the Free Software Foundation, version 3.
  26. *
  27. * This program is distributed in the hope that it will be useful,
  28. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  29. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  30. * GNU Affero General Public License for more details.
  31. *
  32. * You should have received a copy of the GNU Affero General Public License
  33. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  34. */
  35.  
  36. (function () {
  37. 'use strict';
  38.  
  39. /*
  40. * Implementation for GitWeb
  41. * Documentation:
  42. * - https://git-scm.com/docs/gitweb
  43. * - https://git-scm.com/book/en/v2/Git-on-the-Server-GitWeb
  44. *
  45. * Example URL for userscript testing:
  46. * - https://repo.or.cz/alt-git.git/commit/1f0fc1db8599f87520494ca4f0e3c1b6fabdf997
  47. *
  48. * TODO maybe add support for commitdiff pages, e.g.:
  49. * https://repo.or.cz/alt-git.git/commitdiff/1f0fc1db8599f87520494ca4f0e3c1b6fabdf997
  50. */
  51. class GitWeb extends GitHosting {
  52. getTargetSelector() {
  53. if (document.querySelector('.page_nav_sub')) {
  54. return '.page_nav_sub';
  55. }
  56. return '.page_nav';
  57. }
  58.  
  59. wrapButtonContainer(innerContainer) {
  60. const barSeparator = document.createElement('span');
  61. barSeparator.append(document.createTextNode(' | '));
  62. /*
  63. * CSS class is from 09deab1 (gitweb: enclose ' · ' and ' | ' in span tags, 2015-04-12)
  64. * https://repo.or.cz/git/gitweb.git/commit/09deab16f1feac32142bd6db4cd15294a26915a5
  65. */
  66. barSeparator.classList.add('barsep');
  67. const container = document.createElement('span');
  68. container.append(barSeparator);
  69. const tab = document.createElement('span');
  70. tab.classList.add('tab');
  71. tab.append(innerContainer);
  72. container.append(tab);
  73. return container;
  74. }
  75.  
  76. addButtonContainerToTarget(target, buttonContainer) {
  77. if (target.classList.contains('page_nav_sub')) {
  78. super.addButtonContainerToTarget(target, buttonContainer);
  79. return;
  80. }
  81. target.insertBefore(buttonContainer, target.querySelector('br'));
  82. }
  83.  
  84. getButtonText() {
  85. // use all lowercase for consistency with the rest of the UI
  86. return "copy commit reference";
  87. }
  88.  
  89. getFullHash() {
  90. /*
  91. * <td>commit</td> is always above <td>parent</td> and <td>tree</td>
  92. * so it's fine to just take the first <td> with CSS class `sha1`.
  93. */
  94. const cell = document.querySelector('.title_text .object_header td.sha1');
  95. return cell.innerText;
  96. }
  97.  
  98. getDateIso(hash) {
  99. /*
  100. * <td>author</td> is always above <td>committer</td>
  101. * so it's fine to just take the first <td> with CSS class `sha1`.
  102. */
  103. const cell = document.querySelector('.title_text .object_header .datetime');
  104. const s = cell.innerText;
  105. const d = new Date(s);
  106. return d.toISOString().slice(0, 'YYYY-MM-DD'.length);
  107. }
  108.  
  109. getCommitMessage(hash) {
  110. return document.querySelector('.page_body').innerText;
  111. }
  112. }
  113.  
  114. CopyCommitReference.runForGitHostings(new GitWeb());
  115. })();

QingJ © 2025

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