8.6 KiB
| phase | plan | type | wave | depends_on | files_modified | autonomous | gap_closure | requirements | must_haves | |||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 25-file-system | 04 | execute | 1 |
|
|
true | true |
|
|
Purpose: FILE-06 requires "code files show a syntax-highlighted preview" but ChatFilePreview currently renders only a ChatFileCard for code files. This plan fetches code file content via the existing GET /api/files/:fileId/content endpoint and renders it with highlight.js (already installed and used by ChatMarkdownMessage via rehype-highlight). Also formally marks FILE-07 (download) and FILE-13 (cross-device access) as Complete since they are functionally implemented.
Output: ChatCodeFilePreview component, updated ChatFilePreview, updated REQUIREMENTS.md
<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/25-file-system/25-03-SUMMARY.md Task 1: Create ChatCodeFilePreview component ui/src/components/ChatCodeFilePreview.tsx - ui/src/components/ChatFilePreview.tsx - ui/src/components/ChatCodeBlock.tsx - ui/src/components/ChatMarkdownMessage.tsx - ui/src/index.css (for hljs theme CSS classes) Create `ui/src/components/ChatCodeFilePreview.tsx` that:- Accepts props:
{ file: ChatFile; contentPath: string }(same as ChatFilePreview) - Uses
useStateforcontent: string | null,loading: boolean,error: boolean - Uses
useEffectto fetchcontentPathwithcredentials: "include"and read as text. Cap at 50KB (if text.length > 50000, truncate and append\n// ... truncated). Set loading=false after fetch. - While loading, render a skeleton:
<div className="rounded-lg border border-border bg-muted animate-pulse h-[120px]" /> - On error, fall back to
<ChatFileCard file={file} contentPath={contentPath} /> - On success, render:
- A
<div className="paperclip-markdown rounded-lg border border-border overflow-hidden">wrapper (thepaperclip-markdownclass activates existing hljs theme CSS) - A header bar:
<div className="flex items-center justify-between bg-card border-b border-border px-3 py-1">with:- Language label from file extension (use extToLang mapping function)
- Copy button using same pattern as ChatCodeBlock (Copy/Check icons from lucide-react, navigator.clipboard.writeText)
- A
<pre><code>block. Usehljs.highlight(content, { language: lang })fromhighlight.js/lib/coreto produce highlighted HTML. Render the highlighted output safely. hljs.highlight produces only<span class="hljs-...">tokens from source code — this is the same trust model as rehype-highlight used in ChatMarkdownMessage. If the language is not registered, fall back tohljs.highlightAuto(content). - Max height:
max-h-[400px] overflow-auto - Below the code block, render
<ChatFileCard file={file} contentPath={contentPath} />for the download button
- A
Import highlight.js: import hljs from "highlight.js/lib/core". Since rehype-highlight already uses highlight.js, the package is available. Register common languages explicitly (import from highlight.js/lib/languages/...) for: typescript, javascript, python, css, json, xml, bash, sql, go, rust, java, cpp, markdown, yaml.
Extension-to-language map function:
function extToLang(filename: string): string {
const ext = filename.split(".").pop()?.toLowerCase() ?? "";
const map: Record<string, string> = {
ts: "typescript", tsx: "typescript", js: "javascript", jsx: "javascript",
py: "python", rb: "ruby", rs: "rust", go: "go", java: "java",
css: "css", html: "xml", json: "json", sh: "bash", bash: "bash",
yaml: "yaml", yml: "yaml", toml: "ini", md: "markdown",
c: "c", cpp: "cpp", cs: "csharp", kt: "kotlin", swift: "swift",
php: "php", sql: "sql", xml: "xml",
};
return map[ext] ?? ext;
}
cd /opt/nexus && npx tsc --noEmit -p ui/tsconfig.json 2>&1 | head -20
- File `ui/src/components/ChatCodeFilePreview.tsx` exists
- Contains `import hljs from` for highlight.js
- Contains `fetch(contentPath` for loading file content
- Contains `hljs.highlight` for rendering highlighted code
- Contains `paperclip-markdown` class on wrapper div
- Contains `ChatFileCard` import and render for download fallback
- Contains `max-h-[400px]` for scroll containment
- Contains `extToLang` or equivalent extension mapping function
ChatCodeFilePreview component renders fetched code content with syntax highlighting, copy button, language label, and download card
Task 2: Wire ChatCodeFilePreview into ChatFilePreview and update REQUIREMENTS.md
ui/src/components/ChatFilePreview.tsx, .planning/REQUIREMENTS.md
- ui/src/components/ChatFilePreview.tsx
- ui/src/components/ChatCodeFilePreview.tsx
- .planning/REQUIREMENTS.md
1. Update `ui/src/components/ChatFilePreview.tsx`:
- Add import: `import { ChatCodeFilePreview } from "./ChatCodeFilePreview";`
- Add a new branch before the fallback return, after the image branch:
```
if (file.category === "code") {
return ;
}
```
- Keep the existing fallback `return ` for document/other categories
- Update
.planning/REQUIREMENTS.md:- Change FILE-07 line from
- [ ] **FILE-07**to- [x] **FILE-07**(ChatFileCard implements one-click download) - Change FILE-13 line from
- [ ] **FILE-13**to- [x] **FILE-13**(GET /api/files/:fileId/content serves files over HTTP for cross-device access) - In the Traceability table, change FILE-07 status from
PendingtoComplete - In the Traceability table, change FILE-13 status from
PendingtoCompletecd /opt/nexus && grep -n "ChatCodeFilePreview" ui/src/components/ChatFilePreview.tsx && grep "FILE-07" .planning/REQUIREMENTS.md | head -3 && grep "FILE-13" .planning/REQUIREMENTS.md | head -3 <acceptance_criteria> ui/src/components/ChatFilePreview.tsxcontainsimport { ChatCodeFilePreview }ui/src/components/ChatFilePreview.tsxcontainsfile.category === "code"branch routing to ChatCodeFilePreview.planning/REQUIREMENTS.mdcontains- [x] **FILE-07**.planning/REQUIREMENTS.mdcontains- [x] **FILE-13**- REQUIREMENTS.md Traceability table shows FILE-07 as Complete
- REQUIREMENTS.md Traceability table shows FILE-13 as Complete </acceptance_criteria> Code files in chat messages render with syntax highlighting; FILE-07 and FILE-13 marked Complete in REQUIREMENTS.md
- Change FILE-07 line from
<success_criteria>
- Code file attachments in chat render with syntax-highlighted preview (not just a download card)
- FILE-07 and FILE-13 marked Complete in REQUIREMENTS.md
- TypeScript compiles without errors </success_criteria>