Copy Code in Code Block Footer

Duplicate the header of code blocks as a footer to give a second copy code button

  1. // ==UserScript==
  2. // @name Copy Code in Code Block Footer
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0
  5. // @description Duplicate the header of code blocks as a footer to give a second copy code button
  6. // @author Gavin Trutzenbach / @gaveroid
  7. // @match https://chat.openai.com/*
  8. // ==/UserScript==
  9.  
  10. (function() {
  11. 'use strict';
  12.  
  13. // Helper function to copy text to clipboard
  14. function copyToClipboard(text) {
  15. var dummy = document.createElement("textarea");
  16. document.body.appendChild(dummy);
  17. dummy.value = text;
  18. dummy.select();
  19. document.execCommand("copy");
  20. document.body.removeChild(dummy);
  21. }
  22.  
  23. // Function to process code blocks
  24. function processCodeBlocks() {
  25. var codeBlocks = document.querySelectorAll('div[class^="bg-black"]');
  26. codeBlocks.forEach(function(codeBlock) {
  27. var headerDiv = codeBlock.querySelector('div[class^="flex items-center"]');
  28. if (headerDiv && !codeBlock.querySelector('.duplicated-footer')) {
  29. var footerDiv = headerDiv.cloneNode(true);
  30. footerDiv.classList.add('duplicated-footer');
  31. codeBlock.appendChild(footerDiv);
  32.  
  33. // Update copy button function
  34. var updateCopyButtonFunction = function(button) {
  35. var originalInnerHTML = button.innerHTML; // Store the original inner HTML
  36. var copyFunction = function() {
  37. var codeText = codeBlock.querySelector('code').innerText;
  38. copyToClipboard(codeText);
  39. this.innerHTML = '✔ Copied!'; // ASCII icon for checkmark
  40. var btn = this;
  41. setTimeout(function() {
  42. btn.innerHTML = originalInnerHTML; // Revert to original inner HTML
  43. }, 3000); // Revert back after 3 seconds
  44. };
  45. button.removeEventListener('click', copyFunction); // Remove old event listener
  46. button.addEventListener('click', copyFunction); // Add new event listener
  47. };
  48.  
  49. // Update copy buttons in header and footer
  50. var copyButtonHeader = headerDiv.querySelector('button');
  51. var copyButtonFooter = footerDiv.querySelector('button');
  52. updateCopyButtonFunction(copyButtonHeader);
  53. updateCopyButtonFunction(copyButtonFooter);
  54. }
  55. });
  56. }
  57.  
  58. // Create a MutationObserver to monitor the DOM for changes
  59. var observer = new MutationObserver(function(mutationsList, observer) {
  60. processCodeBlocks();
  61. });
  62.  
  63. // Start observing the document with the configured parameters
  64. observer.observe(document, { childList: true, subtree: true });
  65. })();