Graceful handling of broken and external links (Issue #837)#847
Conversation
- Add error feedback for broken nodespace:// links instead of silent failure - Show status bar error: "This link points to a deleted or non-existent document" - Show error for empty/invalid link references - Add external link handling (http/https) opening in system browser - Create external-links.ts utility with openUrl(), isExternalUrl(), isNodespaceUrl() - Use Tauri opener plugin in desktop mode - Fall back to window.open() in browser dev mode - Add comprehensive tests for link handling edge cases - 16 new tests covering URL validation and protocol detection Co-Authored-By: Claude <noreply@anthropic.com>
Code Review - PR #847: Graceful handling of broken and external linksReview Type: Initial Review Reviewer: Claude Code (Principal Engineer AI Reviewer) Requirements CheckFrom Issue #837:
All acceptance criteria have been met. Code Review FindingsOverall AssessmentThis is a well-structured, focused PR that addresses the stated requirements cleanly. The implementation follows established patterns in the codebase, adds appropriate error handling, and includes comprehensive tests. Suggested Improvements1. [Improvement] Consider DRY principle for protocol detection The protocol detection logic is duplicated between // app-shell.svelte line 247-248
if (href.startsWith('http://') || href.startsWith('https://')) {
// external-links.ts has isExternalUrl() that does the same thing
export function isExternalUrl(url: string): boolean {
return url.startsWith('http://') || url.startsWith('https://');
}The utility functions import { openUrl, isExternalUrl, isNodespaceUrl } from '$lib/utils/external-links';
// Then:
if (isExternalUrl(href)) { ... }
if (!isNodespaceUrl(href)) return;Engineering principle: DRY (Don't Repeat Yourself) - Single source of truth for protocol detection logic makes future changes safer. Severity: 🟢 Suggestion - The current implementation works correctly; this is about maintainability. 2. [Nit] Potential double resolution in link handler The code calls // Line 315: First resolution
const target = await navService.resolveNodeTarget(nodeId);
if (!target) { ... return; }
// Line 326-329: These methods call resolveNodeTarget internally again
navService.navigateToNodeInOtherPane(nodeId, sourcePaneId);
// or
navService.navigateToNode(nodeId, openInNewTab, sourcePaneId);This is acceptable given the current implementation because:
Consider adding a comment explaining this is intentional for user feedback purposes, or future refactoring could pass the already-resolved target to navigation methods. Severity: 🟢 Nit - Minor inefficiency but acceptable tradeoff for UX. 3. [Nit] Test coverage for Tauri mode The Tauri mode test is acknowledged to be imperfect due to dynamic import caching limitations: // Note: Due to dynamic import caching, this test may not work perfectly
// in all environments. The important thing is that the code path exists.This is honest and pragmatic. The browser fallback is well-tested, and manual testing is noted in the PR checklist. Consider adding an integration test in the future that runs in Tauri mode if CI infrastructure supports it. Severity: 🟢 Nit - Documentation is clear; no action required. What Went Well
RecommendationAPPROVE ✅ This PR is a net positive improvement to code health. It:
The suggestions above are minor improvements that don't block merging. Generated by Claude Code - Principal Engineer AI Reviewer |
malibio
left a comment
There was a problem hiding this comment.
Review Status: APPROVE (GitHub prevents self-approval, but this PR passes review criteria)
All acceptance criteria met. Implementation is clean and follows project standards. Minor DRY improvements suggested in detailed review - these do not block merge.
- Import and use isExternalUrl() and isNodespaceUrl() utilities instead of inline startsWith checks (DRY principle) - Add comment explaining intentional double resolution pattern for user feedback purposes (result is cached in SharedNodeStore) Addresses reviewer suggestions from PR #847 code review. Co-Authored-By: Claude <noreply@anthropic.com>
Review Feedback Addressed ✅Commit: 497c97b Addressed Recommendations
Changes Made
Tests
Generated by |
* Graceful handling of broken and external links (Issue #837) - Add error feedback for broken nodespace:// links instead of silent failure - Show status bar error: "This link points to a deleted or non-existent document" - Show error for empty/invalid link references - Add external link handling (http/https) opening in system browser - Create external-links.ts utility with openUrl(), isExternalUrl(), isNodespaceUrl() - Use Tauri opener plugin in desktop mode - Fall back to window.open() in browser dev mode - Add comprehensive tests for link handling edge cases - 16 new tests covering URL validation and protocol detection Co-Authored-By: Claude <noreply@anthropic.com> * Address review: DRY principle and clarifying comments - Import and use isExternalUrl() and isNodespaceUrl() utilities instead of inline startsWith checks (DRY principle) - Add comment explaining intentional double resolution pattern for user feedback purposes (result is cached in SharedNodeStore) Addresses reviewer suggestions from PR #847 code review. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
* Graceful handling of broken and external links (Issue #837) - Add error feedback for broken nodespace:// links instead of silent failure - Show status bar error: "This link points to a deleted or non-existent document" - Show error for empty/invalid link references - Add external link handling (http/https) opening in system browser - Create external-links.ts utility with openUrl(), isExternalUrl(), isNodespaceUrl() - Use Tauri opener plugin in desktop mode - Fall back to window.open() in browser dev mode - Add comprehensive tests for link handling edge cases - 16 new tests covering URL validation and protocol detection Co-Authored-By: Claude <noreply@anthropic.com> * Address review: DRY principle and clarifying comments - Import and use isExternalUrl() and isNodespaceUrl() utilities instead of inline startsWith checks (DRY principle) - Add comment explaining intentional double resolution pattern for user feedback purposes (result is cached in SharedNodeStore) Addresses reviewer suggestions from PR #847 code review. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
* Graceful handling of broken and external links (Issue #837) - Add error feedback for broken nodespace:// links instead of silent failure - Show status bar error: "This link points to a deleted or non-existent document" - Show error for empty/invalid link references - Add external link handling (http/https) opening in system browser - Create external-links.ts utility with openUrl(), isExternalUrl(), isNodespaceUrl() - Use Tauri opener plugin in desktop mode - Fall back to window.open() in browser dev mode - Add comprehensive tests for link handling edge cases - 16 new tests covering URL validation and protocol detection Co-Authored-By: Claude <noreply@anthropic.com> * Address review: DRY principle and clarifying comments - Import and use isExternalUrl() and isNodespaceUrl() utilities instead of inline startsWith checks (DRY principle) - Add comment explaining intentional double resolution pattern for user feedback purposes (result is cached in SharedNodeStore) Addresses reviewer suggestions from PR #847 code review. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
Summary
nodespace://links now show a helpful error message via the status bar instead of crashinghttp://,https://) now open in the system default browserChanges
New External Links Utility (
src/lib/utils/external-links.ts)openUrl(url)- Opens URL in system browser (Tauri) or new tab (browser dev mode)isExternalUrl(url)- Detects http/https URLsisNodespaceUrl(url)- Detects nodespace:// URLs@tauri-apps/plugin-openerin desktop mode for native browser integrationEnhanced Link Click Handler (
app-shell.svelte)http://andhttps://links to open in system browsernodespace://links via status barTests
Test Plan
bun run test- all 3488 tests pass (16 new)bun run quality:check- no errorsAcceptance Criteria Status
From issue #837:
nodespace://link shows a helpful error message instead of crashingCloses #837
🤖 Generated with Claude Code