您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在 GitHub 仓库页面的 Star/Watch/Fork 按钮旁添加 DeepWiki 按钮,方便一键跳转到对应仓库的 DeepWiki 页面。
当前为
- // ==UserScript==
- // @name GitHub DeepWiki Button
- // @namespace http://tampermonkey.net/
- // @version 0.1
- // @description 在 GitHub 仓库页面的 Star/Watch/Fork 按钮旁添加 DeepWiki 按钮,方便一键跳转到对应仓库的 DeepWiki 页面。
- // @author nuttycc
- // @match https://github.com/*/*
- // @icon https://deepwiki.com/favicon.ico
- // @grant none
- // @license MIT
- // ==/UserScript==
- (function () {
- "use strict";
- // 配置
- const CONFIG = {
- DEBUG: false, // 设置为 true 开启调试日志
- DEBOUNCE_DELAY: 300, // 防抖延迟时间(毫秒)
- };
- // 缓存常用数据
- const CACHE = {
- excludedPaths: [
- "settings",
- "marketplace",
- "explore",
- "topics",
- "trending",
- "collections",
- "events",
- "sponsors",
- "notifications",
- ],
- // 预定义 SVG 图标
- svgIcon: `<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="margin-right:4px">
- <path d="M21 4H3a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h18a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1zm-1 14H4V6h16v12z"></path>
- <path d="M7 9h10v1H7zm0 4h10v1H7z"></path>
- </svg>`,
- };
- // 日志函数,只在调试模式下输出
- function log(...args) {
- if (CONFIG.DEBUG) {
- console.debug("[DeepWiki]", ...args);
- }
- }
- // 防抖函数
- function debounce(func, delay) {
- let timer;
- return function (...args) {
- clearTimeout(timer);
- timer = setTimeout(() => func.apply(this, args), delay);
- };
- }
- // 获取仓库路径
- function getRepoPath() {
- const pathParts = window.location.pathname.split("/").filter(Boolean);
- if (pathParts.length < 2) return null;
- return `${pathParts[0]}/${pathParts[1]}`;
- }
- // 检查当前页面是否是仓库页面
- function isRepoPage() {
- // 快速检查 URL 格式
- const pathParts = window.location.pathname.split("/").filter(Boolean);
- // 必须至少有用户名和仓库名两部分
- if (pathParts.length < 2) {
- return false;
- }
- // 排除特殊页面
- if (CACHE.excludedPaths.includes(pathParts[0])) {
- return false;
- }
- // 检查是否存在 Star/Watch/Fork 按钮容器
- const buttonContainer = document.querySelector("ul.pagehead-actions");
- const isRepo = !!buttonContainer;
- log(
- `[isRepoPage] 检测仓库页面: 路径:${pathParts.join(
- "/"
- )}, 按钮容器是否存在:${isRepo}`
- );
- return isRepo;
- }
- // 创建 DeepWiki 按钮
- function createDeepWikiButton(repoPath) {
- // 使用 DocumentFragment 提高性能
- const fragment = document.createDocumentFragment();
- // 创建列表项
- const listItem = document.createElement("li");
- listItem.className = "deepwiki-button d-flex";
- // 创建按钮
- const button = document.createElement("a");
- button.href = `https://deepwiki.com/${repoPath}`;
- button.className = "btn btn-sm";
- button.target = "_blank";
- button.rel = "noopener noreferrer";
- button.style.display = "flex";
- button.style.alignItems = "center";
- button.style.gap = "4px";
- // 使用预定义的 SVG 图标
- button.innerHTML = CACHE.svgIcon;
- // 添加文本
- const text = document.createElement("span");
- text.textContent = "DeepWiki";
- button.appendChild(text);
- // 组装
- listItem.appendChild(button);
- fragment.appendChild(listItem);
- return fragment;
- }
- // 添加 DeepWiki 按钮
- function addDeepWikiButton() {
- // 如果按钮已存在,则不再添加
- if (document.querySelector(".deepwiki-button")) {
- log("按钮已存在,跳过添加。");
- return;
- }
- // 获取仓库路径
- const repoPath = getRepoPath();
- if (!repoPath) {
- log("路径不符合要求,跳过添加。");
- return;
- }
- log(`[addDeepWikiButton] 检测到仓库路径: ${repoPath}`);
- // 获取按钮容器
- const buttonContainer = document.querySelector("ul.pagehead-actions");
- if (!buttonContainer) {
- log("未找到 ul.pagehead-actions 容器,跳过添加。");
- return;
- }
- // 创建并添加按钮
- const buttonFragment = createDeepWikiButton(repoPath);
- buttonContainer.insertBefore(buttonFragment, buttonContainer.firstChild);
- log("🎉 按钮添加成功。");
- }
- // 处理页面变化的统一函数
- const handlePageChange = debounce(() => {
- if (isRepoPage()) {
- addDeepWikiButton();
- }
- }, CONFIG.DEBOUNCE_DELAY);
- // 初始化函数
- function init() {
- // 页面加载完成时检查
- window.addEventListener("load", () => {
- log("[event] load 事件触发");
- handlePageChange();
- });
- // 监听 PJAX 结束事件
- document.addEventListener("pjax:end", () => {
- log("[event] pjax:end 事件触发");
- handlePageChange();
- });
- // 监听 turbo:render 事件
- document.addEventListener("turbo:render", () => {
- log("[event] turbo:render 事件触发");
- handlePageChange();
- });
- // 使用 turbo:render 监听变化已经足够。故移除下面内容。
- // 使用更精确的 MutationObserver 监听 DOM 变化。
- // let lastUrl = location.href;
- // const urlObserver = new MutationObserver(() => {
- // const url = location.href;
- // if (url !== lastUrl) {
- // lastUrl = url;
- // log("[Observer CallBack] URL 变化:", url);
- // handlePageChange();
- // }
- // });
- // // 只观察 body 元素,减少不必要的回调
- // const observeTarget = document.querySelector("body");
- // if (observeTarget) {
- // urlObserver.observe(observeTarget, {
- // childList: true,
- // subtree: true,
- // });
- // }
- // 初始检查
- log("[init] 初始检查。");
- handlePageChange();
- }
- // 启动脚本
- init();
- })();