TomatoMTL Auto Copy Cleaner (Button Fix)

Automatically removes boilerplate when copying text via button or selection on tomatomtl.com.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         TomatoMTL Auto Copy Cleaner (Button Fix)
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Automatically removes boilerplate when copying text via button or selection on tomatomtl.com.
// @author       tertium
// @match        *://tomatomtl.com/*
// @license      MIT
// @grant        unsafeWindow
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // Use unsafeWindow to access the page's native navigator object
    const realNavigator = typeof unsafeWindow !== 'undefined' ? unsafeWindow.navigator : window.navigator;

    if (!realNavigator.clipboard || !realNavigator.clipboard.writeText) {
        console.warn('TomatoMTL Cleaner: navigator.clipboard.writeText is not available. Script cannot function.');
        return;
    }

    // --- Your Cleaning Logic ---
    const boilerplateRegex = /TomatoMTL – Simple MTL Reading Assist Tool[\s\S]*?URL: [\s\S]*(?=\n|$)/g;
    const extraNewlinesRegex = /\n{3,}/g;

    function cleanText(text) {
        if (typeof text !== 'string') {
            return text; // Don't process non-strings
        }
        console.log("Original text length:", text.length); // Debug: See original
        let cleaned = text.replace(boilerplateRegex, '').replace(extraNewlinesRegex, '\n\n').trim();
        console.log("Cleaned text length:", cleaned.length); // Debug: See cleaned
        // Debug: Check if cleaning actually happened
        // if (text.length !== cleaned.length) {
        //    console.log("TomatoMTL Cleaner: Text was modified.");
        // } else {
        //     console.log("TomatoMTL Cleaner: Text was NOT modified (boilerplate likely not found).");
        // }
        return cleaned;
    }
    // --- End Cleaning Logic ---


    // --- Intercept clipboard.writeText ---

    // Store the original function safely, ensuring 'this' context is preserved
    const originalWriteText = realNavigator.clipboard.writeText.bind(realNavigator.clipboard);

    // Create our wrapper function
    const modifiedWriteText = async function(text) {
        // console.log('TomatoMTL Cleaner: Intercepting writeText...'); // Debug
        const cleanedText = cleanText(text);
        // Call the original function with the cleaned text
        return originalWriteText(cleanedText);
    };

    // Replace the original function with our modified one
    // We need to make the property writable first on some browsers/strict modes
    try {
         Object.defineProperty(realNavigator.clipboard, 'writeText', {
             value: modifiedWriteText,
             writable: true, // Keep it potentially replaceable by other scripts if needed
             configurable: true,
         });
         console.log('TomatoMTL Cleaner: Successfully intercepted navigator.clipboard.writeText.');
    } catch (e) {
        console.error('TomatoMTL Cleaner: Failed to intercept navigator.clipboard.writeText.', e);
         // Fallback attempt (less robust)
         try {
              realNavigator.clipboard.writeText = modifiedWriteText;
              console.log('TomatoMTL Cleaner: Successfully intercepted navigator.clipboard.writeText (fallback method).');
         } catch (e2) {
               console.error('TomatoMTL Cleaner: Fallback interception failed too.', e2);
         }
    }


    // --- Optional: Also keep the 'copy' event listener as a fallback/complement ---
    // This might help if some copy actions DON'T use writeText, though less likely for custom buttons.
    document.addEventListener('copy', function(event) {
        const selectedText = unsafeWindow.getSelection().toString(); // Use unsafeWindow here too
        if (selectedText) {
            const cleanedSelectedText = cleanText(selectedText);
            // Only intervene if cleaning actually changed something OR if clipboardData is available
            if (cleanedSelectedText !== selectedText && event.clipboardData) {
                event.preventDefault();
                event.clipboardData.setData('text/plain', cleanedSelectedText);
                // console.log('TomatoMTL Cleaner: Cleaned text via "copy" event.'); // Debug
            }
        }
    }, true); // Use capture phase


    // console.log('TomatoMTL Auto Copy Cleaner (Button Fix) script loaded.'); // Debug

})();