Copy Button for Code Blocks on Azure DevOps

Add a copy button for every code highlighting block in Markdown on Azure DevOps

  1. // ==UserScript==
  2. // @name Copy Button for Code Blocks on Azure DevOps
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.3
  5. // @description Add a copy button for every code highlighting block in Markdown on Azure DevOps
  6. // @author You
  7. // @match https://dev.azure.com/*
  8. // @grant none
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. function addCopyButtonToCodeBlock(codeBlock) {
  16. const copyButton = document.createElement('button');
  17. copyButton.className = 'copy-btn';
  18.  
  19. // Use the Fluent "Copy" icon
  20. copyButton.innerHTML = '<span aria-hidden="true" class="type-icon fontSizeML flex-noshrink fabric-icon ms-Icon--Copy"></span> <span style="vertical-align: middle;">Copy</span>';
  21.  
  22. copyButton.onclick = function () {
  23. copyToClipboard(codeBlock.innerText);
  24. };
  25.  
  26. // Modern styling
  27. copyButton.style.backgroundColor = '#007acc'; // Azure DevOps color
  28. copyButton.style.border = 'none';
  29. copyButton.style.color = '#fff';
  30. copyButton.style.padding = '8px';
  31. copyButton.style.borderRadius = '4px';
  32. copyButton.style.cursor = 'pointer';
  33. copyButton.style.display = 'flex'; // Use flexbox for centering
  34.  
  35. // Align items vertically in the center
  36. copyButton.style.alignItems = 'center';
  37.  
  38. // Position the button at the top right of the code block
  39. copyButton.style.position = 'absolute';
  40. copyButton.style.top = '8px';
  41. copyButton.style.right = '8px';
  42.  
  43. codeBlock.parentNode.style.position = 'relative'; // Ensure the parent has a relative position
  44.  
  45. codeBlock.parentNode.insertBefore(copyButton, codeBlock);
  46.  
  47. // Add some padding to the code block to prevent overlap with the button
  48. codeBlock.style.paddingTop = '30px';
  49. }
  50.  
  51. // Function to copy text to clipboard
  52. function copyToClipboard(text) {
  53. const textArea = document.createElement('textarea');
  54. textArea.value = text;
  55. document.body.appendChild(textArea);
  56. textArea.select();
  57. document.execCommand('copy');
  58. document.body.removeChild(textArea);
  59. alert('Code copied to clipboard!');
  60. }
  61.  
  62. function processCodeBlocks() {
  63. const codeBlocks = document.querySelectorAll('pre code:not(.copy-processed)');
  64. codeBlocks.forEach((codeBlock) => {
  65. addCopyButtonToCodeBlock(codeBlock);
  66. codeBlock.classList.add('copy-processed');
  67. });
  68. }
  69.  
  70. // Observe changes to the DOM and add copy buttons when code blocks are added
  71. const observer = new MutationObserver(processCodeBlocks);
  72. const config = { childList: true, subtree: true };
  73. observer.observe(document.body, config);
  74.  
  75. // Add copy buttons for code blocks on initial script execution
  76. processCodeBlocks();
  77. })();