Some more cleanup

This commit is contained in:
Vincent Prouillet 2021-05-11 18:28:01 +02:00
parent a97779567e
commit b0937fa5b7
4 changed files with 129 additions and 127 deletions

1
Cargo.lock generated
View file

@ -2595,6 +2595,7 @@ dependencies = [
"serde_json", "serde_json",
"sha2", "sha2",
"svg_metadata", "svg_metadata",
"tempfile",
"tera", "tera",
"toml", "toml",
"url", "url",

View file

@ -31,3 +31,4 @@ features = ["blocking", "rustls-tls"]
[dev-dependencies] [dev-dependencies]
mockito = "0.30" mockito = "0.30"
tempfile = "3"

View file

@ -0,0 +1,83 @@
use tera::{from_value, to_value, Error, Function as TeraFn, Result, Value};
use config::Config;
use std::collections::HashMap;
#[derive(Debug)]
pub struct Trans {
config: Config,
}
impl Trans {
pub fn new(config: Config) -> Self {
Self { config }
}
}
impl TeraFn for Trans {
fn call(&self, args: &HashMap<String, Value>) -> Result<Value> {
let key = required_arg!(String, args.get("key"), "`trans` requires a `key` argument.");
let lang = optional_arg!(String, args.get("lang"), "`trans`: `lang` must be a string.")
.unwrap_or_else(|| self.config.default_language.clone());
let term = self
.config
.get_translation(&lang, &key)
.map_err(|e| Error::chain("Failed to retrieve term translation", e))?;
Ok(to_value(term).unwrap())
}
}
#[cfg(test)]
mod tests {
use super::*;
const TRANS_CONFIG: &str = r#"
base_url = "https://remplace-par-ton-url.fr"
default_language = "fr"
[translations]
title = "Un titre"
[languages]
[languages.en]
[languages.en.translations]
title = "A title" "#;
#[test]
fn can_translate_a_string() {
let config = Config::parse(TRANS_CONFIG).unwrap();
let static_fn = Trans::new(config);
let mut args = HashMap::new();
args.insert("key".to_string(), to_value("title").unwrap());
assert_eq!(static_fn.call(&args).unwrap(), "Un titre");
args.insert("lang".to_string(), to_value("en").unwrap());
assert_eq!(static_fn.call(&args).unwrap(), "A title");
args.insert("lang".to_string(), to_value("fr").unwrap());
assert_eq!(static_fn.call(&args).unwrap(), "Un titre");
}
#[test]
fn error_on_absent_translation_lang() {
let mut args = HashMap::new();
args.insert("lang".to_string(), to_value("absent").unwrap());
args.insert("key".to_string(), to_value("title").unwrap());
let config = Config::parse(TRANS_CONFIG).unwrap();
let error = Trans::new(config).call(&args).unwrap_err();
assert_eq!("Failed to retrieve term translation", format!("{}", error));
}
#[test]
fn error_on_absent_translation_key() {
let mut args = HashMap::new();
args.insert("lang".to_string(), to_value("en").unwrap());
args.insert("key".to_string(), to_value("absent").unwrap());
let config = Config::parse(TRANS_CONFIG).unwrap();
let error = Trans::new(config).call(&args).unwrap_err();
assert_eq!("Failed to retrieve term translation", format!("{}", error));
}
}

View file

@ -4,7 +4,7 @@ use std::{fs, io, result};
use base64::encode as encode_b64; use base64::encode as encode_b64;
use sha2::{digest, Sha256, Sha384, Sha512}; use sha2::{digest, Sha256, Sha384, Sha512};
use tera::{from_value, to_value, Error, Function as TeraFn, Result, Value}; use tera::{from_value, to_value, Function as TeraFn, Result, Value};
use config::Config; use config::Config;
use utils::site::resolve_internal_link; use utils::site::resolve_internal_link;
@ -13,37 +13,15 @@ use utils::site::resolve_internal_link;
mod macros; mod macros;
mod content; mod content;
mod i18n;
mod images; mod images;
mod load_data; mod load_data;
pub use self::content::{GetPage, GetSection, GetTaxonomy, GetTaxonomyUrl}; pub use self::content::{GetPage, GetSection, GetTaxonomy, GetTaxonomyUrl};
pub use self::i18n::Trans;
pub use self::images::{GetImageMeta, ResizeImage}; pub use self::images::{GetImageMeta, ResizeImage};
pub use self::load_data::LoadData; pub use self::load_data::LoadData;
#[derive(Debug)]
pub struct Trans {
config: Config,
}
impl Trans {
pub fn new(config: Config) -> Self {
Self { config }
}
}
impl TeraFn for Trans {
fn call(&self, args: &HashMap<String, Value>) -> Result<Value> {
let key = required_arg!(String, args.get("key"), "`trans` requires a `key` argument.");
let lang = optional_arg!(String, args.get("lang"), "`trans`: `lang` must be a string.")
.unwrap_or_else(|| self.config.default_language.clone());
let term = self
.config
.get_translation(&lang, &key)
.map_err(|e| Error::chain("Failed to retrieve term translation", e))?;
Ok(to_value(term).unwrap())
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct GetUrl { pub struct GetUrl {
config: Config, config: Config,
@ -238,49 +216,38 @@ impl TeraFn for GetFileHash {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{GetFileHash, GetTaxonomy, GetTaxonomyUrl, GetUrl, Trans}; use super::{GetFileHash, GetUrl};
use std::collections::HashMap; use std::collections::HashMap;
use std::env::temp_dir;
use std::fs::remove_dir_all;
use std::path::PathBuf;
use std::sync::{Arc, RwLock};
use lazy_static::lazy_static; use tempfile::{tempdir, TempDir};
use tera::{to_value, Function};
use tera::{to_value, Function, Value}; use config::Config;
use utils::fs::create_file;
use config::{Config, Taxonomy as TaxonomyConfig}; fn create_temp_dir() -> TempDir {
use library::{Library, Taxonomy, TaxonomyItem}; let dir = tempdir().unwrap();
use utils::fs::{create_directory, create_file}; create_file(&dir.path().join("app.css"), "// Hello world!").expect("Failed to create file");
use utils::slugs::SlugifyStrategy; dir
struct TestContext {
static_path: PathBuf,
}
impl TestContext {
fn setup() -> Self {
let dir = temp_dir().join("static");
create_directory(&dir).expect("Could not create test directory");
create_file(&dir.join("app.css"), "// Hello world!")
.expect("Could not create test content (app.css)");
Self { static_path: dir }
}
}
impl Drop for TestContext {
fn drop(&mut self) {
remove_dir_all(&self.static_path).expect("Could not free test directory");
}
} }
lazy_static! { const CONFIG_DATA: &str = r#"
static ref TEST_CONTEXT: TestContext = TestContext::setup(); base_url = "https://remplace-par-ton-url.fr"
} default_language = "fr"
[translations]
title = "Un titre"
[languages.en]
[languages.en.translations]
title = "A title"
"#;
#[test] #[test]
fn can_add_cachebust_to_url() { fn can_add_cachebust_to_url() {
let config = Config::default(); let config = Config::default();
let static_fn = GetUrl::new(config, HashMap::new(), vec![TEST_CONTEXT.static_path.clone()]); let static_fn = GetUrl::new(config, HashMap::new(), vec![create_temp_dir().into_path()]);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert("path".to_string(), to_value("app.css").unwrap()); args.insert("path".to_string(), to_value("app.css").unwrap());
args.insert("cachebust".to_string(), to_value(true).unwrap()); args.insert("cachebust".to_string(), to_value(true).unwrap());
@ -290,7 +257,7 @@ mod tests {
#[test] #[test]
fn can_add_trailing_slashes() { fn can_add_trailing_slashes() {
let config = Config::default(); let config = Config::default();
let static_fn = GetUrl::new(config, HashMap::new(), vec![TEST_CONTEXT.static_path.clone()]); let static_fn = GetUrl::new(config, HashMap::new(), vec![create_temp_dir().into_path()]);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert("path".to_string(), to_value("app.css").unwrap()); args.insert("path".to_string(), to_value("app.css").unwrap());
args.insert("trailing_slash".to_string(), to_value(true).unwrap()); args.insert("trailing_slash".to_string(), to_value(true).unwrap());
@ -300,7 +267,7 @@ mod tests {
#[test] #[test]
fn can_add_slashes_and_cachebust() { fn can_add_slashes_and_cachebust() {
let config = Config::default(); let config = Config::default();
let static_fn = GetUrl::new(config, HashMap::new(), vec![TEST_CONTEXT.static_path.clone()]); let static_fn = GetUrl::new(config, HashMap::new(), vec![create_temp_dir().into_path()]);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert("path".to_string(), to_value("app.css").unwrap()); args.insert("path".to_string(), to_value("app.css").unwrap());
args.insert("trailing_slash".to_string(), to_value(true).unwrap()); args.insert("trailing_slash".to_string(), to_value(true).unwrap());
@ -311,66 +278,16 @@ mod tests {
#[test] #[test]
fn can_link_to_some_static_file() { fn can_link_to_some_static_file() {
let config = Config::default(); let config = Config::default();
let static_fn = GetUrl::new(config, HashMap::new(), vec![TEST_CONTEXT.static_path.clone()]); let static_fn = GetUrl::new(config, HashMap::new(), vec![create_temp_dir().into_path()]);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert("path".to_string(), to_value("app.css").unwrap()); args.insert("path".to_string(), to_value("app.css").unwrap());
assert_eq!(static_fn.call(&args).unwrap(), "http://a-website.com/app.css"); assert_eq!(static_fn.call(&args).unwrap(), "http://a-website.com/app.css");
} }
const TRANS_CONFIG: &str = r#"
base_url = "https://remplace-par-ton-url.fr"
default_language = "fr"
[translations]
title = "Un titre"
[languages]
[languages.en]
[languages.en.translations]
title = "A title" "#;
#[test]
fn can_translate_a_string() {
let config = Config::parse(TRANS_CONFIG).unwrap();
let static_fn = Trans::new(config);
let mut args = HashMap::new();
args.insert("key".to_string(), to_value("title").unwrap());
assert_eq!(static_fn.call(&args).unwrap(), "Un titre");
args.insert("lang".to_string(), to_value("en").unwrap());
assert_eq!(static_fn.call(&args).unwrap(), "A title");
args.insert("lang".to_string(), to_value("fr").unwrap());
assert_eq!(static_fn.call(&args).unwrap(), "Un titre");
}
#[test]
fn error_on_absent_translation_lang() {
let mut args = HashMap::new();
args.insert("lang".to_string(), to_value("absent").unwrap());
args.insert("key".to_string(), to_value("title").unwrap());
let config = Config::parse(TRANS_CONFIG).unwrap();
let error = Trans::new(config).call(&args).unwrap_err();
assert_eq!("Failed to retrieve term translation", format!("{}", error));
}
#[test]
fn error_on_absent_translation_key() {
let mut args = HashMap::new();
args.insert("lang".to_string(), to_value("en").unwrap());
args.insert("key".to_string(), to_value("absent").unwrap());
let config = Config::parse(TRANS_CONFIG).unwrap();
let error = Trans::new(config).call(&args).unwrap_err();
assert_eq!("Failed to retrieve term translation", format!("{}", error));
}
#[test] #[test]
fn error_when_language_not_available() { fn error_when_language_not_available() {
let config = Config::parse(TRANS_CONFIG).unwrap(); let config = Config::parse(CONFIG_DATA).unwrap();
let static_fn = GetUrl::new(config, HashMap::new(), vec![TEST_CONTEXT.static_path.clone()]); let static_fn = GetUrl::new(config, HashMap::new(), vec![create_temp_dir().into_path()]);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert("path".to_string(), to_value("@/a_section/a_page.md").unwrap()); args.insert("path".to_string(), to_value("@/a_section/a_page.md").unwrap());
args.insert("lang".to_string(), to_value("it").unwrap()); args.insert("lang".to_string(), to_value("it").unwrap());
@ -383,7 +300,7 @@ title = "A title" "#;
#[test] #[test]
fn can_get_url_with_default_language() { fn can_get_url_with_default_language() {
let config = Config::parse(TRANS_CONFIG).unwrap(); let config = Config::parse(CONFIG_DATA).unwrap();
let mut permalinks = HashMap::new(); let mut permalinks = HashMap::new();
permalinks.insert( permalinks.insert(
"a_section/a_page.md".to_string(), "a_section/a_page.md".to_string(),
@ -393,7 +310,7 @@ title = "A title" "#;
"a_section/a_page.en.md".to_string(), "a_section/a_page.en.md".to_string(),
"https://remplace-par-ton-url.fr/en/a_section/a_page/".to_string(), "https://remplace-par-ton-url.fr/en/a_section/a_page/".to_string(),
); );
let static_fn = GetUrl::new(config, permalinks, vec![TEST_CONTEXT.static_path.clone()]); let static_fn = GetUrl::new(config, permalinks, vec![create_temp_dir().into_path()]);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert("path".to_string(), to_value("@/a_section/a_page.md").unwrap()); args.insert("path".to_string(), to_value("@/a_section/a_page.md").unwrap());
args.insert("lang".to_string(), to_value("fr").unwrap()); args.insert("lang".to_string(), to_value("fr").unwrap());
@ -405,7 +322,7 @@ title = "A title" "#;
#[test] #[test]
fn can_get_url_with_other_language() { fn can_get_url_with_other_language() {
let config = Config::parse(TRANS_CONFIG).unwrap(); let config = Config::parse(CONFIG_DATA).unwrap();
let mut permalinks = HashMap::new(); let mut permalinks = HashMap::new();
permalinks.insert( permalinks.insert(
"a_section/a_page.md".to_string(), "a_section/a_page.md".to_string(),
@ -415,7 +332,7 @@ title = "A title" "#;
"a_section/a_page.en.md".to_string(), "a_section/a_page.en.md".to_string(),
"https://remplace-par-ton-url.fr/en/a_section/a_page/".to_string(), "https://remplace-par-ton-url.fr/en/a_section/a_page/".to_string(),
); );
let static_fn = GetUrl::new(config, permalinks, vec![TEST_CONTEXT.static_path.clone()]); let static_fn = GetUrl::new(config, permalinks, vec![create_temp_dir().into_path()]);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert("path".to_string(), to_value("@/a_section/a_page.md").unwrap()); args.insert("path".to_string(), to_value("@/a_section/a_page.md").unwrap());
args.insert("lang".to_string(), to_value("en").unwrap()); args.insert("lang".to_string(), to_value("en").unwrap());
@ -427,9 +344,9 @@ title = "A title" "#;
#[test] #[test]
fn can_get_feed_url_with_default_language() { fn can_get_feed_url_with_default_language() {
let config = Config::parse(TRANS_CONFIG).unwrap(); let config = Config::parse(CONFIG_DATA).unwrap();
let static_fn = let static_fn =
GetUrl::new(config.clone(), HashMap::new(), vec![TEST_CONTEXT.static_path.clone()]); GetUrl::new(config.clone(), HashMap::new(), vec![create_temp_dir().into_path()]);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert("path".to_string(), to_value(config.feed_filename).unwrap()); args.insert("path".to_string(), to_value(config.feed_filename).unwrap());
args.insert("lang".to_string(), to_value("fr").unwrap()); args.insert("lang".to_string(), to_value("fr").unwrap());
@ -438,9 +355,9 @@ title = "A title" "#;
#[test] #[test]
fn can_get_feed_url_with_other_language() { fn can_get_feed_url_with_other_language() {
let config = Config::parse(TRANS_CONFIG).unwrap(); let config = Config::parse(CONFIG_DATA).unwrap();
let static_fn = let static_fn =
GetUrl::new(config.clone(), HashMap::new(), vec![TEST_CONTEXT.static_path.clone()]); GetUrl::new(config.clone(), HashMap::new(), vec![create_temp_dir().into_path()]);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert("path".to_string(), to_value(config.feed_filename).unwrap()); args.insert("path".to_string(), to_value(config.feed_filename).unwrap());
args.insert("lang".to_string(), to_value("en").unwrap()); args.insert("lang".to_string(), to_value("en").unwrap());
@ -449,7 +366,7 @@ title = "A title" "#;
#[test] #[test]
fn can_get_file_hash_sha256() { fn can_get_file_hash_sha256() {
let static_fn = GetFileHash::new(vec![TEST_CONTEXT.static_path.clone()]); let static_fn = GetFileHash::new(vec![create_temp_dir().into_path()]);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert("path".to_string(), to_value("app.css").unwrap()); args.insert("path".to_string(), to_value("app.css").unwrap());
args.insert("sha_type".to_string(), to_value(256).unwrap()); args.insert("sha_type".to_string(), to_value(256).unwrap());
@ -461,7 +378,7 @@ title = "A title" "#;
#[test] #[test]
fn can_get_file_hash_sha256_base64() { fn can_get_file_hash_sha256_base64() {
let static_fn = GetFileHash::new(vec![TEST_CONTEXT.static_path.clone()]); let static_fn = GetFileHash::new(vec![create_temp_dir().into_path()]);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert("path".to_string(), to_value("app.css").unwrap()); args.insert("path".to_string(), to_value("app.css").unwrap());
args.insert("sha_type".to_string(), to_value(256).unwrap()); args.insert("sha_type".to_string(), to_value(256).unwrap());
@ -471,7 +388,7 @@ title = "A title" "#;
#[test] #[test]
fn can_get_file_hash_sha384() { fn can_get_file_hash_sha384() {
let static_fn = GetFileHash::new(vec![TEST_CONTEXT.static_path.clone()]); let static_fn = GetFileHash::new(vec![create_temp_dir().into_path()]);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert("path".to_string(), to_value("app.css").unwrap()); args.insert("path".to_string(), to_value("app.css").unwrap());
assert_eq!( assert_eq!(
@ -482,7 +399,7 @@ title = "A title" "#;
#[test] #[test]
fn can_get_file_hash_sha384_base64() { fn can_get_file_hash_sha384_base64() {
let static_fn = GetFileHash::new(vec![TEST_CONTEXT.static_path.clone()]); let static_fn = GetFileHash::new(vec![create_temp_dir().into_path()]);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert("path".to_string(), to_value("app.css").unwrap()); args.insert("path".to_string(), to_value("app.css").unwrap());
args.insert("base64".to_string(), to_value(true).unwrap()); args.insert("base64".to_string(), to_value(true).unwrap());
@ -494,7 +411,7 @@ title = "A title" "#;
#[test] #[test]
fn can_get_file_hash_sha512() { fn can_get_file_hash_sha512() {
let static_fn = GetFileHash::new(vec![TEST_CONTEXT.static_path.clone()]); let static_fn = GetFileHash::new(vec![create_temp_dir().into_path()]);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert("path".to_string(), to_value("app.css").unwrap()); args.insert("path".to_string(), to_value("app.css").unwrap());
args.insert("sha_type".to_string(), to_value(512).unwrap()); args.insert("sha_type".to_string(), to_value(512).unwrap());
@ -506,7 +423,7 @@ title = "A title" "#;
#[test] #[test]
fn can_get_file_hash_sha512_base64() { fn can_get_file_hash_sha512_base64() {
let static_fn = GetFileHash::new(vec![TEST_CONTEXT.static_path.clone()]); let static_fn = GetFileHash::new(vec![create_temp_dir().into_path()]);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert("path".to_string(), to_value("app.css").unwrap()); args.insert("path".to_string(), to_value("app.css").unwrap());
args.insert("sha_type".to_string(), to_value(512).unwrap()); args.insert("sha_type".to_string(), to_value(512).unwrap());
@ -519,7 +436,7 @@ title = "A title" "#;
#[test] #[test]
fn error_when_file_not_found_for_hash() { fn error_when_file_not_found_for_hash() {
let static_fn = GetFileHash::new(vec![TEST_CONTEXT.static_path.clone()]); let static_fn = GetFileHash::new(vec![create_temp_dir().into_path()]);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert("path".to_string(), to_value("doesnt-exist").unwrap()); args.insert("path".to_string(), to_value("doesnt-exist").unwrap());
let err = format!("{}", static_fn.call(&args).unwrap_err()); let err = format!("{}", static_fn.call(&args).unwrap_err());