codewithcopy.html 3.0 KB

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