rowboat/apps/x/PLAN.md

83 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
1. Add `knowledge:readHtmlFile` handler in `apps/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
2. Add the channel type to `packages/shared/src/ipc.ts`
### Test ✅
- Open a `.html` file 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.txt` is 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
1. In the file loading logic (`App.tsx:12841357`), when extension is `.html`:
- Call `knowledge:readHtmlFile` via IPC
- Store the HTML string in state
2. In the knowledge view render switch (`App.tsx:45224527`):
- Add a condition: if extension is `.html` → render `<HtmlFileViewer html={htmlContent} />`
- Otherwise fall through to existing `<pre>` fallback
3. Create `apps/renderer/src/components/html-file-viewer.tsx`:
- Accepts `html: string` prop
- Renders `<iframe srcdoc={html} sandbox="allow-scripts" />` with full width/height, no border
### Test ✅
- Open a real `.html` file 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
1. Loading state — show a spinner while the IPC call is in flight
2. Error state — if `knowledge:readHtmlFile` throws (file deleted, permission error), show a clean error message with the file path
3. Empty file — if HTML string is empty, show "This file is empty" instead of a blank iframe
4. 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 `.html` file → "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 uses `srcdoc` which 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