Copy NeetCode

Adds a copy button to copy content from neetcode.io

Versión del día 23/10/2024. Echa un vistazo a la versión más reciente.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         Copy NeetCode
// @namespace    tzway
// @version      0.1
// @description  Adds a copy button to copy content from neetcode.io
// @author       tzway
// @license     GPL-3.0-or-later; https://www.gnu.org/licenses/gpl-3.0-standalone.html
// @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();

})();