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:
- Creating a
child_paragraph
- Recursively calling
parse_paragraph on children (which pushes marked InlineNodes into child_paragraph)
- 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.
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, theparse_paragraphfunction handlesNode::StrongandNode::Emphasisby:child_paragraphparse_paragraphon children (which pushes markedInlineNodes intochild_paragraph)child_paragraphand creating a newInlineNodefrom only the returned text string, applying just the current markFor
***bold and italic***, the markdown AST produces:When
Strongprocesses its children,Emphasispushes an italic-marked node intochild_paragraph— butStrongignores that and creates a new node with onlybold(). The italic mark is lost.Relevant code (lines ~76-92):
Suggested Fix
When the children produce
InlineNodes with marks (inchild_paragraph), merge those marks with the current formatting mark rather than discarding them. For example, whenStrongfinds that its childEmphasisalready produced italic-marked nodes, the result should carry bothboldanditalic.Reproduction
Environment
gpui-componentversion: 0.5.1Impact
Low — workaround is to avoid
***text***syntax. But it's standard markdown that users expect to work.