Skip to content

Commit 5b5fc34

Browse files
vishrclaude
andcommitted
fix(docs): address PR review — robust version guard + bounded observer
- github.ts: require a 'vX' tag (reject empty/garbage so the badge can't render blank), and add a 5s fetch timeout to both build-time fetches so a hung connection falls back instead of stalling the build. - Search.astro: bound the empty-state MutationObserver with a 10s timeout + dev-only warning, so it can't watch the whole body forever if Pagefind never mounts (dev) or selectors change upstream. Mark decorative icons aria-hidden. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 759b829 commit 5b5fc34

2 files changed

Lines changed: 26 additions & 9 deletions

File tree

site/src/components/Search.astro

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ import Default from '@astrojs/starlight/components/Search.astro';
1111
<div class="echo-search-empty">
1212
<div class="ess-group">
1313
<div class="ess-label">Start here</div>
14-
<a class="ess-link" href="/guide/quickstart/"><i class="ph ph-rocket-launch"></i> Quickstart <span class="ess-sec">Guide</span></a>
15-
<a class="ess-link" href="/guide/routing/"><i class="ph ph-signpost"></i> Routing <span class="ess-sec">Guide</span></a>
16-
<a class="ess-link" href="/guide/binding/"><i class="ph ph-brackets-curly"></i> Binding <span class="ess-sec">Guide</span></a>
14+
<a class="ess-link" href="/guide/quickstart/"><i aria-hidden="true" class="ph ph-rocket-launch"></i> Quickstart <span class="ess-sec">Guide</span></a>
15+
<a class="ess-link" href="/guide/routing/"><i aria-hidden="true" class="ph ph-signpost"></i> Routing <span class="ess-sec">Guide</span></a>
16+
<a class="ess-link" href="/guide/binding/"><i aria-hidden="true" class="ph ph-brackets-curly"></i> Binding <span class="ess-sec">Guide</span></a>
1717
</div>
1818
<div class="ess-group">
1919
<div class="ess-label">Popular</div>
20-
<a class="ess-link" href="/middleware/jwt/"><i class="ph ph-lock-key"></i> JWT <span class="ess-sec">Middleware</span></a>
21-
<a class="ess-link" href="/middleware/cors/"><i class="ph ph-globe"></i> CORS <span class="ess-sec">Middleware</span></a>
22-
<a class="ess-link" href="/cookbook/hello-world/"><i class="ph ph-cube"></i> Hello World <span class="ess-sec">Cookbook</span></a>
20+
<a class="ess-link" href="/middleware/jwt/"><i aria-hidden="true" class="ph ph-lock-key"></i> JWT <span class="ess-sec">Middleware</span></a>
21+
<a class="ess-link" href="/middleware/cors/"><i aria-hidden="true" class="ph ph-globe"></i> CORS <span class="ess-sec">Middleware</span></a>
22+
<a class="ess-link" href="/cookbook/hello-world/"><i aria-hidden="true" class="ph ph-cube"></i> Hello World <span class="ess-sec">Cookbook</span></a>
2323
</div>
2424
<div class="ess-foot">
2525
<span><kbd>↵</kbd>open</span><span><kbd>↑</kbd><kbd>↓</kbd>navigate</span><span><kbd>esc</kbd>close</span>
@@ -39,5 +39,14 @@ import Default from '@astrojs/starlight/components/Search.astro';
3939
if (!inject()) {
4040
const obs = new MutationObserver(() => { if (inject()) obs.disconnect(); });
4141
obs.observe(document.body, { childList: true, subtree: true });
42+
// Bound the observer: if Pagefind never mounts (disabled in dev, or the
43+
// Starlight markup changed on upgrade), stop watching so it can't run for
44+
// the page's lifetime. Losing the launchpad is harmless; search still works.
45+
setTimeout(() => {
46+
obs.disconnect();
47+
if (import.meta.env.DEV && !document.querySelector('.echo-search-empty')) {
48+
console.warn('[search] empty-state panel not injected — .pagefind-ui selectors may have changed');
49+
}
50+
}, 10000);
4251
}
4352
</script>

site/src/data/github.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ async function fetchStars(): Promise<number> {
1515
const token = process.env.GITHUB_TOKEN;
1616
if (token) headers.Authorization = `Bearer ${token}`;
1717

18-
const res = await fetch(`https://api.github.com/repos/${REPO}`, { headers });
18+
const res = await fetch(`https://api.github.com/repos/${REPO}`, { headers, signal: AbortSignal.timeout(5000) });
1919
if (!res.ok) throw new Error(`GitHub API responded ${res.status}`);
2020
const data = await res.json();
2121
return typeof data.stargazers_count === 'number' ? data.stargazers_count : FALLBACK_STARS;
@@ -36,10 +36,18 @@ const FALLBACK_VERSION = 'v5';
3636
// (avoids GitHub "latest release" occasionally pointing at a v4 patch).
3737
async function fetchLatestVersion(): Promise<string> {
3838
try {
39-
const res = await fetch('https://proxy.golang.org/github.com/labstack/echo/v5/@latest');
39+
const res = await fetch('https://proxy.golang.org/github.com/labstack/echo/v5/@latest', {
40+
signal: AbortSignal.timeout(5000),
41+
});
4042
if (!res.ok) throw new Error(`Go proxy responded ${res.status}`);
4143
const data = await res.json();
42-
return typeof data.Version === 'string' ? data.Version : FALLBACK_VERSION;
44+
const v = typeof data.Version === 'string' ? data.Version.trim() : '';
45+
// Require a real "vX..." tag — an empty/garbage value would silently render a blank badge.
46+
if (!/^v\d/.test(v)) {
47+
console.warn(`[github] unexpected version ${JSON.stringify(data.Version)}; using fallback ${FALLBACK_VERSION}`);
48+
return FALLBACK_VERSION;
49+
}
50+
return v;
4351
} catch (e) {
4452
console.warn(`[github] version fetch failed; using fallback ${FALLBACK_VERSION}:`, e);
4553
return FALLBACK_VERSION;

0 commit comments

Comments
 (0)