This repository has no description
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="/">← 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 →</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>`;