Convert HTML content to markdown in presenter output#184
Conversation
Pure bc-attachment payloads (Basecamp mentions, file references) without wrapping <div>/<p> tags bypassed HTML detection because reSafeTag did not include bc-attachment. This caused raw tags to leak through formatText() and every downstream renderer.
The Basecamp API returns Trix HTML in content, description, and body fields. The TUI already converts via richtext.HTMLToMarkdown → glamour, but the CLI presenter rendered strings verbatim, leaking <div>, <br>, <bc-attachment>, <blockquote>, etc. into every output mode. - formatText() now detects HTML and converts to markdown at the universal formatting point, so all output modes benefit - singleLine() helper collapses multi-line converted content for compact renderers (list rows, task items, table cells, metadata) - RenderHeadline() normalizes HTML headlines and strips emphasis markers that would nest with the bold/primary rendering context
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 06a5ae7b9a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
Updates the presenter output pipeline to detect Basecamp rich-text HTML (including pure <bc-attachment> payloads) and convert HTML to Markdown consistently, while keeping list/table/task renderers compact by collapsing multi-line conversions.
Changes:
- Extend
richtext.IsHTML()detection to treat<bc-attachment>as HTML. - Convert HTML → Markdown in
presenter.formatText()(used byFormatField) and normalize headlines that contain HTML. - Collapse formatted values to a single line in compact renderers (list rows, task items, markdown table cells), with added tests.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/richtext/richtext.go | Expands HTML detection regex to include bc-attachment. |
| internal/richtext/richtext_test.go | Adds IsHTML coverage for bc-attachment variants. |
| internal/presenter/format.go | Adds HTML→Markdown conversion to formatText(); introduces singleLine(). |
| internal/presenter/template.go | Normalizes HTML headlines (convert→single-line→strip bold markers). |
| internal/presenter/render.go | Collapses list/table/task rendered values to a single line for compact views. |
| internal/presenter/presenter_test.go | Adds tests for HTML conversion, single-line collapsing, and headline/task/table behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- singleLine: add fast-path when no newlines to avoid slice allocation
on the common case (every cell/value in list rendering)
- RenderHeadline: replace blanket strings.ReplaceAll("**","") with regex
that unwraps **...** pairs, preserving literal ** in content like 2**10
- Narrow doc comment to describe bold-only unwrapping, not general emphasis
Summary
<bc-attachment>tags inrichtext.IsHTML()so pure-attachment payloads (mentions, file refs) no longer bypass HTML detectionformatText(), the universal text formatting path, so all output modes (terminal, markdown, JSON) get clean contentTest plan
make checkpasses (vet, lint, unit tests, e2e tests)bc-attachmenthandling,singleLine()behavior, headline normalization with<strong>, task metadata HTML, list rows, and table cellsbasecamp reports assigned— no HTML tags in terminal outputbasecamp reports assigned -m— readable markdown, no raw HTML