您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
OpenAI playground accessibility enhancements with keyboard navigation. Quickly edit/delete/expand messages.
当前为
// ==UserScript== // @name OpenAI Playground Hotkeys and Accessibility Enhancements // @namespace http://tampermonkey.net/ // @license MIT // @author Rekt // @version 1.1.0 // @description OpenAI playground accessibility enhancements with keyboard navigation. Quickly edit/delete/expand messages. // @match https://platform.openai.com/playground/prompts* // @grant none // ==/UserScript== (function() { 'use strict'; // Tracks if user is editing a message let isEditing = false; // --- Message Box and Action Selectors --- function getMessageBoxes() { return Array.from(document.querySelectorAll("div.LT9iz > div > div > div:nth-child(1) > div")); } function getButtonsBarInMessageBox(msgBox) { return msgBox.querySelector(".rqgky > ._5qprQ"); } function getButtonsInMessageBox(msgBox) { let btnBar = getButtonsBarInMessageBox(msgBox); if (!btnBar) return []; return Array.from(btnBar.querySelectorAll("button")).filter(btn => btn.offsetParent !== null); } // --- Message Type Detection --- function isAssistantMessage(msgBox) { let roleElement = msgBox.querySelector("div"); if (roleElement && roleElement.innerText) { return roleElement.innerText.toLowerCase().includes("assistant"); } let boxes = getMessageBoxes(); let idx = boxes.indexOf(msgBox); return idx !== -1 && idx % 2 === 1; } // --- Robust Edit Button Selector --- function getEditButton(msgBox) { let btnBar = getButtonsBarInMessageBox(msgBox); if (!btnBar) return null; let isAssistant = isAssistantMessage(msgBox); let btns = getButtonsInMessageBox(msgBox); if (isAssistant) { let btn = btnBar.querySelector("button:nth-child(1)"); if (btn && btn.offsetParent !== null) return btn; } else { let btn = btnBar.querySelector("button:nth-child(4)"); if (btn && btn.offsetParent !== null) return btn; } for (let btn of btns) { let svg = btn.querySelector("svg"); let ariaLabel = svg ? svg.getAttribute("aria-label") : ""; if ( (btn.innerText && btn.innerText.toLowerCase().includes('edit')) || (btn.title && btn.title.toLowerCase().includes('edit')) || (ariaLabel && ariaLabel.toLowerCase().includes('edit')) ) { return btn; } } return null; } // --- Delete Button Selector --- function getDeleteButton(msgBox) { let btnBar = getButtonsBarInMessageBox(msgBox); if (!btnBar) return null; let btns = getButtonsInMessageBox(msgBox); for (let btn of btns) { let svg = btn.querySelector("svg"); let ariaLabel = svg ? svg.getAttribute("aria-label") : ""; if ( (btn.innerText && btn.innerText.toLowerCase().includes('delete')) || (btn.title && btn.title.toLowerCase().includes('delete')) || (ariaLabel && ariaLabel.toLowerCase().includes('delete')) || (ariaLabel && ariaLabel.toLowerCase().includes('trash')) ) { return btn; } } if (btns.length) return btns[btns.length - 1]; return null; } // --- Expand Button Selector --- function getExpandButton(msgBox) { let btn = msgBox.querySelector(".G3JSV .BODGE > button"); return btn && btn.offsetParent !== null ? btn : null; } // --- Keyboard + Click State --- let selectedIdx = 0; // --- Highlight/Select Logic --- function highlightSelected(noScroll) { const boxes = getMessageBoxes(); boxes.forEach((box, idx) => { box.style.outline = ""; box.style.zIndex = ""; box.dataset.vimnavSelected = ""; }); if (boxes[selectedIdx]) { if (!noScroll) boxes[selectedIdx].scrollIntoView({block: "center", behavior: "smooth"}); boxes[selectedIdx].style.outline = "2px solid #00ffd0"; boxes[selectedIdx].style.zIndex = "10"; boxes[selectedIdx].dataset.vimnavSelected = "1"; } } // --- Input Blocking --- function notInInput() { const ae = document.activeElement; if (!ae) return true; if (ae.matches("input, textarea, select")) return false; if (ae.closest("[contenteditable='true']")) return false; return true; } function inContentEditable() { const ae = document.activeElement; if (!ae) return false; if (ae.closest("[contenteditable='true']")) return true; return false; } // --- Move Selection --- function moveSelection(delta) { const boxes = getMessageBoxes(); if (!boxes.length) return; selectedIdx = Math.max(0, Math.min(selectedIdx + delta, boxes.length - 1)); highlightSelected(); } // --- Toggle Edit for Selected Message --- function toggleEditOfSelectedMessage() { const boxes = getMessageBoxes(); if (!boxes.length || selectedIdx >= boxes.length) return; const box = boxes[selectedIdx]; const btn = getEditButton(box); if (btn) { btn.click(); } } // --- Toggle Expand for Selected Message --- function expandSelectedMessage() { const boxes = getMessageBoxes(); if (!boxes.length || selectedIdx >= boxes.length) return; const box = boxes[selectedIdx]; const btn = getExpandButton(box); if (btn) btn.click(); } // --- Keyboard Navigation, Expand/Contract, Toggle Edit, Delete --- document.addEventListener("keydown", function(e) { if (e.key === 'Escape' && inContentEditable()) { toggleEditOfSelectedMessage(); e.preventDefault(); return; } if (isEditing) return; // Prevent navigation when editing if (!notInInput()) return; const boxes = getMessageBoxes(); if (!boxes.length) return; if (e.key === 'j' || e.key === 'ArrowDown') { moveSelection(+1); e.preventDefault(); } else if (e.key === 'k' || e.key === 'ArrowUp') { moveSelection(-1); e.preventDefault(); } else if (e.key === 'e') { toggleEditOfSelectedMessage(); e.preventDefault(); } else if (e.key === 'x' || e.key === 'Delete') { let box = boxes[selectedIdx]; let btn = getDeleteButton(box); if (btn) { btn.click(); e.preventDefault(); } } else if (e.key === ' ' || e.key === 'Spacebar') { if (!inContentEditable()) { expandSelectedMessage(); e.preventDefault(); } } }); // --- Click/DoubleClick for Selection & Expanding --- function handleMsgBoxClick(e, idx) { selectedIdx = idx; highlightSelected(true); } function handleMsgBoxDoubleClick(e, idx) { selectedIdx = idx; highlightSelected(true); expandSelectedMessage(); } // --- On New Messages/UI Mutation: Maintain Highlight, Re-install Click Listeners --- function ensureHighlightAndListeners() { const boxes = getMessageBoxes(); boxes.forEach((box, idx) => { if (!box.dataset.vimnavClickSet) { box.addEventListener('click', e => handleMsgBoxClick(e, idx)); box.addEventListener('dblclick', e => handleMsgBoxDoubleClick(e, idx)); box.dataset.vimnavClickSet = '1'; } // Add focus/blur listeners to editable elements within message boxes const editableElements = box.querySelectorAll("[contenteditable='true'], input, textarea"); editableElements.forEach(el => { el.addEventListener('focus', () => { isEditing = true; }); el.addEventListener('blur', () => { isEditing = false; }); }); }); if (selectedIdx >= boxes.length) selectedIdx = boxes.length - 1; if (selectedIdx < 0) selectedIdx = 0; highlightSelected(true); } // Initial Setup setTimeout(ensureHighlightAndListeners, 1500); // Observe DOM Changes const observer = new MutationObserver(ensureHighlightAndListeners); observer.observe(document.body, {childList: true, subtree: true}); // Expose for Debugging window.OpenAIPlaygroundMsgNav = { getMessageBoxes, highlightSelected, moveSelection, getEditButton, getDeleteButton, expandSelectedMessage, toggleEditOfSelectedMessage }; })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址