use crate::helpers::re;
use regex::Captures;
use std::collections::HashMap;
use url::Url;
#[derive(Debug)]
struct Link {
pub href: String,
pub title: String,
pub is_footnote: bool
}
fn validate_title_definitions(opener: &str, closer: &str, name: &str) {
if opener != closer && !(opener == "(" && closer == ")") {
panic!("Marcus: ParseError: The title declaration for {name} must use quotes (\"), apostrophes (') or matching parenthesis \"(\" & \")\"");
}
}
fn get_footnote(mut identifier: String) -> (String, bool) {
let mut is_footnote: bool = false;
while identifier.starts_with("^") {
identifier = identifier[1..].trim().to_string();
if is_footnote == false {
is_footnote = true;
}
}
(identifier, is_footnote)
}
fn html_from_link<F: Fn(&Link) -> String>(links: &HashMap<String, Link>, src: String, defined: String, undefined: F) -> String {
if links.contains_key(&src) {
let link: &Link = links.get(&src).unwrap();
if link.is_footnote == false {
return undefined(link);
}
}
return defined;
}
pub fn default(html: &mut String) {
let mut links: HashMap<String, Link> = HashMap::new();
re::parse(html, re::from(re::LINK_DEFINE_WITH_TITLE), | capture: Captures | {
validate_title_definitions(&capture[3], &capture[5], "links");
let (href, title): (String, String) = (capture[2].trim().to_string(), capture[4].trim().to_string());
let (identifier, is_footnote): (String, bool) = get_footnote(capture[1].trim().to_string());
links.insert(identifier, Link { href, title, is_footnote });
String::new()
});
re::parse(html, re::from(re::LINK_DEFINE), | capture: Captures | {
let href: String = capture[2].trim().to_string();
let (identifier, is_footnote): (String, bool) = get_footnote(capture[1].trim().to_string());
links.insert(identifier, Link { href, title: String::new(), is_footnote });
String::new()
});
re::parse(html, re::from(re::IMAGE_WITH_TITLE), | capture: Captures | {
validate_title_definitions(&capture[3], &capture[5], "images");
let (src, alt): (String, &str) = (capture[2].trim().to_string(), &capture[1].trim());
let defined: String = format!("<img src=\"{}\" title=\"{}\" alt=\"{}\" />", &src, &capture[4].trim(), alt);
html_from_link(&links, src, defined, | link: &Link | -> String {
if !link.title.is_empty() {
format!("<img src=\"{}\" title=\"{}\" alt=\"{}\" />", link.href, link.title, alt)
} else {
format!("<img src=\"{}\" alt=\"{}\" />", link.href, alt)
}
})
});
re::parse(html, re::from(re::IMAGE), | capture: Captures | {
let (src, alt): (String, &str) = (capture[2].trim().to_string(), &capture[1].trim());
let defined: String = format!("<img src=\"{src}\" alt=\"{alt}\" />");
html_from_link(&links, src, defined, | link: &Link | -> String {
if !link.title.is_empty() {
format!("<img src=\"{src}\" alt=\"{alt}\" title=\"{title}\" />", src = link.href, title = link.title)
} else {
format!("<img src=\"{src}\" alt=\"{alt}\" />", src = link.href)
}
})
});
re::parse(html, re::from(re::LINK_WITH_TITLE), | capture: Captures | {
validate_title_definitions(&capture[3], &capture[5], "images");
let (href, text): (String, &str) = (capture[2].trim().to_string(), &capture[1].trim());
let defined: String = format!("<a href=\"{}\" title=\"{}\">{}</a>", &href, &capture[4].trim(), text);
html_from_link(&links, href, defined, | link: &Link | -> String {
if !link.title.is_empty() {
format!("<a href=\"{}\" title=\"{}\">{}</a>", link.href, link.title, text)
} else {
format!("<a href=\"{}\">{}</a>", link.href, text)
}
})
});
re::parse(html, re::from(re::LINK), | capture: Captures | {
let (href, text): (String, &str) = (capture[2].trim().to_string(), &capture[1].trim());
let defined: String = format!("<a href=\"{href}\">{text}</a>");
html_from_link(&links, href, defined, | link: &Link | -> String {
if !link.title.is_empty() {
format!("<a href=\"{href}\" title=\"{title}\">{text}</a>", href = link.href, title = link.title)
} else {
format!("<a href=\"{href}\">{text}</a>", href = link.href)
}
})
});
re::parse(html, re::from(re::FOOTNOTE), | capture: Captures | {
let index: String = capture[1].trim().to_string();
if links.contains_key(&index) {
let link: &Link = links.get(&index).unwrap();
if link.is_footnote == true {
return match Url::parse(&link.href) {
Ok(_) => format!("<sup><a href=\"{}\">[{}]</a></sup>", link.href, index),
Err(_) => format!("<sup title=\"{}\" style=\"cursor:help\">[{}]</sup>", link.href, index)
};
}
}
return format!("<sup style=\"cursor:not-allowed\">[{}]</sup>", index);
});
}