From e9ec3bb16a4c1b6cbdbbfd98afd93f27d3bf101c Mon Sep 17 00:00:00 2001 From: you Date: Thu, 19 Mar 2026 01:20:23 +0000 Subject: [PATCH] =?UTF-8?q?Fix=20escapeHtml=20=E2=86=92=20esc,=20flag=20se?= =?UTF-8?q?lf-loop=20subpaths=20with=20=F0=9F=94=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Self-loops (likely prefix collisions) shown at 60% opacity with amber frequency bar and 🔄 icon with tooltip explaining the collision. --- public/analytics.js | 8 +++++--- public/style.css | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/public/analytics.js b/public/analytics.js index 986aef5..c7e26b3 100644 --- a/public/analytics.js +++ b/public/analytics.js @@ -783,12 +783,14 @@ ${data.subpaths.map((s, i) => { const barW = Math.max(2, Math.round(s.count / maxCount * 100)); - return ` + const hops = s.path.split(' → '); + const hasSelfLoop = hops.some((h, j) => j > 0 && h === hops[j - 1]); + return ` ${i + 1} - ${escapeHtml(s.path)} + ${esc(s.path)}${hasSelfLoop ? ' 🔄' : ''} ${s.count.toLocaleString()} ${s.pct}% -
+
`; }).join('')} `; diff --git a/public/style.css b/public/style.css index e60389b..31fc9f4 100644 --- a/public/style.css +++ b/public/style.css @@ -1146,3 +1146,7 @@ button.ch-item.ch-item-encrypted .ch-badge { filter: grayscale(0.6); } /* Ambiguous hop indicator */ .hop-ambiguous { border-bottom: 1px dashed #f59e0b; } .hop-warn { font-size: 0.7em; margin-left: 2px; vertical-align: super; } + +/* Self-loop subpath rows */ +.subpath-selfloop { opacity: 0.6; } +.subpath-selfloop td:first-child::after { content: ''; }