您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Быстрое копирование описяния продукта на 3D Маркетплейсах.
// ==UserScript== // @name Click-to-Copy Ultimate Pro // @namespace http://tampermonkey.net/ // @version 24.1 // @description Быстрое копирование описяния продукта на 3D Маркетплейсах. // @author Bogus // @match *://*/* // @grant GM_setClipboard // @grant GM_addStyle // ==/UserScript== (function() { 'use strict'; // --- НАСТРОЙКИ --- const configurations = [ { container: '.description .std', blocks: 'p', needsPreprocessing: false }, { container: '.prodInfo', blocks: 'span', needsPreprocessing: true }, { container: '#description', blocks: 'span', needsPreprocessing: true }, { container: '.data_for_whats_included', blocks: 'li', needsPreprocessing: false } ]; const defaultClickAction = 'copyAll'; // 'copyOne' или 'copyAll' // Список точных фраз для исключения. const excludedPhrases = [ "Please see each product's page for details.", "See each product page for details." ]; // --- КОНЕЦ НАСТРОЕК --- let cumulativeClipboardText = ''; GM_addStyle(` .tm-highlight-copy { background-color: #e6f7ff !important; outline: 1px solid #91d5ff !important; transition: all 0.2s ease-out; } .tm-flash-clear { background-color: #fff1f0 !important; outline: 2px solid #ffccc7 !important; transition: all 0.1s ease-in; } .tm-flash-copy-all { background-color: #e6f7ff !important; outline: 2px solid #91d5ff !important; transition: all 0.1s ease-in; } ${configurations.map(c => c.container).join(', ')} { cursor: copy; } .tm-preprocessed span { display: block !important; margin-bottom: 1em; } `); // --- УЛУЧШЕННАЯ ФУНКЦИЯ ФИЛЬТРАЦИИ --- const filterText = (text) => { if (!text) return null; const trimmedText = text.trim(); // 1. НОВОЕ ПРАВИЛО: Проверяем, начинается ли строка со звездочки. if (trimmedText.startsWith('*')) { console.log(`Фильтрация (по правилу '*'): Абзац "${trimmedText}" был исключен.`); return null; } // 2. СТАРОЕ ПРАВИЛО: Проверяем на полное совпадение с фразами из списка. const lowercasedText = trimmedText.toLowerCase(); const lowercasedExclusions = excludedPhrases.map(p => p.toLowerCase()); if (lowercasedExclusions.includes(lowercasedText)) { console.log(`Фильтрация (по списку): Абзац "${trimmedText}" был исключен.`); return null; } // Если все проверки пройдены, возвращаем оригинальный текст. return text; }; const clearBuffer = (targetElement) => { cumulativeClipboardText = ''; GM_setClipboard(''); targetElement.classList.add('tm-flash-clear'); setTimeout(() => targetElement.classList.remove('tm-flash-clear'), 500); }; const copyAllParagraphs = (targetElement, blockSelector) => { const allTextElements = targetElement.querySelectorAll(blockSelector); if (allTextElements.length === 0) return; const texts = Array.from(allTextElements) .map(el => filterText(el.textContent)) .filter(Boolean) .map(text => text.trim()); if (texts.length === 0) { console.log("Все абзацы были отфильтрованы."); return; } cumulativeClipboardText = texts.join('\n\n'); GM_setClipboard(cumulativeClipboardText); targetElement.classList.add('tm-flash-copy-all'); setTimeout(() => targetElement.classList.remove('tm-flash-copy-all'), 500); }; const copyOneParagraph = (clickedBlock) => { const paragraphText = filterText(clickedBlock.textContent); if (!paragraphText) return; const trimmedText = paragraphText.trim(); cumulativeClipboardText = cumulativeClipboardText === '' ? trimmedText : cumulativeClipboardText + '\n\n' + trimmedText; GM_setClipboard(cumulativeClipboardText); clickedBlock.classList.add('tm-highlight-copy'); setTimeout(() => clickedBlock.classList.remove('tm-highlight-copy'), 500); }; const preprocessContainer = (containerElement) => { containerElement.classList.add('tm-preprocessed'); let html = containerElement.innerHTML; const separator = '{{TM_PARAGRAPH_BREAK}}'; html = html.replace(/<br\s*\/?>\s*<br\s*\/?>/gi, separator); const htmlParagraphs = html.split(separator); containerElement.innerHTML = ''; htmlParagraphs.forEach(p_html => { const p_with_newlines = p_html.replace(/<br\s*\/?>/gi, '\n'); const tempDiv = document.createElement('div'); tempDiv.innerHTML = p_with_newlines; const cleanText = (tempDiv.textContent || tempDiv.innerText || '').trim(); if (cleanText) { const span = document.createElement('span'); span.textContent = cleanText; containerElement.appendChild(span); } }); }; const attachListeners = (containerElement, finalBlockSelector) => { containerElement.addEventListener('click', (event) => { event.preventDefault(); event.stopPropagation(); const copyOneAction = () => { const clickedBlock = event.target.closest(finalBlockSelector); if (clickedBlock && containerElement.contains(clickedBlock)) { copyOneParagraph(clickedBlock); } }; const copyAllAction = () => copyAllParagraphs(containerElement, finalBlockSelector); if (event.ctrlKey) { (defaultClickAction === 'copyAll') ? copyOneAction() : copyAllAction(); } else { (defaultClickAction === 'copyAll') ? copyAllAction() : copyOneAction(); } }); containerElement.addEventListener('contextmenu', (event) => { event.preventDefault(); event.stopPropagation(); clearBuffer(containerElement); }); }; function initialize() { for (const config of configurations) { const containerElement = document.querySelector(config.container); if (containerElement) { let finalBlockSelector = config.blocks; if (config.needsPreprocessing) { setTimeout(() => { preprocessContainer(containerElement); finalBlockSelector = 'span'; attachListeners(containerElement, finalBlockSelector); }, 500); } else { attachListeners(containerElement, finalBlockSelector); } } } } initialize(); })();