您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在 GitHub 仓库页面添加按钮,以快速打开对应的 DeepWiki 页面。
- // ==UserScript==
- // @name GitHub to DeepWiki
- // @namespace http://tampermonkey.net/
- // @version 0.1
- // @description Adds a button to GitHub repo pages to open the corresponding DeepWiki page.
- // @description:zh-CN 在 GitHub 仓库页面添加按钮,以快速打开对应的 DeepWiki 页面。
- // @author Leihao Zhou
- // @match https://github.com/*/*
- // @grant GM_addStyle
- // @grant window.open
- // @run-at document-idle
- // @name:zh-CN GitHub 跳转 DeepWiki
- // @license MIT
- // ==/UserScript==
- (function() {
- 'use strict';
- const BUTTON_ID = 'deepwiki-button-userscript'; // Unique ID
- const addDeepWikiButton = () => {
- // 1. Check if already added
- if (document.getElementById(BUTTON_ID)) {
- return;
- }
- // 2. Check if on a valid repo page (path needs at least user/repo)
- const pathParts = location.pathname.split('/').filter(Boolean);
- // Ensure it's a repo page, not settings, issues, PRs etc. within the repo for simplicity
- // A more robust check might involve looking for specific page elements.
- if (pathParts.length !== 2) {
- // console.log('DeepWiki Button: Not on a main repo page.');
- return; // Only target the main repo page for now
- }
- // 3. Find insertion point (try a few common selectors for GitHub's layout)
- const potentialTargets = [
- '.gh-header-actions', // Newer layout
- '.pagehead-actions', // Older layout
- '#repository-container-header > div > div > div > ul' // Fallback selector observed
- ];
- let targetElement = null;
- for (const selector of potentialTargets) {
- targetElement = document.querySelector(selector);
- if (targetElement) break;
- }
- if (!targetElement) {
- // console.log('DeepWiki Button: Target element not found using selectors:', potentialTargets);
- // Try again after a short delay in case the element is slow to render
- setTimeout(() => {
- if (!document.getElementById(BUTTON_ID)) { // Check again before retrying
- targetElement = document.querySelector(potentialTargets.join(', ')); // Try all at once
- if (targetElement) {
- insertButton(targetElement);
- } else {
- console.warn('DeepWiki Button: Target element still not found after delay.');
- }
- }
- }, 1000); // Wait 1 second
- return;
- }
- insertButton(targetElement);
- };
- const insertButton = (targetElement) => {
- // 4. Create button
- const button = document.createElement('a');
- button.id = BUTTON_ID;
- button.textContent = '🚀 Open in DeepWiki';
- button.target = '_blank';
- button.rel = 'noopener noreferrer';
- button.href = '#'; // Set href to '#' initially to make it behave like a link
- button.setAttribute('aria-label', 'Open this repository in DeepWiki');
- button.setAttribute('role', 'button');
- button.setAttribute('tabindex', '0'); // Make it focusable
- // Apply styles using GM_addStyle for better management or inline styles
- // Using inline styles for simplicity here
- button.style.marginLeft = '8px';
- button.style.padding = '5px 16px'; // Adjusted padding like GitHub buttons
- button.style.border = '1px solid rgba(240, 246, 252, 0.1)'; // GitHub's border color
- button.style.borderRadius = '6px';
- button.style.backgroundColor = '#21262d'; // GitHub's dark button background
- button.style.color = '#c9d1d9'; // GitHub's dark button text color
- button.style.fontWeight = '500';
- button.style.fontSize = '14px'; // Match GitHub button font size
- button.style.lineHeight = '20px';
- button.style.cursor = 'pointer';
- button.style.textDecoration = 'none';
- button.style.display = 'inline-flex';
- button.style.alignItems = 'center';
- button.style.verticalAlign = 'middle'; // Ensure vertical alignment
- // Add hover/focus effect mimicking GitHub
- const hoverBg = '#30363d';
- const hoverBorder = '#8b949e';
- const defaultBg = '#21262d';
- const defaultBorder = 'rgba(240, 246, 252, 0.1)';
- button.onmouseover = () => { button.style.backgroundColor = hoverBg; button.style.borderColor = hoverBorder; };
- button.onmouseout = () => { button.style.backgroundColor = defaultBg; button.style.borderColor = defaultBorder; };
- button.onfocus = () => { button.style.outline = '2px solid #58a6ff'; button.style.outlineOffset = '2px'; }; // Accessibility focus ring
- button.onblur = () => { button.style.outline = 'none'; };
- const handleClick = (event) => {
- event.preventDefault(); // Prevent default link navigation
- event.stopPropagation(); // Stop event bubbling
- const currentUrl = location.href;
- // More robust replacement: ensure we only replace the domain and the base path
- const urlObject = new URL(currentUrl);
- const pathParts = urlObject.pathname.split('/').filter(Boolean);
- if (pathParts.length >= 2) {
- const user = pathParts[0];
- const repo = pathParts[1];
- const deepwikiUrl = `https://deepwiki.com/${user}/${repo}`;
- window.open(deepwikiUrl, '_blank');
- } else {
- console.error('DeepWiki Button: Could not extract user/repo from URL:', currentUrl);
- }
- };
- // 5. Add click handler
- button.addEventListener('click', handleClick);
- // Add keydown handler for accessibility (Enter/Space)
- button.addEventListener('keydown', (event) => {
- if (event.key === 'Enter' || event.key === ' ') {
- handleClick(event);
- }
- });
- // 6. Insert button (prepend to appear first in the actions list, or append if prepend not suitable)
- // Using prepend is generally better for visibility
- if (targetElement.prepend) {
- targetElement.prepend(button);
- } else {
- targetElement.insertBefore(button, targetElement.firstChild); // Fallback for older browsers
- }
- console.log('DeepWiki Button added.');
- }
- // --- Handling SPA Navigation ---
- // GitHub uses Turbo (formerly Turbolinks) for navigation. Observe changes to the body or a specific container.
- let previousUrl = location.href;
- const observer = new MutationObserver((mutationsList) => {
- // Check if URL changed - simple way to detect SPA navigation
- if (location.href !== previousUrl) {
- previousUrl = location.href;
- // Wait a bit for the new page elements to likely render after URL change
- setTimeout(addDeepWikiButton, 300);
- } else {
- // If URL didn't change, check if the button is missing and the target exists (e.g., partial DOM update)
- if (!document.getElementById(BUTTON_ID)) {
- const target = document.querySelector('.gh-header-actions, .pagehead-actions, #repository-container-header > div > div > div > ul');
- if (target) {
- addDeepWikiButton(); // Try adding if target exists but button doesn't
- }
- }
- }
- });
- // Start observing the body for subtree modifications and child list changes.
- // Observing 'body' is broad but reliable for catching SPA navigations.
- observer.observe(document.body, { childList: true, subtree: true });
- // Initial run in case the page is already loaded
- // Use requestIdleCallback or setTimeout for potentially better timing
- if (document.readyState === 'complete' || document.readyState === 'interactive') {
- setTimeout(addDeepWikiButton, 500); // Delay slightly
- } else {
- document.addEventListener('DOMContentLoaded', () => setTimeout(addDeepWikiButton, 500));
- }
- })();