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
extern crate regex;
#[macro_use] extern crate lazy_static;
use regex::{RegexBuilder, Regex, Captures};
fn reg(s: &str) -> Regex {
RegexBuilder::new(s)
.multi_line(true)
.build()
.unwrap()
}
lazy_static!{
static ref CODE_BLOCK: Regex = reg(r"```(\s*)([\s\S]*?)(\s*)```");
static ref CODE_INLINE: Regex = reg(r"(`)(.*?)(`)");
static ref LINK: Regex = reg(r"\[([^\[]+)\]\(([^\)]+)\)");
static ref HEADING: Regex = reg(r"\n(#+\s*)(.*)");
static ref EMPHASIS: Regex = reg(r"(\*{1,2})(.*?)(\*{1,2})");
static ref STRIKETHROUGH: Regex = reg(r"(\~\~)(.*?)(\~\~)");
static ref HORIZONTAL: Regex = reg(r"\n((\-{3,})|(={3,}))");
static ref UNORDERED: Regex = reg(r"(\n\s*(\-|\+)\s.*)+");
static ref ORDERED: Regex = reg(r"(\n\s*([0-9]+\.)\s.*)+");
static ref LT: Regex = reg(r"<");
static ref GT: Regex = reg(r">");
static ref AMP: Regex = reg(r"&");
static ref AST: Regex = reg(r"\*");
static ref UND: Regex = reg(r"_");
static ref TIC: Regex = reg(r"`");
static ref EQL: Regex = reg(r"=");
static ref HYP: Regex = reg(r"-");
static ref HASH: Regex = reg(r"#");
}
fn symbols(s: &str) -> String {
HYP.replace_all(&EQL.replace_all(&TIC.replace_all(&UND.replace_all(&AST.replace_all(<.replace_all(>.replace_all(&HASH.replace_all(&.replace_all(s, "&"), "#"), ">"), "<"), "*"), "_"), "`"), "="), "-").to_string()
}
fn code_block_replacer(cap: &Captures) -> String {
format!("<pre>{}</pre>", symbols(&cap[2]))
}
fn code_inline_replacer(cap: &Captures) -> String {
format!("<code>{}</code>", &cap[2])
}
fn link_replacer(cap: &Captures) -> String {
format!("<a href='{}'>{}</a>", &cap[2], &cap[1])
}
fn heading_replacer(cap: &Captures) -> String {
format!("\n<h{}>{}</h{}>", cap[1].len().to_string(), &cap[2], cap[1].len().to_string())
}
fn emphasis_replacer(cap: &Captures) -> String {
format!("<{}>{}</{}>", if{cap[1].len()==1}{"em"}else{"strong"}, &cap[2], if{cap[1].len()==1}{"em"}else{"strong"})
}
fn rule_replacer(cap: &Captures) -> String {
format!("\n<hr />")
}
fn unordered_replacer(cap: &Captures) -> String {
let mut items = String::from("");
for i in cap[0].trim().split('\n') {
items = format!("{}<li>{}</li>", items, &i[2..]);
}
format!("<ul>{}</ul>", items)
}
fn ordered_replacer(cap: &Captures) -> String {
let mut items = String::from("");
for i in cap[0].trim().split('\n') {
items = format!("{}<li>{}</li>", items, &i[i.find('.').unwrap()+2..]);
}
format!("<ol>{}</ol>", items)
}
pub fn replace_all(s: &String) -> String {
replace::unordered(&replace::ordered(&replace::rules(&replace::emphasis(&replace::headings(&replace::links(&replace::code_inline(&replace::code_blocks(s))))))))
}
pub mod replace {
use crate::*;
pub fn code_blocks(s: &String) -> String {
CODE_BLOCK.replace_all(s, &code_block_replacer).to_string()
}
pub fn code_inline(s: &String) -> String {
CODE_INLINE.replace_all(s, &code_inline_replacer).to_string()
}
pub fn links(s: &String) -> String {
LINK.replace_all(s, &link_replacer).to_string()
}
pub fn headings(s: &String) -> String {
HEADING.replace_all(s, &heading_replacer).to_string()
}
pub fn emphasis(s: &String) -> String {
EMPHASIS.replace_all(s, &emphasis_replacer).to_string()
}
pub fn rules(s: &String) -> String {
HORIZONTAL.replace_all(s, &rule_replacer).to_string()
}
pub fn unordered(s: &String) -> String {
UNORDERED.replace_all(s, &unordered_replacer).to_string()
}
pub fn ordered(s: &String) -> String {
ORDERED.replace_all(s, &ordered_replacer).to_string()
}
}