Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 57 additions & 4 deletions dfetch_hub/site/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,22 @@
.vbadge-branch{background:#e8f4f8;color:#1a5276;border:1px solid #aed6f1}
.vtable tbody tr{cursor:pointer}
.vtable tbody tr.ver-selected td{background:rgba(0,113,188,.1)!important}
/* Hierarchical tag tree */
.vtree-group-hdr td{
background:var(--bg)!important;
cursor:pointer;
font-size:.8rem;
font-weight:700;
padding:.45rem .85rem;
color:var(--muted);
user-select:none;
border-bottom:1px solid var(--border)
}
.vtree-group-hdr:hover td{background:var(--border)!important}
.vtree-chevron{display:inline-block;width:1rem;font-size:.7rem}
.vtree-prefix{color:var(--text)}
.vtree-count{margin-left:.35rem;font-size:.72rem;font-weight:400;color:var(--subtle)}
.vtree-item td:first-child{padding-left:1.8rem}
/* Version pill */
.action-card{margin-bottom:.65rem}
.ver-pill{display:flex;align-items:center;gap:.4rem;margin-top:.45rem;padding:.3rem .7rem;background:var(--bg);border:1px solid var(--border);border-radius:var(--rm)}
Expand Down Expand Up @@ -848,14 +864,15 @@
allRefsCache=allRefs.slice(0,50);
const firstTag=sortedTags.length?{name:sortedTags[0].name,kind:'tag'}:null;
curVersion=firstTag||{name:c.default_branch||'main',kind:'branch'};
document.getElementById('vtbody').innerHTML=allRefsCache.length?allRefsCache.map((r,i)=>{
const hasHierTags=allRefsCache.some(r=>r.kind==='tag'&&r.name.includes('/'));
document.getElementById('vtbody').innerHTML=allRefsCache.length?(hasHierTags?_renderVerTree(allRefsCache):allRefsCache.map((r,i)=>{
const sel=curVersion&&curVersion.name===r.name&&curVersion.kind===r.kind;
return `<tr class="${sel?'ver-selected':''}" onclick="selectVersion(${i})">
return `<tr class="${sel?'ver-selected':''}" data-vidx="${i}" onclick="selectVersion(${i})">
<td class="vtag-name">${esc(r.name)}${i===0&&r.kind==='tag'?'<span class="vtag-latest">latest</span>':''}</td>
<td><span class="vbadge vbadge-${r.kind}">${r.kind}</span></td>
<td class="vsha">${r.commit_sha?r.commit_sha.slice(0,10):'—'}</td>
<td style="font-size:.79rem;color:var(--subtle)">${r.date?r.date.slice(0,10):'—'}</td>
</tr>`;}).join(''):'<tr><td colspan="4" style="text-align:center;color:var(--subtle)">No version info</td></tr>';
</tr>`;}).join('')):'<tr><td colspan="4" style="text-align:center;color:var(--subtle)">No version info</td></tr>';
// Snippet
document.getElementById('dSnip').innerHTML=buildSnipHtml(c,curVersion);
// Aside
Expand Down Expand Up @@ -884,7 +901,7 @@
const r=allRefsCache[i];if(!r)return;
curVersion={name:r.name,kind:r.kind};
_replaceURL({pkg:curPkg,v:r.name,vk:r.kind});
document.querySelectorAll('#vtbody tr').forEach((tr,idx)=>tr.classList.toggle('ver-selected',idx===i));
document.querySelectorAll('#vtbody tr[data-vidx]').forEach(tr=>tr.classList.toggle('ver-selected',+tr.dataset.vidx===i));
const c=curPkg?RAW[curPkg]:null;
if(c)document.getElementById('dSnip').innerHTML=buildSnipHtml(c,curVersion);
updSelVerInfo();
Expand All @@ -896,6 +913,42 @@
document.getElementById('selVerKind').textContent=curVersion.kind;
el.style.display='';
}
function _renderVerTree(refs){
// Group tags whose names contain '/' by their prefix (part before first /)
const groups=new Map();
refs.forEach((r,i)=>{
if(r.kind!=='tag'||!r.name.includes('/'))return;
const pfx=r.name.slice(0,r.name.indexOf('/'));
if(!groups.has(pfx))groups.set(pfx,[]);
groups.get(pfx).push(i);
});
let html='';
// Render grouped tags — collapsed by default, open if selected version is inside
groups.forEach((idxs,pfx)=>{
const open=idxs.some(i=>curVersion&&refs[i].name===curVersion.name&&refs[i].kind===curVersion.kind);
html+=`<tr class="vtree-group-hdr" onclick="toggleTreeGroup(this)"><td colspan="4"><span class="vtree-chevron">${open?'▾':'▸'}</span><span class="vtree-prefix">${esc(pfx)}/</span><span class="vtree-count">(${idxs.length})</span></td></tr>`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Group expand/collapse control is not keyboard accessible.

The toggle is attached to a clickable <tr> only, so keyboard users can’t focus/activate it.

Suggested fix
-.vtree-group-hdr td{background:var(--bg)!important;cursor:pointer;font-size:.8rem;font-weight:700;padding:.45rem .85rem;color:var(--muted);user-select:none;border-bottom:1px solid var(--border)}
+.vtree-group-hdr td{background:var(--bg)!important;font-size:.8rem;font-weight:700;padding:.45rem .85rem;color:var(--muted);user-select:none;border-bottom:1px solid var(--border)}
+.vtree-group-btn{display:flex;align-items:center;gap:0;width:100%;border:none;background:none;padding:0;text-align:left;cursor:pointer;color:inherit;font:inherit}
+.vtree-group-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
- html+=`<tr class="vtree-group-hdr" onclick="toggleTreeGroup(this)"><td colspan="4"><span class="vtree-chevron">${open?'▾':'▸'}</span><span class="vtree-prefix">${esc(pfx)}/</span><span class="vtree-count">(${idxs.length})</span></td></tr>`;
+ html+=`<tr class="vtree-group-hdr"><td colspan="4"><button type="button" class="vtree-group-btn" onclick="toggleTreeGroup(this.closest('tr'))"><span class="vtree-chevron">${open?'▾':'▸'}</span><span class="vtree-prefix">${esc(pfx)}/</span><span class="vtree-count">(${idxs.length})</span></button></td></tr>`;

Also applies to: 936-942

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dfetch_hub/site/index.html` at line 920, The row-level toggle
(vtree-group-hdr) currently only uses an onclick on the <tr> so it isn’t
keyboard accessible; update the markup and handlers around toggleTreeGroup to
make the control focusable and operable via keyboard: replace or augment the
clickable <tr> content with a focusable element (e.g., a <button> or a span with
role="button" and tabindex="0") containing the chevron and prefix, set an
appropriate aria-expanded attribute reflecting open, and wire the same
toggleTreeGroup logic to that element’s click and keydown (handle Enter/Space)
events; apply the same change for the other group header occurrences handled by
toggleTreeGroup (the similar vtree-group-hdr blocks).

idxs.forEach(i=>{
const r=refs[i];const sel=curVersion&&r.name===curVersion.name&&r.kind===curVersion.kind;
const isLatest=i===0;
html+=`<tr class="vtree-item${sel?' ver-selected':''}" data-vidx="${i}" onclick="selectVersion(${i})"${open?'':' style="display:none"'}><td class="vtag-name">${esc(r.name.slice(pfx.length+1))}${isLatest?'<span class="vtag-latest">latest</span>':''}</td><td><span class="vbadge vbadge-tag">tag</span></td><td class="vsha">${r.commit_sha?r.commit_sha.slice(0,10):'—'}</td><td style="font-size:.79rem;color:var(--subtle)">${r.date?r.date.slice(0,10):'—'}</td></tr>`;
});
});
// Render ungrouped tags and branches
refs.forEach((r,i)=>{
if(r.kind==='tag'&&r.name.includes('/'))return;
const sel=curVersion&&r.name===curVersion.name&&r.kind===curVersion.kind;
const isLatest=i===0&&r.kind==='tag';
html+=`<tr class="${sel?'ver-selected':''}" data-vidx="${i}" onclick="selectVersion(${i})"><td class="vtag-name">${esc(r.name)}${isLatest?'<span class="vtag-latest">latest</span>':''}</td><td><span class="vbadge vbadge-${r.kind}">${r.kind}</span></td><td class="vsha">${r.commit_sha?r.commit_sha.slice(0,10):'—'}</td><td style="font-size:.79rem;color:var(--subtle)">${r.date?r.date.slice(0,10):'—'}</td></tr>`;
});
return html||'<tr><td colspan="4" style="text-align:center;color:var(--subtle)">No version info</td></tr>';
}
Comment on lines +916 to +944
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Multiple lines exceed 120-character limit.

Lines 920, 924, and 932 contain very long template literals (200-300+ characters). Consider breaking these into multiple statements or helper functions for readability.

As per coding guidelines: "Enforce maximum line length of 120 characters in HTML/CSS/JS".

Example refactor for line 924
-      html+=`<tr class="vtree-item${sel?' ver-selected':''}" data-vidx="${i}" onclick="selectVersion(${i})"${open?'':' style="display:none"'}><td class="vtag-name">${esc(r.name.slice(pfx.length+1))}${isLatest?'<span class="vtag-latest">latest</span>':''}</td><td><span class="vbadge vbadge-tag">tag</span></td><td class="vsha">${r.commit_sha?r.commit_sha.slice(0,10):'—'}</td><td style="font-size:.79rem;color:var(--subtle)">${r.date?r.date.slice(0,10):'—'}</td></tr>`;
+      const dispStyle = open ? '' : ' style="display:none"';
+      const latestBadge = isLatest ? '<span class="vtag-latest">latest</span>' : '';
+      const sha = r.commit_sha ? r.commit_sha.slice(0,10) : '—';
+      const date = r.date ? r.date.slice(0,10) : '—';
+      html += `<tr class="vtree-item${sel?' ver-selected':''}" data-vidx="${i}" ` +
+        `onclick="selectVersion(${i})"${dispStyle}>` +
+        `<td class="vtag-name">${esc(r.name.slice(pfx.length+1))}${latestBadge}</td>` +
+        `<td><span class="vbadge vbadge-tag">tag</span></td>` +
+        `<td class="vsha">${sha}</td>` +
+        `<td style="font-size:.79rem;color:var(--subtle)">${date}</td></tr>`;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dfetch_hub/site/index.html` around lines 907 - 935, The _renderVerTree
function has multiple template-literal lines that exceed the 120-char limit
(notably the per-group header, grouped-item row, and ungrouped-item row);
refactor by extracting small helper functions such as buildGroupHeader(prefix,
count, open), buildGroupItem(r, i, sel, isLatest, pfx), and buildItemRow(r, i,
sel, isLatest) (or buildBadge(kind)/buildDate(date)) and compose the HTML from
those shorter template pieces/variables, or split attributes and content into
multiple concatenated strings so no single line exceeds 120 chars; update calls
in _renderVerTree (where groups.forEach and refs.forEach produce html) to use
these helpers and preserve behavior for toggleTreeGroup/selectVersion and the
data-vidx, vtag-latest, vbadge, vtree-chevron, and vtree-prefix pieces.

function toggleTreeGroup(hdr){
const chevron=hdr.querySelector('.vtree-chevron');
const open=chevron&&chevron.textContent==='▾';
if(chevron)chevron.textContent=open?'▸':'▾';
let sib=hdr.nextElementSibling;
while(sib&&sib.classList.contains('vtree-item')){sib.style.display=open?'none':'';sib=sib.nextElementSibling;}
}
function switchTab(name){
document.querySelectorAll('.tabbtn').forEach((b,i)=>{const ns=['readme','versions'];b.classList.toggle('active',ns[i]===name)});
document.querySelectorAll('.tabcontent').forEach(el=>el.classList.remove('active'));
Expand Down