github加速按钮

为github中的特定链接(releases、文件、项目地址)添加一个悬浮按钮,提供代理后的加速链接

当前为 2021-03-18 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name gh-proxy-buttons
  3. // @name:zh-CN github加速按钮
  4. // @namespace https://github.com/du33169/gh-proxy-buttons
  5. // @version 0.5
  6. // @require https://cdn.bootcdn.net/ajax/libs/clipboard.js/2.0.6/clipboard.min.js
  7. // @description add a button beside github link(releases,files and repository url), click to get alternative url according to previously specified proxy.
  8. // @description:zh-CN 为github中的特定链接(releases、文件、项目地址)添加一个悬浮按钮,提供代理后的加速链接
  9. // @author du33169
  10. // @match *://github.com/*
  11. // @grant none
  12. // @run-at document-end
  13. // ==/UserScript==
  14. (function()
  15. {
  16. 'use strict';
  17. //--------------------------代理设置-------------------------------
  18. //用于在线代理的workers地址
  19. var proxy_url= 'https://gh-proxy.du33169.workers.dev/';
  20. /*
  21. 备用: 'https://gh.api.99988866.xyz/'; (来自gh-proxy项目作者)
  22. 代理服务器地址可自行修改,末尾斜杠不可省略!
  23. */
  24. //--------------------------目标设置------------------------------
  25. //[↓Code ] 按钮中仓库git地址文本框
  26. var repo_url_input=document.querySelector(`div.p-3:nth-child(1) > tab-container:nth-child(3) > div:nth-child(2) > div:nth-child(1) > input:nth-child(1)`);
  27.  
  28. // 仓库界面容器
  29. var repo_container=document.querySelector('#js-repo-pjax-container');
  30.  
  31. // releases 页面内容容器
  32. var release_container=document.querySelector('#repo-content-pjax-container');
  33.  
  34. //--------------------------其他设置------------------------------
  35. //是否打开调试输出
  36. var open_log=false;
  37.  
  38.  
  39.  
  40. console.log('[gh-proxy-buttons] processing...');
  41. function moveHere(e,originLink)//用于注册mouseenter事件,e为当前元素
  42. {
  43. if(document.getElementById('gh-proxy-button'))//如果已经产生按钮则返回,删去在Firefox会死循环(原因未知)
  44. return;
  45. //创建按钮对象,github中使用.btn的class可以为<a>标签加上按钮外观
  46. var btn=document.createElement(e.tagName=="INPUT"?'button':'a');//对于仓库地址使用button以实现点击复制
  47. btn.setAttribute('class','btn');
  48. btn.id="gh-proxy-button";
  49. btn.title="get proxy link";
  50. btn.style.position="absolute";
  51. btn.role="button";
  52. btn.innerText="🚀";
  53.  
  54. if(e.tagName=="INPUT")//仓库地址input标签特殊处理,使用ClipboardJS实现点击复制
  55. {
  56. btn.innerText+="📄";
  57. new ClipboardJS(btn);
  58. btn.setAttribute('data-clipboard-text',proxy_url+originLink);
  59. //console.log('[gh-proxy-buttons] input url processed');
  60. }
  61. else btn.href=proxy_url+originLink;
  62.  
  63. e.parentNode.appendChild(btn);
  64. //按钮位置左上角,与原元素有小部分重叠以确保从原元素移到按钮时不会因移出元素消失
  65. var padding=Math.min(20,e.offsetHeight/2,e.offsetWidth/4);
  66. btn.style.top=(e.offsetTop-btn.offsetHeight+padding).toString()+'px';//top等样式必须带有单位且为字符串类型
  67. btn.style.left=(e.offsetLeft-btn.offsetWidth+padding).toString()+'px';
  68.  
  69. if(open_log)console.debug('[gh-proxy-buttons] mousein');
  70. //以下逻辑处理鼠标移出的情况
  71. var onbtn=false;//鼠标移到btn上
  72. btn.addEventListener('mouseenter',function(){
  73. if(open_log)console.debug('[gh-proxy-buttons] onbtn');
  74. onbtn=true;
  75. });
  76. btn.addEventListener('mouseleave',function(){
  77. e.parentNode.removeChild(btn);
  78. if(open_log)console.debug('[gh-proxy-buttons] mouseleave-btn');
  79. });
  80.  
  81. function emoveout(){//鼠标移出原元素
  82. setTimeout(function(){//setTimeout是个trick,确保在btn的mouseenter之后执行下述流程
  83. if(!onbtn)
  84. {
  85. e.parentNode.removeChild(btn);
  86. if(open_log)
  87. console.debug('[gh-proxy-buttons] mouseleave',originLink);
  88. e.removeEventListener('mouseleave',emoveout);
  89. }
  90. },3);
  91. }
  92. e.addEventListener('mouseleave',emoveout);
  93. }
  94.  
  95. //使用事件委托添加代理下载按钮
  96. function eventDelegation(e)
  97. {
  98. // e.target 是事件触发的元素
  99. if(e.target!=null)
  100. {
  101. var ourTarget=e.target;
  102. while(ourTarget!=e.currentTarget&&ourTarget.tagName!='A'&&ourTarget!=repo_url_input)//releases页面触发元素为<a>内的span,需要上浮寻找
  103. {
  104. ourTarget=ourTarget.parentNode;
  105. }
  106.  
  107. if(open_log)
  108. console.log('[gh-proxy-buttons] ',ourTarget);
  109. if(
  110. ourTarget.tagName=='A'
  111. &&(
  112. ourTarget.getAttribute('class')!=null//利用&&短路特性防止没有class属性的元素导致脚本终止
  113. &&ourTarget.getAttribute('class').indexOf("js-navigation-open")!=-1
  114. &&ourTarget.parentNode.parentNode.previousElementSibling
  115. .querySelector('svg[aria-label=File]')//仓库文件
  116. ||
  117.  
  118. ourTarget.rel=="nofollow"
  119. &&ourTarget.title!="Go to parent directory"
  120. &&/github.com/.test(ourTarget.href)==true//"Download ZIP"
  121. )
  122. )
  123. {
  124. //console.log('[gh-proxy-buttons] added button on <a>');
  125. moveHere(ourTarget,ourTarget.href);
  126. }
  127. else if(ourTarget==repo_url_input)//地址input标签
  128. {
  129. //console.log('[gh-proxy-buttons] added button on <input>');
  130. moveHere(ourTarget,ourTarget.value);
  131. }
  132. }
  133. }
  134. if(repo_container!=null)
  135. repo_container.addEventListener("mouseover", eventDelegation);
  136. if(release_container!=null)
  137. release_container.addEventListener("mouseover", eventDelegation);
  138.  
  139. })();