templates/snippet.html 5.0 K raw
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>{{ name }} | Sipp</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
    <div class="nav">
32
      <a href="/" class="header">
33
        <h1>SIPP</h1>
34
      </a>
35
36
      <a class="icon" target="_blank" href="https://github.com/stevedylandev/sipp">
37
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
38
          <title>GitHub</title>
39
          <path d="m21.838 11.677l-9.549-9.58c-.129-.13-.451-.13-.645 0L9 4.742l2.452 2.452c.193-.097.419-.13.645-.13c.903 0 1.58.742 1.58 1.581c0 .226-.032.452-.129.645l1.968 1.968c.194-.097.42-.129.645-.129c.904 0 1.58.742 1.58 1.58c0 .904-.741 1.581-1.58 1.581c-.903 0-1.58-.742-1.58-1.58c0-.226.032-.452.129-.646l-1.968-1.967h-.032v3.71c.58.258 1 .806 1 1.483c0 .904-.742 1.581-1.581 1.581c-.903 0-1.58-.742-1.58-1.58c0-.678.419-1.259 1-1.485v-3.612c-.581-.259-1-.807-1-1.484c0-.226.032-.452.128-.645L8.225 5.613l-6.097 6.064c-.129.13-.129.452 0 .646l9.58 9.58c.13.13.452.13.646 0l9.548-9.58a.59.59 0 0 0-.064-.646"/>
40
        </svg>
41
      </a>
42
    </div>
43
44
    <div id="snippetForm">
45
        <label id="snippetName">{{ name }}</label>
46
        <div class="code-container">{{ highlighted_content|safe }}</div>
47
        <textarea id="content" style="display:none;">{{ content }}</textarea>
48
      <div class="button-group">
49
        <button type="button" id="copyLinkBtn" data-original-text="Copy Link">Copy Link</button>
50
        <button type="button" id="copyContentBtn" data-original-text="Copy Content">Copy Content</button>
51
        <button type="button" id="createNewBtn">Create New Snippet</button>
52
      </div>
53
    </div>
54
55
    <script>
56
      async function copyToClipboard(text, button) {
57
        try {
58
          await navigator.clipboard.writeText(text);
59
          showButtonFeedback(button, '\u2714 Copied', 'success');
60
        } catch (error) {
61
          console.error('Copy failed:', error);
62
          showButtonFeedback(button, '\u2718 Failed', 'error');
63
64
          try {
65
            const textArea = document.createElement('textarea');
66
            textArea.value = text;
67
            textArea.style.position = 'fixed';
68
            textArea.style.opacity = '0';
69
            document.body.appendChild(textArea);
70
            textArea.select();
71
            document.execCommand('copy');
72
            document.body.removeChild(textArea);
73
            showButtonFeedback(button, '\u2714 Copied', 'success');
74
          } catch (fallbackError) {
75
            showButtonFeedback(button, '\u2718 Failed', 'error');
76
          }
77
        }
78
      }
79
80
      function showButtonFeedback(button, message, type = 'success') {
81
        const originalText = button.dataset.originalText || button.textContent;
82
        const originalDisabled = button.disabled;
83
84
        if (!button.dataset.originalText) {
85
          button.dataset.originalText = originalText;
86
        }
87
88
        button.textContent = message;
89
        button.disabled = true;
90
        button.classList.add(`copy-${type}`);
91
92
        setTimeout(() => {
93
          button.textContent = originalText;
94
          button.disabled = originalDisabled;
95
          button.classList.remove(`copy-${type}`);
96
        }, 1000);
97
      }
98
99
      document.getElementById('copyContentBtn').addEventListener('click', async () => {
100
        const content = document.getElementById('content').value;
101
        const button = document.getElementById('copyContentBtn');
102
        await copyToClipboard(content, button);
103
      });
104
105
      document.getElementById('copyLinkBtn').addEventListener('click', async () => {
106
        const currentUrl = window.location.href;
107
        const button = document.getElementById('copyLinkBtn');
108
        await copyToClipboard(currentUrl, button);
109
      });
110
111
      document.getElementById('createNewBtn').addEventListener('click', () => {
112
        window.location.href = '/';
113
      });
114
    </script>
115
  </body>
116
</html>