From 34304546ada03d131334302933c19db1567e2286 Mon Sep 17 00:00:00 2001 From: Kerdonov Date: Fri, 26 Dec 2025 16:36:57 +0200 Subject: [PATCH] added support for parsing lists --- src/ast.rs | 2 + src/generator/block.rs | 18 ++++++- src/parser/block.rs | 103 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 121 insertions(+), 2 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 3474045..4c241ad 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -31,4 +31,6 @@ pub enum Block { Code { content: String, lang: String }, Quote { inner: Box }, Paragraph { inner: Vec }, + UnorderedList { items: Vec }, + OrderedList { items: Vec }, } diff --git a/src/generator/block.rs b/src/generator/block.rs index 1b520be..0d33b4d 100644 --- a/src/generator/block.rs +++ b/src/generator/block.rs @@ -15,12 +15,28 @@ impl ToHtml for Vec { impl ToHtml for Block { fn to_html(&self) -> String { match self { - Block::Paragraph { inner } => format!("

{}


", inner.to_html()), + Block::Paragraph { inner } => format!("

{}

", inner.to_html()), Block::Heading { inner, level } => { format!("{}", level, inner.to_html(), level) } Block::Code { content, lang: _ } => format!("
{content}
"), Block::Quote { inner } => format!("
{}
", inner.to_html()), + Block::UnorderedList { items } => { + let mut html = "
    ".to_string(); + for item in items { + html.push_str(&format!("
  • {}
  • ", &item.to_html())); + } + html.push_str("
"); + html + } + Block::OrderedList { items } => { + let mut html = "
    ".to_string(); + for item in items { + html.push_str(&format!("
  1. {}
  2. ", &item.to_html())); + } + html.push_str("
"); + html + } } } } diff --git a/src/parser/block.rs b/src/parser/block.rs index 07fd23c..433841a 100644 --- a/src/parser/block.rs +++ b/src/parser/block.rs @@ -17,7 +17,14 @@ pub fn blocks(input: &str) -> IResult<&str, Vec, MarkdownParseError> { pub fn block(input: &str) -> IResult<&str, Block, MarkdownParseError> { //alt((heading_block, code_block, quote_block, paragraph_block)).parse(input) terminated( - alt((heading_block, code_block, quote_block, paragraph_block)), + alt(( + heading_block, + code_block, + quote_block, + paragraph_block, + ordered_list, + unordered_list, + )), tag("\n"), ) .parse(input) @@ -74,6 +81,20 @@ fn quote_block(input: &str) -> IResult<&str, Block, MarkdownParseError> { }) } +fn unordered_list(input: &str) -> IResult<&str, Block, MarkdownParseError> { + many1((tag("- "), block)).parse(input).map(|(rem, v)| { + let items = v.into_iter().map(|(_, b)| b).collect(); + (rem, Block::UnorderedList { items }) + }) +} + +fn ordered_list(input: &str) -> IResult<&str, Block, MarkdownParseError> { + many1((tag("1. "), block)).parse(input).map(|(rem, v)| { + let items = v.into_iter().map(|(_, b)| b).collect(); + (rem, Block::OrderedList { items }) + }) +} + //|-------------------------------------------------------------------------------| //| TESTS TESTS TESTS TESTS TESTS TESTS TESTS TESTS TESTS TESTS TESTS TESTS TESTS | //|-------------------------------------------------------------------------------| @@ -235,4 +256,84 @@ Hello MD ] ); } + + #[test] + fn simple_unordered_list() { + let md = "- a\n- b\n- c\n- b again with some `code`\n\n"; + let (rem, block) = unordered_list(md).unwrap(); + + assert_eq!(rem, "\n"); + assert_eq!( + block, + Block::UnorderedList { + items: vec![ + Block::Paragraph { + inner: vec![Inline::Text { + content: "a".to_string() + }] + }, + Block::Paragraph { + inner: vec![Inline::Text { + content: "b".to_string() + }] + }, + Block::Paragraph { + inner: vec![Inline::Text { + content: "c".to_string() + }] + }, + Block::Paragraph { + inner: vec![ + Inline::Text { + content: "b again with some ".to_string() + }, + Inline::Code { + content: "code".to_string() + } + ] + }, + ] + } + ); + } + + #[test] + fn simple_ordered_list() { + let md = "1. a\n1. b\n1. c\n1. b again with some `code`\n\n"; + let (rem, block) = ordered_list(md).unwrap(); + + assert_eq!(rem, "\n"); + assert_eq!( + block, + Block::OrderedList { + items: vec![ + Block::Paragraph { + inner: vec![Inline::Text { + content: "a".to_string() + }] + }, + Block::Paragraph { + inner: vec![Inline::Text { + content: "b".to_string() + }] + }, + Block::Paragraph { + inner: vec![Inline::Text { + content: "c".to_string() + }] + }, + Block::Paragraph { + inner: vec![ + Inline::Text { + content: "b again with some ".to_string() + }, + Inline::Code { + content: "code".to_string() + } + ] + }, + ] + } + ); + } }