This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

nanopub / src / nanopub-page.ts
6.6 kB 123 lines
1export const NANOPUB_PAGE = `<!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>Nanopub — Detail</title> 7 <style> 8 :root { --bg: #0a0a0a; --surface: #141414; --border: #222; --text: #e0e0e0; --dim: #888; --accent: #6d9bc0; --accent2: #8fb8d4; } 9 * { margin: 0; padding: 0; box-sizing: border-box; } 10 body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; background: var(--bg); color: var(--text); line-height: 1.6; } 11 a { color: var(--accent); text-decoration: none; } 12 a:hover { color: var(--accent2); text-decoration: underline; } 13 .container { max-width: 800px; margin: 0 auto; padding: 2rem 1.5rem; } 14 .back { font-size: 0.85rem; margin-bottom: 1.5rem; } 15 h1 { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.5rem; } 16 .type-badge { display: inline-block; background: var(--accent); color: var(--bg); font-size: 0.7rem; font-weight: 600; padding: 0.15rem 0.5rem; border-radius: 4px; text-transform: uppercase; letter-spacing: 0.05em; margin-left: 0.5rem; } 17 .type-badge.retraction { background: #c06d6d; } 18 .type-badge.new-version { background: #6dc08b; } 19 .section { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 1.25rem; margin-bottom: 1rem; } 20 .section h2 { font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--dim); margin-bottom: 0.75rem; } 21 .triple { font-family: 'SF Mono', 'Fira Code', monospace; font-size: 0.85rem; padding: 0.5rem 0; border-bottom: 1px solid var(--border); } 22 .triple:last-child { border-bottom: none; } 23 .triple .subject { color: var(--accent); } 24 .triple .predicate { color: #c0a06d; } 25 .triple .object { color: #6dc08b; } 26 .meta-row { display: flex; gap: 0.5rem; padding: 0.3rem 0; font-size: 0.9rem; } 27 .meta-row .key { color: var(--dim); min-width: 120px; } 28 .meta-row .val { color: var(--text); word-break: break-all; } 29 .empty { color: var(--dim); font-style: italic; } 30 footer { margin-top: 2rem; padding-top: 1rem; border-top: 1px solid var(--border); color: var(--dim); font-size: 0.8rem; } 31 </style> 32</head> 33<body> 34 <div class="container"> 35 <div class="back"><a href="/">&larr; All nanopubs</a></div> 36 <div id="content"></div> 37 <footer>Nanopub appview on AT Protocol</footer> 38 </div> 39 <script> 40 const n = window.__NANOPUB__ || {}; 41 const el = document.getElementById('content'); 42 43 if (!n.rkey) { 44 el.innerHTML = '<h1>Not Found</h1>'; 45 } else { 46 const type = n.nanopubType ? n.nanopubType.split('#').pop() : 'assertion'; 47 const typeClass = type === 'retraction' ? ' retraction' : type === 'newVersion' ? ' new-version' : ''; 48 const label = n.assertion?.label || n.assertion?.subjectIri || 'Untitled nanopublication'; 49 50 let html = '<h1>' + escHtml(label) + '<span class="type-badge' + typeClass + '">' + type + '</span></h1>'; 51 52 // Assertion 53 html += '<div class="section"><h2>Assertion</h2>'; 54 if (n.assertion?.triples?.length) { 55 for (const t of n.assertion.triples) { 56 html += '<div class="triple"><span class="subject">' + escHtml(t.subject || '') + '</span> <span class="predicate">' + escHtml(t.predicate || '') + '</span> <span class="object">' + escHtml(t.object || '') + '</span></div>'; 57 } 58 } else if (n.assertion?.subjectIri) { 59 html += '<div class="triple"><span class="subject">' + escHtml(n.assertion.subjectIri) + '</span> <span class="predicate">' + escHtml(n.assertion.predicateIri || '') + '</span> <span class="object">' + escHtml(n.assertion.objectIri || '') + '</span></div>'; 60 } else { 61 html += '<div class="empty">No assertion data</div>'; 62 } 63 html += '</div>'; 64 65 // Provenance 66 if (n.provenance) { 67 html += '<div class="section"><h2>Provenance</h2>'; 68 if (n.provenance.generatedBy) html += metaRow('Generated by', n.provenance.generatedBy); 69 if (n.provenance.derivedFrom) html += metaRow('Derived from', n.provenance.derivedFrom); 70 if (n.provenance.evidence) html += metaRow('Evidence', n.provenance.evidence); 71 if (n.provenance.method) html += metaRow('Method', n.provenance.method); 72 if (n.provenance.authoredOn) html += metaRow('Authored on', n.provenance.authoredOn); 73 if (n.provenance.items?.length) { 74 for (const item of n.provenance.items) { 75 html += metaRow(item.predicate, item.object); 76 } 77 } 78 html += '</div>'; 79 } 80 81 // Publication Info 82 if (n.pubInfo) { 83 html += '<div class="section"><h2>Publication Info</h2>'; 84 if (n.pubInfo.creators?.length) html += metaRow('Creators', n.pubInfo.creators.join(', ')); 85 if (n.pubInfo.license) html += metaRow('License', n.pubInfo.license); 86 if (n.pubInfo.createdOn) html += metaRow('Created', n.pubInfo.createdOn); 87 if (n.pubInfo.subject) html += metaRow('Subject', n.pubInfo.subject); 88 if (n.pubInfo.items?.length) { 89 for (const item of n.pubInfo.items) { 90 html += metaRow(item.predicate, item.object); 91 } 92 } 93 html += '</div>'; 94 } 95 96 // Source / metadata 97 html += '<div class="section"><h2>Metadata</h2>'; 98 if (n.sourceNanopubUri) html += metaRow('Source URI', '<a href="' + escHtml(n.sourceNanopubUri) + '">' + escHtml(n.sourceNanopubUri) + '</a>'); 99 if (n.trustUri) html += metaRow('Trusty URI', n.trustUri); 100 if (n.signerPubkey) html += metaRow('Signer pubkey', n.signerPubkey.substring(0, 16) + '...'); 101 if (n.createdAt) html += metaRow('Indexed', n.createdAt); 102 if (n.retracts) html += metaRow('Retracts', n.retracts); 103 if (n.supersedes) html += metaRow('Supersedes', n.supersedes); 104 html += '</div>'; 105 106 // Island link 107 if (n._islandUrl) { 108 html += '<div class="section"><h2>Island</h2>'; 109 html += '<p>This nanopub has a derived island on Stigmergic:</p>'; 110 html += '<p><a href="' + escHtml(n._islandUrl) + '" style="font-size:1.1rem;font-weight:600;">View Island &rarr;</a></p>'; 111 html += '</div>'; 112 } 113 114 el.innerHTML = html; 115 } 116 117 function metaRow(key, val) { 118 return '<div class="meta-row"><span class="key">' + escHtml(key) + '</span><span class="val">' + val + '</span></div>'; 119 } 120 function escHtml(s) { if (!s) return ''; const d = document.createElement('div'); d.textContent = s; return d.innerHTML; } 121 </script> 122</body> 123</html>`;