use comrak::{markdown_to_html, Options};
use regex::RegexBuilder;
pub fn render(input: &str) -> String {
let mut options = Options::default();
options.extension.table = true;
options.extension.superscript = true;
options.extension.strikethrough = true;
options.extension.autolink = true;
options.extension.header_ids = Option::Some(String::new());
options.render.escape = true;
options.parse.smart = false;
let mut out = markdown_to_html(&input, &options);
let allowed_elements: Vec<&str> = Vec::from([
"hue", "sat", "lit", "theme", "comment", "p", "span", "style", "img", "div", "a", "b", "i",
"strong", "em", "r", "rf",
]);
for element in allowed_elements {
out = regex_replace(
&out,
&format!("<{}>", element),
&format!("<{}>", element),
);
out = regex_replace(
&out,
&format!("<{}(.*?)>", element),
&format!("<{}$1>", element),
);
out = regex_replace(
&out,
&format!("</{}>", element),
&format!("</{}>", element),
);
}
let image_sizing_regex = RegexBuilder::new("(!)\\[(.*?)\\]\\((.*?)\\)\\:\\{(.*?)x(.*?)\\}")
.multi_line(true)
.build()
.unwrap();
for capture in image_sizing_regex.captures_iter(&out.clone()) {
let title = capture.get(2).unwrap().as_str();
let src = capture.get(3).unwrap().as_str();
let width = capture.get(4).unwrap().as_str();
let height = capture.get(5).unwrap().as_str();
let result = &format!("<img alt=\"{title}\" title=\"{title}\" src=\"{src}\" style=\"width: {width}px; height: {height}px;\" />");
out = out.replace(capture.get(0).unwrap().as_str(), result);
}
out = regex_replace(
&out,
"^(\\!{3})\\s(?<TYPE>.*?)\\s(?<TITLE>.+)\\n(?<CONTENT>.+)$",
"<div class=\"mdnote note-$2\">
<b class=\"mdnote-title\">$3</b>
<p>$4</p>
</div>\n",
);
out = regex_replace(
&out,
"^(\\!{3})\\s(?<TYPE>.*?)\\s(?<TITLE>.*?)$",
"<div class=\"mdnote note-$2\"><b class=\"mdnote-title\">$3</b></div>\n",
);
out = regex_replace(
&out,
"(\\={2})(.*?)(\\={2})",
"<span class=\"highlight\">$2</span>",
);
out = regex_replace(&out, "->>", "->>");
out = regex_replace(&out, "<<-", "<<-");
out = regex_replace(&out, "->", "->");
out = regex_replace(&out, "<-", "<-");
let arrow_alignment_flex_regex = RegexBuilder::new("(\\->{2})(.*?)(\\->{2}|<{2}\\-)")
.multi_line(true)
.dot_matches_new_line(true)
.build()
.unwrap();
for capture in arrow_alignment_flex_regex.captures_iter(&out.clone()) {
let _match = capture.get(0).unwrap().as_str();
let content = capture.get(2).unwrap().as_str();
let align = if _match.ends_with(">") {
"right"
} else {
"center"
};
out = out.replacen(
_match,
&format!("<rf class=\"justify-{align}\">{content}</rf>\n"),
1,
);
}
let arrow_alignment_regex = RegexBuilder::new("(\\->{1})(.*?)(\\->{1}|<{1}\\-)")
.multi_line(true)
.dot_matches_new_line(true)
.build()
.unwrap();
for capture in arrow_alignment_regex.captures_iter(&out.clone()) {
let _match = capture.get(0).unwrap().as_str();
let content = capture.get(2).unwrap().as_str();
let align = if _match.ends_with(">") {
"right"
} else {
"center"
};
out = out.replacen(
_match,
&format!("<r class=\"text-{align}\">{content}</r>\n"),
1,
);
}
out = regex_replace(&out, r"\[b\](.*?)\[/b\]", "<strong>$1</strong>"); out = regex_replace(&out, r"\[i\](.*?)\[/i\]", "<em>$1</em>"); out = regex_replace(&out, r"\[bi\](.*?)\[/bi\]", "<strong><em>$1</em></strong>"); out = regex_replace(
&out,
r"\[u\](.*?)\[/u\]",
"<span style=\"text-decoration: underline;\" role=\"underline\">$1</span>",
);
out = regex_replace_dmnl(&out, r"\[c\](.*?)\[/c\]", "<r class=\"text-center\">$1</r>"); out = regex_replace_dmnl(&out, r"\[r\](.*?)\[/r\]", "<r class=\"text-right\">$1</r>"); out = regex_replace_dmnl(
&out,
r"\[t (.*?)\](.*?)\[/t\]",
"<span style=\"color: $1;\" role=\"custom-color\">$2</span>",
);
out = regex_replace_dmnl(
&out,
r"\[m (.*?)\](.*?)\[/m\]",
"<span title=\"$1\" role=\"custom-message\">$2</span>",
);
out = regex_replace(
&out,
r"\[h\](.*?)\[/h\]",
"<span class=\"highlight\">$1</span>",
);
out = regex_replace(
&out,
r"\[h\](.*?)\[/h\]",
"<span class=\"highlight\">$1</span>",
);
for i in 1..7 {
out = regex_replace(
&out,
&format!(r"\[h{i}\](.*?)\[/h{i}\]"),
&format!("<h{i} id=\"$1\">$1</h{i}>"),
);
}
out = regex_replace(&out, r"\[/\]", "<br />"); out = regex_replace(
&out,
r"\[cl\](.*?)\[/cl\]",
"<code>$1</code>",
);
out = regex_replace_dmnl(
&out,
r"\[src (.*?)\]\n(.*?)\n\[/src\]",
"<pre class=\"lang-$1\"><code>$2</code></pre>",
);
out = regex_replace(
&out,
"(\\|\\|)\\s*(?<CONTENT>.*?)\\s*(\\|\\|)",
"<span role=\"spoiler\">$2</span>",
);
out = regex_replace(&out, "^(on)(.*)\\=(.*)\"$", "");
out = regex_replace(&out, "(href)\\=\"(javascript\\:)(.*)\"", "");
out = regex_replace(&out, "(<script.*>)(.*?)(<\\/script>)", "");
out = regex_replace(&out, "(<script.*>)", "");
out = regex_replace(&out, "(<link.*>)", "");
out = regex_replace(&out, "(<meta.*>)", "");
out
}
fn regex_replace(input: &str, pattern: &str, replace_with: &str) -> String {
RegexBuilder::new(pattern)
.multi_line(true)
.build()
.unwrap()
.replace_all(input, replace_with)
.to_string()
}
fn regex_replace_dmnl(input: &str, pattern: &str, replace_with: &str) -> String {
RegexBuilder::new(pattern)
.multi_line(true)
.dot_matches_new_line(true)
.build()
.unwrap()
.replace_all(input, replace_with)
.to_string()
}
#[allow(dead_code)]
fn regex_replace_exp(input: &str, pattern: &mut RegexBuilder, replace_with: &str) -> String {
pattern
.build()
.unwrap()
.replace_all(input, replace_with)
.to_string()
}