ChatGPT Template Text Buttons

Adds buttons to ChatGPT text inputs to paste predefined templates.

目前為 2024-12-04 提交的版本,檢視 最新版本

// ==UserScript==
// @name         ChatGPT Template Text Buttons
// @namespace    https://chatgpt.com/
// @version      1.0
// @description  Adds buttons to ChatGPT text inputs to paste predefined templates.
// @author       63OR63
// @license      MIT
// @match        https://chatgpt.com/*
// @icon         data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZpZXdCb3g9IjAgMCAyNDA2IDI0MDYiPjxjaXJjbGUgY3g9IjEyMDMiIGN5PSIxMjAzIiByPSIxMjAzIiBmaWxsPSIjNzRhYTljIi8+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTIwNjcgMTAxOGMxMC0xNTktNzYtMzIzLTIwOC00MDdhNDYzIDQ2MyAwIDAgMC0zODQtMjQ4IDQ2MiA0NjIgMCAwIDAtNDU3LTI0IDQ2MyA0NjMgMCAwIDAtNDA3IDIwOCA0NjMgNDYzIDAgMCAwLTI0OCAzODQgNDYyIDQ2MiAwIDAgMC0yNCA0NTcgNDYzIDQ2MyAwIDAgMCAyMDggNDA3IDQ2MyA0NjMgMCAwIDAgMzg0IDI0OGMxMzQgODkgMzE4IDk3IDQ1NyAyNCAxNTkgOSAzMjMtNzYgNDA3LTIwOGE0NjMgNDYzIDAgMCAwIDI0OC0zODRjODktMTMzIDk3LTMxOCAyNC00NTd6bS00NTYgMzQwLTM5IDE0My02Ni0yNDggMTA1IDEwNXptLTEzMiAxODMtMTA1IDEwNSA2Ni0yNDggMzkgMTQzem0tNjg0LTQ5MyAzOS0xNDMgNjYgMjQ4LTEwNS0xMDV6bTEzMi0xODMgMTA1LTEwNS02NiAyNDgtMzktMTQzem00NjEgMzM4LTI0IDkzLTY4IDY4LTkzIDI0LTkzLTI0LTY4LTY4LTI0LTkzIDI0LTkzIDY4LTY4IDkzLTI0IDkzIDI0IDY4IDY4IDI0IDkzem0tMjU1LTQzMCAxNDMtMzktMTgxIDE4MiAzOC0xNDN6bS0zNjAgNTAwLTM5LTE0MyAxODIgMTgxLTE0My0zOHptOTIgMjA2LTEwNS0xMDUgMjQ4IDY2LTE0MyAzOXptMTgzIDEzMi0xNDMtMzkgMjQ4LTY2LTEwNSAxMDV6bTIyNSAyMi0xNDMgMzkgMTgxLTE4Mi0zOCAxNDN6bTM2MC01MDAgMzkgMTQzLTE4Mi0xODEgMTQzIDM4em0tOTItMjA2IDEwNSAxMDUtMjQ4LTY2IDE0My0zOXptLTE4My0xMzIgMTQzIDM5LTI0OCA2NiAxMDUtMTA1em0tMjExLTE0OWM0NS00NSAxMDAtMTA4IDE1OS0xMzMgNDEtMjAgODUtMzEgMTMwLTMzIDI1IDIwIDQ4IDQ0IDY3IDcwbC0zNTYgOTZ6bTExMiAxMTE1Yy00NSA0NC0xMDAgMTA3LTE1OSAxMzItNDEgMjAtODUgMzEtMTMwIDMzLTI1LTIwLTQ4LTQ0LTY3LTcwbDM1Ni05NXptNjU5LTYyNS0yNjAtMjYwYzYxIDE3IDE0MiAzMiAxOTQgNzEgMzggMjYgNjkgNTkgOTMgOTctNCAzMS0xMyA2Mi0yNyA5MnptLTEyOS0zNDgtMzU2LTk2YzYyLTE2IDE0MC00MyAyMDQtMzUgNDYgMyA4OSAxNiAxMjkgMzcgMTIgMzAgMjAgNjEgMjMgOTR6bS02NTMtMzAwTDg3NiA3NDhjMTctNjEgMzItMTQyIDcxLTE5NCAyNi0zOCA1OS02OSA5Ny05MyAzMSA0IDYyIDEzIDkyIDI3ek03ODggNjE3bC05NiAzNTZjLTE2LTYyLTQzLTE0MC0zNS0yMDQgMy00NSAxNi04OSAzNy0xMjkgMzAtMTIgNjEtMjAgOTQtMjN6TTU1MCA5MDNsOTYgMzU2Yy00NS00NS0xMDgtOTktMTMzLTE1OS0yMC00MS0zMS04NS0zMy0xMzAgMjAtMjUgNDQtNDggNzAtNjd6bS02MiAzNjcgMjYwIDI2MGMtNjEtMTctMTQyLTMyLTE5NC03MS0zOC0yNi02OS01OS05My05NyA0LTMxIDEzLTYyIDI3LTkyem0xMjkgMzQ5IDM1NiA5NWMtNjIgMTYtMTQwIDQzLTIwNCAzNS00NS0zLTg5LTE2LTEyOS0zNy0xMi0yOS0yMC02MS0yMy05M3ptNjUzIDI5OSAyNjAtMjYwYy0xNyA2MS0zMiAxNDItNzEgMTk0LTI2IDM4LTU5IDY5LTk3IDkzLTMxLTQtNjItMTMtOTItMjd6bTM0OS0xMjkgOTUtMzU2YzE2IDYyIDQzIDE0MCAzNSAyMDQtMyA0Ni0xNiA4OS0zNyAxMjktMjkgMTItNjEgMjAtOTMgMjN6bTIzNy0yODYtOTYtMzU2YzQ1IDQ1IDEwOCA5OSAxMzMgMTU5IDIwIDQxIDMxIDg1IDMzIDEzMC0yMCAyNS00NCA0OC03MCA2N3oiLz48L3N2Zz4=
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    // Button definitions: { button_name: { text: "pasted_text", color: "color_code" } }
    const buttonDefinitions = {
        Refactor: {
            text: `Refactor the following code to improve efficiency or readability without altering its functionality:
\`\`\`
{clipboard}
\`\`\`
Do not explain the code in your response.
`,
            color: "#FFC1CC", // Pastel pink
        },
        Fix: {
            text: `Fix any errors in the following code without changing its core functionality:
\`\`\`
{clipboard}
\`\`\`
Explain the fixes you made by comments in the code's body and give a laconic explanation after.
`,
            color: "#FFDDC1", // Pastel peach
        },
        Explain: {
            text: `Explain the following code concisely:
\`\`\`
{clipboard}
\`\`\`
Focus on key functionality and purpose.
`,
            color: "#FFEBCC", // Pastel yellow
        },
        Review: {
            text: `You are a highly skilled software engineer specializing in code reviews.
Review the following code:
\`\`\`
{clipboard}
\`\`\`
Ensure your feedback is constructive and professional.
Propose improvements with concise explanation.
Reference to guidelines and known best practices where applicable.
`,
            color: "#E6E0FF", // Pastel lavender
        },
        Docs: {
            text: `Generate comprehensive documentation for the following code:
\`\`\`
{clipboard}
\`\`\`
Use the standard documentation format for the provided language. If unsure, use a widely accepted format.
Do not explain the changes in your response.
Do not refactor the code.
`,
            color: "#D8F3DC", // Pastel mint green
        },
        Template: {
            text: `
\`\`\`
{clipboard}
\`\`\`
    `,
            color: "#D1E7FF", // Pastel blue
        },
    };

    // Create buttons for a textarea's parent container
    const createButtonsForTextarea = (textarea) => {
        const buttonContainer = document.createElement('div');
        buttonContainer.style.display = 'flex';
        buttonContainer.style.flexDirection = 'row';
        buttonContainer.style.gap = '10px'; // gap between buttons
        buttonContainer.style.marginTop = '12px'; // margin below the textarea
        buttonContainer.style.alignItems = 'center';

        Object.entries(buttonDefinitions).forEach(([name, config]) => {
            const button = document.createElement('button');
            button.innerText = name;
            button.type = 'button';
            button.style.backgroundColor = config.color;
            button.style.color = '#333';
            button.style.border = 'none';
            button.style.borderRadius = '5px';
            button.style.padding = '3px 8px';
            button.style.cursor = 'pointer';
            button.style.fontSize = '14px';
            button.style.transition = 'none';

            // Add effect when button is pressed
            button.addEventListener('mousedown', () => {
                button.style.transform = 'scale(0.95)';
            });
            button.addEventListener('mouseup', () => {
                button.style.transform = 'scale(1)';
            });
            button.addEventListener('mouseleave', () => {
                button.style.transform = 'scale(1)';
            });

            // Add click event to paste text
            button.addEventListener('mousedown', async (e) => {
                e.preventDefault(); // Prevent losing focus on the currently focused element
                e.stopPropagation(); // Stop the event from propagating further

                const focusedElement = document.activeElement; // Save the currently focused element
                const promptTextarea = document.getElementById('prompt-textarea');

                // Read clipboard content
                let clipboardText = '';
                try {
                    clipboardText = await navigator.clipboard.readText();
                } catch (err) {
                    console.error("Clipboard access failed:", err);
                    return;
                }

                // Replace the placeholder with clipboard content
                const finalText = config.text.replace("{clipboard}", clipboardText);

                if (promptTextarea === focusedElement) {
                    // Paste into the focused "prompt-textarea"
                    const lines = finalText.split(/\r?\n/); // Split finalText into lines by newlines
                    lines.forEach(line => {
                        const paragraph = document.createElement('p'); // Create a new <p> element
                        paragraph.textContent = line; // Set the text content of the <p> element to the line
                        promptTextarea.appendChild(paragraph); // Append the <p> element to promptTextarea
                    });

                } else if (focusedElement && focusedElement.tagName === 'TEXTAREA') {
                    // Use setRangeText to ensure persistence and proper event firing
                    const cursorPosition = focusedElement.selectionStart || focusedElement.value.length;
                    focusedElement.setRangeText(finalText, cursorPosition, cursorPosition, "end");

                    // Trigger events to simulate manual entry
                    focusedElement.dispatchEvent(new Event('input', { bubbles: true }));
                }
            });

            buttonContainer.appendChild(button);
        });

        return buttonContainer;
    };

    // Attach buttons to all relevant textareas
    const attachButtons = () => {
        const main = document.querySelector('main');
        if (!main) return;

        const textareas = main.querySelectorAll('textarea');
        textareas.forEach((textarea) => {
            const parent = textarea.parentElement;
            if (!parent.querySelector('.button-container')) {
                const buttonContainer = createButtonsForTextarea(textarea);
                buttonContainer.classList.add('button-container');
                parent.appendChild(buttonContainer);
            }
        });
    };

    // Observe the DOM for dynamically added textareas
    const observer = new MutationObserver(() => {
        attachButtons();
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true,
    });

    // Initial attachment
    attachButtons();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址