Button to copy the raw file URL | Github

Adds a button at the end of each file row to copy the raw file URL

  1. // ==UserScript==
  2. // @name Button to copy the raw file URL | Github
  3. // @name:de Button zum Kopieren der Raw-Datei URL | Github
  4. // @namespace https://greasyfork.org/users/928242
  5. // @version 2.1
  6. // @description Adds a button at the end of each file row to copy the raw file URL
  7. // @description:de Fügt am Ende jeder Dateizeile eine Schaltfläche zum Kopieren der Raw File URL hinzu
  8. // @author Kamikaze (https://github.com/Kamiikaze)
  9. // @supportURL https://github.com/Kamiikaze/Tampermonkey/issues
  10. // @match https://github.com/*
  11. // @icon https://www.google.com/s2/favicons?sz=64&domain=github.com
  12. // @run-at document-ready
  13. // @license MIT
  14. // ==/UserScript==
  15.  
  16.  
  17. // Need an Interval to detect path changes on github tree one-pager
  18. // Define the number of seconds
  19. const scanInterval = 2
  20.  
  21.  
  22. const waitForFilelist = setInterval(() => {
  23. let fileListContainer = document.querySelector("div.Box > div.js-details-container.Details div") || document.querySelector("table")
  24. let fileList = []
  25. let isTable = false
  26.  
  27. if (fileListContainer.tBodies) {
  28. fileList = fileListContainer.tBodies[0].children
  29. isTable = true
  30. } else {
  31. fileList = fileListContainer.children
  32. }
  33.  
  34. if (fileList < 1) return
  35.  
  36. appendButtons(fileList, isTable)
  37.  
  38. }, scanInterval * 1000)
  39.  
  40. function appendButtons(fileList, isTable = false) {
  41. let fileUrl = ""
  42. let rawFileUrl = ""
  43. for (let i = 0; i < fileList.length; i++) {
  44. let file = fileList[i]
  45.  
  46. if (file.classList.contains("cp-btn-rdy")) continue;
  47.  
  48. file.classList.add("cp-btn-rdy")
  49.  
  50. if (!isTable) {
  51. if (
  52. file.classList.contains("sr-only") ||
  53. file.childElementCount !== 4
  54. ) continue;
  55.  
  56. fileUrl = file.querySelector('div:nth-child(2) .js-navigation-open')
  57. .href
  58. } else {
  59. if (i === 0) continue;
  60.  
  61. if (
  62. file.classList.contains("sr-only")
  63. ) continue;
  64.  
  65.  
  66. fileUrl = file.querySelector("a")
  67. .href
  68. file = file.querySelector("td:nth-child(4) > div")
  69. }
  70.  
  71. // Dont add button if its a folder
  72. if (!fileUrl.includes("/blob/")) continue;
  73.  
  74. rawFileUrl = fileUrl.replace('/blob/', '/raw/')
  75. file.style = "display: flex; justify-content: flex-end;"
  76. file.append(creatyCopyButton(rawFileUrl))
  77. }
  78. };
  79.  
  80. function creatyCopyButton(copyText) {
  81. const copy2clipboard = `
  82. <clipboard-copy aria-label="Copy" value="test value" data-view-component="true" class="" tabindex="0" role="button" title="Copy raw file url">
  83. <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy">
  84. <path fill-rule="evenodd" d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 010 1.5h-1.5a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-1.5a.75.75 0 011.5 0v1.5A1.75 1.75 0 019.25 16h-7.5A1.75 1.75 0 010 14.25v-7.5z"></path><path fill-rule="evenodd" d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0114.25 11h-7.5A1.75 1.75 0 015 9.25v-7.5zm1.75-.25a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-7.5a.25.25 0 00-.25-.25h-7.5z"></path>
  85. </svg>
  86. </clipboard-copy>`
  87.  
  88. const copyButton = document.createElement('div')
  89. copyButton.setAttribute('role', 'gridcell')
  90. copyButton.style = "margin-left: 10px; display: inline;"
  91. copyButton.innerHTML = copy2clipboard
  92. copyButton.children[0].value = copyText
  93. copyButton.children[0].style = "cursor: pointer;"
  94.  
  95. return copyButton
  96. }