Skip to content

emrg: gui — tiptap rich-text composer (Stage 1) - #1062

Merged
argszero merged 1 commit into
masterfrom
feature/tiptap-composer
Aug 28, 2026
Merged

emrg: gui — tiptap rich-text composer (Stage 1)#1062
argszero merged 1 commit into
masterfrom
feature/tiptap-composer

Conversation

@argszero

Copy link
Copy Markdown
Owner

tiptap rich-text composer — Stage 1 (editor core)

Addresses rant 2026-08-28T14:07:29 (GUI 输入框富文本化, design v1, plan A — pure WYSIWYG).

What changed

  • Composer.tsx: replaced the <textarea> with @tiptap/react (useEditor/EditorContent) using @tiptap/starter-kit + @tiptap/extension-link + @tiptap/extension-placeholder + tiptap-markdown for serialization.
  • Markdown serialization (core design principle): on send, editor.storage.markdown.getMarkdown() produces the markdown string and the existing sendMessage path is unchanged — history.jsonl, protocol layer and TUI are untouched (storage stays a markdown string, both ends render markdown).
  • Preserved behaviors: Enter = send, Shift+Enter = newline (hardBreak), Ctrl+Enter = send, / command menu (now driven by editor.onUpdate + keydown interception), height cap ≤150px, G143 pre-generated requestId, P2 busy-queue injection (emrg: queue messages sent while tool loop busy — inject at round boundary (P1, rant 2026-08-10T21:55:37) #655), G49 failure restore (markdown re-fill via setContent).
  • TranscriptView.tsx: user + history messages now render through the existing markdown renderer (TUI UserMarkdown parity) — previously plain text, so **bold** from tiptap would have shown literally. MarkdownText gained a stripMark option (the ✦ strip stays assistant-only).
  • layout.css: .tiptap-input contenteditable rules share the textarea flex/scroll/padding; placeholder styling via p.is-editor-empty (theme-guard 2/2 — all colors via tokens.css vars).
  • Test migration (per rant): Composer.test.tsx switched from userEvent.type on a textarea to editor-command driven tests (editor.commands.insertContent / direct send); Shell.test.tsx chat-wiring tests type into the contenteditable via userEvent.type. test/setup.ts gained jsdom polyfills prosemirror needs (Text/Range.getClientRects, Range.getBoundingClientRect, document.elementFromPoint).

Acceptance coverage (rant)

  • 发送富文本(粗体/链接/列表/代码块)→ 历史存储为等价 markdown 字符串 → transcript 渲染正确: covered by the markdown round-trip test (getMarkdown serialization) + TranscriptView user-markdown render test.
  • 旧纯文本消息编辑回显不损坏: setContent(md) round-trip test (plain text in → plain text out).
  • / 命令菜单键盘导航不回归: menu navigation tests (↑↓ wrap, Enter select, Esc close) + Shell /help/rename/clear wiring tests.
  • GUI 测试全绿: renderer 451/451 + typecheck + build, GUI 87 pass / 8 skip, theme-guard 2/2.

Verification

  • emrg/gui/renderer: npm run typecheck clean · npm test 451/451 (44 files) · npm run build OK
  • emrg/gui: npm test 87 pass / 8 skip · theme-guard 2/2
  • Repo: uv run pytest tests/ 1147 passed + 1 skipped (matches Agent.md)
  • Agent.md renderer breakdown updated 449 → 451 (TranscriptView 7→8, Composer 14→15)

Stage 2 (format bar / shortcuts / paste sanitize) lands in a follow-up cycle.

Replace the Composer textarea with @tiptap/react (StarterKit + Link +
Placeholder + tiptap-markdown). Send path now serializes markdown via
editor.storage.markdown.getMarkdown(); history.jsonl / protocol / TUI
unchanged (storage stays a markdown string). Preserved: Enter-send,
Shift+Enter newline, Ctrl+Enter send, / command menu (onUpdate +
keydown), height cap, G143 requestId, P2 busy queue, G49 failure
restore. TranscriptView now renders user/history messages through the
markdown renderer (TUI parity) so rich text from tiptap displays
correctly. Tests migrated to editor-command style; jsdom polyfills for
prosemirror (getClientRects / elementFromPoint). Renderer 451/451,
GUI 87+8, theme-guard 2/2.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle (1/3)

Reviewed the full diff (Composer.tsx tiptap migration, TranscriptView user-markdown render, layout.css, test migration + jsdom polyfills). Independent verification on this branch:

  • Renderer: npm test 451/451 (44 files), npm run typecheck clean
  • GUI: theme-guard 2/2
  • CI: test + test-windows both pass (run 33149595609), mergeable CLEAN

Acceptance mapping (rant 2026-08-28T14:07:29):

  • Rich text send → markdown stored → transcript renders correctly: covered by markdown round-trip test + TranscriptView user-markdown render test
  • Legacy plain-text messages survive setContent round-trip: round-trip test asserts plain text in/out
  • / command menu keyboard nav preserved: menu nav tests + Shell wiring tests pass

No issues found. Stage 2 (format bar / shortcuts / paste sanitize) tracked in the rant.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle (2/3)

Re-verified PR #1062 (tiptap rich-text composer Stage 1):

  • Head 1a936e2 unchanged since the (1/3) vote; no new commits
  • CI: test + test-windows both pass (run 33149595609)
  • mergeable: MERGEABLE / mergeStateStatus: CLEAN
  • No ❌ or change requests in between; previous ✅ from cycle 150230 still valid

No issues found. Awaiting 1 more consecutive LGTM from a distinct cycle before merge.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle (3/3)

Final re-verification of PR #1062 (tiptap rich-text composer Stage 1):

  • Head 1a936e2 unchanged since (1/3) and (2/3) votes; no new commits
  • CI: test + test-windows both pass (run 33149595609)
  • mergeable: MERGEABLE / mergeStateStatus: CLEAN
  • Three consecutive ✅ from distinct cycles (150230 → 151203 → this cycle), no ❌ in between

Merging now.

@argszero
argszero merged commit 4cdd33e into masterAug 28, 2026
2 checks passed
@argszero
argszero deleted the feature/tiptap-composer branch August 28, 2026 07:21
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@argszero