extern crate regex;
use regex::{Regex, Captures};
use crate::reg;
pub mod rust_syntax;
pub mod rasm_syntax;
lazy_static!{
static ref CODE_BLOCK: Regex = reg(r"(\n|^)```(\S*)\s+([\s\S]+?)\s+```$");
static ref CODE_INLINE: Regex = reg(r"(`)(.+?)(`)");
static ref LINK: Regex = reg(r"\[([^\[]+)\]\(([^\)]+)\)");
static ref HEADING: Regex = reg(r"(\n|^)(#+)(.+)$");
static ref EMPHASIS: Regex = reg(r"(\*{1,2})(.+?)(\*{1,2})");
static ref EMPHASIS_UNDER: Regex = reg(r"(_{1,2})(.+?)(_{1,2})");
static ref STRIKETHROUGH: Regex = reg(r"(\~\~)(.+?)(\~\~)");
static ref HORIZONTAL: Regex = reg(r"(\n|^)((\-{3,})|(={3,})|(#{3,}))$");
static ref UNORDERED: Regex = reg(r"((\n|^)(\-|\+)\s.*$)+");
static ref ORDERED: Regex = reg(r"((\n|^)([0-9]+\.)\s.*$)+");
static ref PARAGRAPH: Regex = reg(r"^\n([\s\S]+?)\n$");
static ref BLOCKQUOTE: Regex = reg(r"(\n|^)>(.+)$");
static ref IMG: Regex = reg(r"^!\[([^\[]+)\]\(([^\)]+)\)");
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"#");
static ref LFEED: Regex = reg(r"(\r\n|\n)");
}
fn symbols(s: &str) -> String {
LFEED.replace_all(&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 break_replacer(_: &Captures) -> String {
format!("<br />")
}
fn paragraph_replacer(cap: &Captures) -> String {
format!("<p>{}</p>", replace::line_breaks(cap[1].to_string()))
}
fn code_block_replacer(cap: &Captures) -> String {
let code = match &cap[2] {
"rust" => rust_syntax::parse(symbols(&cap[3])),
"rasm" => rasm_syntax::parse(symbols(&cap[3])),
_ => symbols(&cap[3]),
};
format!("<pre>{}</pre>", code)
}
fn code_inline_replacer(cap: &Captures) -> String {
format!("<code>{}</code>", symbols(&cap[2]))
}
fn strikethrough_replacer(cap: &Captures) -> String {
format!("<del>{}</del>", &cap[2])
}
fn blockquote_replacer(cap: &Captures) -> String {
format!("<blockquote>{}</blockquote>", &cap[1])
}
fn link_replacer(cap: &Captures) -> String {
format!("<a href='{}'>{}</a>", &cap[2], &cap[1])
}
fn heading_replacer(cap: &Captures) -> String {
format!("<h{len}>{}</h{len}>", &cap[3], len = cap[2].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!("<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)
}
fn image_replacer(cap: &Captures) -> String {
format!("<img src='{}' alt='{}' />", &cap[1], &cap[2])
}
pub fn parse(s: String) -> String {
replace::paragraphs(replace::unordered(replace::ordered(replace::blockquotes(replace::strikethrough(replace::emphasis(replace::headings(replace::rules(replace::links(replace::images(replace::code_inline(replace::code_blocks(s))))))))))))
}
pub mod replace {
use crate::markdown::*;
pub fn paragraphs(s: String) -> String {
PARAGRAPH.replace_all(&s, ¶graph_replacer).to_string()
}
pub fn line_breaks(s: String) -> String {
LFEED.replace_all(&s, &break_replacer).to_string()
}
pub fn code_blocks(s: String) -> String {
CODE_BLOCK.replace_all(&s, &code_block_replacer).to_string()
}
pub fn blockquotes(s: String) -> String {
BLOCKQUOTE.replace_all(&s, &blockquote_replacer).to_string()
}
pub fn strikethrough(s: String) -> String {
STRIKETHROUGH.replace_all(&s, strikethrough_replacer).to_string()
}
pub fn code_inline(s: String) -> String {
CODE_INLINE.replace_all(&s, &code_inline_replacer).to_string()
}
pub fn images(s: String) -> String {
IMG.replace_all(&s, &image_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_UNDER.replace_all(&EMPHASIS.replace_all(&s, &emphasis_replacer), &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()
}
}