docs(21-02): complete markdown renderer plan — ChatMarkdownMessage, ChatCodeBlock, hljs theme CSS
This commit is contained in:
parent
9e9b38d587
commit
ec345f6067
4 changed files with 110 additions and 8 deletions
|
|
@ -70,7 +70,7 @@
|
|||
### Theme Integration (3)
|
||||
|
||||
- [ ] **THEME-01** — Chat interface respects the Nexus theme system (Catppuccin Mocha, Tokyo Night, Catppuccin Latte)
|
||||
- [ ] **THEME-02** — Code blocks use theme-appropriate syntax highlighting colors
|
||||
- [x] **THEME-02** — Code blocks use theme-appropriate syntax highlighting colors
|
||||
- [ ] **THEME-03** — Agent avatars/colors are visually distinguishable in all three themes
|
||||
|
||||
### Performance (5)
|
||||
|
|
@ -161,7 +161,7 @@ The following are explicitly deferred:
|
|||
| PWA-07 | Phase 26 | Pending |
|
||||
| PWA-08 | Phase 26 | Pending |
|
||||
| THEME-01 | Phase 21 | Pending |
|
||||
| THEME-02 | Phase 21 | Pending |
|
||||
| THEME-02 | Phase 21 | Complete |
|
||||
| THEME-03 | Phase 22 | Pending |
|
||||
| PERF-01 | Phase 26 | Pending |
|
||||
| PERF-02 | Phase 22 | Pending |
|
||||
|
|
|
|||
|
|
@ -31,12 +31,12 @@
|
|||
3. Agent messages render with full markdown: code blocks with syntax highlighting and a copy button, tables, lists, headings, links, and inline images
|
||||
4. Conversations and all messages are stored in libSQL and survive a server restart
|
||||
5. The chat interface applies Catppuccin Mocha, Tokyo Night, and Catppuccin Latte themes correctly; code block highlighting matches the active theme
|
||||
**Plans:** 2/6 plans executed
|
||||
**Plans:** 3/6 plans executed
|
||||
|
||||
Plans:
|
||||
- [x] 21-00-PLAN.md — Wave 0 test stubs (chat-service, chat-routes, ChatMarkdownMessage, ChatInput)
|
||||
- [x] 21-01-PLAN.md — DB schema (chat_conversations + chat_messages) and shared types/validators
|
||||
- [ ] 21-02-PLAN.md — Markdown renderer with rehype-highlight, code block copy button, theme CSS
|
||||
- [x] 21-02-PLAN.md — Markdown renderer with rehype-highlight, code block copy button, theme CSS
|
||||
- [ ] 21-03-PLAN.md — Server chat service and REST API routes (CRUD + pagination)
|
||||
- [ ] 21-04-PLAN.md — ChatPanel shell, ChatPanelContext, ChatInput, Layout integration
|
||||
- [ ] 21-05-PLAN.md — Full UI wiring: API client, conversation list, message thread, infinite scroll
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ gsd_state_version: 1.0
|
|||
milestone: v1.3
|
||||
milestone_name: milestone
|
||||
status: executing
|
||||
stopped_at: Completed 21-chat-foundation-21-00-PLAN.md
|
||||
last_updated: "2026-04-01T16:39:05.467Z"
|
||||
stopped_at: Completed 21-chat-foundation-21-02-PLAN.md
|
||||
last_updated: "2026-04-01T16:42:00.000Z"
|
||||
last_activity: 2026-04-01
|
||||
progress:
|
||||
total_phases: 6
|
||||
|
|
@ -59,6 +59,7 @@ Progress: [░░░░░░░░░░] 0%
|
|||
|
||||
*Updated after each plan completion*
|
||||
| Phase 01-foundation P01 | 2 | 2 tasks | 7 files |
|
||||
| Phase 21-chat-foundation P02 | ~15min | 2 tasks | 5 files |
|
||||
| Phase 21-chat-foundation P01 | 2 | 2 tasks | 8 files |
|
||||
| Phase 21-chat-foundation P00 | 2 | 2 tasks | 4 files |
|
||||
|
||||
|
|
@ -81,6 +82,8 @@ Recent decisions affecting current work:
|
|||
- [Phase 21-chat-foundation]: Used object-syntax (table) => ({}) for Drizzle index callbacks to match existing codebase convention in documents.ts, agents.ts
|
||||
- [Phase 21-chat-foundation]: Use it.todo() (not it.skip()) for Wave 0 test scaffolding — vitest marks todos semantically, no false positives
|
||||
- [Phase 21-chat-foundation]: Minimal imports in test stubs — no service mocks until Plans 01-05 wire up implementations
|
||||
- [Phase 21-02]: Use ExtraProps from react-markdown for ChatCodeBlock type signature to satisfy ComponentType constraint
|
||||
- [Phase 21-02]: Add hljs CSS as plain rules (not @import) scoped to .dark, .theme-tokyo-night, :root selectors
|
||||
|
||||
### Pending Todos
|
||||
|
||||
|
|
@ -93,6 +96,6 @@ None yet.
|
|||
|
||||
## Session Continuity
|
||||
|
||||
Last session: 2026-04-01T16:39:05.464Z
|
||||
Stopped at: Completed 21-chat-foundation-21-00-PLAN.md
|
||||
Last session: 2026-04-01T16:42:00.000Z
|
||||
Stopped at: Completed 21-chat-foundation-21-02-PLAN.md
|
||||
Resume file: None
|
||||
|
|
|
|||
99
.planning/phases/21-chat-foundation/21-02-SUMMARY.md
Normal file
99
.planning/phases/21-chat-foundation/21-02-SUMMARY.md
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
---
|
||||
phase: 21-chat-foundation
|
||||
plan: "02"
|
||||
subsystem: ui
|
||||
tags: [chat, markdown, syntax-highlighting, rehype-highlight, components]
|
||||
dependency_graph:
|
||||
requires: ["21-00"]
|
||||
provides: [ChatMarkdownMessage, ChatCodeBlock]
|
||||
affects: [chat-message-list]
|
||||
tech_stack:
|
||||
added: [rehype-highlight@7.0.2]
|
||||
patterns: [TDD, ExtraProps-typed react-markdown components]
|
||||
key_files:
|
||||
created:
|
||||
- ui/src/components/ChatMarkdownMessage.tsx
|
||||
- ui/src/components/ChatCodeBlock.tsx
|
||||
- ui/src/components/ChatMarkdownMessage.test.tsx
|
||||
modified:
|
||||
- ui/package.json
|
||||
- ui/src/index.css
|
||||
decisions:
|
||||
- Use ExtraProps from react-markdown for ChatCodeBlock type signature to satisfy ComponentType constraint
|
||||
- Add hljs CSS as plain rules (not @import) scoped to .dark, .theme-tokyo-night, :root selectors
|
||||
metrics:
|
||||
duration: ~15 minutes
|
||||
completed_date: "2026-04-01"
|
||||
tasks: 2
|
||||
files: 5
|
||||
---
|
||||
|
||||
# Phase 21 Plan 02: Chat Markdown Renderer with Syntax Highlighting Summary
|
||||
|
||||
**One-liner:** rehype-highlight markdown renderer with theme-aware hljs CSS overrides and ChatCodeBlock copy button using navigator.clipboard.writeText.
|
||||
|
||||
## Completed Tasks
|
||||
|
||||
| Task | Name | Commit | Files |
|
||||
|------|------|--------|-------|
|
||||
| 1 | Install rehype-highlight and add hljs theme CSS overrides | 3e2bc1ae | ui/package.json, ui/src/index.css |
|
||||
| 2 (RED) | Add failing tests for ChatMarkdownMessage | 732032a6 | ui/src/components/ChatMarkdownMessage.test.tsx |
|
||||
| 2 (GREEN) | Create ChatCodeBlock and ChatMarkdownMessage components | 576e302a | ui/src/components/ChatCodeBlock.tsx, ui/src/components/ChatMarkdownMessage.tsx |
|
||||
|
||||
## What Was Built
|
||||
|
||||
### ChatMarkdownMessage
|
||||
|
||||
Markdown renderer component wrapping react-markdown with:
|
||||
- `rehypePlugins={[rehypeHighlight]}` — applies hljs token classes to code blocks
|
||||
- `remarkPlugins={[remarkGfm]}` — GitHub Flavored Markdown
|
||||
- `components={{ pre: ChatCodeBlock }}` — custom code block with toolbar
|
||||
- `paperclip-markdown` class — picks up existing prose styles from index.css
|
||||
|
||||
### ChatCodeBlock
|
||||
|
||||
Pre-element override for react-markdown that provides:
|
||||
- **Language label** extracted from `language-xxx` className on the child `<code>` element
|
||||
- **Copy button** using `navigator.clipboard.writeText` (Copy/Check icon toggle with 1500ms success state)
|
||||
- **Plain pre fallback** when no code child present (e.g. plain preformatted text)
|
||||
- Typed using `HTMLAttributes<HTMLPreElement> & ExtraProps` to satisfy react-markdown's `ComponentType` constraint
|
||||
|
||||
### Highlight.js Theme CSS (index.css)
|
||||
|
||||
Added 60 lines of CSS overrides covering 15 token types across three themes:
|
||||
- `.dark .hljs*` — Catppuccin Mocha palette (#cba6f7 keywords, #a6e3a1 strings, etc.)
|
||||
- `.theme-tokyo-night .hljs*` — Tokyo Night palette (#bb9af7 keywords, #9ece6a strings, etc.)
|
||||
- `:root .hljs*` — Catppuccin Latte palette (#8839ef keywords, #40a02b strings, etc.)
|
||||
|
||||
No external CSS file imports — all overrides are scoped custom properties, avoiding FOUC and theme conflicts.
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Auto-fixed Issues
|
||||
|
||||
**1. [Rule 1 - Bug] Fixed ChatCodeBlock TypeScript type signature**
|
||||
- **Found during:** Task 2 — TypeScript type check after implementation
|
||||
- **Issue:** `[key: string]: unknown` index signature incompatible with `ClassAttributes<HTMLPreElement> & HTMLAttributes<HTMLPreElement> & ExtraProps` from react-markdown
|
||||
- **Fix:** Changed component props type to `HTMLAttributes<HTMLPreElement> & ExtraProps` (importing `ExtraProps` from `react-markdown`)
|
||||
- **Files modified:** `ui/src/components/ChatCodeBlock.tsx`
|
||||
- **Commit:** 576e302a (included in same commit)
|
||||
|
||||
## Verification Results
|
||||
|
||||
- `pnpm --filter @paperclipai/ui exec -- tsc --noEmit` — PASS (0 errors)
|
||||
- `pnpm vitest run ui/src/components/ChatMarkdownMessage.test.tsx` — PASS (4/4 tests)
|
||||
- `rehype-highlight` present in ui/package.json — PASS
|
||||
- `.dark .hljs-keyword { color: #cba6f7; }` in index.css — PASS
|
||||
- `.theme-tokyo-night .hljs-keyword { color: #bb9af7; }` in index.css — PASS
|
||||
- `:root .hljs-keyword { color: #8839ef; }` in index.css — PASS
|
||||
- `navigator.clipboard.writeText` in ChatCodeBlock — PASS
|
||||
- `aria-label="Copy code"` / `"Copied!"` in ChatCodeBlock — PASS
|
||||
- Language extraction from `language-xxx` pattern — PASS
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
All files created and commits verified.
|
||||
|
||||
## Known Stubs
|
||||
|
||||
None — both components are fully wired. ChatMarkdownMessage uses rehype-highlight for real syntax highlighting; ChatCodeBlock calls navigator.clipboard.writeText for real copy functionality.
|
||||
Loading…
Add table
Reference in a new issue