GitHub Ingest Button

Add an "Ingest" button to GitHub repo pages with improved visual alignment.

  1. // ==UserScript==
  2. // @name GitHub Ingest Button
  3. // @namespace http://github.com/
  4. // @version 1.3
  5. // @description Add an "Ingest" button to GitHub repo pages with improved visual alignment.
  6. // @author Nighthawk
  7. // @match https://github.com/*/*
  8. // @grant none
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. "use strict";
  14.  
  15. function addIngestButton() {
  16. console.log('Attempting to add Ingest button...');
  17.  
  18. // Locate the container for header actions (Watch, Fork, Star, etc.)
  19. const actionList = document.querySelector('.pagehead-actions');
  20. if (!actionList) {
  21. console.log('Action list not found. Retrying in 500ms.');
  22. return setTimeout(addIngestButton, 500); // Retry if not yet loaded
  23. }
  24.  
  25. // Prevent duplicate insertion by checking for our marker class.
  26. if (document.querySelector('.ingest-button')) {
  27. console.log('Ingest button already exists.');
  28. return;
  29. }
  30.  
  31. // Create a new list item using GitHub’s own flex-based styling.
  32. const listItem = document.createElement('li');
  33. listItem.className = 'd-flex';
  34.  
  35. // Create the button element
  36. const button = document.createElement('button');
  37. button.className = 'btn btn-sm btn-secondary ingest-button'; // Added btn-secondary for GitHub styling
  38. button.type = 'button'; // Specify button type
  39.  
  40. // Add a click handler
  41. button.addEventListener('click', () => {
  42. const currentUrl = window.location.href;
  43. const repoRegex = /^https:\/\/github\.com\/([^\/]+\/[^\/?#]+)/i;
  44. const match = currentUrl.match(repoRegex);
  45. if (match && match[1]) {
  46. const repoPath = match[1];
  47. const ingestUrl = 'https://gitingest.com/' + repoPath;
  48. window.open(ingestUrl, '_blank');
  49. } else {
  50. alert('Unable to parse repository path from the URL.');
  51. }
  52. });
  53.  
  54. // Create the SVG icon element
  55. const svgNS = "http://www.w3.org/2000/svg";
  56. const svg = document.createElementNS(svgNS, "svg");
  57. svg.setAttribute("width", "16");
  58. svg.setAttribute("height", "16");
  59. svg.setAttribute("viewBox", "0 0 16 16");
  60. svg.setAttribute("fill", "currentColor");
  61. svg.style.marginRight = "4px";
  62. svg.innerHTML = `
  63. <circle cx="8" cy="8" r="7" stroke="currentColor" fill="none" stroke-width="1"/>
  64. <path d="M5 8a1 1 0 0 1 2 0v1H5V8zm4 0a1 1 0 0 1 2 0v1H9V8zm-1.5 1.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1 0-1z" fill="currentColor"/>
  65. `;
  66.  
  67. // Append the SVG icon and text to the button
  68. button.appendChild(svg);
  69. button.appendChild(document.createTextNode('Ingest'));
  70.  
  71. // Insert the button inside our list item
  72. listItem.appendChild(button);
  73.  
  74. // Insert the new list item into the action list.
  75. const firstItem = actionList.firstElementChild;
  76. if (firstItem) {
  77. actionList.insertBefore(listItem, firstItem);
  78. } else {
  79. actionList.appendChild(listItem);
  80. }
  81. console.log('Ingest button added successfully.');
  82. }
  83.  
  84. // Run when the DOM is ready.
  85. if (document.readyState === "loading") {
  86. document.addEventListener("DOMContentLoaded", addIngestButton);
  87. } else {
  88. addIngestButton();
  89. }
  90.  
  91. // Re-run the function if GitHub’s PJAX (or similar) replaces parts of the page.
  92. const observer = new MutationObserver(() => {
  93. if (!document.querySelector('.ingest-button')) {
  94. console.log('Ingest button not found. Re-adding...');
  95. addIngestButton();
  96. }
  97. });
  98. observer.observe(document.body, { childList: true, subtree: true });
  99. })();