marky

Lightweight bookmarking + plaintext archive
Log | Files | Refs | README | LICENSE

bookmarklet.html (3203B)


      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" />
      6     <title>bookmarklet | marky</title>
      7     <link rel="stylesheet" href="/styles.css" />
      8     <style>
      9       a.btn{display:inline-block;background:#222;color:#fff;text-decoration:none;padding:10px 14px;border-radius:6px}
     10       .notice{margin-top:12px;color:#666}
     11     </style>
     12     <script src="/vendor/vue.global.prod.js"></script>
     13   </head>
     14   <body>
     15     <div id="hdr">{{HEADER}}</div>
     16     <main class="container">
     17       <h2>Save to Marky</h2>
     18       <p>Drag this to your bookmarks bar:</p>
     19       <p>
     20         <a class="btn" href="javascript:(function(){try{var d=document,s=encodeURIComponent,u=location.href,t=document.title,sel='';var ae=d.activeElement;if(ae&&((ae.tagName==='TEXTAREA')||(ae.tagName==='INPUT'&&/^(?:text|search|url|tel|email)$/i.test(ae.type)))){var ss=ae.selectionStart||0,se=ae.selectionEnd||0;if(typeof ss==='number'&&typeof se==='number'&&se>ss){sel=ae.value.substring(ss,se)}}if(!sel&&d.getSelection){sel=d.getSelection().toString()}else if(!sel&&window.getSelection){sel=window.getSelection().toString()}else if(!sel&&d.selection){sel=d.selection.createRange().text}var win=window.open('{{ORIGIN}}/bookmarklet?u='+s(u)+'&t='+s(t)+'&d='+s(sel)+'{{AUTH}}','marky','width=520,height=520');if(win){win.focus()}}catch(e){alert('Could not open Marky: '+e)}})();">Save to Marky</a>
     21       </p>
     22       <div class="notice">
     23         <p>When clicked on any page, this opens a small form prefilled with the page URL and title. On submit, it saves to your Marky account.</p>
     24       </div>
     25     </main>
     26     <script>
     27       const { createApp } = window.Vue;
     28       createApp({
     29         data(){ return { me:null, api:{ present:false, value:'', show:false, busy:false, copied:false } } },
     30         async mounted(){
     31           try { const r = await fetch('/me'); if (r.ok) this.me = await r.json(); } catch {}
     32           if (this.me && this.me.username) {
     33             try { const r = await fetch('/api/token'); if (r.ok) { const j = await r.json(); this.api.present = !!j.present; } } catch {}
     34           }
     35         },
     36         methods:{
     37           async logout(){ await fetch('/logout', { method:'POST' }).catch(()=>{}); location.replace('/'); },
     38           async revealApiKey(){ this.api.busy=true; try { const r=await fetch('/api/token?reveal=1'); if(!r.ok) throw 0; const j=await r.json(); this.api.present=true; this.api.value=j.api_token||''; this.api.show=true; this.api.copied=false; } finally { this.api.busy=false; } },
     39           async generateApiKey(){ this.api.busy=true; try { const r=await fetch('/api/token',{method:'POST'}); if(!r.ok) throw 0; const j=await r.json(); this.api.present=true; this.api.value=j.api_token||''; this.api.show=true; this.api.copied=false; } finally { this.api.busy=false; } },
     40           async regenerateApiKey(){ return this.generateApiKey(); },
     41           async copyApiKey(){ try { await navigator.clipboard.writeText(this.api.value||''); this.api.copied=true; setTimeout(()=>{ this.api.copied=false; },1500); } catch(e){ alert('Failed to copy token'); } },
     42         }
     43       }).mount('#hdr');
     44     </script>
     45   </body>
     46   </html>