1 pub fn parse(source: &str) -> String {
3 let lines = source.split("\n");
4 let mut is_preformatted = false;
6 let mut html:String = "".to_owned();
7 let mut current_line_type: Option<LineType> = None;
10 let line_type = identify_line(&(line[..3]), is_preformatted);
12 LineType::PreformattedToggle => is_preformatted = !is_preformatted,
14 // Close previous block if needed
15 if let Some(line) = ¤t_line_type {
16 if line != &line_type && is_block(line) {
17 html.push_str(get_line_closer(line));
22 if is_block(&line_type) {
23 if let Some(line) = ¤t_line_type {
24 if line != &line_type {
25 html.push_str(get_line_opener(&line_type));
28 html.push_str(get_line_opener(&line_type));
31 let line_content = get_partial_line_content(&line_type, line);
32 html.push_str(&line_content);
34 let line_content = get_full_line_content(&line_type, line);
35 html.push_str(&line_content);
37 current_line_type = Some(line_type);
41 if let Some(line) = ¤t_line_type {
43 html.push_str(get_line_closer(line));
49 fn is_block(line_type: &LineType) -> bool {
50 return match line_type {
51 LineType::PreformattedText => true,
52 LineType::ListItem => true,
53 LineType::Quote => true,
58 fn get_partial_line_content(line_type: &LineType, line: &str) -> String {
59 return match line_type {
60 LineType::ListItem => format!("<li>{}</li>", line[2..].trim()),
61 LineType::Quote => line[1..].trim().to_string(),
62 LineType::PreformattedText => format!("{}\n", line),
67 fn get_full_line_content(line_type: &LineType, line: &str) -> String {
69 LineType::Text => format!("<p>{}</p>\n", line.trim()),
70 LineType::Blank => "<br/>\n".to_string(),
71 LineType::Link => format!("<div><a href=\"{}\">{}</a></div>\n", get_link_address(line), get_link_content(line)),
72 LineType::Heading1 => format!("<h1>{}</h1>\n", line[1..].trim()),
73 LineType::Heading2 => format!("<h2>{}</h2>\n", line[2..].trim()),
74 LineType::Heading3 => format!("<h3>{}</h3>\n", line[3..].trim()),
79 fn get_line_opener(line_type: &LineType) -> &'static str {
81 LineType::ListItem => "<ul>",
82 LineType::Quote => "<blockquote>",
83 LineType::PreformattedText => "<pre>",
88 fn get_line_closer(line_type: &LineType) -> &'static str {
90 LineType::ListItem => "</ul>\n",
91 LineType::Quote => "</blockquote>\n",
92 LineType::PreformattedText => "</pre>\n",
97 fn get_link_content(line: &str) -> &str {
98 let components: Vec<&str> = line[2..].trim().splitn(2, " ").collect();
99 if components.len() > 1 {
100 return components[1].trim()
105 fn get_link_address(line: &str) -> &str {
106 let components: Vec<&str> = line[2..].trim().splitn(2, " ").collect();
110 fn identify_line(line: &str, is_preformatted: bool) -> LineType {
111 if line.starts_with("```") {
112 return LineType::PreformattedToggle;
115 return LineType::PreformattedText;
118 return LineType::Blank;
120 if line.starts_with("=>") {
121 return LineType::Link;
123 if line.starts_with("* ") {
124 return LineType::ListItem;
126 if line.starts_with(">") {
127 return LineType::Quote;
129 if line.starts_with("###") {
130 return LineType::Heading3;
132 if line.starts_with("##") {
133 return LineType::Heading2;
135 if line.starts_with("#") {
136 return LineType::Heading1;
142 #[derive(PartialEq, Eq)]