-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathgh-proxy-buttons.user.js
197 lines (185 loc) · 8.05 KB
/
gh-proxy-buttons.user.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// ==UserScript==
// @name gh-proxy-buttons
// @name:zh-CN github加速按钮
// @namespace https://github.com/du33169/gh-proxy-buttons
// @version 0.7
// @license MPL-2.0
// @require https://cdn.bootcdn.net/ajax/libs/clipboard.js/2.0.6/clipboard.min.js
// @description add a button beside github link(releases,files and repository url), click to get alternative url according to previously specified proxy.
// @description:zh-CN 为github中的特定链接(releases、文件、项目地址)添加一个悬浮按钮,提供代理后的加速链接
// @author du33169
// @match *://github.com/*
// @grant none
// @run-at document-end
// ==/UserScript==
(function()
{
'use strict';
//--------------------------代理设置-------------------------------
//用于在线代理的workers地址
const proxy_url= 'https://gh-proxy.du33169.workers.dev/';
/*
备用: 'https://gh.api.99988866.xyz/'; (来自gh-proxy项目作者)
代理服务器地址可自行修改,末尾斜杠不可省略!
*/
//--------------------------其他设置------------------------------
//是否打开调试输出
const open_log=true;
//鼠标离开链接或按钮后消失前等待的时间
const fade_timeout=100;//ms
//--------------------------功能代码------------------------------
function isRepoFile(ourTarget){
return (ourTarget.tagName=='A'
&&ourTarget.getAttribute('aria-label')!=null//利用&&短路特性防止没有属性的元素导致脚本终止
&&ourTarget.classList.contains("Link--primary")
&&ourTarget.getAttribute('aria-label').endsWith('(File)')
&&ourTarget.closest('#js-repo-pjax-container')!=null
);
}
function isReleaseAsset(ourTarget){
return (ourTarget.tagName=='A'
&&ourTarget.getAttribute('rel')!=null
&&ourTarget.rel=="nofollow"
//&&/github.com/.test(ourTarget.href)==true
&&(ourTarget.closest('#repo-content-pjax-container')!=null)||(ourTarget.closest('.js-truncated-assets-fragment')!=null)
);
}
function isDownloadZip(e){
return (e.tagName=='A'
&&e.classList.contains("kHKEGN")
&&e.getAttribute('rel')!=null
&&e.rel=="nofollow"
&&e.getAttribute('role')!=null
&&e.role=="menuitem"
);
}
function isHttpCopyGit(e){
return (
e.tagName=='BUTTON'
&&e.classList.contains('hUTZcL')
&&e.previousElementSibling!=null
&&e.previousElementSibling.tagName=='INPUT'
&&e.previousElementSibling.value.startsWith('https')
);
}
function getBtn(originLink,filename,copy=false)
{
var ghBtn=document.getElementById("gh-proxy-button");
//existed
if(!ghBtn){
//not existed, create instance
ghBtn=document.createElement('a');
ghBtn.setAttribute('class','btn');
ghBtn.id="gh-proxy-button";
ghBtn.title="[gh-proxy-buttons] get proxy link";
ghBtn.style.position="absolute";
ghBtn.role="button";
ghBtn.style.zIndex=9999;
//ghBtn.style.top=0;//must be set for transition
//ghBtn.style.left=0;
//ghBtn.style.transition="transform 0.5s ease-in-out";
ghBtn.addEventListener('mouseenter',function(){
if(open_log)console.debug('[gh-proxy-buttons] onbtn');
if(ghBtn.timerId !=undefined && ghBtn.timerId!=-1){
clearTimeout(ghBtn.timerId);
ghBtn.timerId=-1;
}
});
ghBtn.addEventListener('mouseleave',function(){
if(open_log)console.debug('[gh-proxy-buttons] mouseleave-btn');
if(ghBtn.timerId !=undefined && ghBtn.timerId!=-1)return;
ghBtn.timerId=setTimeout(function(){
ghBtn.style.visibility="hidden";
ghBtn.timerId=-1;
if(open_log)console.debug('[gh-proxy-buttons] timeout fade mouseleave-btn');
},fade_timeout);
if(open_log)console.debug('[gh-proxy-buttons] btn leave timerid:',ghBtn.timerId);
});
document.documentElement.appendChild(ghBtn);
}
//now gh-proxy-button exists
if(copy)//仓库地址input标签特殊处理,使用ClipboardJS实现点击复制
{
ghBtn.removeAttribute('target');
ghBtn.removeAttribute('download');
ghBtn.href="javascript:void(0)";
ghBtn.innerText="🚀📄";
ghBtn.clip=new ClipboardJS(ghBtn);
ghBtn.clip.on('success',function(){
ghBtn.innerText="🚀📄✔";
});
ghBtn.setAttribute('data-clipboard-text',proxy_url+originLink);
//console.log('[gh-proxy-buttons] input url processed');
}
else{
ghBtn.innerText="🚀";
ghBtn.target="_blank";
if(ghBtn.clip)ghBtn.clip.destroy();
ghBtn.clip=undefined;
ghBtn.download=filename;
ghBtn.removeAttribute('data-clipboard-text');
ghBtn.href=proxy_url+originLink;
}
return ghBtn;
}
console.log('[gh-proxy-buttons] processing...');
function moveHere(e,originLink,copy=false)//用于注册mouseenter事件,e为当前元素
{
//创建按钮对象,github中使用.btn的class可以为<a>标签加上按钮外观
var btn=getBtn(originLink,e.title,copy);
if(open_log)console.debug("[gh-proxy-buttons]",btn);
//e.parentElement.insertBefore(btn,e);
if(btn.timerId !=undefined && btn.timerId!=-1){
clearTimeout(btn.timerId);
btn.timerId=-1;
}
const rect = e.getBoundingClientRect();
const btnRect=btn.getBoundingClientRect();
const x = rect.left + window.scrollX - btnRect.width;
const y = rect.top + window.scrollY;
console.log(`Element coordinates (relative to document): x: ${x}, y: ${y}`);
btn.style.left=`${x}px`;
btn.style.top =`${y}px`;
if(btn.style.visibility=="visible"){
//btn.style.transform = `translate(${event.x}px, ${event.y}px)`;
}
else{
//btn.style.transform="";
btn.style.visibility="visible";
}
if(open_log)console.debug(`[gh-proxy-buttons] mousein, move btn to ${event.x},${event.y}`);
e.addEventListener('mouseleave',function(){
if(open_log)console.debug('[gh-proxy-buttons] mouseleave-target');
if(btn.timerId !=undefined && btn.timerId!=-1)return;
btn.timerId=setTimeout(function(){
btn.style.visibility="hidden";
btn.timerId=-1;
if(open_log)console.debug('[gh-proxy-buttons] timeout fade mouseleave-target');
},fade_timeout);
if(open_log)console.debug('[gh-proxy-buttons] target leave timerid:',btn.timerId);
});
}
function eventDelegation(e)
{
// e.target 是事件触发的元素
if(e.target!=null)
{
var ourTarget=e.target;
while(ourTarget!=e.currentTarget&&ourTarget.tagName!='A'&&ourTarget.tagName!='BUTTON')//releases页面触发元素为<a>内的span,需要上浮寻找
{
ourTarget=ourTarget.parentNode;
}
if(ourTarget==e.currentTarget)return;
//if(open_log)console.debug('[gh-proxy-buttons]','found A',ourTarget);
if(isRepoFile(ourTarget)||isReleaseAsset(ourTarget)||isDownloadZip(ourTarget))
{
console.log('[gh-proxy-buttons] ','found target',ourTarget);
moveHere(ourTarget,ourTarget.href);
}else if(isHttpCopyGit(ourTarget)){
console.log('[gh-proxy-buttons] ','found target copy button',ourTarget);
moveHere(ourTarget,ourTarget.previousElementSibling.value,true);
}
}
}
document.body.addEventListener("mouseover", eventDelegation);
})();