GitHub to DeepWiki Link

一个快速在github仓库页面跳转到DeepWiki的脚本;A script to quickly jump to DeepWiki from the GitHub repository page

  1. // ==UserScript==
  2. // @name GitHub to DeepWiki Link
  3. // @name_zh GitHub 到 DeepWiki 链接
  4. // @namespace https://github.com/worryzyy/fast2deepwiki
  5. // @version 0.1
  6. // @description 一个快速在github仓库页面跳转到DeepWiki的脚本;A script to quickly jump to DeepWiki from the GitHub repository page
  7. // @author weilei
  8. // @match https://github.com/*
  9. // @grant none
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. ;(function () {
  14. 'use strict'
  15.  
  16. // Generate a unique page instance ID to ensure each page's script runs independently
  17. const PAGE_INSTANCE_ID =
  18. 'deepwiki_' + Math.random().toString(36).substring(2, 15)
  19.  
  20. // Add page ID to debug logs to distinguish between multiple pages
  21. function debugLog(message, obj = null) {
  22. const debug = false; // Set to true to enable debugging
  23. if (debug) {
  24. console.log(`[DeepWiki Debug ${PAGE_INSTANCE_ID}] ${message}`, obj || '')
  25. }
  26. }
  27.  
  28. // Add page ID prefix to ensure DOM element IDs are unique across pages
  29. const BUTTON_ID = `deepwiki-button-${PAGE_INSTANCE_ID}`
  30. const STYLES_ID = `deepwiki-styles-${PAGE_INSTANCE_ID}`
  31.  
  32. // Main function - add DeepWiki link to the page
  33. function addDeepWikiLink() {
  34. // First check if we're on a GitHub repository page
  35. const repoInfo = getRepositoryInfo()
  36. if (!repoInfo) {
  37. debugLog('Not a valid repository page')
  38. return
  39. }
  40.  
  41. debugLog('Repository info detected', repoInfo)
  42.  
  43. // Create DeepWiki link URL
  44. const deepWikiUrl = `https://deepwiki.com/${repoInfo.owner}/${repoInfo.repo}`
  45.  
  46. // Add custom CSS styles to the page
  47. addCustomCSS()
  48.  
  49. // Check if button already exists (avoid duplicate buttons)
  50. if (document.getElementById(BUTTON_ID)) {
  51. debugLog('Button already exists, skipping')
  52. return
  53. }
  54.  
  55. // Create DeepWiki button
  56. const deepWikiButton = createDeepWikiButton(deepWikiUrl)
  57.  
  58. // Find README link as insertion point
  59. const readmeLink = document.querySelector('a[href*="readme-ov-file"]')
  60. if (readmeLink) {
  61. debugLog('README link found')
  62. // Insert button after README link
  63. deepWikiButton.style.marginLeft = '10px'
  64. readmeLink.insertAdjacentElement('afterend', deepWikiButton)
  65. }
  66. debugLog('No suitable insertion point found')
  67. }
  68.  
  69. // Create DeepWiki button element
  70. function createDeepWikiButton(url) {
  71. // Create button link directly
  72. const link = document.createElement('a')
  73. link.id = BUTTON_ID
  74. link.href = url
  75. link.target = '_blank'
  76. link.className = 'btn btn-sm'
  77. link.style.display = 'inline-flex'
  78. link.style.alignItems = 'center'
  79. link.style.justifyContent = 'center'
  80. link.style.position = 'relative'
  81. link.style.overflow = 'hidden'
  82. link.style.background = 'linear-gradient(90deg, #2188ff 0%, #43e97b 100%)'
  83. link.style.border = 'none'
  84. link.style.transition = 'all 0.2s cubic-bezier(.4,0,.2,1)'
  85. link.style.marginLeft = '8px'
  86. link.style.borderRadius = '6px'
  87. link.style.padding = '4px 14px'
  88. link.style.color = '#fff'
  89. link.style.fontWeight = '500'
  90. link.style.boxShadow = '0 1px 2px rgba(33,136,255,0.08)'
  91.  
  92. // Add hover and click effects to the button
  93. link.addEventListener('mouseover', () => {
  94. link.style.background = 'linear-gradient(90deg, #0366d6 0%, #3bce6f 100%)'
  95. link.style.boxShadow = '0 4px 12px rgba(33,136,255,0.18)'
  96. link.style.transform = 'translateY(-1px)'
  97. })
  98.  
  99. link.addEventListener('mouseout', () => {
  100. link.style.background = 'linear-gradient(90deg, #2188ff 0%, #43e97b 100%)'
  101. link.style.boxShadow = '0 1px 2px rgba(33,136,255,0.08)'
  102. link.style.transform = 'translateY(0)'
  103. })
  104.  
  105. link.addEventListener('mousedown', () => {
  106. link.style.transform = 'scale(0.98) translateY(0)'
  107. link.style.boxShadow = '0 1px 3px rgba(33,136,255,0.12)'
  108. })
  109.  
  110. link.addEventListener('mouseup', () => {
  111. link.style.transform = 'scale(1) translateY(-1px)'
  112. link.style.boxShadow = '0 4px 12px rgba(33,136,255,0.18)'
  113. })
  114.  
  115. // Set button content
  116. link.innerHTML = `
  117. <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" style="margin-right: 8px;" class="deepwiki-icon">
  118. <path fill="currentColor" d="M12 0C5.372 0 0 5.372 0 12s5.372 12 12 12 12-5.372 12-12S18.628 0 12 0zm0 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2zm-3 5v2h3.586L7.293 14.293l1.414 1.414L14 10.414V14h2V7H9z"/>
  119. </svg>
  120. <span>DeepWiki</span>
  121. `
  122. return link
  123. }
  124.  
  125. // Get repository information from current page
  126. function getRepositoryInfo() {
  127. // Extract repository info from URL
  128. const path = window.location.pathname.substring(1).split('/')
  129.  
  130. // Check if there are enough path segments to represent a repository
  131. if (path.length < 2) return null
  132.  
  133. // Check path parts are not GitHub special pages
  134. const nonRepoPathParts = [
  135. 'settings',
  136. 'trending',
  137. 'new',
  138. 'organizations',
  139. 'marketplace',
  140. 'explore',
  141. 'topics'
  142. ]
  143. if (
  144. nonRepoPathParts.includes(path[0]) ||
  145. nonRepoPathParts.includes(path[1])
  146. ) {
  147. return null
  148. }
  149.  
  150. return {
  151. owner: path[0],
  152. repo: path[1]
  153. }
  154. }
  155.  
  156. // Add custom CSS to the page
  157. function addCustomCSS() {
  158. if (document.getElementById(STYLES_ID)) return
  159.  
  160. const styleElement = document.createElement('style')
  161. styleElement.id = STYLES_ID
  162. styleElement.textContent = `
  163. #${BUTTON_ID}::after {
  164. content: '';
  165. position: absolute;
  166. bottom: 0;
  167. left: 0;
  168. width: 100%;
  169. height: 100%;
  170. background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.1), transparent);
  171. transform: translateX(-100%);
  172. transition: transform 0.6s ease;
  173. }
  174. #${BUTTON_ID}:hover::after {
  175. transform: translateX(100%);
  176. }
  177. @keyframes pulse {
  178. 0% { transform: scale(1); opacity: 1; }
  179. 50% { transform: scale(1.1); opacity: 0.8; }
  180. 100% { transform: scale(1); opacity: 1; }
  181. }
  182. .deepwiki-icon {
  183. animation: pulse 2s infinite;
  184. filter: drop-shadow(0 0 1px rgba(255,255,255,0.5));
  185. }
  186. `
  187.  
  188. document.head.appendChild(styleElement)
  189. }
  190.  
  191. // Enhanced page observation
  192. function observePageChanges() {
  193. // Monitor URL changes - for SPA page navigation
  194. let lastUrl = location.href
  195. const urlChecker = setInterval(() => {
  196. if (location.href !== lastUrl) {
  197. lastUrl = location.href
  198. debugLog('URL changed, attempting to add button')
  199. setTimeout(addDeepWikiLink, 500) // Delay execution to wait for DOM updates
  200. }
  201. }, 1000)
  202.  
  203. // Monitor DOM changes - for asynchronously loaded content
  204. const domObserver = new MutationObserver((mutations) => {
  205. if (!document.getElementById(BUTTON_ID)) {
  206. // Determine if changes are significant enough to retry adding the button
  207. const significantChanges = mutations.some((mutation) => {
  208. // Only retry when new nodes are added
  209. return mutation.addedNodes.length > 0
  210. })
  211.  
  212. if (significantChanges) {
  213. debugLog('DOM changes detected, attempting to add button')
  214. addDeepWikiLink()
  215. }
  216. }
  217. })
  218.  
  219. domObserver.observe(document.body, {
  220. childList: true,
  221. subtree: true
  222. })
  223.  
  224. // Initial execution
  225. addDeepWikiLink()
  226.  
  227. // Delayed retry in case DOM is not fully ready on initial load
  228. setTimeout(addDeepWikiLink, 1000)
  229. }
  230.  
  231. // Start monitoring when page is loaded
  232. window.addEventListener('load', observePageChanges)
  233.  
  234. // Also execute once when DOM is loaded
  235. if (document.readyState === 'loading') {
  236. document.addEventListener('DOMContentLoaded', addDeepWikiLink)
  237. } else {
  238. addDeepWikiLink()
  239. }
  240. })()

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址