Adds a copy button to copy content from neetcode.io
当前为
// ==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();
})();