Add get_taxonomy_url global_fn
And fix bug with taxonomies urls
This commit is contained in:
parent
8759323a16
commit
322d2f30fb
|
@ -1,5 +1,10 @@
|
|||
# Changelog
|
||||
|
||||
## 0.2.3 (unreleased)
|
||||
|
||||
- Add `get_taxonomy_url` to retrieve the permalink of a tag/category
|
||||
- Fix bug when generating permalinks for taxonomies
|
||||
|
||||
## 0.2.2 (2017-11-01)
|
||||
|
||||
- Fix shortcodes without arguments being ignored
|
||||
|
|
1452
Cargo.lock
generated
1452
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -120,6 +120,8 @@ impl Config {
|
|||
format!("{}{}{}", self.base_url, &path[1..], trailing_bit)
|
||||
} else if self.base_url.ends_with('/') {
|
||||
format!("{}{}{}", self.base_url, path, trailing_bit)
|
||||
} else if path.starts_with('/') {
|
||||
format!("{}{}{}", self.base_url, path, trailing_bit)
|
||||
} else {
|
||||
format!("{}/{}{}", self.base_url, path, trailing_bit)
|
||||
}
|
||||
|
@ -272,6 +274,13 @@ hello = "world"
|
|||
assert_eq!(config.make_permalink("/hello"), "http://vincent.is/hello/");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_make_url_with_localhost() {
|
||||
let mut config = Config::default();
|
||||
config.base_url = "http://127.0.0.1:1111".to_string();
|
||||
assert_eq!(config.make_permalink("/tags/rust"), "http://127.0.0.1:1111/tags/rust/");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_merge_with_theme_data_and_preserve_config_value() {
|
||||
let config_str = r#"
|
||||
|
|
|
@ -251,6 +251,10 @@ impl Site {
|
|||
pub fn register_tera_global_fns(&mut self) {
|
||||
self.tera.register_global_function("get_page", global_fns::make_get_page(&self.pages));
|
||||
self.tera.register_global_function("get_section", global_fns::make_get_section(&self.sections));
|
||||
self.tera.register_global_function(
|
||||
"get_taxonomy_url",
|
||||
global_fns::make_get_taxonomy_url(self.tags.clone(), self.categories.clone())
|
||||
);
|
||||
self.tera.register_global_function(
|
||||
"get_url",
|
||||
global_fns::make_get_url(self.permalinks.clone(), self.config.clone())
|
||||
|
|
|
@ -44,7 +44,7 @@ impl TaxonomyItem {
|
|||
let (mut pages, ignored_pages) = sort_pages(pages, SortBy::Date);
|
||||
let slug = slugify(name);
|
||||
let permalink = {
|
||||
let kind_path = if kind == TaxonomyKind::Tags { "tag" } else { "category" };
|
||||
let kind_path = if kind == TaxonomyKind::Tags { "tags" } else { "categories" };
|
||||
config.make_permalink(&format!("/{}/{}", kind_path, slug))
|
||||
};
|
||||
|
||||
|
|
|
@ -13,3 +13,4 @@ errors = { path = "../errors" }
|
|||
utils = { path = "../utils" }
|
||||
content = { path = "../content" }
|
||||
config = { path = "../config" }
|
||||
taxonomies = { path = "../taxonomies" }
|
||||
|
|
|
@ -6,8 +6,21 @@ use tera::{GlobalFn, Value, from_value, to_value, Result};
|
|||
use content::{Page, Section};
|
||||
use config::Config;
|
||||
use utils::site::resolve_internal_link;
|
||||
use taxonomies::Taxonomy;
|
||||
|
||||
|
||||
macro_rules! required_string_arg {
|
||||
($e: expr, $err: expr) => {
|
||||
match $e {
|
||||
Some(v) => match from_value::<String>(v.clone()) {
|
||||
Ok(u) => u,
|
||||
Err(_) => return Err($err.into())
|
||||
},
|
||||
None => return Err($err.into())
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
pub fn make_get_page(all_pages: &HashMap<PathBuf, Page>) -> GlobalFn {
|
||||
let mut pages = HashMap::new();
|
||||
for page in all_pages.values() {
|
||||
|
@ -15,17 +28,10 @@ pub fn make_get_page(all_pages: &HashMap<PathBuf, Page>) -> GlobalFn {
|
|||
}
|
||||
|
||||
Box::new(move |args| -> Result<Value> {
|
||||
match args.get("path") {
|
||||
Some(val) => match from_value::<String>(val.clone()) {
|
||||
Ok(v) => {
|
||||
match pages.get(&v) {
|
||||
Some(p) => Ok(to_value(p).unwrap()),
|
||||
None => Err(format!("Page `{}` not found.", v).into())
|
||||
}
|
||||
},
|
||||
Err(_) => Err(format!("`get_page` received path={:?} but it requires a string", val).into()),
|
||||
},
|
||||
None => Err("`get_page` requires a `path` argument.".into()),
|
||||
let path = required_string_arg!(args.get("path"), "`get_page` requires a `path` argument with a string value");
|
||||
match pages.get(&path) {
|
||||
Some(p) => Ok(to_value(p).unwrap()),
|
||||
None => Err(format!("Page `{}` not found.", path).into())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -37,17 +43,10 @@ pub fn make_get_section(all_sections: &HashMap<PathBuf, Section>) -> GlobalFn {
|
|||
}
|
||||
|
||||
Box::new(move |args| -> Result<Value> {
|
||||
match args.get("path") {
|
||||
Some(val) => match from_value::<String>(val.clone()) {
|
||||
Ok(v) => {
|
||||
match sections.get(&v) {
|
||||
Some(p) => Ok(to_value(p).unwrap()),
|
||||
None => Err(format!("Section `{}` not found.", v).into())
|
||||
}
|
||||
},
|
||||
Err(_) => Err(format!("`get_section` received path={:?} but it requires a string", val).into()),
|
||||
},
|
||||
None => Err("`get_section` requires a `path` argument.".into()),
|
||||
let path = required_string_arg!(args.get("path"), "`get_section` requires a `path` argument with a string value");
|
||||
match sections.get(&path) {
|
||||
Some(p) => Ok(to_value(p).unwrap()),
|
||||
None => Err(format!("Section `{}` not found.", path).into())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -59,51 +58,67 @@ pub fn make_get_url(permalinks: HashMap<String, String>, config: Config) -> Glob
|
|||
.map_or(false, |c| {
|
||||
from_value::<bool>(c.clone()).unwrap_or(false)
|
||||
});
|
||||
|
||||
|
||||
let trailing_slash = args
|
||||
.get("trailing_slash")
|
||||
.map_or(true, |c| {
|
||||
from_value::<bool>(c.clone()).unwrap_or(true)
|
||||
});
|
||||
|
||||
match args.get("path") {
|
||||
Some(val) => match from_value::<String>(val.clone()) {
|
||||
Ok(v) => {
|
||||
// Internal link
|
||||
if v.starts_with("./") {
|
||||
match resolve_internal_link(&v, &permalinks) {
|
||||
Ok(url) => Ok(to_value(url).unwrap()),
|
||||
Err(_) => Err(format!("Could not resolve URL for link `{}` not found.", v).into())
|
||||
}
|
||||
} else {
|
||||
// anything else
|
||||
let mut permalink = config.make_permalink(&v);
|
||||
if !trailing_slash && permalink.ends_with("/") {
|
||||
permalink.pop(); // Removes the slash
|
||||
}
|
||||
|
||||
if cachebust {
|
||||
permalink = format!("{}?t={}", permalink, config.build_timestamp.unwrap());
|
||||
}
|
||||
Ok(to_value(permalink).unwrap())
|
||||
}
|
||||
},
|
||||
Err(_) => Err(format!("`get_url` received path={:?} but it requires a string", val).into()),
|
||||
},
|
||||
None => Err("`get_url` requires a `path` argument.".into()),
|
||||
let path = required_string_arg!(args.get("path"), "`get_url` requires a `path` argument with a string value");
|
||||
if path.starts_with("./") {
|
||||
match resolve_internal_link(&path, &permalinks) {
|
||||
Ok(url) => Ok(to_value(url).unwrap()),
|
||||
Err(_) => Err(format!("Could not resolve URL for link `{}` not found.", path).into())
|
||||
}
|
||||
} else {
|
||||
// anything else
|
||||
let mut permalink = config.make_permalink(&path);
|
||||
if !trailing_slash && permalink.ends_with("/") {
|
||||
permalink.pop(); // Removes the slash
|
||||
}
|
||||
|
||||
if cachebust {
|
||||
permalink = format!("{}?t={}", permalink, config.build_timestamp.unwrap());
|
||||
}
|
||||
Ok(to_value(permalink).unwrap())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn make_get_taxonomy_url(tags: Option<Taxonomy>, categories: Option<Taxonomy>) -> GlobalFn {
|
||||
Box::new(move |args| -> Result<Value> {
|
||||
let kind = required_string_arg!(args.get("kind"), "`get_taxonomy_url` requires a `kind` argument with a string value");
|
||||
let name = required_string_arg!(args.get("name"), "`get_taxonomy_url` requires a `name` argument with a string value");
|
||||
let container = match kind.as_ref() {
|
||||
"tag" => &tags,
|
||||
"category" => &categories,
|
||||
_ => return Err("`get_taxonomy_url` can only get `tag` or `category` for the `kind` argument".into()),
|
||||
};
|
||||
|
||||
if let Some(ref c) = *container {
|
||||
for item in &c.items {
|
||||
if item.name == name {
|
||||
return Ok(to_value(item.permalink.clone()).unwrap());
|
||||
}
|
||||
}
|
||||
bail!("`get_taxonomy_url`: couldn't find `{}` in `{}` taxonomy", name, kind);
|
||||
} else {
|
||||
bail!("`get_taxonomy_url` tried to get a taxonomy of kind `{}` but there isn't any", kind);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::make_get_url;
|
||||
use super::{make_get_url, make_get_taxonomy_url};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use tera::to_value;
|
||||
|
||||
use config::Config;
|
||||
use taxonomies::{Taxonomy, TaxonomyKind, TaxonomyItem};
|
||||
|
||||
|
||||
#[test]
|
||||
|
@ -115,7 +130,7 @@ mod tests {
|
|||
args.insert("cachebust".to_string(), to_value(true).unwrap());
|
||||
assert_eq!(static_fn(args).unwrap(), "http://a-website.com/app.css/?t=1");
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn can_remove_trailing_slashes() {
|
||||
let config = Config::default();
|
||||
|
@ -125,7 +140,7 @@ mod tests {
|
|||
args.insert("trailing_slash".to_string(), to_value(false).unwrap());
|
||||
assert_eq!(static_fn(args).unwrap(), "http://a-website.com/app.css");
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn can_remove_slashes_and_cachebust() {
|
||||
let config = Config::default();
|
||||
|
@ -145,4 +160,30 @@ mod tests {
|
|||
args.insert("path".to_string(), to_value("app.css").unwrap());
|
||||
assert_eq!(static_fn(args).unwrap(), "http://a-website.com/app.css/");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_get_tag_url() {
|
||||
let tag = TaxonomyItem::new(
|
||||
"Prog amming",
|
||||
TaxonomyKind::Tags,
|
||||
&Config::default(),
|
||||
vec![],
|
||||
);
|
||||
let tags = Taxonomy {
|
||||
kind: TaxonomyKind::Tags,
|
||||
items: vec![tag],
|
||||
};
|
||||
|
||||
let static_fn = make_get_taxonomy_url(Some(tags), None);
|
||||
// can find it correctly
|
||||
let mut args = HashMap::new();
|
||||
args.insert("kind".to_string(), to_value("tag").unwrap());
|
||||
args.insert("name".to_string(), to_value("Prog amming").unwrap());
|
||||
assert_eq!(static_fn(args).unwrap(), "http://a-website.com/tag/prog-amming/");
|
||||
// and errors if it can't find it
|
||||
let mut args = HashMap::new();
|
||||
args.insert("kind".to_string(), to_value("tag").unwrap());
|
||||
args.insert("name".to_string(), to_value("random").unwrap());
|
||||
assert!(static_fn(args).is_err());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,12 @@ extern crate tera;
|
|||
extern crate base64;
|
||||
extern crate pulldown_cmark;
|
||||
|
||||
#[macro_use]
|
||||
extern crate errors;
|
||||
extern crate utils;
|
||||
extern crate content;
|
||||
extern crate config;
|
||||
extern crate taxonomies;
|
||||
|
||||
pub mod filters;
|
||||
pub mod global_fns;
|
||||
|
|
|
@ -79,3 +79,14 @@ when dealing with certain hosting providers. An example is:
|
|||
|
||||
In the case of non-internal links, you can also add a cachebust of the format `?t=1290192` at the end of a URL
|
||||
by passing `cachebust=true` to the `get_url` function.
|
||||
|
||||
|
||||
### ` get_taxonomy_url`
|
||||
Gets the permalink for the tag or category given.
|
||||
|
||||
```jinja2
|
||||
{% set url = get_taxonomy_url(kind="category", name=page.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.
|
||||
|
|
Loading…
Reference in a new issue