1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use crate::parser::{tags, tags::TagType, utils, Parser};
use regex::Regex;
impl Parser {
/// Checks if next set of character represents a ordered list element
/// eg: `1.` `22.`
/// This function doesn't consume the `input` and doesn't move the `pos`
pub fn check_if_ordered_list_marker(&self) -> bool {
let reg = Regex::new(r"([0-9])+\.").unwrap();
let peeked = self.peek_ahead_while(|c| {
return !char::is_whitespace(*c) && (c.is_numeric() || *c == '.');
});
return reg.is_match(&peeked);
}
/// Parses an ordered list and return list of elements under `ol` tag
/// TODO : NEEDS fixing
pub fn parse_ordered_list(&mut self) -> String {
let mut items: Vec<String> = vec![];
loop {
self.consume_whitespace(false);
// check if starting character are for an ordered list only
if !self.check_if_ordered_list_marker() {
break;
}
// consume while there are only numbers
self.consume_while(|c| !char::is_whitespace(c) && char::is_numeric(c));
// check if next char is .
// to match like 11.
if self.next_char() != '.' {
break;
} else {
self.consume_char();
}
self.consume_whitespace(false);
let text = self.parse_md_line(None);
items.push(text);
// if newline char,
// check if there are more than one new line
// if more than one, list if finished
if self.next_char() == '\n' {
self.consume_char();
if self.next_char() == '\n' {
break;
}
}
}
self.wrap_elements("ol", items)
}
/// Parses an unordered list in markdown content
pub fn parse_list(&mut self) -> String {
let mut items: Vec<String> = vec![];
let mut i = 0;
// Loop while first character of every line is '-'
'outer: loop {
i = i + 1; //For debugging
//Consumes the `-` or `*` literal
self.consume_char();
self.consume_whitespace(true);
//Get all the remaining text in line
let text = self.parse_md_line(None);
items.push(text);
// Debugging
//println!("I -> {}", i);
//println!("POS -> {}", self.pos);
//println!(
// "character -> {}",
// self.input[self.pos..].chars().next().unwrap()
//);
let mut newlines = 0;
while self.input[self.pos..].starts_with('\n') {
newlines += 1;
self.pos += 1;
self.consume_whitespace(false);
if newlines > 1 {
break 'outer;
}
}
self.consume_while(|c| utils::is_whitespace(c));
if !self.input[self.pos..].starts_with('-') {
break;
}
}
self.wrap_elements("ul", items)
}
/// Wrap a list of items in a html tag
/// eg: `ol`, `div`, `ul`
fn wrap_elements(&self, tag: &str, items: Vec<String>) -> String {
let mut html = String::from(tags::make_tag(tag, TagType::Opening));
for item in items {
let s = utils::create_html_element("li".to_string(), item);
html.push_str(&s);
}
html.push_str(tags::make_tag(tag, TagType::Closing).as_str());
html
}
}
#[cfg(test)]
mod tests {
use crate::parser::parse;
// #[ignore]
#[test]
fn test_parse_ordered_list() {
let md = r#"
# Numbered list
1. Number One
2. Number Two
3. Number Three
What a number is the
"#;
let html = parse(md.to_string());
println!("ORDERED LIST");
println!("{}", html);
assert_eq!("", "");
}
}