您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
通过点击 GitHub Issue 标题栏快速进入编辑模式
当前为
// ==UserScript== // @name GitHub Issue 快速编辑器 // @namespace https://github.com/ // @version 0.1 // @description 通过点击 GitHub Issue 标题栏快速进入编辑模式 // @author RainbowBird // @match https://github.com/*/*/issues/* // @grant none // @run-at document-end // @license MIT // ==/UserScript== (function() { 'use strict'; // 添加全局样式 const styles = ` .issue-title-hover { transition: background-color 0.2s ease; position: relative; overflow: hidden; } .issue-title-hover:hover { background-color: rgba(180, 180, 180, 0.1); } .ripple { position: absolute; border-radius: 50%; background-color: rgba(0, 120, 215, 0.2); transform: scale(0); animation: ripple-effect 0.6s linear; z-index: 0; } @keyframes ripple-effect { to { transform: scale(2.5); opacity: 0; } } `; // 添加样式到页面 const addStyle = (css) => { const style = document.createElement('style'); style.textContent = css; document.head.appendChild(style); }; addStyle(styles); /** * GitHub Issue快速编辑器主类 */ class IssueQuickEditor { constructor() { this.initialized = false; this.titleBar = null; this.isEditing = false; this.config = { selectors: { issueBody: '.IssueBodyViewer-module__IssueBody--MXyFt', markdownBody: '[data-testid="markdown-body"]', actionButton: 'button[aria-label="Issue body actions"]', portalRoot: '#__primerPortalRoot__' }, styles: { cursor: 'pointer' }, tooltips: { titleBar: '点击编辑Issue' }, maxAttempts: { loadWait: 20, menuItemWait: 10 }, animationDuration: { ripple: 600 } }; } /** * 初始化编辑器 */ init() { if (this.initialized) { console.log('Issue快速编辑功能已初始化,跳过'); return; } this.waitForElements() .then(() => this.setupTitleBar()) .catch(error => console.error('初始化失败:', error)); } /** * 等待关键元素加载 */ waitForElements() { return new Promise((resolve, reject) => { let attempts = 0; const checkInterval = setInterval(() => { const issueBodyContainer = document.querySelector(this.config.selectors.issueBody); attempts++; if (issueBodyContainer) { clearInterval(checkInterval); resolve(); } else if (attempts >= this.config.maxAttempts.loadWait) { clearInterval(checkInterval); reject(new Error('页面元素加载超时')); } }, 500); }); } /** * 定位标题栏元素 */ findTitleBar() { const issueBodyContainer = document.querySelector(this.config.selectors.issueBody); if (!issueBodyContainer) { throw new Error('找不到Issue正文容器'); } const titleBar = issueBodyContainer.previousElementSibling; if (!titleBar || titleBar.tagName !== 'DIV') { throw new Error('无法找到标题栏'); } return titleBar; } /** * 查找菜单按钮 */ findMenuButton() { // 首先尝试找到"Issue body actions"按钮 const actionButton = document.querySelector(this.config.selectors.actionButton); if (actionButton) return actionButton; // 备用方法 const markdownBody = document.querySelector(this.config.selectors.markdownBody); if (!markdownBody) return null; const issueBodyModule = markdownBody.closest(this.config.selectors.issueBody); if (!issueBodyModule) return null; // 找到活动标头区域 const activityHeader = issueBodyModule.previousElementSibling; if (!activityHeader) return null; // 查找任何aria-haspopup="true"的按钮 return activityHeader.querySelector('button[aria-haspopup="true"]'); } /** * 创建水波纹动画效果 */ createRippleEffect(event) { // 获取点击位置相对于标题栏的坐标 const rect = this.titleBar.getBoundingClientRect(); const x = event.clientX - rect.left; const y = event.clientY - rect.top; // 计算动画尺寸(取容器宽高的较大值) const size = Math.max(rect.width, rect.height); // 创建水波纹元素 const ripple = document.createElement('span'); ripple.className = 'ripple'; ripple.style.left = `${x}px`; ripple.style.top = `${y}px`; ripple.style.width = `${size}px`; ripple.style.height = `${size}px`; // 添加到标题栏 this.titleBar.appendChild(ripple); // 动画结束后移除元素 setTimeout(() => { ripple.remove(); }, this.config.animationDuration.ripple); } /** * 查找编辑选项 */ findEditOption() { return new Promise(resolve => { const findEditItem = () => { // 从portal root查找 const portalRoot = document.getElementById('__primerPortalRoot__'.substring(1)); if (portalRoot) { // 获取最后一个子div const lastDiv = Array.from(portalRoot.children) .filter(child => child.tagName === 'DIV') .pop(); if (lastDiv) { const ul = lastDiv.querySelector('ul[role="menu"]'); if (ul) { // 查找包含"Edit"文本的li const menuItems = ul.querySelectorAll('li'); for (const item of menuItems) { if (item.textContent.includes('Edit') || item.textContent.includes('编辑')) { return item; } } } } } // 回退方法 return Array.from(document.querySelectorAll('[role="menuitem"], li')) .filter(item => { const rect = item.getBoundingClientRect(); return rect.width > 0 && rect.height > 0; }) .find(item => { const text = item.textContent?.toLowerCase() || ''; return text.includes('edit') || text.includes('编辑'); }); }; // 查找逻辑 let editItem = findEditItem(); if (editItem) { resolve(editItem); return; } let attempts = 0; const intervalId = setInterval(() => { editItem = findEditItem(); attempts++; if (editItem || attempts >= this.config.maxAttempts.menuItemWait) { clearInterval(intervalId); resolve(editItem); } }, 50); }); } /** * 设置标题栏样式和事件 */ setupTitleBar() { try { this.titleBar = this.findTitleBar(); // 设置样式 this.titleBar.style.cursor = this.config.styles.cursor; this.titleBar.title = this.config.tooltips.titleBar; this.titleBar.classList.add('issue-title-hover'); // 添加点击事件 this.titleBar.addEventListener('click', this.handleTitleBarClick.bind(this)); this.initialized = true; console.log('Issue快速编辑功能已启用 - 点击标题栏触发编辑'); } catch (error) { console.error('设置标题栏失败:', error); } } /** * 处理标题栏点击事件 */ async handleTitleBarClick(event) { // 如果点击了链接或按钮,不触发编辑 if (event.target.tagName === 'A' || event.target.tagName === 'BUTTON' || event.target.closest('a') || event.target.closest('button')) { return; } // 如果已经在编辑中,防止重复点击 if (this.isEditing) { return; } try { // 设置编辑状态 this.isEditing = true; // 创建水波纹动画效果 this.createRippleEffect(event); // 找到菜单按钮 const menuButton = this.findMenuButton(); if (!menuButton) { throw new Error('找不到菜单按钮'); } // 点击打开菜单 menuButton.click(); // 等待菜单打开并点击编辑选项 const editOption = await this.findEditOption(); if (!editOption) { this.isEditing = false; throw new Error('找不到编辑选项'); } // 点击编辑选项 editOption.click(); // 监听编辑状态变化 this.watchForEditModeEnd(); } catch (error) { console.error('编辑操作失败:', error); this.isEditing = false; } } /** * 监听编辑模式结束 */ watchForEditModeEnd() { // 检查是否存在编辑表单 const checkForEditForm = () => { const editForm = document.querySelector('form.js-quick-submit'); if (!editForm) { this.isEditing = false; return; } setTimeout(checkForEditForm, 1000); }; setTimeout(checkForEditForm, 1000); } } // 创建并初始化编辑器实例 const editor = new IssueQuickEditor(); // 页面加载后启动 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => editor.init()); } else { setTimeout(() => editor.init(), 500); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址