Markdown_to_HTML_rs/
lib.rs

1extern crate regex;
2#[macro_use] extern crate lazy_static;
3
4use regex::{RegexBuilder, Regex, Captures};
5
6fn reg(s: &str) -> Regex {
7    RegexBuilder::new(s)
8        .multi_line(true)
9        .build()
10        .unwrap()
11}
12
13//All of the Regexs
14lazy_static!{
15    static ref CODE_BLOCK: Regex = reg(r"```(\s*)([\s\S]*?)(\s*)```");
16
17    static ref CODE_INLINE: Regex = reg(r"(`)(.*?)(`)");
18
19    static ref LINK: Regex = reg(r"\[([^\[]+)\]\(([^\)]+)\)");
20
21    static ref HEADING: Regex = reg(r"\n(#+\s*)(.*)");
22
23    static ref EMPHASIS: Regex = reg(r"(\*{1,2})(.*?)(\*{1,2})");
24
25    static ref STRIKETHROUGH: Regex = reg(r"(\~\~)(.*?)(\~\~)");
26
27    static ref HORIZONTAL: Regex = reg(r"\n((\-{3,})|(={3,}))");
28
29    static ref UNORDERED: Regex = reg(r"(\n\s*(\-|\+)\s.*)+");
30
31    static ref ORDERED: Regex = reg(r"(\n\s*([0-9]+\.)\s.*)+");
32
33    /* Markdown or HTML reserved symbols */
34    static ref LT: Regex = reg(r"<");
35
36    static ref GT: Regex = reg(r">");
37
38    static ref AMP: Regex = reg(r"&");
39
40    static ref AST: Regex = reg(r"\*");
41
42    static ref UND: Regex = reg(r"_");
43
44    static ref TIC: Regex = reg(r"`");
45
46    static ref EQL: Regex = reg(r"=");
47
48    static ref HYP: Regex = reg(r"-");
49
50    static ref HASH: Regex = reg(r"#");
51}
52
53//function to replace HTML or Markdown reserved symbols
54fn symbols(s: &str) -> String {
55    HYP.replace_all(&EQL.replace_all(&TIC.replace_all(&UND.replace_all(&AST.replace_all(&LT.replace_all(&GT.replace_all(&HASH.replace_all(&AMP.replace_all(s, "&amp;"), "&#35;"), "&gt;"), "&lt;"), "&#42;"), "&#95;"), "&#96;"), "&#61;"), "&#45;").to_string()
56}
57
58/* The replacer functions */
59
60fn code_block_replacer(cap: &Captures) -> String {
61    format!("<pre>{}</pre>", symbols(&cap[2]))
62}
63
64fn code_inline_replacer(cap: &Captures) -> String {
65    format!("<code>{}</code>", &cap[2])
66}
67
68fn link_replacer(cap: &Captures) -> String {
69    format!("<a href='{}'>{}</a>", &cap[2], &cap[1])
70}
71
72fn heading_replacer(cap: &Captures) -> String {
73    format!("\n<h{}>{}</h{}>", cap[1].len().to_string(), &cap[2], cap[1].len().to_string())
74}
75
76fn emphasis_replacer(cap: &Captures) -> String {
77    format!("<{}>{}</{}>", if{cap[1].len()==1}{"em"}else{"strong"}, &cap[2], if{cap[1].len()==1}{"em"}else{"strong"})
78}
79
80fn rule_replacer(cap: &Captures) -> String {
81    format!("\n<hr />")
82}
83
84fn unordered_replacer(cap: &Captures) -> String {
85    let mut items = String::from("");
86    for i in cap[0].trim().split('\n') {
87        items = format!("{}<li>{}</li>", items, &i[2..]);
88    }
89    format!("<ul>{}</ul>", items)
90}
91
92fn ordered_replacer(cap: &Captures) -> String {
93    let mut items = String::from("");
94    for i in cap[0].trim().split('\n') {
95        items = format!("{}<li>{}</li>", items, &i[i.find('.').unwrap()+2..]);
96    }
97    format!("<ol>{}</ol>", items)
98}
99
100//The main format function; call this to get markdown with the best results
101pub fn replace_all(s: &String) -> String {
102    replace::unordered(&replace::ordered(&replace::rules(&replace::emphasis(&replace::headings(&replace::links(&replace::code_inline(&replace::code_blocks(s))))))))
103}
104
105//Individual markdown replacement functions.
106pub mod replace {
107    use crate::*;
108
109    pub fn code_blocks(s: &String) -> String {
110        CODE_BLOCK.replace_all(s, &code_block_replacer).to_string()
111    }
112
113    pub fn code_inline(s: &String) -> String {
114        CODE_INLINE.replace_all(s, &code_inline_replacer).to_string()
115    }
116
117    pub fn links(s: &String) -> String {
118        LINK.replace_all(s, &link_replacer).to_string()
119    }
120
121    pub fn headings(s: &String) -> String {
122        HEADING.replace_all(s, &heading_replacer).to_string()
123    }
124
125    pub fn emphasis(s: &String) -> String {
126        EMPHASIS.replace_all(s, &emphasis_replacer).to_string()
127    }
128
129    pub fn rules(s: &String) -> String {
130        HORIZONTAL.replace_all(s, &rule_replacer).to_string()
131    }
132
133    pub fn unordered(s: &String) -> String {
134        UNORDERED.replace_all(s, &unordered_replacer).to_string()
135    }
136
137    pub fn ordered(s: &String) -> String {
138        ORDERED.replace_all(s, &ordered_replacer).to_string()
139    }
140}