diff --git a/CHANGELOG.md b/CHANGELOG.md index ef5123ab..822d6cef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,6 @@ ### Breaking - 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` ### Others @@ -23,6 +21,7 @@ instead of just the URL of a term - Add a 404 template - Enable preserve-order feature of Tera - Add an external link checker +- Add `get_taxonomy` global function to return the full taxonomy ## 0.3.4 (2018-06-22) diff --git a/README.md b/README.md index 00e22483..9a4c6cd1 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ in the `docs/content` folder of the repository. | Automatic header anchors | ✔ | ✕ | ✔ | ✔ | | Aliases | ✔ | ✕ | ✔ | ✔ | | Pagination | ✔ | ✕ | ✔ | ✔ | -| Custom taxonomies | ✕ | ✕ | ✔ | ✕ | +| Custom taxonomies | ✔ | ✕ | ✔ | ✕ | | Search | ✔ | ✕ | ✕ | ✔ | | Data files | ✕ | ✔ | ✔ | ✕ | diff --git a/components/site/src/lib.rs b/components/site/src/lib.rs index 81437bbb..dd351ef7 100644 --- a/components/site/src/lib.rs +++ b/components/site/src/lib.rs @@ -302,6 +302,10 @@ impl Site { "get_taxonomy", 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 diff --git a/components/templates/src/global_fns.rs b/components/templates/src/global_fns.rs index 23877af5..9ca217d8 100644 --- a/components/templates/src/global_fns.rs +++ b/components/templates/src/global_fns.rs @@ -139,6 +139,7 @@ pub fn make_get_taxonomy(all_taxonomies: Vec) -> GlobalFn { for taxonomy in all_taxonomies { taxonomies.insert(taxonomy.kind.name.clone(), taxonomy); } + Box::new(move |args| -> Result { let kind = required_arg!( String, @@ -156,6 +157,42 @@ pub fn make_get_taxonomy(all_taxonomies: Vec) -> GlobalFn { }) } +pub fn make_get_taxonomy_url(all_taxonomies: Vec) -> GlobalFn { + let mut taxonomies = HashMap::new(); + for taxonomy in all_taxonomies { + taxonomies.insert(taxonomy.kind.name.clone(), taxonomy); + } + + Box::new(move |args| -> Result { + 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>) -> GlobalFn { static DEFAULT_OP: &'static str = "fill"; const DEFAULT_Q: u8 = 75; @@ -206,7 +243,7 @@ pub fn make_resize_image(imageproc: Arc>) -> GlobalF #[cfg(test)] 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; @@ -260,7 +297,7 @@ mod tests { fn can_get_taxonomy() { let taxo_config = TaxonomyConfig { name: "tags".to_string(), ..TaxonomyConfig::default() }; let tag = TaxonomyItem::new( - "Prog amming", + "Progamming", "tags", &Config::default(), vec![], @@ -281,6 +318,33 @@ mod tests { 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] fn can_translate_a_string() { let trans_config = r#" diff --git a/docs/content/documentation/content/page.md b/docs/content/documentation/content/page.md index 08105242..7d61c27c 100644 --- a/docs/content/documentation/content/page.md +++ b/docs/content/documentation/content/page.md @@ -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 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 -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. ## Front-matter @@ -42,7 +42,7 @@ description = "" # 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` # will not be rendered. -date = +date = # 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` @@ -62,24 +62,23 @@ slug = "" # It should not start with a `/` and the slash will be removed if it does 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. aliases = [] # 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 in_search_index = true # Template to use to render this page 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 [extra] +++ @@ -89,7 +88,7 @@ Some content ## 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. To do so, add <!-- more --> 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 [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: `Continue Reading` diff --git a/docs/content/documentation/content/taxonomies.md b/docs/content/documentation/content/taxonomies.md index d70878c5..7ddad6b3 100644 --- a/docs/content/documentation/content/taxonomies.md +++ b/docs/content/documentation/content/taxonomies.md @@ -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. 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 are available at the following paths: diff --git a/docs/content/documentation/templates/overview.md b/docs/content/documentation/templates/overview.md index c2179df7..f12fc4c0 100644 --- a/docs/content/documentation/templates/overview.md +++ b/docs/content/documentation/templates/overview.md @@ -20,21 +20,21 @@ A few variables are available on all templates minus RSS and sitemap: - `current_url`: the full URL for that page ## 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). 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. The page and section variables are described in more detail in the next section of this documentation. ## 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). -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 same name in the correct path. For example, you can override the RSS template by creating a `templates/rss.xml` file. @@ -120,15 +120,22 @@ by passing `cachebust=true` to the `get_url` function. ### `get_taxonomy_url` -Gets the permalink for the tag or category given. +Gets the permalink for the taxonomy item found. ```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 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` Gets the translation of the given `key`, for the `default_language` or the `language given