Greasy Fork 支持简体中文。

GitHub: inline patch view

Clicking on a commit ID shows the patch inline. Second click opens the link.

  1. // ==UserScript==
  2. // @name GitHub: inline patch view
  3. // @namespace https://akinori.org/
  4. // @description Clicking on a commit ID shows the patch inline. Second click opens the link.
  5. // @license 2-clause BSDL
  6. // @author Akinori MUSHA
  7. // @include https://github.com/*/*/commits
  8. // @include https://github.com/*/*/commits/*
  9. // @include https://github.com/*/*/compare/*
  10. // @include https://github.com/*/*/pull/*
  11. // @version 1.0.2
  12. // @homepage https://github.com/knu/userjs-github_inline_patch_view
  13. // @homepage https://greasyfork.org/scripts/17016-github-inline-patch-view
  14. // @grant none
  15. // ==/UserScript==
  16. "use strict";
  17. (function () {
  18. let cloneNode = function (node) {
  19. let clone = document.createElement(node.tagName);
  20. Array.prototype.forEach.
  21. call(node.attributes,
  22. function (attr) {
  23. clone.setAttribute(attr.name, attr.value);
  24. });
  25. return clone;
  26. };
  27. let insertInlinePatch = function (commit, sha) {
  28. if (commit.classList.contains("inline-patch")) {
  29. return false;
  30. }
  31. let url = sha.href;
  32. let xhr = new XMLHttpRequest();
  33. xhr.onload = function () {
  34. let patch = this.responseXML.getElementById("files");
  35. switch (commit.tagName) {
  36. case "TR":
  37. // Split the table to avoid CSS rule conflicts
  38. let container = null;
  39. for (let node = commit.parentNode;
  40. node !== null;
  41. node = node.parentNode) {
  42. let clone = cloneNode(node);
  43. if (container === null) {
  44. // Move following siblings to a new container
  45. let siblings = [];
  46. for (let sibling = commit.nextSibling;
  47. sibling !== null;
  48. sibling = sibling.nextSibling) {
  49. siblings.push(sibling);
  50. }
  51. siblings.forEach(function (sibling) {
  52. clone.appendChild(sibling);
  53. });
  54. } else {
  55. clone.appendChild(container);
  56. }
  57. container = clone;
  58. if (node.tagName === "TABLE") {
  59. node.parentNode.insertBefore(container, node.nextSibling);
  60. patch.style.marginLeft = commit.querySelector(".commit-message").offsetLeft.toString() + "px";
  61. node.parentNode.insertBefore(patch, container);
  62. break;
  63. }
  64. }
  65. break;
  66. default:
  67. let meta = commit.querySelector(".commit-meta");
  68. if (meta) {
  69. meta.parentNode.appendChild(patch);
  70. }
  71. }
  72. commit.classList.add("inline-patch");
  73. let caret = sha.querySelector('.inline-patch-dropdown');
  74. if (caret) {
  75. sha.removeChild(caret);
  76. }
  77. };
  78. xhr.onerror = function () {
  79. console.log("Failed to load the patch from " + url);
  80. };
  81. xhr.open("GET", url);
  82. xhr.responseType = "document";
  83. xhr.send();
  84. return true;
  85. };
  86. let activateInlinePatch = function (commit) {
  87. // */commit/*, */commits/*
  88. let sha = commit.querySelector("a.sha[href*='/commit'], a.commit-id[href*='/commit']");
  89. if (!sha) {
  90. return;
  91. }
  92. let caret = document.createElement('span');
  93. caret.className = 'inline-patch-dropdown dropdown-caret';
  94. caret.style.display = 'inline';
  95. sha.appendChild(caret);
  96. sha.addEventListener("click",
  97. function (e) {
  98. if (insertInlinePatch(commit, sha)) {
  99. e.preventDefault();
  100. }
  101. },
  102. false);
  103. let expander = commit.querySelector(".hidden-text-expander a[href]");
  104. if (expander) {
  105. expander.addEventListener("click",
  106. function (e) {
  107. insertInlinePatch(commit, sha);
  108. },
  109. false);
  110. }
  111. };
  112. Array.prototype.forEach.
  113. call(document.querySelectorAll(".commit"),
  114. activateInlinePatch);
  115. })();