| 1 | <!doctype html> |
| 2 | <html lang="en"> |
| 3 | <head> |
| 4 | <meta charset="UTF-8" /> |
| 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
| 6 | <link rel="stylesheet" href="/static/styles.css" /> |
| 7 | <meta name="theme-color" content="#121113" /> |
| 8 | <link rel="apple-touch-icon" sizes="180x180" href="/assets/apple-touch-icon.png"> |
| 9 | <link rel="icon" type="image/png" sizes="32x32" href="/assets/favicon-32x32.png"> |
| 10 | <link rel="icon" type="image/png" sizes="16x16" href="/assets/favicon-16x16.png"> |
| 11 | <link rel="manifest" href="/assets/site.webmanifest"> |
| 12 | |
| 13 | <title>Sipp | {{ name }}</title> |
| 14 | <meta name="description" content="Minimal Code Sharing"> |
| 15 | |
| 16 | <meta property="og:url" content="https://sipp.so"> |
| 17 | <meta property="og:type" content="website"> |
| 18 | <meta property="og:title" content="Sipp | {{ name }}"> |
| 19 | <meta property="og:description" content="Minimal Code Sharing"> |
| 20 | <meta property="og:image" content="https://sipp.so/assets/og.png"> |
| 21 | |
| 22 | <meta name="twitter:card" content="summary_large_image"> |
| 23 | <meta property="twitter:domain" content="sipp.so"> |
| 24 | <meta property="twitter:url" content="https://sipp.so"> |
| 25 | <meta name="twitter:title" content="Sipp | {{ name }}"> |
| 26 | <meta name="twitter:description" content="Minimal Code Sharing"> |
| 27 | <meta name="twitter:image" content="https://sipp.so/assets/og.png"> |
| 28 | |
| 29 | </head> |
| 30 | <body> |
| 31 | <a href="/" class="header"> |
| 32 | <h1>SIPP</h1> |
| 33 | </a> |
| 34 | <div class="links"> |
| 35 | <a target="_blank" href="https://github.com/stevedylandev/sipp"> |
| 36 | GitHub |
| 37 | </a> |
| 38 | <a href="/about">About</a> |
| 39 | <p>by <a target="_blank" href="https://stevedylan.dev">Steve</a></p> |
| 40 | </div> |
| 41 | |
| 42 | <div id="snippetForm"> |
| 43 | <label id="snippetName">{{ name }}</label> |
| 44 | <div class="code-container">{{ highlighted_content|safe }}</div> |
| 45 | <textarea id="content" style="display:none;">{{ content }}</textarea> |
| 46 | <div class="button-group"> |
| 47 | <button type="button" id="copyLinkBtn" data-original-text="Copy Link">Copy Link</button> |
| 48 | <button type="button" id="copyContentBtn" data-original-text="Copy Content">Copy Content</button> |
| 49 | <button type="button" id="createNewBtn">Create New Snippet</button> |
| 50 | </div> |
| 51 | </div> |
| 52 | |
| 53 | <script> |
| 54 | async function copyToClipboard(text, button) { |
| 55 | try { |
| 56 | await navigator.clipboard.writeText(text); |
| 57 | showButtonFeedback(button, '\u2714 Copied', 'success'); |
| 58 | } catch (error) { |
| 59 | console.error('Copy failed:', error); |
| 60 | showButtonFeedback(button, '\u2718 Failed', 'error'); |
| 61 | |
| 62 | try { |
| 63 | const textArea = document.createElement('textarea'); |
| 64 | textArea.value = text; |
| 65 | textArea.style.position = 'fixed'; |
| 66 | textArea.style.opacity = '0'; |
| 67 | document.body.appendChild(textArea); |
| 68 | textArea.select(); |
| 69 | document.execCommand('copy'); |
| 70 | document.body.removeChild(textArea); |
| 71 | showButtonFeedback(button, '\u2714 Copied', 'success'); |
| 72 | } catch (fallbackError) { |
| 73 | showButtonFeedback(button, '\u2718 Failed', 'error'); |
| 74 | } |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | function showButtonFeedback(button, message, type = 'success') { |
| 79 | const originalText = button.dataset.originalText || button.textContent; |
| 80 | const originalDisabled = button.disabled; |
| 81 | |
| 82 | if (!button.dataset.originalText) { |
| 83 | button.dataset.originalText = originalText; |
| 84 | } |
| 85 | |
| 86 | button.textContent = message; |
| 87 | button.disabled = true; |
| 88 | button.classList.add(`copy-${type}`); |
| 89 | |
| 90 | setTimeout(() => { |
| 91 | button.textContent = originalText; |
| 92 | button.disabled = originalDisabled; |
| 93 | button.classList.remove(`copy-${type}`); |
| 94 | }, 1000); |
| 95 | } |
| 96 | |
| 97 | document.getElementById('copyContentBtn').addEventListener('click', async () => { |
| 98 | const content = document.getElementById('content').value; |
| 99 | const button = document.getElementById('copyContentBtn'); |
| 100 | await copyToClipboard(content, button); |
| 101 | }); |
| 102 | |
| 103 | document.getElementById('copyLinkBtn').addEventListener('click', async () => { |
| 104 | const currentUrl = window.location.href; |
| 105 | const button = document.getElementById('copyLinkBtn'); |
| 106 | await copyToClipboard(currentUrl, button); |
| 107 | }); |
| 108 | |
| 109 | document.getElementById('createNewBtn').addEventListener('click', () => { |
| 110 | window.location.href = '/'; |
| 111 | }); |
| 112 | </script> |
| 113 | </body> |
| 114 | </html> |