Add trailing slash to paths and permalinks. Fix #85
This commit is contained in:
parent
0037f743cd
commit
2d949249c3
|
@ -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('/') {
|
let trailing_bit = if path.ends_with('/') { "" } else { "/" };
|
||||||
format!("{}{}", self.base_url, &path[1..])
|
|
||||||
|
// 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.path, "posts/intro/hello-world/");
|
||||||
assert_eq!(page.permalink, "http://hello.com/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 page_path = format!("{}/{}/", paginate_path, index + 1);
|
||||||
let permalink = if section.permalink.ends_with('/') {
|
let permalink = format!("{}{}", section.permalink, page_path);
|
||||||
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.path = "posts/".to_string();
|
||||||
s.permalink = "https://vincent.is/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].permalink, "https://vincent.is/posts/");
|
||||||
assert_eq!(paginator.pagers[0].path, "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].permalink, "https://vincent.is/posts/page/2/");
|
||||||
assert_eq!(paginator.pagers[1].path, "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].permalink, "https://vincent.is/page/2/");
|
||||||
assert_eq!(paginator.pagers[1].path, "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["first"], to_value("https://vincent.is/posts/").unwrap());
|
||||||
assert_eq!(context["last"], to_value("https://vincent.is/posts/page/2").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["first"], to_value("https://vincent.is/posts/").unwrap());
|
||||||
assert_eq!(context["last"], to_value("https://vincent.is/posts/page/2").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/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/</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/</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/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/</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/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", "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", "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", "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", "Last: https://replace-this-with-your-url.com/posts/page/3/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue