Skip to content

Keep a contact note's formatting when the TUI edits it - #504

Merged
robzolkos merged 1 commit into
mainfrom
tui-note-keeps-formatting
Sep 27, 2026
Merged

robzolkos merged 1 commit into
mainfrom
tui-note-keeps-formatting

Conversation

@robzolkos

@robzolkos robzolkos commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator

The TUI's contact note editor was handed HEY's plain note — to_plain_text, where bold is dropped and a list item becomes "•" — and saved that text back as the whole note. Editing a note written in HEY's web app, even without changing a word, stripped its bold, lists and links.

The editor now works the way hey contact note set already does:

  • Edit the note as Markdown, read from note_html by htmlutil.ToMarkdown (which ignores the trix-content wrapper), in contactNoteMarkdown.
  • Save it as HTML through htmlutil.FromMarkdown, so bold, italics, lists, links, headings and line breaks round-trip.
  • Show the note in the contact's detail rendered by markdown.Render, as the journal and thread bodies are, rather than as plain text. That is the same htmlutil.Markdown value the editor uses, so the view and the editor agree, and it costs one call.
  • Refuse to open a note in the Markdown editor when it holds an attachment or other markup Markdown cannot preserve, rather than dropping that content on save. The detail remains readable and points at HEY or --note-html for editing.

Terminal safety: the note is now an htmlutil.Markdown from end to end, so escape sequences are stripped before it is shown or edited. The editor used to be handed the plain note raw, escape sequences included. TestSinksAreSanitized still passes.

A note HEY serves as plain text only (it serves both or neither) is HTML-escaped first, so its characters stay literal and are saved back as the same text.

An unchanged save still writes, as before; the difference is that what it writes is now the note's own formatting.

After rebasing onto #500, the TUI uses the same MarkdownIsLossless guard as hey contact note set, so the CLI and TUI make the same preservation decision.

Tests in internal/tui/contacts_test.go, with a real HEY note_html shape:

  • TestContactsViewNoteEditorKeepsFormattingWrittenInHEY: an unchanged save keeps <strong> and the list. Fails on main.
  • TestContactsViewNoteEditorAddsToAFormattedNote: adding a list item keeps the existing formatting, and the detail view renders the result. Fails on main.
  • TestContactsViewNoteStripsEscapeSequences: the detail strips escape sequences and the editor refuses the now-lossy rewrite. Fails on main, where the editor held the sequences raw.
  • TestContactsViewRefusesToEditANoteMarkdownCannotPreserve: a note containing a table remains readable but cannot be opened in the Markdown editor or written.
  • TestContactsViewShowsANoteRenderedFromItsFormatting, TestContactsViewEmptyNoteCannotBeSaved, TestContactNoteMarkdownKeepsPlainTextLiteral: rendering, the empty note, and the plain-text fallback.

docs/tui.md now says the note is edited as Markdown and keeps HEY's formatting.


Summary by cubic

The TUI's contact note editor now keeps a note's formatting when you edit it. It previously edited HEY's plain-text note, so an unchanged save stripped bold, lists, and links. The editor now reads the note's note_html as Markdown, edits and saves it as Markdown HTML (like hey contact note set does), and renders the contact detail view from that same Markdown.

Notes are now stripped of escape sequences before being shown or edited; previously the editor held the raw plain note. A note HEY serves only as plain text is HTML-escaped first, keeping its characters literal. A note carrying formatting Markdown can't preserve — like a table or attachment — is shown but the editor refuses to open it, pointing to hey contact note set --note-html, so an unchanged save can't discard that content. An empty note still can't be saved.

Written for commit fd84490. Summary will update on new commits.

Review in cubic

Copilot AI balanced review requested due to automatic review settings September 26, 2026 18:47
@robzolkos
robzolkos requested a review from a team as a code owner September 26, 2026 18:47
Copilot AI previously approved these changes Sep 26, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approved

The implementation is consistent with existing rich-text and terminal-safety mechanisms and has focused regression coverage.

Review effort: Balanced
Findings: None

What changed in this PR

Preserves contact-note formatting during TUI display, editing, and saving.

Changes:

  • Converts HEY note HTML to safe Markdown and saves edits as HTML.
  • Renders formatted notes in contact details.
  • Adds regression tests and updates TUI documentation.

[!TIP]
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.

File Description
internal/​tui/​contacts.go Adds Markdown-based note handling and rendering.
internal/​tui/​contacts_test.go Tests formatting preservation, rendering, safety, and fallbacks.
docs/​tui.md Documents Markdown note editing.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

The TUI's note editor was handed HEY's plain `note`, which to_plain_text
has flattened: bold is gone and a list item is a "•". Saving sent that text
back as the whole note, so editing a note written in HEY's web app, even
without changing a word, stripped its bold, lists and links.

The editor now works the way `hey contact note set` does: it edits the
note's rich text as Markdown, read from `note_html` by htmlutil.ToMarkdown,
and saves it as HTML through htmlutil.FromMarkdown. The detail view renders
that Markdown with markdown.Render, as the journal and thread bodies do,
rather than printing the plain text. Both go through the sealed Markdown
type, so the note is stripped of escape sequences before it is shown or
edited; the editor used to be handed the plain note raw.

A note containing an attachment or other markup Markdown cannot preserve
is still shown, but the TUI now refuses to open it in the Markdown editor.
That keeps the TUI in line with the CLI's lossless guard and prevents an
unchanged save from discarding unsupported content.
@robzolkos
robzolkos force-pushed the tui-note-keeps-formatting branch from 156583d to fd84490 Compare September 27, 2026 03:04

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Approved. Cursor Security Agent completed with no findings that need human review, and Cursor Bugbot was not running on this PR. No reviewers were assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver

@robzolkos
robzolkos requested a balanced review from Copilot September 27, 2026 03:14
Copilot AI dismissed their stale review, a newer Copilot review was requested September 27, 2026 03:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approved

The implementation matches existing CLI behavior and includes focused coverage for formatting, safety, and unsupported markup.

Review effort: Balanced
Findings: None

@robzolkos
robzolkos merged commit 98697f5 into main Sep 27, 2026
26 checks passed
@robzolkos
robzolkos deleted the tui-note-keeps-formatting branch September 27, 2026 03:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants