Copy NeetCode

Adds a copy button to copy content from neetcode.io

当前为 2024-10-23 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Copy NeetCode
  3. // @namespace tzway
  4. // @version 0.1
  5. // @description Adds a copy button to copy content from neetcode.io
  6. // @author tzway
  7. // @match https://neetcode.io/problems/*
  8. // @grant none
  9. // @run-at document-idle
  10. // ==/UserScript==
  11.  
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. // Function to copy formatted content excluding buttons with class 'copy-to-clipboard-button'
  17. function copyToClipboard(button) {
  18. const contentElement = document.querySelector('.my-article-component-container');
  19.  
  20. // Create a deep clone of the content to avoid modifying the original element
  21. const contentClone = contentElement.cloneNode(true);
  22.  
  23. // Remove all elements with the class 'copy-to-clipboard-button'
  24. const buttonsToExclude = contentClone.querySelectorAll('.copy-to-clipboard-button');
  25. buttonsToExclude.forEach(button => button.remove());
  26.  
  27. // Create a temporary container to hold the cleaned content
  28. const tempDiv = document.createElement('div');
  29. tempDiv.appendChild(contentClone);
  30.  
  31. // Copy the cleaned HTML content to the clipboard
  32. navigator.clipboard.write([
  33. new ClipboardItem({
  34. 'text/html': new Blob([tempDiv.innerHTML], { type: 'text/html' }),
  35. 'text/plain': new Blob([tempDiv.innerText], { type: 'text/plain' })
  36. })
  37. ]).then(() => {
  38. // Provide non-intrusive feedback
  39. button.innerText = 'Copied!'; // Change button text
  40. button.style.backgroundColor = '#4caf50'; // Optional: Change color to indicate success
  41.  
  42. // Revert back to original after 2 seconds
  43. setTimeout(() => {
  44. button.innerText = 'Copy Content';
  45. button.style.backgroundColor = ''; // Revert color
  46. }, 1000);
  47. }).catch(err => {
  48. console.error('Failed to copy: ', err);
  49. });
  50. }
  51.  
  52. // Function to add the copy button
  53. function addButton(targetElement) {
  54. // Check if the button already exists to prevent adding duplicates
  55. if (targetElement.querySelector('.copy-to-clipboard-button')) return;
  56.  
  57. const button = document.createElement('button');
  58. button.classList.add('copy-to-clipboard-button');
  59. button.innerText = 'Copy Content';
  60. button.style.marginLeft = 'auto'; // Align to the right
  61. button.style.display = 'inline-block';
  62.  
  63. // Set the parent container to flex to align the button to the right
  64. targetElement.style.display = 'flex';
  65. targetElement.style.alignItems = 'center'; // Align content vertically
  66. targetElement.appendChild(button);
  67.  
  68. // Add the event listener to the button
  69. button.addEventListener('click', () => copyToClipboard(button));
  70. }
  71.  
  72. // Function to observe changes in the DOM and reapply the button
  73. function observePage() {
  74. const targetNode = document.body;
  75.  
  76. // Options for the observer (which mutations to observe)
  77. const config = { childList: true, subtree: true };
  78.  
  79. // Callback function to execute when mutations are observed
  80. const callback = function(mutationsList, observer) {
  81. for (let mutation of mutationsList) {
  82. if (mutation.type === 'childList') {
  83. // Re-add the button if the target element is found
  84. const targetElement = document.querySelector('.question-tab > div:nth-child(1) > div:nth-child(1)');
  85. if (targetElement) {
  86. addButton(targetElement);
  87. }
  88. }
  89. }
  90. };
  91.  
  92. // Create an observer instance linked to the callback function
  93. const observer = new MutationObserver(callback);
  94.  
  95. // Start observing the target node for configured mutations
  96. observer.observe(targetNode, config);
  97. }
  98.  
  99. // Initialize observation of the page
  100. observePage();
  101.  
  102. })();