Make current_path always start with a slash (#1101)
* Make {section, page}.path always start with a slash Change tests accordingly * Fix missing leading/trailing slash in current_path of Taxonomy ("tags") and TaxonomyItem ("some-tag") * Make {Paginator, Pager}.path always start with a slash Fix Paginator.path missing trailing slash in from_taxonomy() Change tests accordingly * Update documentation regarding current_path now always starting with a slash * Fix asymptomatic inverted logic in filter() for {section, page}.assets * Add to 3 integration tests several checks for current_path in different templates * Add a check for current_path in a paginated index section, "/page/2/" This requires adding two dummy pages in the content root. * Fix false passing of test on paginator.last due to URL prefix matching A string formatting such as {name: value} can help prevent this.
This commit is contained in:
parent
28523ac9ad
commit
b9296f7985
|
@ -48,7 +48,7 @@ pub struct Page {
|
|||
/// The slug of that page.
|
||||
/// First tries to find the slug in the meta and defaults to filename otherwise
|
||||
pub slug: String,
|
||||
/// The URL path of the page
|
||||
/// The URL path of the page, always starting with a slash
|
||||
pub path: String,
|
||||
/// The components of the path of the page
|
||||
pub components: Vec<String>,
|
||||
|
@ -182,8 +182,14 @@ impl Page {
|
|||
}
|
||||
};
|
||||
|
||||
if let Some(ref p) = page.meta.path {
|
||||
page.path = p.trim().trim_start_matches('/').to_string();
|
||||
page.path = if let Some(ref p) = page.meta.path {
|
||||
let path = p.trim();
|
||||
|
||||
if path.starts_with('/') {
|
||||
path.into()
|
||||
} else {
|
||||
format!("/{}", path)
|
||||
}
|
||||
} else {
|
||||
let mut path = if page.file.components.is_empty() {
|
||||
page.slug.clone()
|
||||
|
@ -195,8 +201,8 @@ impl Page {
|
|||
path = format!("{}/{}", page.lang, path);
|
||||
}
|
||||
|
||||
page.path = path;
|
||||
}
|
||||
format!("/{}", path)
|
||||
};
|
||||
|
||||
if !page.path.ends_with('/') {
|
||||
page.path = format!("{}/", page.path);
|
||||
|
@ -238,7 +244,7 @@ impl Page {
|
|||
page.assets = assets
|
||||
.into_iter()
|
||||
.filter(|path| match path.file_name() {
|
||||
None => true,
|
||||
None => false,
|
||||
Some(file) => !globset.is_match(file),
|
||||
})
|
||||
.collect();
|
||||
|
@ -420,7 +426,7 @@ Hello world"#;
|
|||
Page::parse(Path::new("content/posts/intro/start.md"), content, &conf, &PathBuf::new());
|
||||
assert!(res.is_ok());
|
||||
let page = res.unwrap();
|
||||
assert_eq!(page.path, "posts/intro/hello-world/");
|
||||
assert_eq!(page.path, "/posts/intro/hello-world/");
|
||||
assert_eq!(page.components, vec!["posts", "intro", "hello-world"]);
|
||||
assert_eq!(page.permalink, "http://hello.com/posts/intro/hello-world/");
|
||||
}
|
||||
|
@ -436,7 +442,7 @@ Hello world"#;
|
|||
let res = Page::parse(Path::new("start.md"), content, &config, &PathBuf::new());
|
||||
assert!(res.is_ok());
|
||||
let page = res.unwrap();
|
||||
assert_eq!(page.path, "hello-world/");
|
||||
assert_eq!(page.path, "/hello-world/");
|
||||
assert_eq!(page.components, vec!["hello-world"]);
|
||||
assert_eq!(page.permalink, config.make_permalink("hello-world"));
|
||||
}
|
||||
|
@ -453,7 +459,7 @@ Hello world"#;
|
|||
let res = Page::parse(Path::new("start.md"), content, &config, &PathBuf::new());
|
||||
assert!(res.is_ok());
|
||||
let page = res.unwrap();
|
||||
assert_eq!(page.path, "hello-world/");
|
||||
assert_eq!(page.path, "/hello-world/");
|
||||
assert_eq!(page.components, vec!["hello-world"]);
|
||||
assert_eq!(page.permalink, config.make_permalink("hello-world"));
|
||||
}
|
||||
|
@ -470,7 +476,7 @@ Hello world"#;
|
|||
let res = Page::parse(Path::new("start.md"), content, &config, &PathBuf::new());
|
||||
assert!(res.is_ok());
|
||||
let page = res.unwrap();
|
||||
assert_eq!(page.path, "日本/");
|
||||
assert_eq!(page.path, "/日本/");
|
||||
assert_eq!(page.components, vec!["日本"]);
|
||||
assert_eq!(page.permalink, config.make_permalink("日本"));
|
||||
}
|
||||
|
@ -491,7 +497,7 @@ Hello world"#;
|
|||
);
|
||||
assert!(res.is_ok());
|
||||
let page = res.unwrap();
|
||||
assert_eq!(page.path, "hello-world/");
|
||||
assert_eq!(page.path, "/hello-world/");
|
||||
assert_eq!(page.components, vec!["hello-world"]);
|
||||
assert_eq!(page.permalink, config.make_permalink("hello-world"));
|
||||
}
|
||||
|
@ -512,7 +518,7 @@ Hello world"#;
|
|||
);
|
||||
assert!(res.is_ok());
|
||||
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"));
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ pub struct Section {
|
|||
pub file: FileInfo,
|
||||
/// The front matter meta-data
|
||||
pub meta: SectionFrontMatter,
|
||||
/// The URL path of the page
|
||||
/// The URL path of the page, always starting with a slash
|
||||
pub path: String,
|
||||
/// The components for the path of that page
|
||||
pub components: Vec<String>,
|
||||
|
@ -111,16 +111,18 @@ impl Section {
|
|||
let (word_count, reading_time) = get_reading_analytics(§ion.raw_content);
|
||||
section.word_count = Some(word_count);
|
||||
section.reading_time = Some(reading_time);
|
||||
|
||||
let path = section.file.components.join("/");
|
||||
if section.lang != config.default_language {
|
||||
if path.is_empty() {
|
||||
section.path = format!("{}/", section.lang);
|
||||
} else {
|
||||
section.path = format!("{}/{}/", section.lang, path);
|
||||
}
|
||||
let lang_path = if section.lang != config.default_language {
|
||||
format!("/{}", section.lang)
|
||||
} else {
|
||||
section.path = format!("{}/", path);
|
||||
}
|
||||
"".into()
|
||||
};
|
||||
section.path = if path.is_empty() {
|
||||
format!("{}/", lang_path)
|
||||
} else {
|
||||
format!("{}/{}/", lang_path, path)
|
||||
};
|
||||
|
||||
section.components = section
|
||||
.path
|
||||
|
@ -156,7 +158,7 @@ impl Section {
|
|||
section.assets = assets
|
||||
.into_iter()
|
||||
.filter(|path| match path.file_name() {
|
||||
None => true,
|
||||
None => false,
|
||||
Some(file) => !globset.is_match(file),
|
||||
})
|
||||
.collect();
|
||||
|
|
|
@ -96,7 +96,7 @@ impl<'a> Paginator<'a> {
|
|||
paginate_by,
|
||||
root: PaginationRoot::Taxonomy(taxonomy, item),
|
||||
permalink: item.permalink.clone(),
|
||||
path: format!("{}/{}", taxonomy.kind.name, item.slug),
|
||||
path: format!("/{}/{}/", taxonomy.kind.name, item.slug),
|
||||
paginate_path: taxonomy
|
||||
.kind
|
||||
.paginate_path
|
||||
|
@ -146,7 +146,7 @@ impl<'a> Paginator<'a> {
|
|||
let permalink = format!("{}{}", self.permalink, page_path);
|
||||
|
||||
let pager_path = if self.is_index {
|
||||
page_path
|
||||
format!("/{}", page_path)
|
||||
} else if self.path.ends_with('/') {
|
||||
format!("{}{}", self.path, page_path)
|
||||
} else {
|
||||
|
@ -252,10 +252,11 @@ mod tests {
|
|||
f.paginate_path = "page".to_string();
|
||||
let mut s = Section::new("content/_index.md", f, &PathBuf::new());
|
||||
if !is_index {
|
||||
s.path = "posts/".to_string();
|
||||
s.path = "/posts/".to_string();
|
||||
s.permalink = "https://vincent.is/posts/".to_string();
|
||||
s.file.components = vec!["posts".to_string()];
|
||||
} else {
|
||||
s.path = "/".into();
|
||||
s.permalink = "https://vincent.is/".to_string();
|
||||
}
|
||||
s
|
||||
|
@ -285,12 +286,12 @@ mod tests {
|
|||
assert_eq!(paginator.pagers[0].index, 1);
|
||||
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].path, "/posts/");
|
||||
|
||||
assert_eq!(paginator.pagers[1].index, 2);
|
||||
assert_eq!(paginator.pagers[1].pages.len(), 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]
|
||||
|
@ -302,12 +303,12 @@ mod tests {
|
|||
assert_eq!(paginator.pagers[0].index, 1);
|
||||
assert_eq!(paginator.pagers[0].pages.len(), 2);
|
||||
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].pages.len(), 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]
|
||||
|
@ -355,12 +356,12 @@ mod tests {
|
|||
assert_eq!(paginator.pagers[0].index, 1);
|
||||
assert_eq!(paginator.pagers[0].pages.len(), 2);
|
||||
assert_eq!(paginator.pagers[0].permalink, "https://vincent.is/tags/something/");
|
||||
assert_eq!(paginator.pagers[0].path, "tags/something");
|
||||
assert_eq!(paginator.pagers[0].path, "/tags/something/");
|
||||
|
||||
assert_eq!(paginator.pagers[1].index, 2);
|
||||
assert_eq!(paginator.pagers[1].pages.len(), 2);
|
||||
assert_eq!(paginator.pagers[1].permalink, "https://vincent.is/tags/something/page/2/");
|
||||
assert_eq!(paginator.pagers[1].path, "tags/something/page/2/");
|
||||
assert_eq!(paginator.pagers[1].path, "/tags/something/page/2/");
|
||||
}
|
||||
|
||||
// https://github.com/getzola/zola/issues/866
|
||||
|
@ -374,12 +375,12 @@ mod tests {
|
|||
assert_eq!(paginator.pagers[0].index, 1);
|
||||
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].path, "/posts/");
|
||||
|
||||
assert_eq!(paginator.pagers[1].index, 2);
|
||||
assert_eq!(paginator.pagers[1].pages.len(), 2);
|
||||
assert_eq!(paginator.pagers[1].permalink, "https://vincent.is/posts/2/");
|
||||
assert_eq!(paginator.pagers[1].path, "posts/2/");
|
||||
assert_eq!(paginator.pagers[1].path, "/posts/2/");
|
||||
|
||||
let context = paginator.build_paginator_context(&paginator.pagers[0]);
|
||||
assert_eq!(context["base_url"], to_value("https://vincent.is/posts/").unwrap());
|
||||
|
|
|
@ -150,7 +150,7 @@ impl Taxonomy {
|
|||
"current_url",
|
||||
&config.make_permalink(&format!("{}/{}", self.kind.name, item.slug)),
|
||||
);
|
||||
context.insert("current_path", &format!("/{}/{}", self.kind.name, item.slug));
|
||||
context.insert("current_path", &format!("/{}/{}/", self.kind.name, item.slug));
|
||||
|
||||
render_template(&format!("{}/single.html", self.kind.name), tera, context, &config.theme)
|
||||
.map_err(|e| {
|
||||
|
@ -172,7 +172,7 @@ impl Taxonomy {
|
|||
context.insert("lang", &self.kind.lang);
|
||||
context.insert("taxonomy", &self.kind);
|
||||
context.insert("current_url", &config.make_permalink(&self.kind.name));
|
||||
context.insert("current_path", &self.kind.name);
|
||||
context.insert("current_path", &format!("/{}/", self.kind.name));
|
||||
|
||||
render_template(&format!("{}/list.html", self.kind.name), tera, context, &config.theme)
|
||||
.map_err(|e| {
|
||||
|
|
|
@ -19,12 +19,12 @@ fn can_parse_site() {
|
|||
let library = site.library.read().unwrap();
|
||||
|
||||
// Correct number of pages (sections do not count as pages, draft are ignored)
|
||||
assert_eq!(library.pages().len(), 21);
|
||||
assert_eq!(library.pages().len(), 23);
|
||||
let posts_path = path.join("content").join("posts");
|
||||
|
||||
// Make sure the page with a url doesn't have any sections
|
||||
let url_post = library.get_page(&posts_path.join("fixed-url.md")).unwrap();
|
||||
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
|
||||
let asset_folder_post =
|
||||
|
@ -37,7 +37,7 @@ fn can_parse_site() {
|
|||
// And that the sections are correct
|
||||
let index_section = library.get_section(&path.join("content").join("_index.md")).unwrap();
|
||||
assert_eq!(index_section.subsections.len(), 4);
|
||||
assert_eq!(index_section.pages.len(), 1);
|
||||
assert_eq!(index_section.pages.len(), 3);
|
||||
assert!(index_section.ancestors.is_empty());
|
||||
|
||||
let posts_section = library.get_section(&posts_path.join("_index.md")).unwrap();
|
||||
|
@ -446,6 +446,16 @@ fn can_build_site_with_pagination_for_section() {
|
|||
"sitemap.xml",
|
||||
"<loc>https://replace-this-with-your-url.com/posts/page/4/</loc>"
|
||||
));
|
||||
|
||||
// current_path
|
||||
assert!(file_contains!(public, "posts/index.html", ¤t_path("/posts/")));
|
||||
assert!(file_contains!(public, "posts/page/2/index.html", ¤t_path("/posts/page/2/")));
|
||||
assert!(file_contains!(public, "posts/python/index.html", ¤t_path("/posts/python/")));
|
||||
assert!(file_contains!(
|
||||
public,
|
||||
"posts/tutorials/index.html",
|
||||
¤t_path("/posts/tutorials/")
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -492,19 +502,28 @@ fn can_build_site_with_pagination_for_index() {
|
|||
"page/1/index.html",
|
||||
"<a href=\"https://replace-this-with-your-url.com/\">Click here</a>"
|
||||
));
|
||||
assert!(file_contains!(public, "index.html", "Num pages: 1"));
|
||||
assert!(file_contains!(public, "index.html", "Num pages: 2"));
|
||||
assert!(file_contains!(public, "index.html", "Current index: 1"));
|
||||
assert!(file_contains!(public, "index.html", "First: https://replace-this-with-your-url.com/"));
|
||||
assert!(file_contains!(public, "index.html", "Last: https://replace-this-with-your-url.com/"));
|
||||
assert!(file_contains!(
|
||||
public,
|
||||
"index.html",
|
||||
"Last: https://replace-this-with-your-url.com/page/2/"
|
||||
));
|
||||
assert_eq!(file_contains!(public, "index.html", "has_prev"), false);
|
||||
assert_eq!(file_contains!(public, "index.html", "has_next"), false);
|
||||
assert_eq!(file_contains!(public, "index.html", "has_next"), true);
|
||||
|
||||
// sitemap contains the pager pages
|
||||
assert!(file_contains!(
|
||||
public,
|
||||
"sitemap.xml",
|
||||
"<loc>https://replace-this-with-your-url.com/page/1/</loc>"
|
||||
))
|
||||
));
|
||||
|
||||
// current_path
|
||||
assert!(file_contains!(public, "index.html", ¤t_path("/")));
|
||||
assert!(file_contains!(public, "page/2/index.html", ¤t_path("/page/2/")));
|
||||
assert!(file_contains!(public, "paginated/index.html", ¤t_path("/paginated/")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -585,7 +604,12 @@ fn can_build_site_with_pagination_for_taxonomy() {
|
|||
public,
|
||||
"sitemap.xml",
|
||||
"<loc>https://replace-this-with-your-url.com/tags/a/page/6/</loc>"
|
||||
))
|
||||
));
|
||||
|
||||
// current_path
|
||||
assert!(file_contains!(public, "tags/index.html", ¤t_path("/tags/")));
|
||||
assert!(file_contains!(public, "tags/a/index.html", ¤t_path("/tags/a/")));
|
||||
assert!(file_contains!(public, "tags/a/page/2/index.html", ¤t_path("/tags/a/page/2/")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -718,3 +742,8 @@ fn check_site() {
|
|||
site.config.enable_check_mode();
|
||||
site.load().expect("link check test_site");
|
||||
}
|
||||
|
||||
// Follows test_site/themes/sample/templates/current_path.html
|
||||
fn current_path(path: &str) -> String {
|
||||
format!("[current_path]({})", path)
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ you can place `{{ __tera_context }}` in the template to print the whole context.
|
|||
A few variables are available on all templates except feeds and the sitemap:
|
||||
|
||||
- `config`: the [configuration](@/documentation/getting-started/configuration.md) without any modifications
|
||||
- `current_path`: the path (full URL without `base_url`) of the current page, never starting with a `/`
|
||||
- `current_path`: the path (full URL without `base_url`) of the current page, always starting with a `/`
|
||||
- `current_url`: the full URL for the current page
|
||||
- `lang`: the language for the current page
|
||||
|
||||
|
@ -165,7 +165,7 @@ Whenever hashing files, whether using `get_file_hash` or `get_url(..., cachebust
|
|||
|
||||
|
||||
### `get_image_metadata`
|
||||
Gets metadata for an image. This supports common formats like JPEG, PNG, as well as SVG.
|
||||
Gets metadata for an image. This supports common formats like JPEG, PNG, as well as SVG.
|
||||
Currently, the only supported keys are `width` and `height`.
|
||||
|
||||
```jinja2
|
||||
|
|
2
test_site/content/root-page-1.md
Normal file
2
test_site/content/root-page-1.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
+++
|
||||
+++
|
2
test_site/content/root-page-2.md
Normal file
2
test_site/content/root-page-2.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
+++
|
||||
+++
|
|
@ -29,5 +29,8 @@
|
|||
</div>
|
||||
{% endblock content %}
|
||||
</div>
|
||||
|
||||
{% include "current_path.html" %}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
{% for tag in terms %}
|
||||
{{ tag.name }} {{ tag.slug }} {{ tag.pages | length }}
|
||||
{% endfor %}
|
||||
|
||||
{% include "current_path.html" %}
|
|
@ -19,3 +19,5 @@
|
|||
{% if paginator.previous %}has_prev{% endif%}
|
||||
{% if paginator.next %}has_next{% endif%}
|
||||
{% endif %}
|
||||
|
||||
{% include "current_path.html" %}
|
1
test_site/themes/sample/templates/current_path.html
Normal file
1
test_site/themes/sample/templates/current_path.html
Normal file
|
@ -0,0 +1 @@
|
|||
<div>[current_path]({{ current_path | safe }})</div>
|
|
@ -16,6 +16,8 @@
|
|||
{% block content %}Hello{% endblock content %}
|
||||
</div>
|
||||
|
||||
{% include "current_path.html" %}
|
||||
|
||||
{% block script %}
|
||||
{% endblock script %}
|
||||
</body>
|
||||
|
|
Loading…
Reference in a new issue