text_view: Fix li > strong render not in same line. (#1016)

## Before

<img width="1294" alt="image"
src="https://github.com/user-attachments/assets/0620f33a-914e-4d2a-8832-16c037351352"
/>

## After

<img width="1131" alt="image"
src="https://github.com/user-attachments/assets/a31b9b5a-6d41-4c04-a415-ff97e7cd1f31"
/>
This commit is contained in:
Jason Lee 2025-06-27 18:41:28 +08:00 committed by GitHub
parent b18a3ff7a9
commit 5b17281374
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 58 additions and 38 deletions

View file

@ -5,8 +5,9 @@
<p> <p>
This is a paragraph inside a div element, have This is a paragraph inside a div element, have
<mention>@Mention Tag</mention> <mention>@Mention Tag</mention>
<a href="https://google.com">Link with: <b>Bold <i>italic</i></b></a>, <strong>bold</strong>, <a href="https://google.com"
<em>italic</em>, and >Link with: <b>Bold <i>italic</i></b></a
>, <strong>bold</strong>, <em>italic</em>, and
<code>code</code> text. <code>code</code> text.
</p> </p>
<script> <script>
@ -24,7 +25,10 @@
} }
</style> </style>
<p> <p>
<img src="https://is1-ssl.mzstatic.com/image/thumb/avICmr1PbBRB-PAeplGreA/1378x774.jpg" height="400px" /> <img
src="https://is1-ssl.mzstatic.com/image/thumb/avICmr1PbBRB-PAeplGreA/1378x774.jpg"
height="400px"
/>
</p> </p>
<div> <div>
<p>This is second paragraph.</p> <p>This is second paragraph.</p>
@ -47,11 +51,11 @@
<li> <li>
Numbered item 1 Numbered item 1
<ol> <ol>
<li>Sub item 1</li> <li>Sub <strong>item</strong> 1</li>
<li>Sub item 2</li> <li>Sub <foo>item</foo> 2</li>
</ol> </ol>
</li> </li>
<li>Numbered item 2</li> <li>Numbered <em>item</em> 2</li>
<li>Numbered item 3</li> <li>Numbered item 3</li>
</ol> </ol>
Text after the Numbered List. Text after the Numbered List.
@ -95,15 +99,27 @@
Text after the section. Text after the section.
<section> <section>
<h2>Images</h2> <h2>Images</h2>
<img src="https://is1-ssl.mzstatic.com/image/thumb/5tQkYfzU9bSMUol0GajO4w/1378x774.jpg" height="400px" /> <img
src="https://is1-ssl.mzstatic.com/image/thumb/5tQkYfzU9bSMUol0GajO4w/1378x774.jpg"
height="400px"
/>
<p> <p>
(A Tesla Model X on display at the June 2024 Shanghai new energy (A Tesla Model X on display at the June 2024 Shanghai new energy
vehicle show. Image credit: CnEVPost) vehicle show. Image credit: CnEVPost)
</p> </p>
<img src="https://miro.medium.com/v2/resize:fit:1400/format:webp/1*-Y9ozbNWSViiCmal1TT32w.jpeg" width="100%" /> <img
src="https://miro.medium.com/v2/resize:fit:1400/format:webp/1*-Y9ozbNWSViiCmal1TT32w.jpeg"
width="100%"
/>
Text before the image. Text before the image.
<img src="https://miro.medium.com/v2/resize:fit:1400/format:webp/0*u4La03Nh6E4zIc9-.jpeg" width="100%" /> <img
src="https://miro.medium.com/v2/resize:fit:1400/format:webp/0*u4La03Nh6E4zIc9-.jpeg"
width="100%"
/>
Text after the image. Text after the image.
<img src="https://miro.medium.com/v2/resize:fit:1400/format:webp/0*Q_JiltniByWLWoUv" style="width: 100%" /> <img
src="https://miro.medium.com/v2/resize:fit:1400/format:webp/0*Q_JiltniByWLWoUv"
style="width: 100%"
/>
</section> </section>
</article> </article>

View file

@ -2,7 +2,7 @@ use std::ops::Range;
use gpui::{ use gpui::{
div, img, prelude::FluentBuilder as _, px, relative, rems, AnyElement, App, DefiniteLength, div, img, prelude::FluentBuilder as _, px, relative, rems, AnyElement, App, DefiniteLength,
ElementId, FontStyle, FontWeight, Half, HighlightStyle, InteractiveElement as _, Div, ElementId, FontStyle, FontWeight, Half, HighlightStyle, InteractiveElement as _,
InteractiveText, IntoElement, Length, ObjectFit, ParentElement, Rems, RenderOnce, SharedString, InteractiveText, IntoElement, Length, ObjectFit, ParentElement, Rems, RenderOnce, SharedString,
SharedUri, Styled, StyledImage as _, StyledText, Window, SharedUri, Styled, StyledImage as _, StyledText, Window,
}; };
@ -310,14 +310,7 @@ impl RenderOnce for Paragraph {
for text_node in children.into_iter() { for text_node in children.into_iter() {
let text_len = text_node.text.len(); let text_len = text_node.text.len();
let part = if text.len() == 0 { text.push_str(&text_node.text);
// trim start for first text
text_node.text.trim_start()
} else {
text_node.text.as_str()
};
text.push_str(part);
let mut node_highlights = vec![]; let mut node_highlights = vec![];
for (range, style) in text_node.marks { for (range, style) in text_node.marks {
@ -415,10 +408,33 @@ impl Node {
} => v_flex() } => v_flex()
.when(spread, |this| this.child(div())) .when(spread, |this| this.child(div()))
.children({ .children({
let mut items = Vec::with_capacity(children.len()); let mut items: Vec<Div> = Vec::with_capacity(children.len());
for child in children.into_iter() { for (child_ix, child) in children.iter().enumerate() {
match &child { match &child {
Node::Paragraph(_) => { Node::Paragraph(_) => {
let last_not_list = child_ix > 0
&& !matches!(children[child_ix - 1], Node::List { .. });
let text = child.clone().render(
Some(ListState {
depth: state.depth + 1,
ordered: state.ordered,
todo: checked.is_some(),
}),
true,
text_view_style,
window,
cx,
);
// merge content into last item.
if last_not_list {
if let Some(item_item) = items.last_mut() {
item_item.extend(vec![text.into_any_element()]);
continue;
}
}
items.push( items.push(
h_flex() h_flex()
.relative() .relative()
@ -455,23 +471,11 @@ impl Node {
}), }),
) )
}) })
.child(div().flex_1().overflow_hidden().child( .child(text),
child.render(
Some(ListState {
depth: state.depth + 1,
ordered: state.ordered,
todo: checked.is_some(),
}),
true,
text_view_style,
window,
cx,
),
)),
); );
} }
Node::List { .. } => { Node::List { .. } => {
items.push(div().ml(rems(1.)).child(child.render( items.push(div().ml(rems(1.)).child(child.clone().render(
Some(ListState { Some(ListState {
depth: state.depth + 1, depth: state.depth + 1,
ordered: state.ordered, ordered: state.ordered,

View file

@ -417,7 +417,6 @@ fn parse_paragraph(
let (child_text, child_marks) = parse_paragraph(&mut child_paragraph, &child); let (child_text, child_marks) = parse_paragraph(&mut child_paragraph, &child);
merge_child_text(&mut text, &mut marks, &child_text, &child_marks); merge_child_text(&mut text, &mut marks, &child_text, &child_marks);
} }
marks.push(( marks.push((
0..text.len(), 0..text.len(),
InlineTextStyle { InlineTextStyle {
@ -530,7 +529,7 @@ fn parse_paragraph(
let (child_text, child_marks) = parse_paragraph(&mut child_paragraph, &child); let (child_text, child_marks) = parse_paragraph(&mut child_paragraph, &child);
merge_child_text(&mut text, &mut marks, &child_text, &child_marks); merge_child_text(&mut text, &mut marks, &child_text, &child_marks);
} }
paragraph.push(element::TextNode { paragraph.push(TextNode {
text: text.clone(), text: text.clone(),
marks: marks.clone(), marks: marks.clone(),
}); });
@ -639,6 +638,7 @@ fn parse_node(node: &Rc<Node>, paragraph: &mut Paragraph) -> element::Node {
let ordered = name.local == local_name!("ol"); let ordered = name.local == local_name!("ol");
let mut list_children = vec![]; let mut list_children = vec![];
for child in node.children.borrow().iter() { for child in node.children.borrow().iter() {
let mut child_paragraph = Paragraph::default(); let mut child_paragraph = Paragraph::default();
list_children.push(parse_node(child, &mut child_paragraph)); list_children.push(parse_node(child, &mut child_paragraph));