fix(docs): make copy markdown work for index pages in production#7520
fix(docs): make copy markdown work for index pages in production#7520mhartington merged 1 commit intomainfrom
Conversation
Retry markdown fetch with an /index.mdx fallback when the slug-based .mdx URL returns 404.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughThis change implements a fallback fetch strategy for Markdown/MDX content in the page-actions component. Two new utility functions handle URL derivation and content fetching with fallback logic, while LLMCopyButton is updated to leverage this strategy with enhanced caching. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
🍈 Lychee Link Check Report3660 links: ❌ Errors
Full Statistics Table
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/docs/src/components/page-actions.tsx`:
- Around line 61-78: The promise passed into ClipboardItem via
fetchMarkdownWithFallback can reject and that error is currently uncaught, so
update the onClick handler (the useCopyButton callback) to wrap the
navigator.clipboard.write call in try/catch around the await and handle failures
from fetchMarkdownWithFallback/ClipboardItem; on error, ensure you still clear
loading (setLoading(false) is in finally) and surface user feedback (e.g., set
an error state or call your app’s toast/notification function) and optionally
log the error and avoid caching on failure—refer to fetchMarkdownWithFallback,
ClipboardItem, navigator.clipboard.write, setLoading, cache, and the
useCopyButton callback to locate the change.
| const [checked, onClick] = useCopyButton(async () => { | ||
| const cached = cache.get(markdownUrl); | ||
| const fallbackUrl = toIndexMarkdownUrl(markdownUrl); | ||
| const cached = cache.get(markdownUrl) ?? (fallbackUrl ? cache.get(fallbackUrl) : undefined); | ||
| if (cached) return navigator.clipboard.writeText(cached); | ||
|
|
||
| setLoading(true); | ||
|
|
||
| try { | ||
| await navigator.clipboard.write([ | ||
| new ClipboardItem({ | ||
| 'text/plain': fetch(markdownUrl).then(async (res) => { | ||
| const content = await res.text(); | ||
| 'text/plain': fetchMarkdownWithFallback(markdownUrl).then(({ content, resolvedUrl }) => { | ||
| cache.set(markdownUrl, content); | ||
| cache.set(resolvedUrl, content); | ||
|
|
||
| return content; | ||
| return new Blob([content], { type: 'text/plain' }); | ||
| }), | ||
| }), | ||
| ]); |
There was a problem hiding this comment.
Smart dual-key caching strategy.
The cache lookup logic on lines 62-63 is clever—by pre-computing the potential fallback URL and checking both cache keys before fetching, you avoid unnecessary network requests when content was previously loaded via either path. The dual caching on lines 72-73 completes this nicely.
One observation: if fetchMarkdownWithFallback rejects (network failure or both URLs returning errors), the promise passed to ClipboardItem will reject. The finally block correctly resets the loading state, but the error itself isn't caught. The user would see the button stop loading with no indication of what went wrong. Consider whether a user-facing error state or toast notification would improve the experience.
💡 Optional: Add error feedback
+ const [error, setError] = useState<string | null>(null);
const [checked, onClick] = useCopyButton(async () => {
+ setError(null);
const fallbackUrl = toIndexMarkdownUrl(markdownUrl);
const cached = cache.get(markdownUrl) ?? (fallbackUrl ? cache.get(fallbackUrl) : undefined);
if (cached) return navigator.clipboard.writeText(cached);
setLoading(true);
try {
await navigator.clipboard.write([
new ClipboardItem({
'text/plain': fetchMarkdownWithFallback(markdownUrl).then(({ content, resolvedUrl }) => {
cache.set(markdownUrl, content);
cache.set(resolvedUrl, content);
return new Blob([content], { type: 'text/plain' });
}),
}),
]);
+ } catch (e) {
+ setError('Failed to copy markdown');
+ console.error(e);
} finally {
setLoading(false);
}
});🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/docs/src/components/page-actions.tsx` around lines 61 - 78, The promise
passed into ClipboardItem via fetchMarkdownWithFallback can reject and that
error is currently uncaught, so update the onClick handler (the useCopyButton
callback) to wrap the navigator.clipboard.write call in try/catch around the
await and handle failures from fetchMarkdownWithFallback/ClipboardItem; on
error, ensure you still clear loading (setLoading(false) is in finally) and
surface user feedback (e.g., set an error state or call your app’s
toast/notification function) and optionally log the error and avoid caching on
failure—refer to fetchMarkdownWithFallback, ClipboardItem,
navigator.clipboard.write, setLoading, cache, and the useCopyButton callback to
locate the change.
Retry markdown fetch with an /index.mdx fallback when the slug-based .mdx URL returns 404.
Summary by CodeRabbit