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:
yanghuidong 2020-07-30 02:44:09 +08:00 committed by GitHub
parent 28523ac9ad
commit b9296f7985
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 97 additions and 45 deletions

View file

@ -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"));
}

View file

@ -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(&section.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();

View file

@ -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());

View file

@ -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| {

View file

@ -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", &current_path("/posts/")));
assert!(file_contains!(public, "posts/page/2/index.html", &current_path("/posts/page/2/")));
assert!(file_contains!(public, "posts/python/index.html", &current_path("/posts/python/")));
assert!(file_contains!(
public,
"posts/tutorials/index.html",
&current_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", &current_path("/")));
assert!(file_contains!(public, "page/2/index.html", &current_path("/page/2/")));
assert!(file_contains!(public, "paginated/index.html", &current_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", &current_path("/tags/")));
assert!(file_contains!(public, "tags/a/index.html", &current_path("/tags/a/")));
assert!(file_contains!(public, "tags/a/page/2/index.html", &current_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)
}

View file

@ -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

View file

@ -0,0 +1,2 @@
+++
+++

View file

@ -0,0 +1,2 @@
+++
+++

View file

@ -29,5 +29,8 @@
</div>
{% endblock content %}
</div>
{% include "current_path.html" %}
</body>
</html>

View file

@ -1,3 +1,5 @@
{% for tag in terms %}
{{ tag.name }} {{ tag.slug }} {{ tag.pages | length }}
{% endfor %}
{% include "current_path.html" %}

View file

@ -19,3 +19,5 @@
{% if paginator.previous %}has_prev{% endif%}
{% if paginator.next %}has_next{% endif%}
{% endif %}
{% include "current_path.html" %}

View file

@ -0,0 +1 @@
<div>[current_path]({{ current_path | safe }})</div>

View file

@ -16,6 +16,8 @@
{% block content %}Hello{% endblock content %}
</div>
{% include "current_path.html" %}
{% block script %}
{% endblock script %}
</body>