diff --git a/frontend/app.js b/frontend/app.js
index 4b1ab86..bafaba4 100644
--- a/frontend/app.js
+++ b/frontend/app.js
@@ -297,16 +297,28 @@ function renderProtocolGrid(protocols) {
grid.innerHTML = '
';
return;
}
- grid.innerHTML = protocols.map(function(p) {
- var sourceLabel = p.source || (p.author ? '@' + p.author : '');
- var tags = (p.tags || []).map(function(t) { return '' + escapeHtml(t) + ''; }).join('');
- return '' +
- '
' + escapeHtml(p.title) + '
' +
- '
' + escapeHtml(p.description || '') + '
' +
- (tags ? '
' + tags + '
' : '') + '
' +
- '
';
- }).join('');
+ grid.innerHTML = protocols.map(renderProtocolPill).join('');
+}
+
+// --- Shared rendering (use everywhere for consistency) ---
+function renderProtocolPill(p) {
+ var sourceLabel = p.source || (p.author ? '@' + p.author : '');
+ var tags = (p.tags || []).map(function(t) { return '' + escapeHtml(t) + ''; }).join('');
+ return '' +
+ '' + escapeHtml(p.title) + '
' +
+ '
' + escapeHtml(p.description || '') + '
' +
+ (tags ? '
' + tags + '
' : '') + '
' +
+ '';
+}
+
+function renderCollectionPill(c) {
+ var sourceLabel = c.source || (c.author ? '@' + c.author : '');
+ return '' +
+ '' + escapeHtml(c.title) + '
' +
+ '
' + escapeHtml(c.description || '') + '
' +
+ '';
}
// (iconFor removed — icons are no longer used)
@@ -563,12 +575,7 @@ async function loadCollections() {
grid.innerHTML = '';
return;
}
- grid.innerHTML = collections.map(function(c) {
- var sourceLabel = c.author ? '@' + c.author : (c.source || '');
- return '' +
- '
' + escapeHtml(c.title) + '
' + escapeHtml(c.description || '') + '
' +
- '
';
- }).join('');
+ grid.innerHTML = collections.map(renderCollectionPill).join('');
} catch (e) {
document.getElementById('collectionsGrid').innerHTML = '' + escapeHtml(e.message) + '
';
}
@@ -729,11 +736,7 @@ async function showCollectionDetail(slug) {
if (item.type === 'protocol') {
try {
var p = await api('/protocols/' + item.slug);
- itemsHtml += '' +
- '
' + escapeHtml(p.title) + '
' +
- '
' + escapeHtml(p.description || '') + '
' +
- (p.tags && p.tags.length ? '
' + p.tags.map(function(t) { return '' + escapeHtml(t) + ''; }).join('') + '
' : '') + '
' +
- '
';
+ itemsHtml += renderProtocolPill(p);
} catch (e2) {
itemsHtml += '' + escapeHtml(item.slug) + '
Protocol not found
';
}
@@ -800,21 +803,12 @@ async function showUser(username) {
'@' + escapeHtml(data.user.username) + '
' +
(data.user.display_name ? '
' + escapeHtml(data.user.display_name) + '
' : '') +
(data.user.bio ? '
' + escapeHtml(data.user.bio) + '
' : '') + '
' +
- (p.length ? 'Protocols (' + p.length + ')
' +
- p.map(function(proto) {
- return '
' +
- '
' + escapeHtml(proto.title) + '
' +
- '
' + escapeHtml(proto.description||'') + '
' +
- (proto.tags && proto.tags.length ? '
' + proto.tags.map(function(t) { return '' + escapeHtml(t) + ''; }).join('') + '
' : '') + '
' +
- '
';
- }).join('') +
- '
' : '') +
- (c.length ? 'Collections (' + c.length + ')
' +
- c.map(function(col) {
- return '
[+]
' +
- '
' + escapeHtml(col.title) + '
' + escapeHtml(col.description||'') + '
';
- }).join('') +
- '
' : '');
+ (p.length ? 'Protocols (' + p.length + ')
' +
+ p.map(renderProtocolPill).join('') +
+ '
' : '') +
+ (c.length ? 'Collections (' + c.length + ')
' +
+ c.map(renderCollectionPill).join('') +
+ '
' : '');
// Add actions if viewing own profile
var actionsHtml = '';
if (currentUser && currentUser.username === username) {
diff --git a/frontend/index.html b/frontend/index.html
index 200be03..911aaa5 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -4,15 +4,22 @@
Protocol Droid
-
+
+
+
+
+
-
$ protocol-droid
-
+
+
+ $ protocol-droid
+
+