diff --git a/browser-extension/content.js b/browser-extension/content.js
index af99022..9c62628 100644
--- a/browser-extension/content.js
+++ b/browser-extension/content.js
@@ -133,6 +133,7 @@
function processCloneUrl() {
if (!config.enabled || !config.cloneAccel || !config.workersUrl) return;
+ // 更广泛的选择器,匹配 GitHub 的各种 clone 输入框
const selectors = [
'input[readonly]',
'input[data-autoselect]',
@@ -140,15 +141,21 @@
'input[aria-label*="clone"]',
'input[aria-label*="Clone"]',
'.input-group input',
- '[data-target="get-repo-modal.cloneInput"]'
+ '[data-target="get-repo-modal.cloneInput"]',
+ // GitHub 新版 UI 选择器
+ '[class*="CloneContainer"] input',
+ '[class*="clone"] input[readonly]',
+ 'div[class*="LocalTab"] input'
];
let cloneInputs = [];
selectors.forEach(sel => {
- const inputs = document.querySelectorAll(sel);
- inputs.forEach(i => {
- if (!cloneInputs.includes(i)) cloneInputs.push(i);
- });
+ try {
+ const inputs = document.querySelectorAll(sel);
+ inputs.forEach(i => {
+ if (!cloneInputs.includes(i)) cloneInputs.push(i);
+ });
+ } catch(e) {}
});
cloneInputs.forEach(input => {
@@ -163,7 +170,17 @@
const acceleratedUrl = generateAcceleratedCloneUrl(originalUrl);
if (!acceleratedUrl) return;
- const inputGroup = input.closest('.input-group') || input.parentElement;
+ // 找到合适的容器(向上查找最多5层)
+ let inputGroup = input.parentElement;
+ for (let i = 0; i < 5 && inputGroup; i++) {
+ if (inputGroup.classList.contains('d-flex') ||
+ inputGroup.className.includes('CloneContainer') ||
+ inputGroup.querySelector('button')) {
+ break;
+ }
+ inputGroup = inputGroup.parentElement;
+ }
+ if (!inputGroup) inputGroup = input.parentElement;
// 创建加速按钮
const accelBtn = document.createElement('button');
@@ -196,57 +213,106 @@
input.select();
});
+ // 插入加速按钮 - 放在 input 后面
input.insertAdjacentElement('afterend', accelBtn);
- // 拦截容器内所有按钮的点击(可能是复制按钮)
+ // 拦截容器内所有可能的复制按钮
interceptCopyButtons(inputGroup, input);
});
}
- // 拦截复制按钮
+ // 拦截复制按钮 - 改进版
function interceptCopyButtons(container, input) {
+ // 向上查找更大范围的容器
let searchContainer = container;
- for (let i = 0; i < 3; i++) {
+ for (let i = 0; i < 5; i++) {
if (searchContainer.parentElement) {
searchContainer = searchContainer.parentElement;
}
}
- const buttons = searchContainer.querySelectorAll('button, [role="button"]');
+ // 查找所有可能是复制按钮的元素
+ const potentialButtons = searchContainer.querySelectorAll('button, [role="button"], clipboard-copy, [data-action*="copy"]');
- buttons.forEach(btn => {
- const ariaLabel = btn.getAttribute('aria-label') || '';
- const title = btn.getAttribute('title') || '';
- const text = btn.textContent || '';
+ potentialButtons.forEach(btn => {
+ // 跳过已经处理过的
+ if (btn._cfspiderIntercepted) return;
- if (ariaLabel.toLowerCase().includes('copy') ||
- title.toLowerCase().includes('copy') ||
- text.toLowerCase().includes('copy') ||
- btn.querySelector('svg.octicon-copy')) {
-
- btn.addEventListener('click', (e) => {
- const state = input._cfspiderState;
- if (state && state.isAccelerated) {
- e.stopImmediatePropagation();
- e.preventDefault();
-
- navigator.clipboard.writeText(state.accelerated).then(() => {
- showCopySuccess(btn);
- });
-
- return false;
- }
- }, true);
+ const ariaLabel = (btn.getAttribute('aria-label') || '').toLowerCase();
+ const title = (btn.getAttribute('title') || '').toLowerCase();
+ const text = (btn.textContent || '').toLowerCase();
+ const dataAction = (btn.getAttribute('data-action') || '').toLowerCase();
+
+ // 判断是否是复制按钮
+ const isCopyButton =
+ ariaLabel.includes('copy') ||
+ title.includes('copy') ||
+ text.includes('copy') ||
+ dataAction.includes('copy') ||
+ btn.tagName.toLowerCase() === 'clipboard-copy' ||
+ btn.querySelector('svg[class*="copy"]') ||
+ btn.querySelector('svg.octicon-copy') ||
+ btn.querySelector('[class*="copy"]');
+
+ if (!isCopyButton) return;
+
+ // 检查按钮是否与当前 input 相关(在同一个 input-group 或相邻)
+ const btnContainer = btn.closest('.input-group') || btn.closest('.d-flex') || btn.parentElement;
+ const inputContainer = input.closest('.input-group') || input.closest('.d-flex') || input.parentElement;
+
+ // 如果按钮和 input 不在相近的容器中,跳过
+ if (btnContainer !== inputContainer && !btnContainer.contains(input) && !inputContainer.contains(btn)) {
+ // 检查是否是相邻元素
+ if (btn.parentElement !== input.parentElement && !btn.parentElement.contains(input)) {
+ return;
+ }
}
+
+ btn._cfspiderIntercepted = true;
+
+ // 使用 capture 阶段拦截点击
+ btn.addEventListener('click', (e) => {
+ const state = input._cfspiderState;
+ if (state && state.isAccelerated) {
+ e.stopImmediatePropagation();
+ e.preventDefault();
+
+ // 写入加速后的 URL 到剪贴板
+ navigator.clipboard.writeText(state.accelerated).then(() => {
+ showCopySuccess(btn);
+ console.log('CFspider: 已复制加速链接:', state.accelerated);
+ }).catch(err => {
+ console.error('CFspider: 复制失败:', err);
+ // 回退方案
+ const textarea = document.createElement('textarea');
+ textarea.value = state.accelerated;
+ document.body.appendChild(textarea);
+ textarea.select();
+ document.execCommand('copy');
+ document.body.removeChild(textarea);
+ showCopySuccess(btn);
+ });
+
+ return false;
+ }
+ }, true);
+
+ console.log('CFspider: 已拦截复制按钮:', btn);
});
}
// 显示复制成功
function showCopySuccess(btn) {
const originalHTML = btn.innerHTML;
- btn.innerHTML = '';
+ const successIcon = '';
+
+ // 显示成功状态
+ btn.innerHTML = successIcon;
+ btn.style.color = '#3fb950';
+
setTimeout(() => {
btn.innerHTML = originalHTML;
+ btn.style.color = '';
}, 1500);
}
diff --git a/browser-extension/manifest.json b/browser-extension/manifest.json
index 21b7d53..7e95a79 100644
--- a/browser-extension/manifest.json
+++ b/browser-extension/manifest.json
@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "CFspider GitHub 加速",
- "version": "1.0.0",
+ "version": "1.2.0",
"description": "使用 CFspider Workers 加速 GitHub 文件下载",
"author": "CFspider",
"homepage_url": "https://github.com/violettoolssite/CFspider",