Skip to content

Markdown: nested bold+italic (***text***) loses inner formatting #2120

@tiborgats

Description

@tiborgats

Bug Description

When rendering markdown with combined bold and italic formatting (***bold and italic***), only the outermost mark is applied — the inner formatting is lost. Bold (**text**) and italic (*text*) work correctly on their own, but not when nested.

Root Cause

In crates/ui/src/text/format/markdown.rs, the parse_paragraph function handles Node::Strong and Node::Emphasis by:

  1. Creating a child_paragraph
  2. Recursively calling parse_paragraph on children (which pushes marked InlineNodes into child_paragraph)
  3. Discarding child_paragraph and creating a new InlineNode from only the returned text string, applying just the current mark

For ***bold and italic***, the markdown AST produces:

Strong
  └── Emphasis
        └── Text("bold and italic")

When Strong processes its children, Emphasis pushes an italic-marked node into child_paragraph — but Strong ignores that and creates a new node with only bold(). The italic mark is lost.

Relevant code (lines ~76-92):

Node::Emphasis(val) => {
    let mut child_paragraph = Paragraph::default();
    for child in val.children.iter() {
        text.push_str(&parse_paragraph(&mut child_paragraph, &child, cx));
    }
    paragraph.push(
        InlineNode::new(&text).marks(vec![(0..text.len(), TextMark::default().italic())]),
    );
}
Node::Strong(val) => {
    let mut child_paragraph = Paragraph::default();
    for child in val.children.iter() {
        text.push_str(&parse_paragraph(&mut child_paragraph, &child, cx));
    }
    paragraph.push(
        InlineNode::new(&text).marks(vec![(0..text.len(), TextMark::default().bold())]),
    );
}

Suggested Fix

When the children produce InlineNodes with marks (in child_paragraph), merge those marks with the current formatting mark rather than discarding them. For example, when Strong finds that its child Emphasis already produced italic-marked nodes, the result should carry both bold and italic.

Reproduction

**bold** works
*italic* works
***bold and italic*** — only shows bold (or italic), not both

Environment

  • gpui-component version: 0.5.1

Impact

Low — workaround is to avoid ***text*** syntax. But it's standard markdown that users expect to work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions