//! Inline content rendering with theme-based formatting. use streamdown_parser::{InlineElement, InlineParser}; use crate::style::InlineStyler; /// Render inline elements to a string using a styler. pub fn render_inline_content(content: &str, styler: &S) -> String { render_inline_elements(&InlineParser::new().parse(content), styler) } /// Render inline elements to a string using a styler. pub fn render_inline_elements(elements: &[InlineElement], styler: &S) -> String { let mut result = String::new(); for element in elements { match element { InlineElement::Text(text) => { result.push_str(&styler.text(text)); } InlineElement::Bold(text) => { result.push_str(&styler.bold(text)); } InlineElement::Italic(text) => { result.push_str(&styler.italic(text)); } InlineElement::BoldItalic(text) => { result.push_str(&styler.bold_italic(text)); } InlineElement::Strikeout(text) => { result.push_str(&styler.strikethrough(text)); } InlineElement::Underline(text) => { result.push_str(&styler.underline(text)); } InlineElement::Code(text) => { result.push_str(&styler.code(text)); } InlineElement::Link { text, url } => { result.push_str(&styler.link(text, url)); } InlineElement::Image { alt, url } => { result.push_str(&styler.image(alt, url)); } InlineElement::Footnote(text) => { result.push_str(&styler.footnote(text)); } } } result } #[cfg(test)] mod tests { use super::*; use crate::theme::TagStyler; fn render(content: &str) -> String { render_inline_content(content, &TagStyler) } #[test] fn test_plain_text() { insta::assert_snapshot!(render("hello world"), @"hello world"); } #[test] fn test_html_entities() { insta::assert_snapshot!(render("& < > ""), @r#"& < > ""#); } #[test] fn test_bold() { insta::assert_snapshot!(render("**bold**"), @"bold"); } #[test] fn test_italic() { insta::assert_snapshot!(render("*italic*"), @"italic"); } #[test] fn test_bold_italic() { insta::assert_snapshot!(render("***text***"), @"text"); } #[test] fn test_strikethrough() { insta::assert_snapshot!(render("~~struck~~"), @"struck"); } #[test] fn test_code() { insta::assert_snapshot!(render("`code`"), @"code"); } #[test] fn test_underline() { insta::assert_snapshot!(render("__underline__"), @"underline"); } #[test] fn test_link() { insta::assert_snapshot!(render("[click](https://example.com)"), @r#"click"#); } #[test] fn test_image() { insta::assert_snapshot!(render("![alt](image.png)"), @r#"alt"#); } #[test] fn test_mixed() { insta::assert_snapshot!(render("hello **bold** and *italic*"), @"hello bold and italic"); } #[test] fn test_multiple_bold() { insta::assert_snapshot!(render("**one** and **two**"), @"one and two"); } #[test] fn test_entities_in_bold() { insta::assert_snapshot!(render("**&**"), @"&"); } #[test] fn test_entities_in_link() { insta::assert_snapshot!(render("[<click>](https://example.com)"), @r#""#); } #[test] fn test_code_content() { insta::assert_snapshot!(render("`let x = 1;`"), @"let x = 1;"); } #[test] fn test_link_special_url() { insta::assert_snapshot!(render("[link](https://example.com/path?q=1&b=2)"), @r#"link"#); } #[test] fn test_empty() { insta::assert_snapshot!(render(""), @""); } #[test] fn test_whitespace() { insta::assert_snapshot!(render("hello world"), @"hello world"); } #[test] fn test_image_empty_alt() { insta::assert_snapshot!(render("![](image.png)"), @r#""#); } }