发布一个油猴脚本-Github增强工具栏
Txy🚀 GitHub 增强工具栏 – 让仓库浏览“一键到位”的油猴插件
GitHub 增强工具栏 是一段只有几百行的用户脚本(Tampermonkey / Violentmonkey),它会在每个 GitHub 仓库页面的右上角注入 3 个实用按钮,帮你瞬间打开 VS Code Web、查询 DeepWiki 文档、或用 ZreadAi 对仓库进行 AI 分析。
安装链接 👉 https://update.greasyfork.org/scripts/544826/GitHub%20%E5%A2%9E%E5%BC%BA%E5%B7%A5%E5%85%B7%E6%A0%8F.user.js
1️⃣ 为何要写这玩意儿?
在日常的开源阅读、代码评审、面试准备中,我经常遇到同样的痛点:
痛点 |
现象 |
结果 |
切换工具太多 |
想在 VS Code Web 里编辑 → 再打开 DeepWiki 看文档 → 再去 ZreadAi 让 AI 给项目总结 |
页面切换、复制 URL、手动拼接,浪费十几秒甚至几分钟 |
GitHub 原生功能不够 |
. 可以打开 github.dev ,但没有文档视图、没有 AI 分析 |
功能碎片化,要么装一大堆 Chrome 扩展,要么手动跳转 |
PJAX/Turbo 导航失效 |
切换仓库时按钮消失,需要刷新页面 |
使用体验不友好 |
于是我决定 把这三件事浓缩成个按钮栏,只要装好油猴脚本,GitHub 页面一刷新就能看到。
这就是 GitHub 增强工具栏的初衷——“少点点,省几秒”。

2️⃣ 适合谁?
角色 |
场景 |
为什么爱上它 |
开发者 / 代码审查者 |
快速打开仓库代码 → 直接在浏览器里编辑 |
Github.dev 一键打开,省去 git clone 、本地 IDE 步骤 |
新人 / 学生党 |
面试前要快速了解陌生项目的结构 |
DeepWiki 自动生成目录树,ZreadAi 10 s 给出项目概览 |
运营 / DevOps |
需要临时查看文档或 audit 代码 |
按钮随时可点,不必装额外的企业内部插件 |
技术布道者 |
想把好用的“油猴+GitHub”技巧分享给团队 |
只需发送一个链接,所有人秒装生效 |
3️⃣ 核心优势一览
优势 |
解释 |
零依赖、即装即用 |
仅依赖油猴 (Tampermonkey / Violentmonkey),不需要任何后端或 Node 环境 |
与 GitHub UI 完美融合 |
使用 GitHub 官方的 btn btn-sm 样式 + 自动暗黑模式适配 |
高兼容性 |
按钮容器通过 4 条备选 selector 自动定位,兼容未来 UI 细微改动 |
防抖 + PJAX/Turbo 兼容 |
debounce 防止多次渲染;监听 pjax:end 、turbo:load 以及 URL 变化,保持按钮始终可见 |
体积极小 |
< 4 KB(gzip ≈ 1.8 KB),加载几乎没有感知 |
安全透明 |
只做 window.open 跳转,不收集任何用户数据,符合 CSP 要求 |
可自行定制 |
代码结构化,所有按钮属性(顺序、文字、图标、目标 URL)在函数内部可直接改动 |
4️⃣ 代码剖析(逐块解释)
以下每段代码均对应博客后面的 进阶魔改 小节,按需复制粘贴即可。
4.1 元信息 & IIFE
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
(function () { 'use strict'; })();
|
@match
限定脚本只在 https://github.com/*
生效,避免对其他站点造成干扰。
'use strict'
防止意外的全局变量泄漏。
- 整个脚本被封装成 IIFE(Immediately‑Invoked Function Expression),确保变量不会污染页面全局空间。
4.2 样式注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| const style = ` .custom-github-button { margin: 0 4px; display: flex; align-items: center; height: 28px; } .custom-github-button .octicon { margin-right: 4px; vertical-align: text-bottom; } .pagehead-actions > li { margin-right: 8px; } `; const styleElement = document.createElement('style'); styleElement.textContent = style; document.head.appendChild(styleElement);
|
- 使用
<style>
动态注入自定义 CSS,确保按钮在不同主题(Light / Dark)下都有合适的间距与对齐。
- 只给自定义按钮加
.custom-github-button
,不影响已有的 GitHub UI。
4.3 按钮容器定位(兼容性神器)
1 2 3 4 5 6 7 8 9 10 11 12 13
| async function findButtonContainer() { const selectors = [ 'ul.pagehead-actions', '.pagehead-actions', '.file-navigation .d-flex', 'nav[aria-label="Repository"] .d-flex' ]; for (const selector of selectors) { const el = document.querySelector(selector); if (el) return el; } return null; }
|
- GitHub 时常改动页面结构,上面的四个 selector 覆盖了 仓库首页、文件列表页、PR/Issues 页 中常见的按钮区域。
- 若全部匹配失败,脚本会在控制台报错(后面会提到调试技巧)。
4.4 统一的按钮生成函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function createCustomButton(id, url, iconHtml, text) { const li = document.createElement('li'); li.id = id; li.className = 'd-flex'; li.style.marginRight = '8px';
const a = document.createElement('a'); a.href = url; a.className = 'btn btn-sm custom-github-button'; a.target = '_blank'; a.rel = 'noopener noreferrer'; a.innerHTML = `${iconHtml}<span>${text}</span>`;
li.appendChild(a); return li; }
|
id
用来在后续 remove 已有按钮,防止重复。
url
为目标跳转地址,**iconHtml
** 与 text
负责视觉。
- 通过
target="_blank"
+ rel="noopener noreferrer"
,安全打开新标签页。
4.5 三个具体按钮的实现
4.5.1 Github.dev
1 2 3 4 5 6
| function createGithubDevButton() { const githubdevUrl = `https://github.dev${location.pathname}${location.search}${location.hash}`; const iconHtml = `<img class="octicon" width="16" height="16" src="https://github.com/favicons/favicon-codespaces.svg" />`; return createCustomButton('githubdevButton', githubdevUrl, iconHtml, 'Github.dev'); }
|
- 直接把当前仓库路径拼进去,打开 VS Code Web(只读也能编辑)。
- 用 GitHub 官方的
favicon-codespaces.svg
作为图标,视觉统一。
4.5.2 DeepWiki
1 2 3 4 5
| function createDeepWikiButton() { const deepwikiUrl = `https://deepwiki.com${location.pathname}${location.search}${location.hash}`; const iconHtml = `<svg class="octicon" …>…</svg>`; return createCustomButton('deepwikiButton', deepwikiUrl, iconHtml, 'DeepWiki'); }
|
- DeepWiki 用来快速展示仓库的文档树、Readme、Wiki 页面等。
- 图标是自定义 SVG,颜色
rgb(33,193,154)
(淡绿),在暗黑主题里也能看清。
4.5.3 ZreadAi
1 2 3 4 5
| function createZreadAiButton() { const zreadAiUrl = `https://zread.ai${location.pathname}${location.search}${location.hash}`; const iconHtml = `<svg aria-hidden="true" …>…</svg>`; return createCustomButton('zreadaiButton', zreadAiUrl, iconHtml, 'ZreadAi'); }
|
- ZreadAi 将仓库内容喂给 AI,返回 项目概览、模块划分、技术栈 等信息。
- 图标采用对称 “×” 形状,视觉上与前两者形成区分。
4.6 将按钮装进页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| async function addButtons() { try { const buttonContainer = await findButtonContainer(); if (!buttonContainer) { console.log('GitHub按钮脚本:找不到合适的按钮容器'); return; }
const existing = document.querySelectorAll('#githubdevButton, #zreadaiButton, #deepwikiButton'); existing.forEach(btn => btn.remove());
const deepWikiButton = createDeepWikiButton(); const zreadAiButton = createZreadAiButton(); const githubDevButton = createGithubDevButton();
buttonContainer.insertBefore(deepWikiButton, buttonContainer.firstChild); buttonContainer.insertBefore(zreadAiButton, buttonContainer.firstChild); buttonContainer.insertBefore(githubDevButton, buttonContainer.firstChild); } catch (e) { console.log('GitHub按钮脚本:添加按钮时发生错误', e); } }
|
- 先清理 再创建,避免在 PJAX / Turbo 导航后出现重复按钮。
- 使用
insertBefore(..., firstChild)
保证按钮永远排在最前面,紧贴 GitHub 原生的 “Watch / Star / Fork” 区域。
4.7 防抖(Debounce)
1 2 3 4 5 6 7 8
| function debounce(func, wait) { let timeout; return function (...args) { clearTimeout(timeout); timeout = setTimeout(() => func.apply(this, args), wait); }; } const debouncedAddButtons = debounce(addButtons, 300);
|
- 当页面频繁触发
pjax:end
、turbo:load
或 URL 变化时,防抖 能有效避免 10 + 次的重复渲染,只保留最后一次执行。
4.8 页面加载 & 导航监听
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', debouncedAddButtons); } else { setTimeout(debouncedAddButtons, 100); }
document.addEventListener('pjax:end', debouncedAddButtons); document.addEventListener('turbo:load', debouncedAddButtons);
let currentUrl = location.href; new MutationObserver(() => { if (location.href !== currentUrl) { currentUrl = location.href; setTimeout(debouncedAddButtons, 500); } }).observe(document.body, { childList: true, subtree: true });
|
- DOM 完成加载 → 初始化一次按钮。
- 通过 PJAX(GitHub 内部的局部刷新)和 Turbo(GitHub 新版的渲染框架)双重监听,保持按钮在切页后仍然存在。
- 额外的
MutationObserver
捕获 URL 手动变化(比如从地址栏敲入新路径)的情况。
小技巧:如果你在公司内部网络中使用,记得把 github.dev
、deepwiki.com
、zread.ai
替换为内部代理域名。只需要改 createGithubDevButton
、createDeepWikiButton
、createZreadAiButton
中的 url
拼接语句即可。