@@ -5,8 +5,6 @@ | |||||
### Breaking | ### Breaking | ||||
- Taxonomies have been rewritten from scratch to allow custom ones with RSS and pagination | - Taxonomies have been rewritten from scratch to allow custom ones with RSS and pagination | ||||
- `get_taxonomy_url` has been renamed to `get_taxonomy` and will now return the full taxonomy | |||||
instead of just the URL of a term | |||||
- `order` sorting has been removed in favour of only having `weight` | - `order` sorting has been removed in favour of only having `weight` | ||||
### Others | ### Others | ||||
@@ -23,6 +21,7 @@ instead of just the URL of a term | |||||
- Add a 404 template | - Add a 404 template | ||||
- Enable preserve-order feature of Tera | - Enable preserve-order feature of Tera | ||||
- Add an external link checker | - Add an external link checker | ||||
- Add `get_taxonomy` global function to return the full taxonomy | |||||
## 0.3.4 (2018-06-22) | ## 0.3.4 (2018-06-22) | ||||
@@ -26,7 +26,7 @@ in the `docs/content` folder of the repository. | |||||
| Automatic header anchors | ✔ | ✕ | ✔ | ✔ | | | Automatic header anchors | ✔ | ✕ | ✔ | ✔ | | ||||
| Aliases | ✔ | ✕ | ✔ | ✔ | | | Aliases | ✔ | ✕ | ✔ | ✔ | | ||||
| Pagination | ✔ | ✕ | ✔ | ✔ | | | Pagination | ✔ | ✕ | ✔ | ✔ | | ||||
| Custom taxonomies | ✕ | ✕ | ✔ | ✕ | | |||||
| Custom taxonomies | ✔ | ✕ | ✔ | ✕ | | |||||
| Search | ✔ | ✕ | ✕ | ✔ | | | Search | ✔ | ✕ | ✕ | ✔ | | ||||
| Data files | ✕ | ✔ | ✔ | ✕ | | | Data files | ✕ | ✔ | ✔ | ✕ | | ||||
@@ -302,6 +302,10 @@ impl Site { | |||||
"get_taxonomy", | "get_taxonomy", | ||||
global_fns::make_get_taxonomy(self.taxonomies.clone()), | global_fns::make_get_taxonomy(self.taxonomies.clone()), | ||||
); | ); | ||||
self.tera.register_global_function( | |||||
"get_taxonomy_url", | |||||
global_fns::make_get_taxonomy_url(self.taxonomies.clone()), | |||||
); | |||||
} | } | ||||
/// Add a page to the site | /// Add a page to the site | ||||
@@ -139,6 +139,7 @@ pub fn make_get_taxonomy(all_taxonomies: Vec<Taxonomy>) -> GlobalFn { | |||||
for taxonomy in all_taxonomies { | for taxonomy in all_taxonomies { | ||||
taxonomies.insert(taxonomy.kind.name.clone(), taxonomy); | taxonomies.insert(taxonomy.kind.name.clone(), taxonomy); | ||||
} | } | ||||
Box::new(move |args| -> Result<Value> { | Box::new(move |args| -> Result<Value> { | ||||
let kind = required_arg!( | let kind = required_arg!( | ||||
String, | String, | ||||
@@ -156,6 +157,42 @@ pub fn make_get_taxonomy(all_taxonomies: Vec<Taxonomy>) -> GlobalFn { | |||||
}) | }) | ||||
} | } | ||||
pub fn make_get_taxonomy_url(all_taxonomies: Vec<Taxonomy>) -> GlobalFn { | |||||
let mut taxonomies = HashMap::new(); | |||||
for taxonomy in all_taxonomies { | |||||
taxonomies.insert(taxonomy.kind.name.clone(), taxonomy); | |||||
} | |||||
Box::new(move |args| -> Result<Value> { | |||||
let kind = required_arg!( | |||||
String, | |||||
args.get("kind"), | |||||
"`get_taxonomy_url` requires a `kind` argument with a string value" | |||||
); | |||||
let name = required_arg!( | |||||
String, | |||||
args.get("name"), | |||||
"`get_taxonomy_url` requires a `name` argument with a string value" | |||||
); | |||||
let container = match taxonomies.get(&kind) { | |||||
Some(c) => c, | |||||
None => return Err( | |||||
format!("`get_taxonomy_url` received an unknown taxonomy as kind: {}", kind).into() | |||||
) | |||||
}; | |||||
for item in &container.items { | |||||
if item.name == name { | |||||
return Ok(to_value(item.permalink.clone()).unwrap()); | |||||
} | |||||
} | |||||
Err( | |||||
format!("`get_taxonomy_url`: couldn't find `{}` in `{}` taxonomy", name, kind).into() | |||||
) | |||||
}) | |||||
} | |||||
pub fn make_resize_image(imageproc: Arc<Mutex<imageproc::Processor>>) -> GlobalFn { | pub fn make_resize_image(imageproc: Arc<Mutex<imageproc::Processor>>) -> GlobalFn { | ||||
static DEFAULT_OP: &'static str = "fill"; | static DEFAULT_OP: &'static str = "fill"; | ||||
const DEFAULT_Q: u8 = 75; | const DEFAULT_Q: u8 = 75; | ||||
@@ -206,7 +243,7 @@ pub fn make_resize_image(imageproc: Arc<Mutex<imageproc::Processor>>) -> GlobalF | |||||
#[cfg(test)] | #[cfg(test)] | ||||
mod tests { | mod tests { | ||||
use super::{make_get_url, make_get_taxonomy, make_trans}; | |||||
use super::{make_get_url, make_get_taxonomy, make_get_taxonomy_url, make_trans}; | |||||
use std::collections::HashMap; | use std::collections::HashMap; | ||||
@@ -260,7 +297,7 @@ mod tests { | |||||
fn can_get_taxonomy() { | fn can_get_taxonomy() { | ||||
let taxo_config = TaxonomyConfig { name: "tags".to_string(), ..TaxonomyConfig::default() }; | let taxo_config = TaxonomyConfig { name: "tags".to_string(), ..TaxonomyConfig::default() }; | ||||
let tag = TaxonomyItem::new( | let tag = TaxonomyItem::new( | ||||
"Prog amming", | |||||
"Progamming", | |||||
"tags", | "tags", | ||||
&Config::default(), | &Config::default(), | ||||
vec![], | vec![], | ||||
@@ -281,6 +318,33 @@ mod tests { | |||||
assert!(static_fn(args).is_err()); | assert!(static_fn(args).is_err()); | ||||
} | } | ||||
#[test] | |||||
fn can_get_taxonomy_url() { | |||||
let taxo_config = TaxonomyConfig { name: "tags".to_string(), ..TaxonomyConfig::default() }; | |||||
let tag = TaxonomyItem::new( | |||||
"Programming", | |||||
"tags", | |||||
&Config::default(), | |||||
vec![], | |||||
); | |||||
let tags = Taxonomy { | |||||
kind: taxo_config, | |||||
items: vec![tag], | |||||
}; | |||||
let static_fn = make_get_taxonomy_url(vec![tags.clone()]); | |||||
// can find it correctly | |||||
let mut args = HashMap::new(); | |||||
args.insert("kind".to_string(), to_value("tags").unwrap()); | |||||
args.insert("name".to_string(), to_value("Programming").unwrap()); | |||||
assert_eq!(static_fn(args).unwrap(), "http://a-website.com/tags/prog-amming/"); | |||||
// and errors if it can't find it | |||||
let mut args = HashMap::new(); | |||||
args.insert("kind".to_string(), to_value("tags").unwrap()); | |||||
args.insert("name".to_string(), to_value("random").unwrap()); | |||||
assert!(static_fn(args).is_err()); | |||||
} | |||||
#[test] | #[test] | ||||
fn can_translate_a_string() { | fn can_translate_a_string() { | ||||
let trans_config = r#" | let trans_config = r#" | ||||
@@ -17,9 +17,9 @@ If the file is given any name *other* than `index.md` or `_index.md`, then it wi | |||||
create a page with that name (without the `.md`). So naming a file in the root of your | create a page with that name (without the `.md`). So naming a file in the root of your | ||||
content directory `about.md` would also create a page at `[base_url]/about`. | content directory `about.md` would also create a page at `[base_url]/about`. | ||||
As you can see, creating an `about.md` file is exactly equivalent to creating an | |||||
As you can see, creating an `about.md` file is exactly equivalent to creating an | |||||
`about/index.md` file. The only difference between the two methods is that creating | `about/index.md` file. The only difference between the two methods is that creating | ||||
the `about` folder allows you to use asset colocation, as discussed in the | |||||
the `about` folder allows you to use asset colocation, as discussed in the | |||||
[Overview](./documentation/content/overview.md) section of this documentation. | [Overview](./documentation/content/overview.md) section of this documentation. | ||||
## Front-matter | ## Front-matter | ||||
@@ -42,7 +42,7 @@ description = "" | |||||
# Do not wrap dates in quotes, the line below only indicates that there is no default date. | # Do not wrap dates in quotes, the line below only indicates that there is no default date. | ||||
# If the section variable `sort_by` is set to `date`, then any page that lacks a `date` | # If the section variable `sort_by` is set to `date`, then any page that lacks a `date` | ||||
# will not be rendered. | # will not be rendered. | ||||
date = | |||||
date = | |||||
# The weight as defined in the Section page | # The weight as defined in the Section page | ||||
# If the section variable `sort_by` is set to `weight`, then any page that lacks a `weight` | # If the section variable `sort_by` is set to `weight`, then any page that lacks a `weight` | ||||
@@ -62,24 +62,23 @@ slug = "" | |||||
# It should not start with a `/` and the slash will be removed if it does | # It should not start with a `/` and the slash will be removed if it does | ||||
path = "" | path = "" | ||||
# An array of strings allowing you to group pages with them | |||||
tags = [] | |||||
# An overarching category name for that page, allowing you to group pages with it | |||||
category = "" | |||||
# Use aliases if you are moving content but want to redirect previous URLs to the | |||||
# Use aliases if you are moving content but want to redirect previous URLs to the | |||||
# current one. This takes an array of path, not URLs. | # current one. This takes an array of path, not URLs. | ||||
aliases = [] | aliases = [] | ||||
# Whether the page should be in the search index. This is only used if | # Whether the page should be in the search index. This is only used if | ||||
# `build_search_index` is set to true in the config and the parent section | |||||
# `build_search_index` is set to true in the config and the parent section | |||||
# hasn't set `in_search_index` to false in its front-matter | # hasn't set `in_search_index` to false in its front-matter | ||||
in_search_index = true | in_search_index = true | ||||
# Template to use to render this page | # Template to use to render this page | ||||
template = "page.html" | template = "page.html" | ||||
# The taxonomies for that page. The keys need to be the same as the taxonomies | |||||
# name configured in `config.toml` and the values an array of String like | |||||
# tags = ["rust", "web"] | |||||
[taxonomies] | |||||
# Your own data | # Your own data | ||||
[extra] | [extra] | ||||
+++ | +++ | ||||
@@ -89,7 +88,7 @@ Some content | |||||
## Summary | ## Summary | ||||
You can ask Gutenberg to create a summary if you only want to show the first | |||||
You can ask Gutenberg to create a summary if you only want to show the first | |||||
paragraph of each page in a list for example. | paragraph of each page in a list for example. | ||||
To do so, add <code><!-- more --></code> in your content at the point | To do so, add <code><!-- more --></code> in your content at the point | ||||
@@ -97,6 +96,6 @@ where you want the summary to end and the content up to that point will be also | |||||
available separately in the | available separately in the | ||||
[template](./documentation/templates/pages-sections.md#page-variables). | [template](./documentation/templates/pages-sections.md#page-variables). | ||||
An anchor link to this position named `continue-reading` is created so you can link | |||||
An anchor link to this position named `continue-reading` is created so you can link | |||||
directly to it if needed for example: | directly to it if needed for example: | ||||
`<a href="{{ page.permalink }}#continue-reading">Continue Reading</a>` | `<a href="{{ page.permalink }}#continue-reading">Continue Reading</a>` |
@@ -16,7 +16,16 @@ For example the default would be page/1 | |||||
- `rss`: if set to `true`, a RSS feed will be generated for each individual term. | - `rss`: if set to `true`, a RSS feed will be generated for each individual term. | ||||
Once this is done, you can then set taxonomies in your content and Gutenberg will pick | Once this is done, you can then set taxonomies in your content and Gutenberg will pick | ||||
them up. | |||||
them up: | |||||
```toml | |||||
+++ | |||||
... | |||||
[taxonomies] | |||||
tags = ["rust", "web"] | |||||
categories = ["programming"] | |||||
+++ | |||||
``` | |||||
The taxonomy pages will only be created if at least one non-draft page is found and | The taxonomy pages will only be created if at least one non-draft page is found and | ||||
are available at the following paths: | are available at the following paths: | ||||
@@ -20,21 +20,21 @@ A few variables are available on all templates minus RSS and sitemap: | |||||
- `current_url`: the full URL for that page | - `current_url`: the full URL for that page | ||||
## Standard Templates | ## Standard Templates | ||||
By default, Gutenberg will look for three templates: `index.html`, which is applied | |||||
to the site homepage; `section.html`, which is applied to all sections (any HTML | |||||
page generated by creating a directory within your `content` directory); and | |||||
`page.html`, which is applied to all pages (any HTML page generated by creating a | |||||
By default, Gutenberg will look for three templates: `index.html`, which is applied | |||||
to the site homepage; `section.html`, which is applied to all sections (any HTML | |||||
page generated by creating a directory within your `content` directory); and | |||||
`page.html`, which is applied to all pages (any HTML page generated by creating a | |||||
`.md` file within your `content` directory). | `.md` file within your `content` directory). | ||||
The homepage is always a section (regardless of whether it contains other pages). | The homepage is always a section (regardless of whether it contains other pages). | ||||
Thus, the `index.html` and `section.html` templates both have access to the | |||||
Thus, the `index.html` and `section.html` templates both have access to the | |||||
section variables. The `page.html` template has access to the page variables. | section variables. The `page.html` template has access to the page variables. | ||||
The page and section variables are described in more detail in the next section of this documentation. | The page and section variables are described in more detail in the next section of this documentation. | ||||
## Built-in Templates | ## Built-in Templates | ||||
Gutenberg comes with three built-in templates: `rss.xml`, `sitemap.xml`, and | |||||
Gutenberg comes with three built-in templates: `rss.xml`, `sitemap.xml`, and | |||||
`robots.txt` (each described in their own section of this documentation). | `robots.txt` (each described in their own section of this documentation). | ||||
Additionally, themes can add their own templates, which will be applied if not | |||||
Additionally, themes can add their own templates, which will be applied if not | |||||
overridden. You can override built-in or theme templates by creating a template with | overridden. You can override built-in or theme templates by creating a template with | ||||
same name in the correct path. For example, you can override the RSS template by | same name in the correct path. For example, you can override the RSS template by | ||||
creating a `templates/rss.xml` file. | creating a `templates/rss.xml` file. | ||||
@@ -120,15 +120,22 @@ by passing `cachebust=true` to the `get_url` function. | |||||
### `get_taxonomy_url` | ### `get_taxonomy_url` | ||||
Gets the permalink for the tag or category given. | |||||
Gets the permalink for the taxonomy item found. | |||||
```jinja2 | ```jinja2 | ||||
{% set url = get_taxonomy_url(kind="category", name=page.category) %} | |||||
{% set url = get_taxonomy_url(kind="categories", name=page.taxonomies.category) %} | |||||
``` | ``` | ||||
The `name` will almost come from a variable but in case you want to do it manually, | The `name` will almost come from a variable but in case you want to do it manually, | ||||
the value should be the same as the one in the front-matter, not the slugified version. | the value should be the same as the one in the front-matter, not the slugified version. | ||||
### `get_taxonomy` | |||||
Gets the whole taxonomy of a specific kind. | |||||
```jinja2 | |||||
{% set categories = get_taxonomy_url(kind="categories") %} | |||||
``` | |||||
### `trans` | ### `trans` | ||||
Gets the translation of the given `key`, for the `default_language` or the `language given | Gets the translation of the given `key`, for the `default_language` or the `language given | ||||