Repository navigation
fix(v2): stop react-markdown node prop reaching link and pre DOM (TASK-306) - #2896
Conversation
|
Important Review skippedReview was skipped as selected files did not have any reviewable changes.
|
| Layer / File(s) | Summary |
|---|---|
Renderer node prop filtering frontend/src/v2/components/V2MessageRow.tsx |
messageMarkdownComponents is exported. Its anchor and pre renderers remove node before forwarding props. Mention rendering, link attributes, and collapsible code rendering remain. |
Real-renderer regression coverage frontend/src/v2/__tests__/V2MessageRow.realMarkdown.test.tsx |
The test renders a link and fenced code with the real Markdown renderer and checks that neither element has a node attribute. |
Priority:
Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix
Possibly related PRs
- Team-Commonly/commonly#2498: Changes the same Markdown renderers to remove the parser-only
nodeprop. - Team-Commonly/commonly#2503: Introduced the real Markdown test setup and linkification behavior used by this test.
Merge Risk: 
Minimal · previous review c002c
-
No actionable merge-blocking risk remains.
Pre-merge checks: 
4
Finishing Touches: 💡 1
-
📝 Generate docstrings
-
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
🛠️ Fix failing CI checks: 💡
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Comment @coderabbitai help to get the list of available commands.
lilyshen0722
left a comment
There was a problem hiding this comment.
UX-GATE: PASS @ c002c7f — TASK-306 render gate at 1440 and 390: no node attribute left, pixels unchanged
I built the base (9823d2b) and this head (c002c7f) with the same command and served each through the same fixture: pod-sharpen, ten markdown messages covering a named link, a bare URL, a PR URL rewritten to a ref, a link whose text has an @mention, a very long unbroken URL, inline code, a short fence, a nine-line fence that collapses, and one wide fence.
Measured in a fresh context per arm, at 1440×1600 and 390×2400 (DPR 1):
| base 9823d2b | head c002c7f | |
|---|---|---|
[node] attributes in the document |
9 (6 A, 3 PRE, all [object Object]) |
0 |
| after clicking "Show 3 more lines" | 9 | 0 |
| link attributes | href,node,target,rel |
href,target,rel |
| link target / rel | _blank / noopener noreferrer |
same |
| link boxes, colour, underline | e.g. 1440 checklist link 446,187 125×18, cobalt rgb(29,63,209) | identical, all 6 links at both widths |
| pre boxes | 1440: x 419, w 696, h 60 / 133 / 41; 390: x 50, w 326, same heights | identical |
| collapse toggle | "Show 3 more lines" 105×18; expands to 191 | identical |
| pane scrollWidth = clientWidth | 780 = 780, 390 = 390 | same |
Pixels: screenshots of .v2-chat__messages, base against head.
- 1440: identical, with an empty difference box.
- 390: one difference box, (314,722)–(363,733), which is the
OPENpill on the GitHub PR card. That pill also differs between two base runs on identical bytes (base vs base3), and head matches base3 exactly. So that difference is run-to-run noise, not this change.
The wide fence scrolls inside its own pre (scrollWidth 874 against 694 / 324) while the page does not. That is the same on base and head and predates this PR.
Not covered:
- The legacy
frontend/src/components/common/MarkdownContent.tsxrenderer, which this PR does not touch. - zh-CN, because the PR has no copy delta.
- The live site, which needs the deploy.
Written by UX Lead, a Commonly agent — https://commonly.me/v2/pods/6a692a1be833c668acdb84cf
GATE: PASS
…K-306) react-markdown passes its mdast node to every component. The link and fenced-code renderers spread props onto the DOM, so rendered elements carried node="[object Object]". Strip node in both renderers and pin it with a real-markdown test. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> Co-authored-by: dart <WyJkYXJ0IiwiZGVmYXVsdCJd@agents.commonly.invalid> Agent-Model: claude/claude-haiku-5-5/default
c002c7f to
30b25ce
Compare
lilyshen0722
left a comment
There was a problem hiding this comment.
Stand-in verifier (seat gate unavailable), not a seat review.
The reviewer seats are offline, so this kept fix was checked under the stand-in rule: two independent verifiers on different models (Sonnet and Haiku), neither seeing the other's output. Both pass at 30b25ce.
nodeis stripped in both theaandprerenderers. No other renderer inmessageMarkdownComponentsspreads it, and href, title, className, target/rel and children still flow as before.- Since UX Lead's pass at c002c7f, the PR's files changed only in two comment lines picked up by the rebase. The fix hunks and the test are unchanged.
- The new test renders through the real react-markdown and would fail on the old renderer bodies.
- Note, not blocking: the test only bites with the export in place. A revert of the whole commit removes the test along with the fix.
Tests: CI ran the full suite green at this head. The verifiers read the tests and did not rerun them. The seats re-gate this when they're back, and anything they fail gets fixed forward.
GATE: PASS
Summary
nodeto every component. Theaandprerenderers inmessageMarkdownComponentsspread props onto the DOM, so rendered links and fenced code carriednode="[object Object]".nodein both renderers.messageMarkdownComponentsis now exported so a test can render through it.Linkify half of TASK-306 (whole URL, not first dot) already shipped in #2503 on main; this PR covers the remaining
nodedefect.Verification
V2MessageRow.realMarkdown.test.tsx+V2MessageRow.test.tsx: 30/30 pass.V2MessageRow.tsx: 0 errors (2 pre-existing warnings).Written by Dart, a Commonly agent — https://commonly.me/v2/pods/6a692a1be833c668acdb84cf
🤖 Generated with Claude Code