Add current_url and current_path

To every templates, useful when doing
navigation to know which link is currently
active
This commit is contained in:
Vincent Prouillet 2017-03-30 17:17:12 +09:00
parent afc4a81ebf
commit 7aeebcc981
10 changed files with 37 additions and 25 deletions

View file

@ -2,6 +2,8 @@
## 0.0.4 (unreleased) ## 0.0.4 (unreleased)
- Fix RSS feed link and description - Fix RSS feed link and description
- Renamed `Page::url` and `Section::url` to `Page::path` and `Section::path`
- Pass `current_url` and `current_path` to every template
## 0.0.3 (2017-04-05) ## 0.0.3 (2017-04-05)
- Add some colours in console - Add some colours in console

View file

@ -60,7 +60,8 @@ Each kind of page get their own variables:
- categories.html: gets `categories` - categories.html: gets `categories`
- category.html: gets `category` and `pages` - category.html: gets `category` and `pages`
Additionally, all pages get a `config` variable representing the data in `config.toml`. Additionally, all pages get a `config` variable representing the data in `config.toml`, `current_url` that represent
the absolute URL of the current page and `current_path` that represents the path of the URL of the current page, starting with `/`.
If you want to know all the data present in a template content, simply put `{{ __tera_context }}` If you want to know all the data present in a template content, simply put `{{ __tera_context }}`
in the templates and it will print it. in the templates and it will print it.

View file

@ -67,8 +67,8 @@ pub struct Page {
/// The slug of that page. /// The slug of that page.
/// First tries to find the slug in the meta and defaults to filename otherwise /// First tries to find the slug in the meta and defaults to filename otherwise
pub slug: String, pub slug: String,
/// The relative URL of the page /// The URL path of the page
pub url: String, pub path: String,
/// The full URL for that page /// The full URL for that page
pub permalink: String, pub permalink: String,
/// The summary for the article, defaults to empty string /// The summary for the article, defaults to empty string
@ -99,7 +99,7 @@ impl Page {
assets: vec![], assets: vec![],
content: "".to_string(), content: "".to_string(),
slug: "".to_string(), slug: "".to_string(),
url: "".to_string(), path: "".to_string(),
permalink: "".to_string(), permalink: "".to_string(),
summary: "".to_string(), summary: "".to_string(),
meta: meta, meta: meta,
@ -151,7 +151,7 @@ impl Page {
// 4. Find sections // 4. Find sections
// Pages with custom urls exists outside of sections // Pages with custom urls exists outside of sections
if let Some(ref u) = page.meta.url { if let Some(ref u) = page.meta.url {
page.url = u.trim().to_string(); page.path = u.trim().to_string();
} else { } else {
if !page.components.is_empty() { if !page.components.is_empty() {
// If we have a folder with an asset, don't consider it as a component // If we have a folder with an asset, don't consider it as a component
@ -162,13 +162,13 @@ impl Page {
} }
// Don't add a trailing slash to sections // Don't add a trailing slash to sections
page.url = format!("{}/{}", page.components.join("/"), page.slug); page.path = format!("{}/{}", page.components.join("/"), page.slug);
} else { } else {
page.url = page.slug.clone(); page.path = page.slug.clone();
} }
} }
page.permalink = config.make_permalink(&page.url); page.permalink = config.make_permalink(&page.path);
Ok(page) Ok(page)
} }
@ -209,11 +209,12 @@ impl Page {
Some(ref l) => l.to_string(), Some(ref l) => l.to_string(),
None => "page.html".to_string() None => "page.html".to_string()
}; };
// TODO: create a helper to create context to ensure all contexts
// have the same names
let mut context = Context::new(); let mut context = Context::new();
context.add("config", config); context.add("config", config);
context.add("page", self); context.add("page", self);
context.add("current_url", &self.permalink);
context.add("current_path", &self.path);
tera.render(&tpl_name, &context) tera.render(&tpl_name, &context)
.chain_err(|| format!("Failed to render page '{}'", self.file_path.display())) .chain_err(|| format!("Failed to render page '{}'", self.file_path.display()))
@ -228,7 +229,7 @@ impl ser::Serialize for Page {
state.serialize_field("description", &self.meta.description)?; state.serialize_field("description", &self.meta.description)?;
state.serialize_field("date", &self.meta.date)?; state.serialize_field("date", &self.meta.date)?;
state.serialize_field("slug", &self.slug)?; state.serialize_field("slug", &self.slug)?;
state.serialize_field("url", &format!("/{}", self.url))?; state.serialize_field("path", &format!("/{}", self.path))?;
state.serialize_field("permalink", &self.permalink)?; state.serialize_field("permalink", &self.permalink)?;
state.serialize_field("tags", &self.meta.tags)?; state.serialize_field("tags", &self.meta.tags)?;
state.serialize_field("draft", &self.meta.draft)?; state.serialize_field("draft", &self.meta.draft)?;

View file

@ -21,8 +21,8 @@ pub struct Section {
pub parent_path: PathBuf, pub parent_path: PathBuf,
/// The folder names from `content` to this section file /// The folder names from `content` to this section file
pub components: Vec<String>, pub components: Vec<String>,
/// The relative URL of the page /// The URL path of the page
pub url: String, pub path: String,
/// The full URL for that page /// The full URL for that page
pub permalink: String, pub permalink: String,
/// The front matter meta-data /// The front matter meta-data
@ -40,7 +40,7 @@ impl Section {
relative_path: "".to_string(), relative_path: "".to_string(),
parent_path: file_path.parent().unwrap().to_path_buf(), parent_path: file_path.parent().unwrap().to_path_buf(),
components: vec![], components: vec![],
url: "".to_string(), path: "".to_string(),
permalink: "".to_string(), permalink: "".to_string(),
meta: meta, meta: meta,
pages: vec![], pages: vec![],
@ -52,8 +52,8 @@ impl Section {
let (meta, _) = split_content(file_path, content)?; let (meta, _) = split_content(file_path, content)?;
let mut section = Section::new(file_path, meta); let mut section = Section::new(file_path, meta);
section.components = find_content_components(&section.file_path); section.components = find_content_components(&section.file_path);
section.url = section.components.join("/"); section.path = section.components.join("/");
section.permalink = config.make_permalink(&section.url); section.permalink = config.make_permalink(&section.path);
section.relative_path = format!("{}/_index.md", section.components.join("/")); section.relative_path = format!("{}/_index.md", section.components.join("/"));
@ -80,6 +80,8 @@ impl Section {
let mut context = Context::new(); let mut context = Context::new();
context.add("config", config); context.add("config", config);
context.add("section", self); context.add("section", self);
context.add("current_url", &self.permalink);
context.add("current_path", &self.path);
tera.render(&tpl_name, &context) tera.render(&tpl_name, &context)
.chain_err(|| format!("Failed to render section '{}'", self.file_path.display())) .chain_err(|| format!("Failed to render section '{}'", self.file_path.display()))
@ -91,7 +93,7 @@ impl ser::Serialize for Section {
let mut state = serializer.serialize_struct("section", 6)?; let mut state = serializer.serialize_struct("section", 6)?;
state.serialize_field("title", &self.meta.title)?; state.serialize_field("title", &self.meta.title)?;
state.serialize_field("description", &self.meta.description)?; state.serialize_field("description", &self.meta.description)?;
state.serialize_field("url", &format!("/{}", self.url))?; state.serialize_field("path", &format!("/{}", self.path))?;
state.serialize_field("permalink", &self.permalink)?; state.serialize_field("permalink", &self.permalink)?;
state.serialize_field("pages", &self.pages)?; state.serialize_field("pages", &self.pages)?;
state.serialize_field("subsections", &self.subsections)?; state.serialize_field("subsections", &self.subsections)?;

View file

@ -303,7 +303,7 @@ impl Site {
// Copy the nesting of the content directory if we have sections for that page // Copy the nesting of the content directory if we have sections for that page
let mut current_path = public.to_path_buf(); let mut current_path = public.to_path_buf();
for component in page.url.split('/') { for component in page.path.split('/') {
current_path.push(component); current_path.push(component);
if !current_path.exists() { if !current_path.exists() {
@ -342,6 +342,8 @@ impl Site {
context.add("pages", &populate_previous_and_next_pages(&pages, false)); context.add("pages", &populate_previous_and_next_pages(&pages, false));
context.add("sections", &self.sections.values().collect::<Vec<&Section>>()); context.add("sections", &self.sections.values().collect::<Vec<&Section>>());
context.add("config", &self.config); context.add("config", &self.config);
context.add("current_url", &self.config.base_url);
context.add("current_path", &"");
let index = self.tera.render("index.html", &context)?; let index = self.tera.render("index.html", &context)?;
create_file(public.join("index.html"), &self.inject_livereload(index))?; create_file(public.join("index.html"), &self.inject_livereload(index))?;
@ -405,6 +407,8 @@ impl Site {
let mut context = Context::new(); let mut context = Context::new();
context.add(name, &sorted_items); context.add(name, &sorted_items);
context.add("config", &self.config); context.add("config", &self.config);
context.add("current_url", &self.config.make_permalink(name));
context.add("current_path", &format!("/{}", name));
// And render it immediately // And render it immediately
let list_output = self.tera.render(list_tpl_name, &context)?; let list_output = self.tera.render(list_tpl_name, &context)?;
create_file(output_path.join("index.html"), &self.inject_livereload(list_output))?; create_file(output_path.join("index.html"), &self.inject_livereload(list_output))?;
@ -424,6 +428,8 @@ impl Site {
context.add(&format!("{}_slug", var_name), &slug); context.add(&format!("{}_slug", var_name), &slug);
context.add("pages", &pages); context.add("pages", &pages);
context.add("config", &self.config); context.add("config", &self.config);
context.add("current_url", &self.config.make_permalink(&format!("{}/{}", name, slug)));
context.add("current_path", &format!("/{}/{}", name, slug));
let single_output = self.tera.render(single_tpl_name, &context)?; let single_output = self.tera.render(single_tpl_name, &context)?;
create_directory(&output_path.join(&slug))?; create_directory(&output_path.join(&slug))?;

View file

@ -3,6 +3,6 @@ Category: {{ category }}
{% for page in pages %} {% for page in pages %}
<article> <article>
<h3 class="post__title"><a href="{{ page.url }}">{{ page.title }}</a></h3> <h3 class="post__title"><a href="{{ page.permalink }}">{{ page.title }}</a></h3>
</article> </article>
{% endfor %} {% endfor %}

View file

@ -17,7 +17,7 @@
<div class="list-posts"> <div class="list-posts">
{% for page in pages %} {% for page in pages %}
<article> <article>
<h3 class="post__title"><a href="{{ page.url }}">{{ page.title }}</a></h3> <h3 class="post__title"><a href="{{ page.permalink }}">{{ page.title }}</a></h3>
</article> </article>
{% endfor %} {% endfor %}
</div> </div>

View file

@ -2,6 +2,6 @@ Tag: {{ tag }}
{% for page in pages %} {% for page in pages %}
<article> <article>
<h3 class="post__title"><a href="{{ page.url }}">{{ page.title }}</a></h3> <h3 class="post__title"><a href="{{ page.permalink }}">{{ page.title }}</a></h3>
</article> </article>
{% endfor %} {% endfor %}

View file

@ -79,7 +79,7 @@ Hello world"#;
assert!(res.is_ok()); assert!(res.is_ok());
let mut page = res.unwrap(); let mut page = res.unwrap();
page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap(); page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap();
assert_eq!(page.url, "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");
} }
@ -98,7 +98,7 @@ Hello world"#;
assert!(res.is_ok()); assert!(res.is_ok());
let mut page = res.unwrap(); let mut page = res.unwrap();
page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap(); page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap();
assert_eq!(page.url, "posts/intro/hello-world"); assert_eq!(page.path, "posts/intro/hello-world");
assert_eq!(page.permalink, format!("{}{}", conf.base_url, "/posts/intro/hello-world")); assert_eq!(page.permalink, format!("{}{}", conf.base_url, "/posts/intro/hello-world"));
} }
@ -115,7 +115,7 @@ Hello world"#;
assert!(res.is_ok()); assert!(res.is_ok());
let mut page = res.unwrap(); let mut page = res.unwrap();
page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap(); page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap();
assert_eq!(page.url, "hello-world"); assert_eq!(page.path, "hello-world");
assert_eq!(page.permalink, format!("{}{}", Config::default().base_url, "hello-world")); assert_eq!(page.permalink, format!("{}{}", Config::default().base_url, "hello-world"));
} }

View file

@ -28,7 +28,7 @@ fn test_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.url, "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")];