5.4 KiB
5.4 KiB
phase, plan, subsystem, tags, dependency_graph, tech_stack, key_files, decisions, metrics
| phase | plan | subsystem | tags | dependency_graph | tech_stack | key_files | decisions | metrics | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| quick-3 | 01 | navigation |
|
|
|
|
|
|
Quick Task 3: Remote Markdown Page Linking Summary
One-liner: Domain-whitelisted HTTP/HTTPS link following with ureq, content-type validation, BBS error screens, and browser history integration.
What Was Built
Users can now follow HTTP/HTTPS links in markdown documents. When a link is activated:
- The domain is extracted from the URL and checked against
allowed_remote_domainsinbbs.toml. - If allowed, ureq fetches the URL with a 10-second timeout.
- The Content-Type header is validated (accepts
text/markdown,text/plain,text/x-markdown, or any.mdURL). - The response body is read with a 5 MB cap.
- The fetched markdown is rendered in the TUI exactly like a local page.
- Remote pages participate in browser history (Backspace/Alt+Left goes back; re-fetches on return).
Error cases show BBS-themed error screens (no history entry pushed):
- Domain not whitelisted: shows domain name and config hint
- Fetch error (network, timeout, non-2xx): shows HTTP status or error message
- Not markdown (HTML, binary): shows Content-Type received
HTTP/HTTPS links are styled in LightMagenta to visually distinguish them from local LightCyan links.
Tasks Completed
| Task | Name | Commit | Key Files |
|---|---|---|---|
| 1 | Add config field, ureq dependency, and remote fetch function | 5759ec8 |
Cargo.toml, src/config.rs, src/vault.rs |
| 2 | Wire remote link navigation into app event loop with history and error screens | c8d4754 |
src/app.rs, src/renderer.rs |
Key Changes
Cargo.toml
- Added
ureq = "2.12"dependency
src/config.rs
- Added
allowed_remote_domains: Vec<String>field with#[serde(default)] - Updated
Defaultimpl to include empty Vec
src/vault.rs
- Added
RemoteDocumentenum (Loaded,DomainNotAllowed,FetchError,NotMarkdown) - Added
extract_domain()— strips scheme, path, port from URL - Added
domain_is_allowed()— exact + subdomain matching (case-insensitive) - Added
fetch_remote_markdown()— whitelist check, 10s timeout, content-type validation, 5MB cap
src/renderer.rs
- HTTP/HTTPS links styled
LightMagentainEvent::Start(Tag::Link)handler (non-wiki, non-local branch)
src/app.rs
- Added
current_url: Option<String>field (Some = remote page, None = local page) - Added
navigate_to_remote()method — saves history, fetches, renders, pushes entry on success - Updated
follow_selected_link()to detect HTTP/HTTPS and dispatch tonavigate_to_remote() - Updated
navigate_back()andnavigate_forward()to re-fetch remote URLs from history - Updated
handle_resize()to passNonevault_path for remote pages - Updated
reload_current_document()to skip live-reload for remote pages - Updated
navigate_to()to clearcurrent_urlwhen going to a local page
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Bug] Fixed clippy lint: manual split_once pattern
- Found during: Task 2 verification (cargo clippy)
- Issue:
url.splitn(2, "://").nth(1)andresp.status_text().to_string()triggered clippy warnings - Fix: Replaced with
url.split_once("://")?.1and removed redundant.to_string()in format! - Files modified: src/vault.rs, src/app.rs
- Commit:
c8d4754
Out-of-scope items (deferred)
None discovered.
Verification Results
cargo buildpasses with no errors (3 pre-existing warnings, unrelated to this task)cargo clippypasses with warnings only (no new errors introduced)- HTTP links styled LightMagenta (verified in renderer.rs code path)
- Domain whitelist check with exact and subdomain matching implemented
- All 4 RemoteDocument variants handled with appropriate error screens
- History integration tested via code review (back/forward re-fetch remote URLs)
- handle_resize passes None vault_path for remote pages
- reload_current_document returns early for remote pages
Self-Check: PASSED
Files exist:
- Cargo.toml: FOUND (ureq = "2.12")
- src/config.rs: FOUND (allowed_remote_domains field)
- src/vault.rs: FOUND (fetch_remote_markdown function)
- src/app.rs: FOUND (navigate_to_remote method, current_url field)
- src/renderer.rs: FOUND (LightMagenta branch)
Commits exist: