Skip to content

fix: render mentions, emojis, and inline elements inside headings - #6911

Merged
Rohit3523 merged 48 commits into
developfrom
mention-markdown-fix
Aug 2, 2026
Merged

fix: render mentions, emojis, and inline elements inside headings#6911
Rohit3523 merged 48 commits into
developfrom
mention-markdown-fix

Conversation

@Rohit3523

@Rohit3523 Rohit3523 commented Jan 11, 2026

Copy link
Copy Markdown
Member

Proposed changes

Users and channels mentioned inside bold, italic, strike, and headings were rendered as raw text (e.g. @user inside **bold** showed as plain @user instead of a tappable mention). Headings only supported plain text — all other inline elements were silently dropped.

This PR fixes the markdown renderer to properly parse and display all inline elements inside formatting wrappers and headings.

Issue(s)

https://rocketchat.atlassian.net/browse/CORE-1667
https://rocketchat.atlassian.net/browse/SUP-1071

How to test or reproduce

  1. Send a message with mixed formatting, e.g.:

    • **@user \*hello\*** — bold mention
    • _@user hello_ — italic mention
    • ~@user hello~ — strikethrough mention
    • # H1 **bold** _italic_ ~strike~ :rocket: @user #channel https://rocket.chat
  2. Verify:

    • Mentions inside bold/italic/strike are tappable (navigate to user profile)
    • Channels inside bold/italic/strike are tappable (navigate to channel)
    • Headings render all inline elements (bold, italic, strike, code, emoji, mentions, channels, links)
    • Text is not clipped on iOS (especially in headings with mixed content)
    • Bold+italic text on Android renders at the correct weight (not synthetic italic weight)

Screenshots

Before After (Android) After (iOS)
Screenshot 2026-03-15 at 7 20 07 PM Screenshot 2026-07-30 at 6 14 12 PM Screenshot 2026-07-30 at 7 03 45 PM
Screenshot 2026-07-07 at 1 27 25 AM Screenshot 2026-07-30 at 6 15 39 PM Screenshot 2026-07-30 at 7 04 35 PM
Screenshot 2026-07-07 at 1 26 31 AM Screenshot 2026-07-30 at 7 12 12 PM Screenshot 2026-07-30 at 7 12 26 PM
Screenshot 2026-07-10 at 12 22 53 AM Screenshot 2026-07-30 at 7 14 19 PM Screenshot 2026-07-30 at 7 14 31 PM

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • Improvement (non-breaking change which improves a current function)
  • New feature (non-breaking change which adds functionality)
  • Documentation update (if none of the other choices apply)

Checklist

  • I have read the CONTRIBUTING doc
  • I have signed the CLA
  • Lint and unit tests pass locally with my changes
  • I have added tests that prove my fix is effective or that my feature works (if applicable)
  • I have added necessary documentation (if applicable)
  • Any dependent changes have been merged and published in downstream modules

Further comments

This PR is inspired by the earlier work in #5367 by @brf153.

That PR is outdated and has conflicts, so I reimplemented the changes from scratch
and added additional improvements to match the current codebase.
All credit for the original idea goes to @brf153.

Summary by CodeRabbit

New Features

  • Added a story showcasing combined user mentions and channel hashtags inside bold, italic, and strikethrough text.

Improvements

  • Markdown now correctly renders and navigates user mentions and channel hashtags within formatted text.
  • Mention styling strengthened on Android for improved legibility.

@coderabbitai

coderabbitai Bot commented Jan 11, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (4)
  • android/app/src/main/assets/fonts/Inter-Bold_italic.otf is excluded by !**/*.otf
  • android/app/src/main/assets/fonts/Inter-Medium_italic.otf is excluded by !**/*.otf
  • android/app/src/main/assets/fonts/Inter-Regular_italic.otf is excluded by !**/*.otf
  • android/app/src/main/assets/fonts/Inter-SemiBold_italic.otf is excluded by !**/*.otf

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e1e9f095-6380-495a-98c4-72cb781904e6

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Inline markdown components (Bold, Italic, Strike) now consume MarkdownContext and render MENTION_USER via AtMention and MENTION_CHANNEL via Hashtag. The Markdown stories file adds a shared channels constant and a MentionsWithFormatting story; mention style gets an Android-specific fontWeight override.

Changes

Cohort / File(s) Summary
Stories
app/containers/markdown/Markdown.stories.tsx
Adds exported channels constant, introduces MentionsWithFormatting story (renders mentions in normal, bold, italic, strike variants), and updates Hashtag story to use the shared channels.
Inline formatting components
app/containers/markdown/components/inline/*Bold.tsx, app/containers/markdown/components/inline/*Italic.tsx, app/containers/markdown/components/inline/*Strike.tsx
Each file now imports and consumes MarkdownContext (useRealName, username, navToRoomInfo, mentions, channels). MENTION_USER blocks are rendered via AtMention; MENTION_CHANNEL via Hashtag. Existing handlers (LINK, PLAIN_TEXT, other formatting) are preserved.
Styles
app/containers/markdown/styles.ts
mention style augmented with Platform.select to apply fontWeight: '700' on Android while keeping existing semibold styles.

Sequence Diagram(s)

sequenceDiagram
    participant Parser as Markdown Parser
    participant Inline as Inline Component
    participant Context as MarkdownContext
    participant AtMention as AtMention
    participant Hashtag as Hashtag
    participant UI as Rendered UI

    Parser->>Inline: emit blocks (text, MENTION_USER, MENTION_CHANNEL, formatting)
    Inline->>Context: read useRealName, username, navToRoomInfo, mentions, channels
    Inline->>AtMention: render MENTION_USER with context props
    Inline->>Hashtag: render MENTION_CHANNEL with channels + navToRoomInfo
    AtMention->>UI: return interactive user mention node
    Hashtag->>UI: return interactive channel mention node
    Inline->>UI: return composed formatted text nodes
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title mentions emojis and headings, but the PR only fixes mention rendering in Markdown formatting like bold, italic, and strikethrough. Revise the title to focus on the actual change, such as fixing mention rendering inside Markdown formatting.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes comprehensively address CORE-1667 requirements: mentions now render correctly within Markdown formatting (Bold, Italic, Strike components updated), and channel mentions are now interactive via Hashtag component.
Out of Scope Changes check ✅ Passed All changes directly support the objective of fixing mention rendering in Markdown: updates to inline formatting components, context-aware rendering in stories, and Android-specific styling adjustments are all focused on this issue.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In @app/containers/markdown/components/inline/Bold.tsx:
- Around line 22-63: The mapped elements inside the Bold component's value.map
(switch on block.type) are missing React key props; update each returned element
(Link, Plain, Strike, Italic, Hashtag, AtMention) to include a unique key
(prefer a stable id from block or block.value if available, otherwise derive a
stable string like `${block.type}-${index}`) so React can reconcile list items
properly; modify the JSX returns in Bold to add key={...} on each returned
component while keeping existing props.

In @app/containers/markdown/components/inline/Italic.tsx:
- Around line 21-62: The mapped children in the Italic component (inside
value.map) are missing key props; for every element returned (Link, Plain,
Strike, Bold, Hashtag, AtMention, etc.) add a unique key (preferably a stable id
on block like block.id or block.value.id, falling back to the map index only if
no stable id exists) so each returned element from value.map has a key prop to
satisfy React's list reconciliation.

In @app/containers/markdown/components/inline/Strike.tsx:
- Around line 21-62: The mapped elements inside Strike's value.map() (components
Link, Plain, Bold, Italic, Hashtag, AtMention returned from the switch) are
missing React key props; add a unique key prop to each returned element in the
value.map callback (prefer a stable identifier from the block object if
available, e.g., block.id or block.value.id, and fall back to the map index only
if no stable id exists) so every element rendered by Strike has a proper key for
reconciliation.
🧹 Nitpick comments (1)
app/containers/markdown/components/inline/Bold.tsx (1)

1-65: Consider extracting shared logic to reduce duplication.

Bold.tsx, Italic.tsx, and Strike.tsx have nearly identical structure—they differ only in the style prop passed to Hashtag and AtMention. Extracting a shared helper function or higher-order component would reduce duplication and improve maintainability.

💡 Example refactoring approach

Create a shared helper:

// utils/renderInlineWithMentions.tsx
const renderInlineBlock = (
  block: any,
  index: number,
  context: MarkdownContextType,
  customStyle: any
) => {
  const { useRealName, username, navToRoomInfo, mentions, channels } = context;
  
  switch (block.type) {
    case 'LINK':
      return <Link key={index} value={block.value} />;
    case 'PLAIN_TEXT':
      return <Plain key={index} value={block.value} />;
    case 'STRIKE':
      return <Strike key={index} value={block.value} />;
    case 'ITALIC':
      return <Italic key={index} value={block.value} />;
    case 'BOLD':
      return <Bold key={index} value={block.value} />;
    case 'MENTION_CHANNEL':
      return (
        <Hashtag
          key={index}
          hashtag={block.value.value}
          channels={channels}
          navToRoomInfo={navToRoomInfo}
          style={[customStyle]}
        />
      );
    case 'MENTION_USER':
      return (
        <AtMention
          key={index}
          mention={block.value.value}
          username={username}
          navToRoomInfo={navToRoomInfo}
          style={[customStyle]}
          useRealName={useRealName}
          mentions={mentions}
        />
      );
    default:
      return null;
  }
};

Then simplify each component:

const Bold = ({ value }: IBoldProps) => {
  const context = useContext(MarkdownContext);
  return (
    <Text style={styles.text}>
      {value.map((block, index) => 
        renderInlineBlock(block, index, context, { fontWeight: 'bold' })
      )}
    </Text>
  );
};
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ede2569 and cfb112b.

⛔ Files ignored due to path filters (1)
  • app/containers/markdown/__snapshots__/Markdown.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (4)
  • app/containers/markdown/Markdown.stories.tsx
  • app/containers/markdown/components/inline/Bold.tsx
  • app/containers/markdown/components/inline/Italic.tsx
  • app/containers/markdown/components/inline/Strike.tsx
🧰 Additional context used
🧬 Code graph analysis (4)
app/containers/markdown/components/inline/Italic.tsx (1)
app/containers/markdown/Markdown.stories.tsx (1)
  • Hashtag (118-122)
app/containers/markdown/Markdown.stories.tsx (2)
app/containers/MessageComposer/components/Toolbar/Markdown.tsx (1)
  • Markdown (9-46)
app/containers/markdown/components/mentions/index.tsx (1)
  • Hashtag (4-4)
app/containers/markdown/components/inline/Strike.tsx (2)
app/containers/markdown/components/inline/index.ts (4)
  • Strike (6-6)
  • Link (6-6)
  • Bold (6-6)
  • Italic (6-6)
app/containers/markdown/components/mentions/index.tsx (2)
  • Hashtag (4-4)
  • AtMention (4-4)
app/containers/markdown/components/inline/Bold.tsx (2)
app/containers/markdown/components/inline/index.ts (4)
  • Bold (6-6)
  • Link (6-6)
  • Strike (6-6)
  • Italic (6-6)
app/containers/markdown/components/mentions/index.tsx (2)
  • Hashtag (4-4)
  • AtMention (4-4)
🪛 Biome (2.1.2)
app/containers/markdown/components/inline/Italic.tsx

[error] 29-29: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 31-31: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 33-33: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 35-35: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 38-43: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 47-54: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

app/containers/markdown/components/inline/Strike.tsx

[error] 29-29: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 31-31: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 33-33: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 35-35: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 38-43: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 47-54: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

app/containers/markdown/components/inline/Bold.tsx

[error] 30-30: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 32-32: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 34-34: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 36-36: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 39-44: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 48-55: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: ESLint and Test / run-eslint-and-test
🔇 Additional comments (2)
app/containers/markdown/Markdown.stories.tsx (2)

80-80: LGTM!

The extracted channels constant improves reusability across stories.


89-116: Good test coverage for mention formatting combinations.

The new MentionsWithFormatting story comprehensively demonstrates how mentions render with various formatting styles (bold, strikethrough, italic combinations), which aligns well with the context-driven rendering changes in the inline components.

Comment thread app/containers/markdown/components/inline/Bold.tsx
Comment thread app/containers/markdown/components/inline/Italic.tsx
Comment thread app/containers/markdown/components/inline/Strike.tsx

@diegolmello diegolmello left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Besides my comments, make sure to test (and update screenshots) for both iOS and Android, since it's handled differently.

Comment thread app/containers/markdown/components/inline/Bold.tsx Outdated
Comment thread app/containers/markdown/components/inline/Bold.tsx Outdated
Comment thread app/containers/markdown/components/inline/Italic.tsx Outdated
@Rohit3523 Rohit3523 changed the title fix: mention markdown fix fix: mention fails to render in markdown Mar 13, 2026
@Rohit3523
Rohit3523 had a problem deploying to experimental_android_build March 15, 2026 13:28 — with GitHub Actions Error
@Rohit3523
Rohit3523 had a problem deploying to official_android_build March 15, 2026 13:28 — with GitHub Actions Error
@Rohit3523
Rohit3523 had a problem deploying to experimental_ios_build March 15, 2026 13:28 — with GitHub Actions Error
@Rohit3523
Rohit3523 had a problem deploying to approve_e2e_testing July 9, 2026 14:59 — with GitHub Actions Error
@Rohit3523
Rohit3523 had a problem deploying to approve_e2e_testing July 9, 2026 15:36 — with GitHub Actions Error
@Rohit3523
Rohit3523 had a problem deploying to approve_e2e_testing July 9, 2026 15:48 — with GitHub Actions Error
Comment thread android/app/src/main/assets/fonts/Inter-SemiBold_italic.otf
Comment thread app/containers/markdown/components/inline/Bold.tsx Outdated
Comment thread app/containers/markdown/components/inline/Italic.tsx Outdated
Comment thread app/containers/markdown/components/inline/Italic.tsx Outdated
@Rohit3523
Rohit3523 temporarily deployed to approve_e2e_testing July 9, 2026 19:05 — with GitHub Actions Inactive
@Rohit3523
Rohit3523 temporarily deployed to approve_e2e_testing July 9, 2026 19:25 — with GitHub Actions Inactive
Comment thread app/containers/markdown/components/inline/Bold.tsx
Comment thread app/containers/markdown/components/Heading.tsx
Comment thread app/containers/markdown/styles.ts Outdated

@OtavioStasiak OtavioStasiak 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.

LGTM, great job!

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.

3 participants