aboutsummaryrefslogtreecommitdiffstats
path: root/crates/atuin-ai/src/tui/components/markdown.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/atuin-ai/src/tui/components/markdown.rs')
-rw-r--r--crates/atuin-ai/src/tui/components/markdown.rs47
1 files changed, 22 insertions, 25 deletions
diff --git a/crates/atuin-ai/src/tui/components/markdown.rs b/crates/atuin-ai/src/tui/components/markdown.rs
index 1cd7dbcf..f164fdc5 100644
--- a/crates/atuin-ai/src/tui/components/markdown.rs
+++ b/crates/atuin-ai/src/tui/components/markdown.rs
@@ -16,20 +16,12 @@ use ratatui_widgets::paragraph::{Paragraph, Wrap};
/// A markdown rendering component backed by pulldown-cmark.
#[props]
-pub struct Markdown {
+pub(crate) struct Markdown {
pub source: String,
}
-impl Markdown {
- pub fn new(source: impl Into<String>) -> Self {
- Self {
- source: source.into(),
- }
- }
-}
-
/// Style configuration for markdown rendering.
-pub struct MarkdownStyles {
+pub(crate) struct MarkdownStyles {
pub base: Style,
pub code_inline: Style,
pub code_block: Style,
@@ -98,26 +90,22 @@ fn parse_markdown<'a>(source: &'a str, styles: &'a MarkdownStyles) -> Text<'stat
let mut style_stack: Vec<Style> = vec![styles.base];
let mut in_code_block = false;
+ let mut in_list_item = false;
+ // True until the first paragraph inside a list item has been opened.
+ // The first paragraph should flow inline with the "- " prefix.
+ let mut list_item_first_para = false;
for event in parser {
match event {
Event::Start(Tag::Strong) => {
- let bold = style_stack
- .last()
- .copied()
- .unwrap_or(styles.base)
- .add_modifier(Modifier::BOLD);
+ let bold = style_stack.last().copied().unwrap_or(styles.bold);
style_stack.push(bold);
}
Event::End(TagEnd::Strong) => {
style_stack.pop();
}
Event::Start(Tag::Emphasis) => {
- let italic = style_stack
- .last()
- .copied()
- .unwrap_or(styles.base)
- .add_modifier(Modifier::ITALIC);
+ let italic = style_stack.last().copied().unwrap_or(styles.italic);
style_stack.push(italic);
}
Event::End(TagEnd::Emphasis) => {
@@ -170,12 +158,17 @@ fn parse_markdown<'a>(source: &'a str, styles: &'a MarkdownStyles) -> Text<'stat
lines.push(Vec::new());
}
Event::Start(Tag::Paragraph) => {
- if current_line > 0 || !lines[0].is_empty() {
- // Two line advances: one to end the current line, one for a blank separator.
- current_line += 1;
- lines.push(Vec::new());
+ if in_list_item && list_item_first_para {
+ // First paragraph flows inline with the "- " prefix
+ list_item_first_para = false;
+ } else if current_line > 0 || !lines[0].is_empty() {
current_line += 1;
lines.push(Vec::new());
+ if !in_list_item {
+ // Blank separator between paragraphs (but not inside list items)
+ current_line += 1;
+ lines.push(Vec::new());
+ }
}
}
Event::End(TagEnd::Paragraph) => {}
@@ -197,8 +190,12 @@ fn parse_markdown<'a>(source: &'a str, styles: &'a MarkdownStyles) -> Text<'stat
lines.push(Vec::new());
}
lines[current_line].push(Span::styled("- ", Style::default().fg(Color::DarkGray)));
+ in_list_item = true;
+ list_item_first_para = true;
+ }
+ Event::End(TagEnd::Item) => {
+ in_list_item = false;
}
- Event::End(TagEnd::Item) => {}
Event::Start(Tag::List(_)) => {
if current_line > 0 || !lines[0].is_empty() {
current_line += 1;