您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds copy button and double-click functionality to extract formatted text from scholarqa.allen.ai
// ==UserScript== // @name ScholarQA Enhanced Copy Tools // @namespace https://violentmonkey.github.io/ // @version 1.4 // @description Adds copy button and double-click functionality to extract formatted text from scholarqa.allen.ai // @author Bui Quoc Dung // @match *://scholarqa.allen.ai/* // @grant none // ==/UserScript== (function() { 'use strict'; // Define CSS selector variables for easier maintenance const ACCORDION_SUMMARY_SELECTOR = '.MuiButtonBase-root.MuiAccordionSummary-root'; const ACCORDION_ROOT_SELECTOR = '.MuiAccordion-root'; const ACCORDION_HEADING_SELECTOR = '.MuiTypography-h5'; const ACCORDION_BODY_SELECTOR = '.MuiTypography-body1'; const CITATION_SELECTOR = '.MuiChip-root'; const PARAGRAPH_SELECTOR = '.MuiCollapse-root'; const COPY_BUTTON_CLASS = 'MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall'; // Find the "Disclaimer" button dynamically based on its text content function findDisclaimerButton() { const buttons = document.querySelectorAll('button'); for (let button of buttons) { if (button.textContent.includes('Disclaimer')) { return button; } } return null; } // Expands all collapsed sections for complete content extraction function expandSections() { console.log("Expanding all sections..."); document.querySelectorAll(ACCORDION_SUMMARY_SELECTOR).forEach(btn => btn.click()); } // Shows notification when content is copied function showNotification(x, y) { let notification = document.createElement('div'); notification.innerText = "Copied!"; Object.assign(notification.style, { position: 'absolute', left: `${x}px`, top: `${y}px`, background: 'rgba(0, 0, 0, 0.8)', color: 'white', padding: '8px 12px', borderRadius: '5px', fontSize: '14px', zIndex: '1000', transition: 'opacity 0.5s' }); document.body.appendChild(notification); setTimeout(() => { notification.style.opacity = '0'; setTimeout(() => document.body.removeChild(notification), 500); }, 1500); } // Copies formatted HTML content to clipboard function copyToClipboard(text) { let tempContainer = document.createElement('div'); tempContainer.innerHTML = text; document.body.appendChild(tempContainer); let range = document.createRange(); range.selectNode(tempContainer); let selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range); try { document.execCommand('copy'); console.log("Copied formatted text."); } catch (err) { console.error("Copy failed", err); } selection.removeAllRanges(); document.body.removeChild(tempContainer); } // Processes text from a single paragraph element function processText(paragraphElement, includeHeading = true) { let tempDiv = paragraphElement.cloneNode(true); let paragraphText = tempDiv.innerHTML; tempDiv.querySelectorAll(CITATION_SELECTOR).forEach(citation => { let linkElement = citation.closest('a'); if (linkElement) { let hyperlink = linkElement.href; let citationText = citation.innerText; let formattedCitation = `<a href="${hyperlink}" target="_blank">${citationText}</a>`; paragraphText = paragraphText.replace(citation.outerHTML, formattedCitation); } }); paragraphText = paragraphText.replace(/<div[^>]*>/g, ' ') .replace(/<\/div>/g, '') .replace(/\s+/g, ' '); paragraphText = paragraphText.replace(/Is this section helpful\? /g, ""); // Remove "Is this section helpful? " if (includeHeading) { let headingText = ""; let intermediateText = ""; let accordion = paragraphElement.closest(ACCORDION_ROOT_SELECTOR); if (accordion) { let headingElement = accordion.querySelector(ACCORDION_HEADING_SELECTOR); if (headingElement) { headingText = `<strong><u>${headingElement.innerText.trim()}</u></strong>`.trim(); } let intermediateElement = accordion.querySelector(ACCORDION_BODY_SELECTOR); if (intermediateElement) { intermediateText = intermediateElement.innerText.trim(); } if (headingText) { let prefix = headingText + ':\n'; if (intermediateText) { prefix += intermediateText + '\n'; } paragraphText = prefix + paragraphText; } } } return paragraphText; } // Adds a copy button next to the "Disclaimer" button function addCopyButton() { let targetButton = findDisclaimerButton(); if (!targetButton) { return; } if (document.querySelector('#custom-copy-button')) { return; } let copyButton = document.createElement('button'); copyButton.id = 'custom-copy-button'; copyButton.className = COPY_BUTTON_CLASS; copyButton.style.marginLeft = '10px'; copyButton.style.color = 'black'; copyButton.title = "Copy Text"; copyButton.textContent = "Copy"; targetButton.parentNode.insertBefore(copyButton, targetButton.nextSibling); copyButton.addEventListener('click', (event) => { console.log("Copy button clicked!"); copyButton.textContent = "Coping"; expandSections(); setTimeout(() => { let copiedText = extractAllText(); copyToClipboard(copiedText); copyButton.textContent = "Copy"; }, 1500); }); } // Extracts formatted text from all paragraphs function extractAllText() { let paragraphs = document.querySelectorAll(PARAGRAPH_SELECTOR); let copiedText = ""; paragraphs = Array.from(paragraphs).slice(0, -1); // Loại bỏ phần tử cuối paragraphs.forEach(paragraph => { let processedText = processText(paragraph, true); copiedText += processedText + '\n\n'; }); return copiedText; } // Handles double-click event to copy individual paragraph function handleDoubleClick(event) { const targetDiv = event.target.closest(PARAGRAPH_SELECTOR); if (!targetDiv) return; let accordion = targetDiv.closest(ACCORDION_ROOT_SELECTOR); if (accordion) { let button = accordion.querySelector(ACCORDION_SUMMARY_SELECTOR); if (button) { button.click(); } } setTimeout(() => { let textContent = processText(targetDiv, true); copyToClipboard(textContent); showNotification(event.pageX, event.pageY); }, 500); } // Initialize both features function initialize() { const observer = new MutationObserver(() => { addCopyButton(); }); observer.observe(document.body, { childList: true, subtree: true }); document.body.addEventListener('dblclick', handleDoubleClick); setTimeout(addCopyButton, 2000); } initialize(); })();