Make co-located asset link permalinks

This commit is contained in:
Vincent Prouillet 2018-05-07 21:03:51 +02:00
parent d39edd8ecb
commit ef543b3d2b
3 changed files with 61 additions and 18 deletions

View file

@ -12,5 +12,4 @@ toml = "0.4"
regex = "1"
lazy_static = "1"
errors = { path = "../errors" }

View file

@ -30,10 +30,15 @@ fn find_anchor(anchors: &[String], name: String, level: u8) -> String {
find_anchor(anchors, name, level + 1)
}
fn is_colocated_asset_link(link: &str) -> bool {
!link.contains("/") // http://, ftp://, ../ etc
&& !link.starts_with("mailto:")
}
pub fn markdown_to_html(content: &str, context: &RenderContext) -> Result<(String, Vec<Header>)> {
// the rendered html
let mut html = String::new();
let mut html = String::with_capacity(content.len());
// Set while parsing
let mut error = None;
@ -104,29 +109,37 @@ pub fn markdown_to_html(content: &str, context: &RenderContext) -> Result<(Strin
Event::Html(Owned("</pre>".to_string()))
},
// Need to handle relative links
Event::Start(Tag::Link(ref link, ref title)) => {
if in_header {
if !title.is_empty() {
temp_header.push(&format!("<a href=\"{}\" title=\"{}\">", link, title));
} else {
temp_header.push(&format!("<a href=\"{}\">", link));
}
return Event::Html(Owned(String::new()));
}
if link.starts_with("./") {
match resolve_internal_link(link, context.permalinks) {
Ok(url) => {
return Event::Start(Tag::Link(Owned(url), title.clone()));
},
Event::Start(Tag::Link(link, title)) => {
// A few situations here:
// - it could be a relative link (starting with `./`)
// - it could be a link to a co-located asset
// - it could be a normal link
// - any of those can be in a header or not: if it's in a header we need to append to a string
let fixed_link = if link.starts_with("./") {
match resolve_internal_link(&link, context.permalinks) {
Ok(url) => url,
Err(_) => {
error = Some(format!("Relative link {} not found.", link).into());
return Event::Html(Owned(String::new()));
}
}
} else if is_colocated_asset_link(&link) {
format!("{}{}", context.current_page_permalink, link)
} else {
link.to_string()
};
if in_header {
let html = if title.is_empty() {
format!("<a href=\"{}\">", fixed_link)
} else {
format!("<a href=\"{}\" title=\"{}\">", fixed_link, title)
};
temp_header.push(&html);
return Event::Html(Owned(String::new()));
}
Event::Start(Tag::Link(link.clone(), title.clone()))
Event::Start(Tag::Link(Owned(fixed_link), title))
},
Event::End(Tag::Link(_, _)) => {
if in_header {

View file

@ -473,3 +473,34 @@ fn can_understand_link_with_title_in_header() {
"<h1 id=\"rust\"><a href=\"https://rust-lang.org\" title=\"Rust homepage\">Rust</a></h1>\n"
);
}
#[test]
fn can_make_valid_relative_link_in_header() {
let mut permalinks = HashMap::new();
permalinks.insert("pages/about.md".to_string(), "https://vincent.is/about/".to_string());
let tera_ctx = Tera::default();
let config = Config::default();
let context = RenderContext::new(&tera_ctx, &config, "", &permalinks, InsertAnchor::None);
let res = render_content(
r#" # [rel link](./pages/about.md)"#,
&context
).unwrap();
assert_eq!(
res.0,
"<h1 id=\"rel-link\"><a href=\"https://vincent.is/about/\">rel link</a></h1>\n"
);
}
#[test]
fn can_make_permalinks_with_colocated_assets() {
let permalinks_ctx = HashMap::new();
let config = Config::default();
let context = RenderContext::new(&GUTENBERG_TERA, &config, "https://vincent.is/about/", &permalinks_ctx, InsertAnchor::None);
let res = render_content("[an image](image.jpg)", &context).unwrap();
assert_eq!(
res.0,
"<p><a href=\"https://vincent.is/about/image.jpg\">an image</a></p>\n"
);
}