@@ -4,6 +4,7 @@ | |||||
- Sort individual tag/category pages by date | - Sort individual tag/category pages by date | ||||
- Add extra builtin shortcode for Streamable videos | - Add extra builtin shortcode for Streamable videos | ||||
- `path` and `permalink` now end with a `/` | |||||
## 0.0.6 (2017-05-24) | ## 0.0.6 (2017-05-24) | ||||
@@ -90,12 +90,20 @@ impl Config { | |||||
/// Makes a url, taking into account that the base url might have a trailing slash | /// Makes a url, taking into account that the base url might have a trailing slash | ||||
pub fn make_permalink(&self, path: &str) -> String { | pub fn make_permalink(&self, path: &str) -> String { | ||||
if self.base_url.ends_with('/') && path.starts_with('/') { | |||||
format!("{}{}", self.base_url, &path[1..]) | |||||
let trailing_bit = if path.ends_with('/') { "" } else { "/" }; | |||||
// Index section with a base url that has a trailing slash | |||||
if self.base_url.ends_with('/') && path == "/" { | |||||
self.base_url.clone() | |||||
} else if path == "/" { | |||||
// index section with a base url that doesn't have a trailing slash | |||||
format!("{}/", self.base_url) | |||||
} else if self.base_url.ends_with('/') && path.starts_with('/') { | |||||
format!("{}{}{}", self.base_url, &path[1..], trailing_bit) | |||||
} else if self.base_url.ends_with('/') { | } else if self.base_url.ends_with('/') { | ||||
format!("{}{}", self.base_url, path) | |||||
format!("{}{}{}", self.base_url, path, trailing_bit) | |||||
} else { | } else { | ||||
format!("{}/{}", self.base_url, path) | |||||
format!("{}/{}{}", self.base_url, path, trailing_bit) | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -192,13 +200,13 @@ hello = "world" | |||||
fn can_make_url_with_non_trailing_slash_base_url() { | fn can_make_url_with_non_trailing_slash_base_url() { | ||||
let mut config = Config::default(); | let mut config = Config::default(); | ||||
config.base_url = "http://vincent.is".to_string(); | config.base_url = "http://vincent.is".to_string(); | ||||
assert_eq!(config.make_permalink("hello"), "http://vincent.is/hello"); | |||||
assert_eq!(config.make_permalink("hello"), "http://vincent.is/hello/"); | |||||
} | } | ||||
#[test] | #[test] | ||||
fn can_make_url_with_trailing_slash_path() { | fn can_make_url_with_trailing_slash_path() { | ||||
let mut config = Config::default(); | let mut config = Config::default(); | ||||
config.base_url = "http://vincent.is/".to_string(); | config.base_url = "http://vincent.is/".to_string(); | ||||
assert_eq!(config.make_permalink("/hello"), "http://vincent.is/hello"); | |||||
assert_eq!(config.make_permalink("/hello"), "http://vincent.is/hello/"); | |||||
} | } | ||||
} | } |
@@ -91,6 +91,9 @@ impl Page { | |||||
format!("{}/{}", page.file.components.join("/"), page.slug) | format!("{}/{}", page.file.components.join("/"), page.slug) | ||||
}; | }; | ||||
} | } | ||||
if !page.path.ends_with('/') { | |||||
page.path = format!("{}/", page.path); | |||||
} | |||||
page.permalink = config.make_permalink(&page.path); | page.permalink = config.make_permalink(&page.path); | ||||
Ok(page) | Ok(page) | ||||
@@ -231,8 +234,8 @@ Hello world"#; | |||||
let res = Page::parse(Path::new("content/posts/intro/start.md"), content, &conf); | let res = Page::parse(Path::new("content/posts/intro/start.md"), content, &conf); | ||||
assert!(res.is_ok()); | assert!(res.is_ok()); | ||||
let page = res.unwrap(); | let page = res.unwrap(); | ||||
assert_eq!(page.path, "posts/intro/hello-world"); | |||||
assert_eq!(page.permalink, "http://hello.com/posts/intro/hello-world"); | |||||
assert_eq!(page.path, "posts/intro/hello-world/"); | |||||
assert_eq!(page.permalink, "http://hello.com/posts/intro/hello-world/"); | |||||
} | } | ||||
#[test] | #[test] | ||||
@@ -246,7 +249,7 @@ Hello world"#; | |||||
let res = Page::parse(Path::new("start.md"), content, &config); | let res = Page::parse(Path::new("start.md"), content, &config); | ||||
assert!(res.is_ok()); | assert!(res.is_ok()); | ||||
let page = res.unwrap(); | let page = res.unwrap(); | ||||
assert_eq!(page.path, "hello-world"); | |||||
assert_eq!(page.path, "hello-world/"); | |||||
assert_eq!(page.permalink, config.make_permalink("hello-world")); | assert_eq!(page.permalink, config.make_permalink("hello-world")); | ||||
} | } | ||||
@@ -74,17 +74,18 @@ impl<'a> Paginator<'a> { | |||||
continue; | continue; | ||||
} | } | ||||
let page_path = format!("{}/{}", paginate_path, index + 1); | |||||
let permalink = if section.permalink.ends_with('/') { | |||||
format!("{}{}", section.permalink, page_path) | |||||
let page_path = format!("{}/{}/", paginate_path, index + 1); | |||||
let permalink = format!("{}{}", section.permalink, page_path); | |||||
let pager_path = if section.is_index() { | |||||
page_path | |||||
} else { | } else { | ||||
format!("{}/{}", section.permalink, page_path) | |||||
format!("{}{}", section.path, page_path) | |||||
}; | }; | ||||
pagers.push(Pager::new( | pagers.push(Pager::new( | ||||
index + 1, | index + 1, | ||||
page.clone(), | page.clone(), | ||||
permalink, | permalink, | ||||
if section.is_index() { page_path } else { format!("{}/{}", section.path, page_path) } | |||||
pager_path, | |||||
)); | )); | ||||
} | } | ||||
@@ -164,11 +165,11 @@ mod tests { | |||||
f.paginate_path = Some("page".to_string()); | f.paginate_path = Some("page".to_string()); | ||||
let mut s = Section::new("content/_index.md", f); | let mut s = Section::new("content/_index.md", f); | ||||
if !is_index { | if !is_index { | ||||
s.path = "posts".to_string(); | |||||
s.permalink = "https://vincent.is/posts".to_string(); | |||||
s.path = "posts/".to_string(); | |||||
s.permalink = "https://vincent.is/posts/".to_string(); | |||||
s.file.components = vec!["posts".to_string()]; | s.file.components = vec!["posts".to_string()]; | ||||
} else { | } else { | ||||
s.permalink = "https://vincent.is".to_string(); | |||||
s.permalink = "https://vincent.is/".to_string(); | |||||
} | } | ||||
s | s | ||||
} | } | ||||
@@ -186,13 +187,13 @@ mod tests { | |||||
assert_eq!(paginator.pagers[0].index, 1); | assert_eq!(paginator.pagers[0].index, 1); | ||||
assert_eq!(paginator.pagers[0].pages.len(), 2); | assert_eq!(paginator.pagers[0].pages.len(), 2); | ||||
assert_eq!(paginator.pagers[0].permalink, "https://vincent.is/posts"); | |||||
assert_eq!(paginator.pagers[0].path, "posts"); | |||||
assert_eq!(paginator.pagers[0].permalink, "https://vincent.is/posts/"); | |||||
assert_eq!(paginator.pagers[0].path, "posts/"); | |||||
assert_eq!(paginator.pagers[1].index, 2); | assert_eq!(paginator.pagers[1].index, 2); | ||||
assert_eq!(paginator.pagers[1].pages.len(), 1); | assert_eq!(paginator.pagers[1].pages.len(), 1); | ||||
assert_eq!(paginator.pagers[1].permalink, "https://vincent.is/posts/page/2"); | |||||
assert_eq!(paginator.pagers[1].path, "posts/page/2"); | |||||
assert_eq!(paginator.pagers[1].permalink, "https://vincent.is/posts/page/2/"); | |||||
assert_eq!(paginator.pagers[1].path, "posts/page/2/"); | |||||
} | } | ||||
#[test] | #[test] | ||||
@@ -208,13 +209,13 @@ mod tests { | |||||
assert_eq!(paginator.pagers[0].index, 1); | assert_eq!(paginator.pagers[0].index, 1); | ||||
assert_eq!(paginator.pagers[0].pages.len(), 2); | assert_eq!(paginator.pagers[0].pages.len(), 2); | ||||
assert_eq!(paginator.pagers[0].permalink, "https://vincent.is"); | |||||
assert_eq!(paginator.pagers[0].permalink, "https://vincent.is/"); | |||||
assert_eq!(paginator.pagers[0].path, ""); | assert_eq!(paginator.pagers[0].path, ""); | ||||
assert_eq!(paginator.pagers[1].index, 2); | assert_eq!(paginator.pagers[1].index, 2); | ||||
assert_eq!(paginator.pagers[1].pages.len(), 1); | assert_eq!(paginator.pagers[1].pages.len(), 1); | ||||
assert_eq!(paginator.pagers[1].permalink, "https://vincent.is/page/2"); | |||||
assert_eq!(paginator.pagers[1].path, "page/2"); | |||||
assert_eq!(paginator.pagers[1].permalink, "https://vincent.is/page/2/"); | |||||
assert_eq!(paginator.pagers[1].path, "page/2/"); | |||||
} | } | ||||
#[test] | #[test] | ||||
@@ -230,18 +231,18 @@ mod tests { | |||||
let context = paginator.build_paginator_context(&paginator.pagers[0]); | let context = paginator.build_paginator_context(&paginator.pagers[0]); | ||||
assert_eq!(context["paginate_by"], to_value(2).unwrap()); | assert_eq!(context["paginate_by"], to_value(2).unwrap()); | ||||
assert_eq!(context["first"], to_value("https://vincent.is/posts").unwrap()); | |||||
assert_eq!(context["last"], to_value("https://vincent.is/posts/page/2").unwrap()); | |||||
assert_eq!(context["first"], to_value("https://vincent.is/posts/").unwrap()); | |||||
assert_eq!(context["last"], to_value("https://vincent.is/posts/page/2/").unwrap()); | |||||
assert_eq!(context["previous"], to_value::<Option<()>>(None).unwrap()); | assert_eq!(context["previous"], to_value::<Option<()>>(None).unwrap()); | ||||
assert_eq!(context["next"], to_value("https://vincent.is/posts/page/2").unwrap()); | |||||
assert_eq!(context["next"], to_value("https://vincent.is/posts/page/2/").unwrap()); | |||||
assert_eq!(context["current_index"], to_value(1).unwrap()); | assert_eq!(context["current_index"], to_value(1).unwrap()); | ||||
let context = paginator.build_paginator_context(&paginator.pagers[1]); | let context = paginator.build_paginator_context(&paginator.pagers[1]); | ||||
assert_eq!(context["paginate_by"], to_value(2).unwrap()); | assert_eq!(context["paginate_by"], to_value(2).unwrap()); | ||||
assert_eq!(context["first"], to_value("https://vincent.is/posts").unwrap()); | |||||
assert_eq!(context["last"], to_value("https://vincent.is/posts/page/2").unwrap()); | |||||
assert_eq!(context["first"], to_value("https://vincent.is/posts/").unwrap()); | |||||
assert_eq!(context["last"], to_value("https://vincent.is/posts/page/2/").unwrap()); | |||||
assert_eq!(context["next"], to_value::<Option<()>>(None).unwrap()); | assert_eq!(context["next"], to_value::<Option<()>>(None).unwrap()); | ||||
assert_eq!(context["previous"], to_value("https://vincent.is/posts").unwrap()); | |||||
assert_eq!(context["previous"], to_value("https://vincent.is/posts/").unwrap()); | |||||
assert_eq!(context["current_index"], to_value(2).unwrap()); | assert_eq!(context["current_index"], to_value(2).unwrap()); | ||||
} | } | ||||
} | } |
@@ -58,7 +58,7 @@ impl Section { | |||||
let (meta, content) = split_section_content(file_path, content)?; | let (meta, content) = split_section_content(file_path, content)?; | ||||
let mut section = Section::new(file_path, meta); | let mut section = Section::new(file_path, meta); | ||||
section.raw_content = content.clone(); | section.raw_content = content.clone(); | ||||
section.path = section.file.components.join("/"); | |||||
section.path = format!("{}/", section.file.components.join("/")); | |||||
section.permalink = config.make_permalink(§ion.path); | section.permalink = config.make_permalink(§ion.path); | ||||
Ok(section) | Ok(section) | ||||
} | } | ||||
@@ -28,7 +28,7 @@ fn can_parse_site() { | |||||
// Make sure the page with a url doesn't have any sections | // Make sure the page with a url doesn't have any sections | ||||
let url_post = &site.pages[&posts_path.join("fixed-url.md")]; | let url_post = &site.pages[&posts_path.join("fixed-url.md")]; | ||||
assert_eq!(url_post.path, "a-fixed-url"); | |||||
assert_eq!(url_post.path, "a-fixed-url/"); | |||||
// Make sure the article in a folder with only asset doesn't get counted as a section | // Make sure the article in a folder with only asset doesn't get counted as a section | ||||
let asset_folder_post = &site.pages[&posts_path.join("with-assets").join("index.md")]; | let asset_folder_post = &site.pages[&posts_path.join("with-assets").join("index.md")]; | ||||
@@ -126,8 +126,8 @@ fn can_build_site_without_live_reload() { | |||||
assert_eq!(file_contains!(public, "index.html", "/livereload.js?port=1112&mindelay=10"), false); | assert_eq!(file_contains!(public, "index.html", "/livereload.js?port=1112&mindelay=10"), false); | ||||
// Both pages and sections are in the sitemap | // Both pages and sections are in the sitemap | ||||
assert!(file_contains!(public, "sitemap.xml", "<loc>https://replace-this-with-your-url.com/posts/simple</loc>")); | |||||
assert!(file_contains!(public, "sitemap.xml", "<loc>https://replace-this-with-your-url.com/posts</loc>")); | |||||
assert!(file_contains!(public, "sitemap.xml", "<loc>https://replace-this-with-your-url.com/posts/simple/</loc>")); | |||||
assert!(file_contains!(public, "sitemap.xml", "<loc>https://replace-this-with-your-url.com/posts/</loc>")); | |||||
} | } | ||||
#[test] | #[test] | ||||
@@ -216,8 +216,8 @@ fn can_build_site_with_categories() { | |||||
assert_eq!(file_exists!(public, "tags/index.html"), false); | assert_eq!(file_exists!(public, "tags/index.html"), false); | ||||
// Categories are in the sitemap | // Categories are in the sitemap | ||||
assert!(file_contains!(public, "sitemap.xml", "<loc>https://replace-this-with-your-url.com/categories</loc>")); | |||||
assert!(file_contains!(public, "sitemap.xml", "<loc>https://replace-this-with-your-url.com/categories/a</loc>")); | |||||
assert!(file_contains!(public, "sitemap.xml", "<loc>https://replace-this-with-your-url.com/categories/</loc>")); | |||||
assert!(file_contains!(public, "sitemap.xml", "<loc>https://replace-this-with-your-url.com/categories/a/</loc>")); | |||||
} | } | ||||
#[test] | #[test] | ||||
@@ -268,8 +268,8 @@ fn can_build_site_with_tags() { | |||||
// Categories aren't | // Categories aren't | ||||
assert_eq!(file_exists!(public, "categories/index.html"), false); | assert_eq!(file_exists!(public, "categories/index.html"), false); | ||||
// Tags are in the sitemap | // Tags are in the sitemap | ||||
assert!(file_contains!(public, "sitemap.xml", "<loc>https://replace-this-with-your-url.com/tags</loc>")); | |||||
assert!(file_contains!(public, "sitemap.xml", "<loc>https://replace-this-with-your-url.com/tags/tag-with-space</loc>")); | |||||
assert!(file_contains!(public, "sitemap.xml", "<loc>https://replace-this-with-your-url.com/tags/</loc>")); | |||||
assert!(file_contains!(public, "sitemap.xml", "<loc>https://replace-this-with-your-url.com/tags/tag-with-space/</loc>")); | |||||
} | } | ||||
#[test] | #[test] | ||||
@@ -327,14 +327,14 @@ fn can_build_site_with_pagination_for_section() { | |||||
assert!(file_contains!( | assert!(file_contains!( | ||||
public, | public, | ||||
"posts/page/1/index.html", | "posts/page/1/index.html", | ||||
"http-equiv=\"refresh\" content=\"0;url=https://replace-this-with-your-url.com/posts\"" | |||||
"http-equiv=\"refresh\" content=\"0;url=https://replace-this-with-your-url.com/posts/\"" | |||||
)); | )); | ||||
assert!(file_contains!(public, "posts/index.html", "Num pagers: 3")); | assert!(file_contains!(public, "posts/index.html", "Num pagers: 3")); | ||||
assert!(file_contains!(public, "posts/index.html", "Page size: 2")); | assert!(file_contains!(public, "posts/index.html", "Page size: 2")); | ||||
assert!(file_contains!(public, "posts/index.html", "Current index: 1")); | assert!(file_contains!(public, "posts/index.html", "Current index: 1")); | ||||
assert!(file_contains!(public, "posts/index.html", "has_next")); | assert!(file_contains!(public, "posts/index.html", "has_next")); | ||||
assert!(file_contains!(public, "posts/index.html", "First: https://replace-this-with-your-url.com/posts")); | |||||
assert!(file_contains!(public, "posts/index.html", "Last: https://replace-this-with-your-url.com/posts/page/3")); | |||||
assert!(file_contains!(public, "posts/index.html", "First: https://replace-this-with-your-url.com/posts/")); | |||||
assert!(file_contains!(public, "posts/index.html", "Last: https://replace-this-with-your-url.com/posts/page/3/")); | |||||
assert_eq!(file_contains!(public, "posts/index.html", "has_prev"), false); | assert_eq!(file_contains!(public, "posts/index.html", "has_prev"), false); | ||||
assert!(file_exists!(public, "posts/page/2/index.html")); | assert!(file_exists!(public, "posts/page/2/index.html")); | ||||
@@ -343,8 +343,8 @@ fn can_build_site_with_pagination_for_section() { | |||||
assert!(file_contains!(public, "posts/page/2/index.html", "Current index: 2")); | assert!(file_contains!(public, "posts/page/2/index.html", "Current index: 2")); | ||||
assert!(file_contains!(public, "posts/page/2/index.html", "has_prev")); | assert!(file_contains!(public, "posts/page/2/index.html", "has_prev")); | ||||
assert!(file_contains!(public, "posts/page/2/index.html", "has_next")); | assert!(file_contains!(public, "posts/page/2/index.html", "has_next")); | ||||
assert!(file_contains!(public, "posts/page/2/index.html", "First: https://replace-this-with-your-url.com/posts")); | |||||
assert!(file_contains!(public, "posts/page/2/index.html", "Last: https://replace-this-with-your-url.com/posts/page/3")); | |||||
assert!(file_contains!(public, "posts/page/2/index.html", "First: https://replace-this-with-your-url.com/posts/")); | |||||
assert!(file_contains!(public, "posts/page/2/index.html", "Last: https://replace-this-with-your-url.com/posts/page/3/")); | |||||
} | } | ||||
#[test] | #[test] | ||||