Copy NeetCode

Adds a copy button to copy content from neetcode.io

Versão de: 23/10/2024. Veja: a última versão.

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==UserScript==
// @name         Copy NeetCode
// @namespace    tzway
// @version      0.1
// @description  Adds a copy button to copy content from neetcode.io
// @author       tzway
// @match        https://neetcode.io/problems/*
// @grant        none
// @run-at document-idle
// ==/UserScript==


(function() {
    'use strict';

    // Function to copy formatted content excluding buttons with class 'copy-to-clipboard-button'
    function copyToClipboard(button) {
        const contentElement = document.querySelector('.my-article-component-container');

        // Create a deep clone of the content to avoid modifying the original element
        const contentClone = contentElement.cloneNode(true);

        // Remove all elements with the class 'copy-to-clipboard-button'
        const buttonsToExclude = contentClone.querySelectorAll('.copy-to-clipboard-button');
        buttonsToExclude.forEach(button => button.remove());

        // Create a temporary container to hold the cleaned content
        const tempDiv = document.createElement('div');
        tempDiv.appendChild(contentClone);

        // Copy the cleaned HTML content to the clipboard
        navigator.clipboard.write([
            new ClipboardItem({
                'text/html': new Blob([tempDiv.innerHTML], { type: 'text/html' }),
                'text/plain': new Blob([tempDiv.innerText], { type: 'text/plain' })
            })
        ]).then(() => {
            // Provide non-intrusive feedback
            button.innerText = 'Copied!'; // Change button text
            button.style.backgroundColor = '#4caf50'; // Optional: Change color to indicate success

            // Revert back to original after 2 seconds
            setTimeout(() => {
                button.innerText = 'Copy Content';
                button.style.backgroundColor = ''; // Revert color
            }, 1000);
        }).catch(err => {
            console.error('Failed to copy: ', err);
        });
    }

    // Function to add the copy button
    function addButton(targetElement) {
        // Check if the button already exists to prevent adding duplicates
        if (targetElement.querySelector('.copy-to-clipboard-button')) return;

        const button = document.createElement('button');
        button.classList.add('copy-to-clipboard-button');
        button.innerText = 'Copy Content';
        button.style.marginLeft = 'auto'; // Align to the right
        button.style.display = 'inline-block';

        // Set the parent container to flex to align the button to the right
        targetElement.style.display = 'flex';
        targetElement.style.alignItems = 'center'; // Align content vertically
        targetElement.appendChild(button);

        // Add the event listener to the button
        button.addEventListener('click', () => copyToClipboard(button));
    }

    // Function to observe changes in the DOM and reapply the button
    function observePage() {
        const targetNode = document.body;

        // Options for the observer (which mutations to observe)
        const config = { childList: true, subtree: true };

        // Callback function to execute when mutations are observed
        const callback = function(mutationsList, observer) {
            for (let mutation of mutationsList) {
                if (mutation.type === 'childList') {
                    // Re-add the button if the target element is found
                    const targetElement = document.querySelector('.question-tab > div:nth-child(1) > div:nth-child(1)');
                    if (targetElement) {
                        addButton(targetElement);
                    }
                }
            }
        };

        // Create an observer instance linked to the callback function
        const observer = new MutationObserver(callback);

        // Start observing the target node for configured mutations
        observer.observe(targetNode, config);
    }

    // Initialize observation of the page
    observePage();

})();