您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在GitHub仓库页面上添加一个与原生UI无缝集成的DeepWiki搜索框。
// ==UserScript== // @name GitHub DeepWiki Search (Visually Integrated) // @namespace http://tampermonkey.net/ // @version 2025-08-07.3 // @description 在GitHub仓库页面上添加一个与原生UI无缝集成的DeepWiki搜索框。 // @author Your Name // @match https://github.com/*/* // @grant GM_xmlhttpRequest // @grant GM_openInTab // @connect api.devin.ai // @run-at document-end // @license MIT // ==/UserScript== (function() { 'use strict'; const observer = new MutationObserver(() => { // **CHANGED**: 直接定位到操作按钮的<ul>列表,这是最稳定的父容器。 const actionsList = document.querySelector('ul.pagehead-actions'); if (actionsList && !document.getElementById('deepwiki-search-container')) { console.log('Found actions list, adding integrated DeepWiki search UI...'); addSearchUI(actionsList); } }); observer.observe(document.body, { childList: true, subtree: true }); /** * @param {HTMLElement} targetList The <ul> element (pagehead-actions) to append to. */ function addSearchUI(targetList) { // 1. 创建最外层的 <li> 元素,这是符合 GitHub 布局的关键 const listItem = document.createElement('li'); // 2. 创建一个 div 作为按钮组 (BtnGroup),让输入框和按钮看起来像一个整体 const btnGroup = document.createElement('div'); btnGroup.id = 'deepwiki-search-container'; btnGroup.className = 'BtnGroup d-flex'; // 使用 GitHub 的 BtnGroup 类 // 3. 创建输入框 const input = document.createElement('input'); input.type = 'text'; input.id = 'deepwiki-search-input'; input.placeholder = 'DeepWiki Search'; // 复用GitHub样式,并作为按钮组的一部分 input.className = 'form-control input-sm BtnGroup-item'; // 样式微调,使其与按钮无缝连接 input.style.borderTopRightRadius = '0'; input.style.borderBottomRightRadius = '0'; input.style.zIndex = '1'; // 确保边框不会被旁边的按钮覆盖 // 4. 创建搜索按钮 const button = document.createElement('button'); button.innerText = 'Search'; button.id = 'deepwiki-search-button'; // 复用GitHub样式,并作为按钮组的一部分 button.className = 'btn btn-sm BtnGroup-item'; // 负外边距,让按钮和输入框紧紧贴在一起 button.style.marginLeft = '-1px'; // 绑定事件 button.addEventListener('click', performSearch); input.addEventListener('keyup', (event) => { if (event.key === "Enter") { performSearch(); } }); // 5. 按正确的层级组装 DOM btnGroup.appendChild(input); btnGroup.appendChild(button); listItem.appendChild(btnGroup); // 6. 将最终的 <li> 添加到操作列表中 targetList.appendChild(listItem); } function performSearch() { const inputElement = document.getElementById('deepwiki-search-input'); const keyword = inputElement.value.trim(); if (!keyword) { alert('请输入搜索关键词!'); return; } const searchButton = document.getElementById('deepwiki-search-button'); searchButton.disabled = true; searchButton.innerText = '...'; // 使用更简洁的加载提示 const repoNameMatch = window.location.pathname.match(/^\/([^/]+\/[^/]+)/); if (!repoNameMatch) { console.error('无法从URL中解析仓库名称。'); alert('无法识别当前 GitHub 仓库!'); searchButton.disabled = false; searchButton.innerText = 'Search'; return; } const repoName = repoNameMatch[1]; const queryId = generateUUID(); const searchUrl = `https://deepwiki.com/search/_${queryId}`; const requestBody = { engine_id: "multihop", user_query: `${keyword}`, keywords: [], repo_names: [repoName], additional_context: "", query_id: `_${queryId}`, use_notes: false, generate_summary: false }; GM_xmlhttpRequest({ method: "POST", url: "https://api.devin.ai/ada/query", headers: { "accept": "*/*", "content-type": "application/json", "Referer": "https://deepwiki.com/" }, data: JSON.stringify(requestBody), onload: function(response) { console.log('DeepWiki API 请求成功:', response); GM_openInTab(searchUrl, { active: true }); inputElement.value = ''; }, onerror: function(error) { console.error('DeepWiki API 请求失败:', error); alert('请求 DeepWiki API 失败,请查看浏览器控制台获取更多信息。'); }, ontimeout: function() { console.error('DeepWiki API 请求超时'); alert('请求 DeepWiki API 超时。'); }, onloadend: function() { searchButton.disabled = false; searchButton.innerText = 'Search'; } }); } function generateUUID() { if (self.crypto && self.crypto.randomUUID) { return self.crypto.randomUUID(); } return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } })();