markdown_line_element.rs
1 use crate::markdown_inline_element::{process_inline_markdown_text, MarkdownToken}; 2 use serde::{Deserialize, Serialize}; 3 4 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] 5 pub enum MarkdownLineElementType { 6 H1, 7 H2, 8 H3, 9 H4, 10 H5, 11 H6, 12 Paragraph, 13 Divider, 14 OrderedList, 15 UnorderedList, 16 ConfigVariable, 17 } 18 impl MarkdownLineElementType { 19 fn get_header_by_int(number: usize) -> MarkdownLineElementType { 20 return match number { 21 1 => MarkdownLineElementType::H1, 22 2 => MarkdownLineElementType::H2, 23 3 => MarkdownLineElementType::H3, 24 4 => MarkdownLineElementType::H4, 25 5 => MarkdownLineElementType::H5, 26 _ => MarkdownLineElementType::H6, 27 }; 28 } 29 } 30 31 #[derive(Debug, Clone, Serialize, Deserialize)] 32 pub struct MarkdownLineElement { 33 pub indent: usize, 34 pub line_type: MarkdownLineElementType, 35 pub markdown: Vec<MarkdownToken>, 36 } 37 38 impl MarkdownLineElement { 39 pub fn new(line: &str) -> Self { 40 let indent = line.chars().take_while(|&c| c == ' ').count() / 2; 41 if indent * 2 != line.chars().take_while(|&c| c == ' ').count() { 42 panic!("Indentation error: Indentation must be a multiple of 2 spaces\nline that fugged ub: {}", &line); 43 } 44 45 let trimmed = line.trim_start(); 46 let (line_type, content): (MarkdownLineElementType, &str) = if trimmed.starts_with("#") { 47 let level = trimmed.chars().take_while(|&c| c == '#').count(); 48 let line_type = MarkdownLineElementType::get_header_by_int(level); 49 (line_type, &trimmed[level..].trim()) 50 } else if trimmed.starts_with("---") { 51 (MarkdownLineElementType::Divider, "") 52 } else if trimmed.starts_with("- ") { 53 (MarkdownLineElementType::UnorderedList, &trimmed[2..].trim()) 54 } else if trimmed.starts_with("* ") { 55 (MarkdownLineElementType::OrderedList, &trimmed[2..].trim()) 56 } else if trimmed.starts_with("@@") { 57 ( 58 MarkdownLineElementType::ConfigVariable, 59 &trimmed[2..].trim(), 60 ) 61 } else { 62 (MarkdownLineElementType::Paragraph, trimmed) 63 }; 64 65 MarkdownLineElement { 66 indent, 67 line_type, 68 markdown: process_inline_markdown_text(&content), 69 } 70 } 71 72 pub fn parse_markdown(md_content: &str) -> Vec<MarkdownLineElement> { 73 md_content.lines().map(MarkdownLineElement::new).collect() 74 } 75 }