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
|
# 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)
|
## 0.2.2 (2017-11-01)
|
||||||
|
|
||||||
- Fix shortcodes without arguments being ignored
|
- 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)
|
format!("{}{}{}", self.base_url, &path[1..], trailing_bit)
|
||||||
} else if self.base_url.ends_with('/') {
|
} else if self.base_url.ends_with('/') {
|
||||||
format!("{}{}{}", self.base_url, path, trailing_bit)
|
format!("{}{}{}", self.base_url, path, trailing_bit)
|
||||||
|
} else if path.starts_with('/') {
|
||||||
|
format!("{}{}{}", self.base_url, path, trailing_bit)
|
||||||
} else {
|
} else {
|
||||||
format!("{}/{}{}", self.base_url, path, trailing_bit)
|
format!("{}/{}{}", self.base_url, path, trailing_bit)
|
||||||
}
|
}
|
||||||
|
@ -272,6 +274,13 @@ hello = "world"
|
||||||
assert_eq!(config.make_permalink("/hello"), "http://vincent.is/hello/");
|
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]
|
#[test]
|
||||||
fn can_merge_with_theme_data_and_preserve_config_value() {
|
fn can_merge_with_theme_data_and_preserve_config_value() {
|
||||||
let config_str = r#"
|
let config_str = r#"
|
||||||
|
|
|
@ -251,6 +251,10 @@ impl Site {
|
||||||
pub fn register_tera_global_fns(&mut self) {
|
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_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_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(
|
self.tera.register_global_function(
|
||||||
"get_url",
|
"get_url",
|
||||||
global_fns::make_get_url(self.permalinks.clone(), self.config.clone())
|
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 (mut pages, ignored_pages) = sort_pages(pages, SortBy::Date);
|
||||||
let slug = slugify(name);
|
let slug = slugify(name);
|
||||||
let permalink = {
|
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))
|
config.make_permalink(&format!("/{}/{}", kind_path, slug))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,3 +13,4 @@ errors = { path = "../errors" }
|
||||||
utils = { path = "../utils" }
|
utils = { path = "../utils" }
|
||||||
content = { path = "../content" }
|
content = { path = "../content" }
|
||||||
config = { path = "../config" }
|
config = { path = "../config" }
|
||||||
|
taxonomies = { path = "../taxonomies" }
|
||||||
|
|
|
@ -6,8 +6,21 @@ use tera::{GlobalFn, Value, from_value, to_value, Result};
|
||||||
use content::{Page, Section};
|
use content::{Page, Section};
|
||||||
use config::Config;
|
use config::Config;
|
||||||
use utils::site::resolve_internal_link;
|
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 {
|
pub fn make_get_page(all_pages: &HashMap<PathBuf, Page>) -> GlobalFn {
|
||||||
let mut pages = HashMap::new();
|
let mut pages = HashMap::new();
|
||||||
for page in all_pages.values() {
|
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> {
|
Box::new(move |args| -> Result<Value> {
|
||||||
match args.get("path") {
|
let path = required_string_arg!(args.get("path"), "`get_page` requires a `path` argument with a string value");
|
||||||
Some(val) => match from_value::<String>(val.clone()) {
|
match pages.get(&path) {
|
||||||
Ok(v) => {
|
Some(p) => Ok(to_value(p).unwrap()),
|
||||||
match pages.get(&v) {
|
None => Err(format!("Page `{}` not found.", path).into())
|
||||||
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()),
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -37,17 +43,10 @@ pub fn make_get_section(all_sections: &HashMap<PathBuf, Section>) -> GlobalFn {
|
||||||
}
|
}
|
||||||
|
|
||||||
Box::new(move |args| -> Result<Value> {
|
Box::new(move |args| -> Result<Value> {
|
||||||
match args.get("path") {
|
let path = required_string_arg!(args.get("path"), "`get_section` requires a `path` argument with a string value");
|
||||||
Some(val) => match from_value::<String>(val.clone()) {
|
match sections.get(&path) {
|
||||||
Ok(v) => {
|
Some(p) => Ok(to_value(p).unwrap()),
|
||||||
match sections.get(&v) {
|
None => Err(format!("Section `{}` not found.", path).into())
|
||||||
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()),
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -66,44 +65,60 @@ pub fn make_get_url(permalinks: HashMap<String, String>, config: Config) -> Glob
|
||||||
from_value::<bool>(c.clone()).unwrap_or(true)
|
from_value::<bool>(c.clone()).unwrap_or(true)
|
||||||
});
|
});
|
||||||
|
|
||||||
match args.get("path") {
|
let path = required_string_arg!(args.get("path"), "`get_url` requires a `path` argument with a string value");
|
||||||
Some(val) => match from_value::<String>(val.clone()) {
|
if path.starts_with("./") {
|
||||||
Ok(v) => {
|
match resolve_internal_link(&path, &permalinks) {
|
||||||
// Internal link
|
Ok(url) => Ok(to_value(url).unwrap()),
|
||||||
if v.starts_with("./") {
|
Err(_) => Err(format!("Could not resolve URL for link `{}` not found.", path).into())
|
||||||
match resolve_internal_link(&v, &permalinks) {
|
}
|
||||||
Ok(url) => Ok(to_value(url).unwrap()),
|
} else {
|
||||||
Err(_) => Err(format!("Could not resolve URL for link `{}` not found.", v).into())
|
// anything else
|
||||||
}
|
let mut permalink = config.make_permalink(&path);
|
||||||
} else {
|
if !trailing_slash && permalink.ends_with("/") {
|
||||||
// anything else
|
permalink.pop(); // Removes the slash
|
||||||
let mut permalink = config.make_permalink(&v);
|
}
|
||||||
if !trailing_slash && permalink.ends_with("/") {
|
|
||||||
permalink.pop(); // Removes the slash
|
|
||||||
}
|
|
||||||
|
|
||||||
if cachebust {
|
if cachebust {
|
||||||
permalink = format!("{}?t={}", permalink, config.build_timestamp.unwrap());
|
permalink = format!("{}?t={}", permalink, config.build_timestamp.unwrap());
|
||||||
}
|
}
|
||||||
Ok(to_value(permalink).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()),
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::make_get_url;
|
use super::{make_get_url, make_get_taxonomy_url};
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use tera::to_value;
|
use tera::to_value;
|
||||||
|
|
||||||
use config::Config;
|
use config::Config;
|
||||||
|
use taxonomies::{Taxonomy, TaxonomyKind, TaxonomyItem};
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -145,4 +160,30 @@ mod tests {
|
||||||
args.insert("path".to_string(), to_value("app.css").unwrap());
|
args.insert("path".to_string(), to_value("app.css").unwrap());
|
||||||
assert_eq!(static_fn(args).unwrap(), "http://a-website.com/app.css/");
|
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 base64;
|
||||||
extern crate pulldown_cmark;
|
extern crate pulldown_cmark;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
extern crate errors;
|
extern crate errors;
|
||||||
extern crate utils;
|
extern crate utils;
|
||||||
extern crate content;
|
extern crate content;
|
||||||
extern crate config;
|
extern crate config;
|
||||||
|
extern crate taxonomies;
|
||||||
|
|
||||||
pub mod filters;
|
pub mod filters;
|
||||||
pub mod global_fns;
|
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
|
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.
|
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