Github Copy Raw File URL and Download File

Add buttons at the end of each file line to copy the raw file URL and download the file

As of 2024-09-10. See the latest version.

  1. // ==UserScript==
  2. // @name Github Copy Raw File URL and Download File
  3. // @name:zh-CN Github 复制原始文件 URL 与下载文件
  4. // @description:zh-CN 在每个文件行的末尾添加按钮,以复制原始文件 URL 和下载文件
  5. // @name:ar Github نسخ الملف الأصلي URL مع تنزيل الملفات
  6. // @description:ar زر إضافة في نهاية كل سطر ملف,لنسخ الملف الأصلي URL وتحميل الملفات
  7. // @name:bg Github Копирайте оригиналния файл URL с файлове за изтегляне
  8. // @description:bg Бутон за добавяне в края на всеки файлов ред,за да копирате оригиналния файл URL и изтегляне на файлове
  9. // @name:cs Github Zkopírujte původní soubor URL se staženými soubory
  10. // @description:cs Tlačítko Přidat na konci každého řádku souboru,pro zkopírování původního souboru URL a stahovat soubory
  11. // @name:da Github Kopiér den originale fil URL med download filer
  12. // @description:da Tilføj knap i slutningen af ​​hver fillinje,for at kopiere den originale fil URL og download filer
  13. // @name:de Github Originaldatei kopieren URL mit Download-Dateien
  14. // @description:de Schaltfläche „Hinzufügen“ am Ende jeder Dateizeile,um die Originaldatei zu kopieren URL und Dateien herunterladen
  15. // @name:el Github Αντιγραφή αρχικού αρχείου URL με λήψη αρχείων
  16. // @description:el Κουμπί προσθήκης στο τέλος κάθε γραμμής αρχείου,για να αντιγράψετε το αρχικό αρχείο URL και λήψη αρχείων
  17. // @name:en Github Copy original file URL with download files
  18. // @description:en Add button at the end of each file line,to copy the original file URL and download files
  19. // @name:eo Github Kopiu originalan dosieron URL kun elŝutaj dosieroj
  20. // @description:eo Aldoni butonon ĉe la fino de ĉiu dosierlinio,por kopii la originalan dosieron URL kaj elŝuti dosierojn
  21. // @name:es Github Copiar archivo original URL con archivos de descarga
  22. // @description:es Botón Agregar al final de cada línea de archivo,para copiar el archivo original URL y descargar archivos
  23. // @name:fi Github Kopioi alkuperäinen tiedosto URL lataustiedostojen kanssa
  24. // @description:fi Lisää-painike jokaisen tiedostorivin lopussa,kopioidaksesi alkuperäisen tiedoston URL ja ladata tiedostoja
  25. // @name:fr Github Copier le fichier original URL avec des fichiers à télécharger
  26. // @description:fr Ajouter un bouton à la fin de chaque ligne de fichier,pour copier le fichier original URL et télécharger des fichiers
  27. // @name:he Github העתק את הקובץ המקורי URL עם קבצים להורדה
  28. // @description:he כפתור הוסף בסוף כל שורת קובץ,כדי להעתיק את הקובץ המקורי URL ולהוריד קבצים
  29. // @name:hr Github Kopiraj izvornu datoteku URL s datotekama za preuzimanje
  30. // @description:hr Dodaj gumb na kraju svakog retka datoteke,za kopiranje izvorne datoteke URL i preuzimanje datoteka
  31. // @name:hu Github Eredeti fájl másolása URL letölthető fájlokkal
  32. // @description:hu Hozzáadás gomb minden fájlsor végén,az eredeti fájl másolásához URL és töltsön le fájlokat
  33. // @name:id Github Salin file asli URL dengan file unduhan
  34. // @description:id Tombol Tambah di akhir setiap baris file,untuk menyalin file asli URL dan mengunduh file
  35. // @name:it Github Copia il file originale URL con file scaricabili
  36. // @description:it Pulsante Aggiungi alla fine di ogni riga del file,per copiare il file originale URL e scaricare file
  37. // @name:ja Github 元のファイルをコピーする URL ダウンロードファイル付き
  38. // @description:ja 各ファイル行の末尾にある「追加」ボタン,元のファイルをコピーするには URL そしてファイルをダウンロードする
  39. // @name:ka Github დააკოპირეთ ორიგინალი ფაილი URL ჩამოტვირთვის ფაილებით
  40. // @description:ka დაამატეთ ღილაკი თითოეული ფაილის ხაზის ბოლოს,ორიგინალური ფაილის კოპირება URL და ჩამოტვირთეთ ფაილები
  41. // @name:ko Github 원본 파일 복사 URL 다운로드 파일 포함
  42. // @description:ko 각 파일 줄 끝에 추가 버튼,원본 파일을 복사하려면 URL 그리고 파일 다운로드
  43. // @name:nl Github Kopieer origineel bestand URL met downloadbestanden
  44. // @description:nl Knop Toevoegen aan het einde van elke bestandsregel,om het originele bestand te kopiëren URL en bestanden downloaden
  45. // @name:nb Github Kopier originalfilen URL med nedlastingsfiler
  46. // @description:nb Legg til-knapp på slutten av hver fillinje,for å kopiere originalfilen URL og last ned filer
  47. // @name:pl Github Skopiuj oryginalny plik URL z plikami do pobrania
  48. // @description:pl Dodaj przycisk na końcu każdej linii pliku,aby skopiować oryginalny plik URL i pobierz pliki
  49. // @name:pt-BR Github Copiar arquivo original URL com download de arquivos
  50. // @description:pt-BR Botão Adicionar no final de cada linha do arquivo,para copiar o arquivo original URL e baixar arquivos
  51. // @name:ro Github Copiați fișierul original URL cu fișiere descărcate
  52. // @description:ro butonul Adaugă la sfârșitul fiecărei linii de fișier,pentru a copia fișierul original URL și descărcați fișiere
  53. // @name:ru Github Скопировать исходный файл URL с загрузкой файлов
  54. // @description:ru Добавить кнопку в конце каждой строки файла,скопировать исходный файл URL и скачать файлы
  55. // @name:sk Github Skopírujte pôvodný súbor URL so stiahnutými súbormi
  56. // @description:sk Tlačidlo Pridať na konci každého riadku súboru,na skopírovanie pôvodného súboru URL a sťahovať súbory
  57. // @name:sr Github Копирајте оригиналну датотеку URL са датотекама за преузимање
  58. // @description:sr Дугме Додај на крају сваке линије датотеке,да копирате оригиналну датотеку URL и преузимање датотека
  59. // @name:sv Github Kopiera originalfilen URL med nedladdningsfiler
  60. // @description:sv Lägg till-knappen i slutet av varje filrad,för att kopiera originalfilen URL och ladda ner filer
  61. // @name:th Github คัดลอกไฟล์ต้นฉบับ URL พร้อมดาวน์โหลดไฟล์
  62. // @description:th เพิ่มปุ่มที่ท้ายแต่ละบรรทัดไฟล์,เพื่อคัดลอกไฟล์ต้นฉบับ URL และดาวน์โหลดไฟล์
  63. // @name:tr Github Orijinal dosyayı kopyala URL indirme dosyalarıyla
  64. // @description:tr Her dosya satırının sonuna ekle düğmesi,orijinal dosyayı kopyalamak için URL ve dosyaları indir
  65. // @name:ug Github ئەسلى ھۆججەتنى كۆچۈرۈڭ URL چۈشۈرۈش ھۆججىتى بىلەن
  66. // @description:ug ھەر بىر ھۆججەت قۇرنىڭ ئاخىرىغا كۇنۇپكا قوشۇڭ,ئەسلى ھۆججەتنى كۆچۈرۈش URL ھۆججەتلەرنى چۈشۈرۈڭ
  67. // @name:uk Github Скопіюйте вихідний файл URL з файлами для завантаження
  68. // @description:uk Кнопка «Додати» в кінці кожного рядка файлу,щоб скопіювати вихідний файл URL і завантажити файли
  69. // @name:vi Github Sao chép tập tin gốc URL với các tập tin tải về
  70. // @description:vi Nút thêm vào cuối mỗi dòng tập tin,để sao chép tập tin gốc URL và tải về các tập tin
  71. // @name:zh-TW Github 複製原始文件 URL 與下載文件
  72. // @description:zh-TW 在每個文件行的末尾新增按鈕,以複製原始文件 URL 和下載文件
  73. // @name:zh-HK Github 複製原始文件 URL 與下載文件
  74. // @description:zh-HK 在每個文件行的末尾新增按鈕,以複製原始文件 URL 和下載文件
  75. // @name:fr-CA Github Copier le fichier original URL avec des fichiers à télécharger
  76. // @description:fr-CA Ajouter un bouton à la fin de chaque ligne de fichier,pour copier le fichier original URL et télécharger des fichiers
  77. // @description Add buttons at the end of each file line to copy the raw file URL and download the file
  78. // @namespace https://github.com/ChinaGodMan/UserScripts
  79. // @version 2.2.0.20
  80. // @author Kamikaze (https://github.com/Kamiikaze) ,人民的勤务员 <toniaiwanowskiskr47@gmail.com>
  81. // @match https://github.com/*
  82. // @icon https://github.githubassets.com/pinned-octocat.svg
  83. // @run-at document-ready
  84. // @license MIT
  85. // @supportURL https://github.com/ChinaGodMan/UserScripts/issues
  86. // @homepageURL https://github.com/ChinaGodMan/UserScripts
  87. // ==/UserScript==
  88.  
  89.  
  90. // Need an Interval to detect path changes on github tree one-pager
  91. // Define the number of seconds
  92. const scanInterval = 2
  93.  
  94.  
  95. const waitForFilelist = setInterval(() => {
  96. let fileListContainer = document.querySelector("div.Box > div.js-details-container.Details div") || document.querySelector("table")
  97. let fileList = []
  98. let isTable = false
  99.  
  100. if (fileListContainer.tBodies) {
  101. fileList = fileListContainer.tBodies[0].children
  102. isTable = true
  103. } else {
  104. fileList = fileListContainer.children
  105. }
  106.  
  107. if (fileList < 1) return
  108.  
  109. appendButtons(fileList, isTable)
  110.  
  111. }, scanInterval * 1000)
  112.  
  113. function appendButtons(fileList, isTable = false) {
  114. let fileUrl = ""
  115. let rawFileUrl = ""
  116. for (let i = 0; i < fileList.length; i++) {
  117. let file = fileList[i]
  118.  
  119. if (file.classList.contains("cp-btn-rdy")) continue
  120.  
  121. file.classList.add("cp-btn-rdy")
  122.  
  123. if (!isTable) {
  124. if (
  125. file.classList.contains("sr-only") ||
  126. file.childElementCount !== 4
  127. ) continue
  128.  
  129. fileUrl = file.querySelector('div:nth-child(2) .js-navigation-open')
  130. .href
  131. } else {
  132. if (i === 0) continue
  133.  
  134. if (
  135. file.classList.contains("sr-only")
  136. ) continue
  137.  
  138.  
  139. fileUrl = file.querySelector("a")
  140. .href
  141. file = file.querySelector("td:nth-child(4) > div")
  142. }
  143. //alert(fileUrl)
  144. // Dont add button if its a folder
  145. if (!fileUrl.includes("/blob/")) continue
  146.  
  147. rawFileUrl = fileUrl.replace('/blob/', '/raw/')
  148. file.style = "display: flex; justify-content: flex-end;"
  149. file.append(creatyCopyButton(rawFileUrl))
  150. file.append(creatyDownButton(rawFileUrl))
  151. }
  152. };
  153.  
  154. function creatyCopyButton(copyText) {
  155. const copy2clipboard = `
  156. <clipboard-copy aria-label="Copy" value="test value" data-view-component="true" class="" tabindex="0" role="button" title="Copy raw file url">
  157. <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy">
  158. <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>
  159. </svg>
  160. </clipboard-copy>`
  161.  
  162. const copyButton = document.createElement('div')
  163. copyButton.setAttribute('role', 'gridcell')
  164. copyButton.style = "margin-left: 10px; display: inline;"
  165. copyButton.innerHTML = copy2clipboard
  166. copyButton.children[0].value = copyText
  167. copyButton.children[0].style = "cursor: pointer;"
  168.  
  169. return copyButton
  170. }
  171. function creatyDownButton(copyText) {
  172. const copy2clipboard = `
  173. <clipboard-copy aria-label="Download" value="test value" data-view-component="true" class="" tabindex="0" role="button" title="Download raw file url">
  174. <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-download">
  175. <path fill-rule="evenodd" d="M1.75 14.25A1.75 1.75 0 013.5 12.5h9a1.75 1.75 0 011.75 1.75v1.5a.75.75 0 01-.75.75H2.5a.75.75 0 01-.75-.75v-1.5zM10.75 9.25a.25.25 0 01.25.25v2.5a.25.25 0 01-.25.25H5.25a.25.25 0 01-.25-.25v-2.5a.25.25 0 01.25-.25h5.5zM8 1.75a.25.25 0 01.25.25v7.5a.25.25 0 01-.25.25H6.75a.25.25 0 01-.25-.25v-7.5a.25.25 0 01.25-.25h1.5zM10.25 5.25l1.5 1.5a.25.25 0 01.35 0l3-3a.25.25 0 00-.35-.35L11 5.25 9.25 3.5a.25.25 0 00-.35.35z"></path>
  176. </svg>
  177. </clipboard-copy>
  178. `
  179.  
  180. const copyButton = document.createElement('div')
  181. copyButton.setAttribute('role', 'gridcell')
  182. copyButton.style = "margin-left: 10px; display: inline;"
  183. copyButton.innerHTML = copy2clipboard
  184. copyButton.children[0].value = copyText
  185. copyButton.children[0].style = "cursor: pointer;"
  186. copyButton.addEventListener('click', () => {
  187. // window.location.href = copyText;
  188. downloadFile(copyText, getFilenameFromUrl(copyText))
  189. })
  190. return copyButton
  191. }
  192. function downloadFile(url, filename) {
  193. var xhr = new XMLHttpRequest()
  194. xhr.open('GET', url, true)
  195. xhr.responseType = 'blob'
  196. xhr.onload = function () {
  197. if (xhr.status === 200) {
  198. var blob = xhr.response
  199. var objectUrl = window.URL.createObjectURL(blob)
  200. var a = document.createElement('a')
  201. a.href = objectUrl
  202. a.download = filename // 设置下载文件名
  203. document.body.appendChild(a)
  204. a.click()
  205. window.URL.revokeObjectURL(objectUrl) // 清理 object URL
  206. document.body.removeChild(a) // 清理 DOM
  207. }
  208. }
  209. xhr.send()
  210. }
  211. function getFilenameFromUrl(url) {
  212. if (typeof url !== 'string' || url.trim() === '') {
  213. logMessage('getFilenameFromUrl', 'URL无效,默认文件名download', false)
  214. return 'download' // 返回一个默认的文件名
  215. }
  216. var lastSlashIndex = url.lastIndexOf('/')
  217. if (lastSlashIndex === -1 || lastSlashIndex === url.length - 1) {
  218. logMessage('getFilenameFromUrl', 'URL格式无效缺少文件名,默认文件名download', false)
  219. return 'download' // 返回一个默认的文件名
  220. }
  221. var filenameWithExtension = url.substring(lastSlashIndex + 1)
  222. var decodedFilename = decodeURIComponent(filenameWithExtension)
  223. decodedFilename = decodedFilename.replace(/%20/g, '_') // 替换所有的 %20 为下划线
  224. return decodedFilename
  225. }