mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-05-11 00:02:38 +02:00
3.6 KiB
3.6 KiB
HTML File Rendering — Implementation Plan
Goal
Replace the <pre> raw text fallback in the knowledge view with a proper HTML file renderer using <iframe srcdoc sandbox="allow-scripts">.
Scope
- Only HTML file rendering for now
- No layout changes, no split pane
- No other file types in this PR
Phase 1 — IPC: Read HTML file content and pass to renderer
What
Add an IPC handler in the main process that reads a local HTML file and returns its content as a string to the renderer.
Work
- Add
knowledge:readHtmlFilehandler inapps/main/src/ipc.ts- Accepts a workspace-relative path
- Resolves to absolute path, validates it stays inside workspace root (path traversal guard)
- Reads file as UTF-8 string
- Returns the HTML string to renderer
- Add the channel type to
packages/shared/src/ipc.ts
Test ✅
- Open a
.htmlfile from the knowledge tree - Console log the returned string in the renderer
- Verify: correct HTML content is returned, no errors
- Verify: attempting a path like
../../secret.txtis rejected with an error
Phase 2 — Renderer: Detect .html files and render in iframe
What
In App.tsx, detect when selectedPath is an .html file and render it in a sandboxed <iframe srcdoc> instead of the <pre> fallback.
Work
- In the file loading logic (
App.tsx:1284–1357), when extension is.html:- Call
knowledge:readHtmlFilevia IPC - Store the HTML string in state
- Call
- In the knowledge view render switch (
App.tsx:4522–4527):- Add a condition: if extension is
.html→ render<HtmlFileViewer html={htmlContent} /> - Otherwise fall through to existing
<pre>fallback
- Add a condition: if extension is
- Create
apps/renderer/src/components/html-file-viewer.tsx:- Accepts
html: stringprop - Renders
<iframe srcdoc={html} sandbox="allow-scripts" />with full width/height, no border
- Accepts
Test ✅
- Open a real
.htmlfile from the knowledge tree - Verify: file renders visually in the iframe (not raw text)
- Verify: a non-html file still shows the
<pre>fallback (no regression) - Verify: an HTML file with a
<script>tag runs its JS (allow-scripts works) - Verify: an HTML file with
<script src="https://evil.com">— open network tab, confirm no request is made (allow-same-origin is absent, so external scripts are blocked by default CSP)
Phase 3 — Polish: Loading state, error state, empty file handling
What
Handle edge cases so the viewer never shows a broken or confusing UI.
Work
- Loading state — show a spinner while the IPC call is in flight
- Error state — if
knowledge:readHtmlFilethrows (file deleted, permission error), show a clean error message with the file path - Empty file — if HTML string is empty, show "This file is empty" instead of a blank iframe
- Large files — if file is over a reasonable size limit (e.g. 5MB), show "File too large to preview — Open in system" button that calls
shell.openPath
Test ✅
- Open a valid HTML file → renders correctly
- Delete the file while it's open, trigger a reload → error state shown cleanly
- Open an empty
.htmlfile → "This file is empty" message shown - Simulate a file over 5MB → "File too large" message with open button shown
- Verify: no console errors in any of the above scenarios
Out of scope for this PR
- PDF, DOCX, image, video rendering
- Split pane / resizable layout
- Relative asset loading (
./style.css) — Phase 2 usessrcdocwhich has no base URL; assets will not load. Acceptable for now, documented as known limitation. app://custom protocol — not needed until we handle relative assets