codewithcopy.html 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. {{ $lang := .Get 0 }}
  2. <style>
  3. .code-block-container {
  4. position: relative;
  5. margin: 1em 0;
  6. }
  7. .code-header {
  8. position: absolute;
  9. top: 8px;
  10. right: 8px;
  11. z-index: 999;
  12. }
  13. .copy-button {
  14. display: inline-flex;
  15. align-items: center;
  16. background: #2d2d2d;
  17. color: white;
  18. border: 1px solid #404040;
  19. border-radius: 4px;
  20. padding: 4px 8px;
  21. font-size: 0.8em;
  22. cursor: pointer;
  23. transition: all 0.2s ease;
  24. }
  25. .copy-button:hover {
  26. background: #404040;
  27. }
  28. .copy-button svg {
  29. width: 14px;
  30. height: 14px;
  31. margin-right: 4px;
  32. }
  33. .tooltip {
  34. position: absolute;
  35. top: -30px;
  36. left: 50%;
  37. transform: translateX(-50%);
  38. background: black;
  39. color: white;
  40. padding: 4px 8px;
  41. border-radius: 4px;
  42. font-size: 12px;
  43. display: none;
  44. }
  45. .tooltip::after {
  46. content: "";
  47. position: absolute;
  48. top: 100%;
  49. left: 50%;
  50. transform: translateX(-50%);
  51. border: 5px solid transparent;
  52. border-top-color: black;
  53. }
  54. .copy-button.copied .tooltip {
  55. display: block;
  56. }
  57. </style>
  58. <div class="code-block-container" data-lang="{{ $lang }}">
  59. <div class="code-header">
  60. <button class="copy-button" onclick="copyCodeBlock(this)" aria-label="Copy code">
  61. <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  62. <path d="M8 4v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.242a2 2 0 0 0-.602-1.43L16.083 2.57A2 2 0 0 0 14.685 2H10a2 2 0 0 0-2 2z"/>
  63. <path d="M16 18v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2"/>
  64. </svg>
  65. <span>Copy</span>
  66. <div class="tooltip">Copied!</div>
  67. </button>
  68. </div>
  69. <div class="code-content">
  70. {{ highlight (trim .Inner "\n") $lang "" }}
  71. </div>
  72. </div>
  73. <script>
  74. function copyCodeBlock(button) {
  75. const container = button.closest('.code-block-container');
  76. const codeContent = container.querySelector('.code-content pre');
  77. const code = codeContent.textContent;
  78. navigator.clipboard.writeText(code.trim()).then(() => {
  79. button.classList.add('copied');
  80. setTimeout(() => {
  81. button.classList.remove('copied');
  82. }, 2000);
  83. }).catch(err => {
  84. console.error('Failed to copy:', err);
  85. // Fallback
  86. const textarea = document.createElement('textarea');
  87. textarea.value = code.trim();
  88. document.body.appendChild(textarea);
  89. textarea.select();
  90. try {
  91. document.execCommand('copy');
  92. button.classList.add('copied');
  93. setTimeout(() => {
  94. button.classList.remove('copied');
  95. }, 2000);
  96. } catch (e) {
  97. console.error('Fallback failed:', e);
  98. }
  99. document.body.removeChild(textarea);
  100. });
  101. }
  102. </script>