Move taxonomies to language options dict

This commit is contained in:
Vincent Prouillet 2021-03-07 13:57:41 +01:00
parent 7484138a91
commit 86b42fc1ab
13 changed files with 183 additions and 243 deletions

View file

@ -5,6 +5,9 @@
### Breaking ### Breaking
- Newlines are now required after the closing `+++` of front-matter - Newlines are now required after the closing `+++` of front-matter
- i18n rework: languages now have their sections in `config.toml` to set up all their options
1. taxonomies don't have a `lang` anymore in the config, you need to declare them in their respective language section
2.
### Other ### Other

View file

@ -4,6 +4,8 @@ use errors::{bail, Result};
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use unic_langid::LanguageIdentifier; use unic_langid::LanguageIdentifier;
use crate::config::taxonomies;
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(default)] #[serde(default)]
pub struct LanguageOptions { pub struct LanguageOptions {
@ -15,11 +17,18 @@ pub struct LanguageOptions {
pub generate_feed: bool, pub generate_feed: bool,
/// Whether to generate search index for that language, defaults to `false` /// Whether to generate search index for that language, defaults to `false`
pub build_search_index: bool, pub build_search_index: bool,
pub taxonomies: Vec<taxonomies::Taxonomy>,
} }
impl Default for LanguageOptions { impl Default for LanguageOptions {
fn default() -> Self { fn default() -> Self {
LanguageOptions { title: None, description: None, generate_feed: false, build_search_index: false } LanguageOptions {
title: None,
description: None,
generate_feed: false,
build_search_index: false,
taxonomies: Vec::new(),
}
} }
} }

View file

@ -138,12 +138,16 @@ impl Config {
// TODO: what to do if there is like an empty dict for the lang? merge it or use the language // TODO: what to do if there is like an empty dict for the lang? merge it or use the language
// TODO: as source of truth? // TODO: as source of truth?
if !config.languages.contains_key(&config.default_language) { if !config.languages.contains_key(&config.default_language) {
config.languages.insert(config.default_language.clone(), languages::LanguageOptions { config.languages.insert(
title: config.title.clone(), config.default_language.clone(),
description: config.title.clone(), languages::LanguageOptions {
generate_feed: config.generate_feed, title: config.title.clone(),
build_search_index: config.build_search_index, description: config.title.clone(),
}); generate_feed: config.generate_feed,
build_search_index: config.build_search_index,
taxonomies: config.taxonomies.clone(),
},
);
} }
if !config.ignored_content.is_empty() { if !config.ignored_content.is_empty() {
@ -164,12 +168,6 @@ impl Config {
Some(glob_set_builder.build().expect("Bad ignored_content in config file.")); Some(glob_set_builder.build().expect("Bad ignored_content in config file."));
} }
for taxonomy in config.taxonomies.iter_mut() {
if taxonomy.lang.is_empty() {
taxonomy.lang = config.default_language.clone();
}
}
if config.highlight_code { if config.highlight_code {
println!("`highlight_code` has been moved to a [markdown] section. Top level `highlight_code` and `highlight_theme` will stop working in 0.14."); println!("`highlight_code` has been moved to a [markdown] section. Top level `highlight_code` and `highlight_theme` will stop working in 0.14.");
} }
@ -270,7 +268,7 @@ impl Config {
fn add_theme_extra(&mut self, theme: &Theme) -> Result<()> { fn add_theme_extra(&mut self, theme: &Theme) -> Result<()> {
for (key, val) in &theme.extra { for (key, val) in &theme.extra {
if !self.extra.contains_key(key) { if !self.extra.contains_key(key) {
// The key is not overriden in site config, insert it // The key is not overridden in site config, insert it
self.extra.insert(key.to_string(), val.clone()); self.extra.insert(key.to_string(), val.clone());
continue; continue;
} }

View file

@ -11,9 +11,6 @@ pub struct Taxonomy {
pub paginate_path: Option<String>, pub paginate_path: Option<String>,
/// Whether to generate a feed only for each taxonomy term, defaults to false /// Whether to generate a feed only for each taxonomy term, defaults to false
pub feed: bool, pub feed: bool,
/// The language for that taxonomy, only used in multilingual sites.
/// Defaults to the config `default_language` if not set
pub lang: String,
} }
impl Taxonomy { impl Taxonomy {

View file

@ -2,7 +2,8 @@ mod config;
pub mod highlighting; pub mod highlighting;
mod theme; mod theme;
pub use crate::config::{ pub use crate::config::{
languages::LanguageOptions, link_checker::LinkChecker, slugify::Slugify, taxonomies::Taxonomy, Config, languages::LanguageOptions, link_checker::LinkChecker, slugify::Slugify, taxonomies::Taxonomy,
Config,
}; };
use errors::Result; use errors::Result;

View file

@ -233,7 +233,7 @@ impl<'a> Paginator<'a> {
PaginationRoot::Taxonomy(t, item) => { PaginationRoot::Taxonomy(t, item) => {
context.insert("taxonomy", &t.kind); context.insert("taxonomy", &t.kind);
context.insert("term", &item.serialize(library)); context.insert("term", &item.serialize(library));
context.insert("lang", &t.kind.lang); context.insert("lang", &t.lang);
} }
}; };
context.insert("current_url", &pager.permalink); context.insert("current_url", &pager.permalink);
@ -419,6 +419,7 @@ mod tests {
}; };
let taxonomy = Taxonomy { let taxonomy = Taxonomy {
kind: taxonomy_def, kind: taxonomy_def,
lang: "en".to_owned(),
slug: "tags".to_string(), slug: "tags".to_string(),
items: vec![taxonomy_item.clone()], items: vec![taxonomy_item.clone()],
}; };
@ -453,6 +454,7 @@ mod tests {
}; };
let taxonomy = Taxonomy { let taxonomy = Taxonomy {
kind: taxonomy_def, kind: taxonomy_def,
lang: "en".to_owned(),
slug: "some-tags".to_string(), slug: "some-tags".to_string(),
items: vec![taxonomy_item.clone()], items: vec![taxonomy_item.clone()],
}; };

View file

@ -55,7 +55,7 @@ pub struct TaxonomyItem {
impl TaxonomyItem { impl TaxonomyItem {
pub fn new( pub fn new(
name: &str, name: &str,
taxonomy: &TaxonomyConfig, lang: &str,
taxo_slug: &str, taxo_slug: &str,
config: &Config, config: &Config,
keys: Vec<DefaultKey>, keys: Vec<DefaultKey>,
@ -76,8 +76,8 @@ impl TaxonomyItem {
.collect(); .collect();
let (mut pages, ignored_pages) = sort_pages_by_date(data); let (mut pages, ignored_pages) = sort_pages_by_date(data);
let item_slug = slugify_paths(name, config.slugify.taxonomies); let item_slug = slugify_paths(name, config.slugify.taxonomies);
let path = if taxonomy.lang != config.default_language { let path = if lang != config.default_language {
format!("/{}/{}/{}/", taxonomy.lang, taxo_slug, item_slug) format!("/{}/{}/{}/", lang, taxo_slug, item_slug)
} else { } else {
format!("/{}/{}/", taxo_slug, item_slug) format!("/{}/{}/", taxo_slug, item_slug)
}; };
@ -107,6 +107,7 @@ impl PartialEq for TaxonomyItem {
#[derive(Debug, Clone, PartialEq, Serialize)] #[derive(Debug, Clone, PartialEq, Serialize)]
pub struct SerializedTaxonomy<'a> { pub struct SerializedTaxonomy<'a> {
kind: &'a TaxonomyConfig, kind: &'a TaxonomyConfig,
lang: &'a str,
items: Vec<SerializedTaxonomyItem<'a>>, items: Vec<SerializedTaxonomyItem<'a>>,
} }
@ -114,7 +115,7 @@ impl<'a> SerializedTaxonomy<'a> {
pub fn from_taxonomy(taxonomy: &'a Taxonomy, library: &'a Library) -> Self { pub fn from_taxonomy(taxonomy: &'a Taxonomy, library: &'a Library) -> Self {
let items: Vec<SerializedTaxonomyItem> = let items: Vec<SerializedTaxonomyItem> =
taxonomy.items.iter().map(|i| SerializedTaxonomyItem::from_item(i, library)).collect(); taxonomy.items.iter().map(|i| SerializedTaxonomyItem::from_item(i, library)).collect();
SerializedTaxonomy { kind: &taxonomy.kind, items } SerializedTaxonomy { kind: &taxonomy.kind, lang: &taxonomy.lang, items }
} }
} }
@ -122,6 +123,7 @@ impl<'a> SerializedTaxonomy<'a> {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Taxonomy { pub struct Taxonomy {
pub kind: TaxonomyConfig, pub kind: TaxonomyConfig,
pub lang: String,
pub slug: String, pub slug: String,
// this vec is sorted by the count of item // this vec is sorted by the count of item
pub items: Vec<TaxonomyItem>, pub items: Vec<TaxonomyItem>,
@ -130,6 +132,7 @@ pub struct Taxonomy {
impl Taxonomy { impl Taxonomy {
fn new( fn new(
kind: TaxonomyConfig, kind: TaxonomyConfig,
lang: &str,
config: &Config, config: &Config,
items: HashMap<String, Vec<DefaultKey>>, items: HashMap<String, Vec<DefaultKey>>,
library: &Library, library: &Library,
@ -137,7 +140,7 @@ impl Taxonomy {
let mut sorted_items = vec![]; let mut sorted_items = vec![];
let slug = slugify_paths(&kind.name, config.slugify.taxonomies); let slug = slugify_paths(&kind.name, config.slugify.taxonomies);
for (name, pages) in items { for (name, pages) in items {
sorted_items.push(TaxonomyItem::new(&name, &kind, &slug, config, pages, library)); sorted_items.push(TaxonomyItem::new(&name, lang, &slug, config, pages, library));
} }
//sorted_items.sort_by(|a, b| a.name.cmp(&b.name)); //sorted_items.sort_by(|a, b| a.name.cmp(&b.name));
sorted_items.sort_by(|a, b| match a.slug.cmp(&b.slug) { sorted_items.sort_by(|a, b| match a.slug.cmp(&b.slug) {
@ -147,7 +150,7 @@ impl Taxonomy {
}); });
sorted_items.dedup_by(|a, b| { sorted_items.dedup_by(|a, b| {
// custom Eq impl checks for equal permalinks // custom Eq impl checks for equal permalinks
// here we make sure all pages from a get coppied to b // here we make sure all pages from a get copied to b
// before dedup gets rid of it // before dedup gets rid of it
if a == b { if a == b {
b.merge(a.to_owned()); b.merge(a.to_owned());
@ -156,7 +159,7 @@ impl Taxonomy {
false false
} }
}); });
Taxonomy { kind, slug, items: sorted_items } Taxonomy { kind, slug, lang: lang.to_owned(), items: sorted_items }
} }
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
@ -176,7 +179,7 @@ impl Taxonomy {
) -> Result<String> { ) -> Result<String> {
let mut context = Context::new(); let mut context = Context::new();
context.insert("config", config); context.insert("config", config);
context.insert("lang", &self.kind.lang); context.insert("lang", &self.lang);
context.insert("term", &SerializedTaxonomyItem::from_item(item, library)); context.insert("term", &SerializedTaxonomyItem::from_item(item, library));
context.insert("taxonomy", &self.kind); context.insert("taxonomy", &self.kind);
context.insert( context.insert(
@ -202,7 +205,7 @@ impl Taxonomy {
let terms: Vec<SerializedTaxonomyItem> = let terms: Vec<SerializedTaxonomyItem> =
self.items.iter().map(|i| SerializedTaxonomyItem::from_item(i, library)).collect(); self.items.iter().map(|i| SerializedTaxonomyItem::from_item(i, library)).collect();
context.insert("terms", &terms); context.insert("terms", &terms);
context.insert("lang", &self.kind.lang); context.insert("lang", &self.lang);
context.insert("taxonomy", &self.kind); context.insert("taxonomy", &self.kind);
context.insert("current_url", &config.make_permalink(&self.kind.name)); context.insert("current_url", &config.make_permalink(&self.kind.name));
context.insert("current_path", &format!("/{}/", self.kind.name)); context.insert("current_path", &format!("/{}/", self.kind.name));
@ -219,11 +222,26 @@ impl Taxonomy {
} }
pub fn find_taxonomies(config: &Config, library: &Library) -> Result<Vec<Taxonomy>> { pub fn find_taxonomies(config: &Config, library: &Library) -> Result<Vec<Taxonomy>> {
let mut slugs_to_lang = HashMap::new();
let taxonomies_def = { let taxonomies_def = {
let mut m = HashMap::new(); let mut m = HashMap::new();
// the default language taxonomies
for t in &config.taxonomies { for t in &config.taxonomies {
let slug = slugify_paths(&t.name, config.slugify.taxonomies); let slug = slugify_paths(&t.name, config.slugify.taxonomies);
m.insert(format!("{}-{}", slug, t.lang), t); let key = format!("{}-{}", slug, config.default_language);
slugs_to_lang.insert(key.clone(), config.default_language.as_str());
m.insert(key, t);
}
// other languages taxonomies
for (code, options) in config.other_languages() {
for t in &options.taxonomies {
let slug = slugify_paths(&t.name, config.slugify.taxonomies);
let key = format!("{}-{}", slug, code);
slugs_to_lang.insert(key.clone(), code);
m.insert(key, t);
}
} }
m m
}; };
@ -257,7 +275,13 @@ pub fn find_taxonomies(config: &Config, library: &Library) -> Result<Vec<Taxonom
let mut taxonomies = vec![]; let mut taxonomies = vec![];
for (name, taxo) in all_taxonomies { for (name, taxo) in all_taxonomies {
taxonomies.push(Taxonomy::new(taxonomies_def[&name].clone(), config, taxo, library)); taxonomies.push(Taxonomy::new(
taxonomies_def[&name].clone(),
slugs_to_lang[&name],
config,
taxo,
library,
));
} }
Ok(taxonomies) Ok(taxonomies)
@ -279,21 +303,9 @@ mod tests {
let mut library = Library::new(2, 0, false); let mut library = Library::new(2, 0, false);
config.taxonomies = vec![ config.taxonomies = vec![
TaxonomyConfig { TaxonomyConfig { name: "categories".to_string(), ..TaxonomyConfig::default() },
name: "categories".to_string(), TaxonomyConfig { name: "tags".to_string(), ..TaxonomyConfig::default() },
lang: config.default_language.clone(), TaxonomyConfig { name: "authors".to_string(), ..TaxonomyConfig::default() },
..TaxonomyConfig::default()
},
TaxonomyConfig {
name: "tags".to_string(),
lang: config.default_language.clone(),
..TaxonomyConfig::default()
},
TaxonomyConfig {
name: "authors".to_string(),
lang: config.default_language.clone(),
..TaxonomyConfig::default()
},
]; ];
let mut page1 = Page::default(); let mut page1 = Page::default();
@ -375,21 +387,9 @@ mod tests {
let mut library = Library::new(2, 0, false); let mut library = Library::new(2, 0, false);
config.taxonomies = vec![ config.taxonomies = vec![
TaxonomyConfig { TaxonomyConfig { name: "categories".to_string(), ..TaxonomyConfig::default() },
name: "categories".to_string(), TaxonomyConfig { name: "tags".to_string(), ..TaxonomyConfig::default() },
lang: config.default_language.clone(), TaxonomyConfig { name: "authors".to_string(), ..TaxonomyConfig::default() },
..TaxonomyConfig::default()
},
TaxonomyConfig {
name: "tags".to_string(),
lang: config.default_language.clone(),
..TaxonomyConfig::default()
},
TaxonomyConfig {
name: "authors".to_string(),
lang: config.default_language.clone(),
..TaxonomyConfig::default()
},
]; ];
let mut page1 = Page::default(); let mut page1 = Page::default();
@ -470,11 +470,8 @@ mod tests {
let mut config = Config::default(); let mut config = Config::default();
let mut library = Library::new(2, 0, false); let mut library = Library::new(2, 0, false);
config.taxonomies = vec![TaxonomyConfig { config.taxonomies =
name: "authors".to_string(), vec![TaxonomyConfig { name: "authors".to_string(), ..TaxonomyConfig::default() }];
lang: config.default_language.clone(),
..TaxonomyConfig::default()
}];
let mut page1 = Page::default(); let mut page1 = Page::default();
let mut taxo_page1 = HashMap::new(); let mut taxo_page1 = HashMap::new();
taxo_page1.insert("tags".to_string(), vec!["rust".to_string(), "db".to_string()]); taxo_page1.insert("tags".to_string(), vec!["rust".to_string(), "db".to_string()]);
@ -499,27 +496,18 @@ mod tests {
let mut library = Library::new(2, 0, true); let mut library = Library::new(2, 0, true);
config.taxonomies = vec![ config.taxonomies = vec![
TaxonomyConfig { TaxonomyConfig { name: "categories".to_string(), ..TaxonomyConfig::default() },
name: "categories".to_string(), TaxonomyConfig { name: "tags".to_string(), ..TaxonomyConfig::default() },
lang: config.default_language.clone(),
..TaxonomyConfig::default()
},
TaxonomyConfig {
name: "tags".to_string(),
lang: config.default_language.clone(),
..TaxonomyConfig::default()
},
TaxonomyConfig {
name: "auteurs".to_string(),
lang: "fr".to_string(),
..TaxonomyConfig::default()
},
TaxonomyConfig {
name: "tags".to_string(),
lang: "fr".to_string(),
..TaxonomyConfig::default()
},
]; ];
let french_taxo = vec![
TaxonomyConfig { name: "auteurs".to_string(), ..TaxonomyConfig::default() },
TaxonomyConfig { name: "tags".to_string(), ..TaxonomyConfig::default() },
];
let lang_options = config::LanguageOptions {
taxonomies: french_taxo,
..config::LanguageOptions::default()
};
config.languages.insert("fr".to_owned(), lang_options);
let mut page1 = Page::default(); let mut page1 = Page::default();
let mut taxo_page1 = HashMap::new(); let mut taxo_page1 = HashMap::new();
@ -553,7 +541,7 @@ mod tests {
for x in taxonomies { for x in taxonomies {
match x.kind.name.as_ref() { match x.kind.name.as_ref() {
"tags" => { "tags" => {
if x.kind.lang == "en" { if x.lang == "en" {
t = Some(x) t = Some(x)
} }
} }
@ -605,14 +593,15 @@ mod tests {
fn can_make_utf8_taxonomies() { fn can_make_utf8_taxonomies() {
let mut config = Config::default(); let mut config = Config::default();
config.slugify.taxonomies = SlugifyStrategy::Safe; config.slugify.taxonomies = SlugifyStrategy::Safe;
config.languages.insert("fr".to_owned(), LanguageOptions::default());
let mut library = Library::new(2, 0, true); let mut library = Library::new(2, 0, true);
config.taxonomies = vec![TaxonomyConfig { let french_taxo =
name: "catégories".to_string(), vec![TaxonomyConfig { name: "catégories".to_string(), ..TaxonomyConfig::default() }];
lang: "fr".to_string(), let lang_options = config::LanguageOptions {
..TaxonomyConfig::default() taxonomies: french_taxo,
}]; ..config::LanguageOptions::default()
};
config.languages.insert("fr".to_owned(), lang_options);
let mut page = Page::default(); let mut page = Page::default();
page.lang = "fr".to_string(); page.lang = "fr".to_string();
@ -634,32 +623,21 @@ mod tests {
fn can_make_slugified_taxonomies_in_multiple_languages() { fn can_make_slugified_taxonomies_in_multiple_languages() {
let mut config = Config::default(); let mut config = Config::default();
config.slugify.taxonomies = SlugifyStrategy::On; config.slugify.taxonomies = SlugifyStrategy::On;
config.languages.insert("fr".to_owned(), LanguageOptions::default());
let mut library = Library::new(2, 0, true); let mut library = Library::new(2, 0, true);
config.taxonomies = vec![ config.taxonomies = vec![
TaxonomyConfig { TaxonomyConfig { name: "categories".to_string(), ..TaxonomyConfig::default() },
name: "categories".to_string(), TaxonomyConfig { name: "tags".to_string(), ..TaxonomyConfig::default() },
lang: config.default_language.clone(),
..TaxonomyConfig::default()
},
TaxonomyConfig {
name: "tags".to_string(),
lang: config.default_language.clone(),
..TaxonomyConfig::default()
},
TaxonomyConfig {
name: "auteurs".to_string(),
lang: "fr".to_string(),
..TaxonomyConfig::default()
},
TaxonomyConfig {
name: "tags".to_string(),
lang: "fr".to_string(),
..TaxonomyConfig::default()
},
]; ];
let french_taxo = vec![
TaxonomyConfig { name: "auteurs".to_string(), ..TaxonomyConfig::default() },
TaxonomyConfig { name: "tags".to_string(), ..TaxonomyConfig::default() },
];
let lang_options = config::LanguageOptions {
taxonomies: french_taxo,
..config::LanguageOptions::default()
};
config.languages.insert("fr".to_owned(), lang_options);
let mut page1 = Page::default(); let mut page1 = Page::default();
let mut taxo_page1 = HashMap::new(); let mut taxo_page1 = HashMap::new();
taxo_page1.insert("tags".to_string(), vec!["rust".to_string(), "db".to_string()]); taxo_page1.insert("tags".to_string(), vec!["rust".to_string(), "db".to_string()]);
@ -692,7 +670,7 @@ mod tests {
for x in taxonomies { for x in taxonomies {
match x.kind.name.as_ref() { match x.kind.name.as_ref() {
"tags" => { "tags" => {
if x.kind.lang == "en" { if x.lang == "en" {
t = Some(x) t = Some(x)
} }
} }
@ -746,26 +724,10 @@ mod tests {
let mut library = Library::new(2, 0, false); let mut library = Library::new(2, 0, false);
config.taxonomies = vec![ config.taxonomies = vec![
TaxonomyConfig { TaxonomyConfig { name: "test-taxonomy".to_string(), ..TaxonomyConfig::default() },
name: "test-taxonomy".to_string(), TaxonomyConfig { name: "test taxonomy".to_string(), ..TaxonomyConfig::default() },
lang: config.default_language.clone(), TaxonomyConfig { name: "test-taxonomy ".to_string(), ..TaxonomyConfig::default() },
..TaxonomyConfig::default() TaxonomyConfig { name: "Test-Taxonomy ".to_string(), ..TaxonomyConfig::default() },
},
TaxonomyConfig {
name: "test taxonomy".to_string(),
lang: config.default_language.clone(),
..TaxonomyConfig::default()
},
TaxonomyConfig {
name: "test-taxonomy ".to_string(),
lang: config.default_language.clone(),
..TaxonomyConfig::default()
},
TaxonomyConfig {
name: "Test-Taxonomy ".to_string(),
lang: config.default_language.clone(),
..TaxonomyConfig::default()
},
]; ];
let mut page1 = Page::default(); let mut page1 = Page::default();
@ -831,26 +793,10 @@ mod tests {
let mut library = Library::new(2, 0, false); let mut library = Library::new(2, 0, false);
config.taxonomies = vec![ config.taxonomies = vec![
TaxonomyConfig { TaxonomyConfig { name: "test-taxonomy".to_string(), ..TaxonomyConfig::default() },
name: "test-taxonomy".to_string(), TaxonomyConfig { name: "test taxonomy".to_string(), ..TaxonomyConfig::default() },
lang: config.default_language.clone(), TaxonomyConfig { name: "test-taxonomy ".to_string(), ..TaxonomyConfig::default() },
..TaxonomyConfig::default() TaxonomyConfig { name: "Test-Taxonomy ".to_string(), ..TaxonomyConfig::default() },
},
TaxonomyConfig {
name: "test taxonomy".to_string(),
lang: config.default_language.clone(),
..TaxonomyConfig::default()
},
TaxonomyConfig {
name: "test-taxonomy ".to_string(),
lang: config.default_language.clone(),
..TaxonomyConfig::default()
},
TaxonomyConfig {
name: "Test-Taxonomy ".to_string(),
lang: config.default_language.clone(),
..TaxonomyConfig::default()
},
]; ];
let mut page1 = Page::default(); let mut page1 = Page::default();
@ -909,26 +855,10 @@ mod tests {
let mut library = Library::new(2, 0, false); let mut library = Library::new(2, 0, false);
config.taxonomies = vec![ config.taxonomies = vec![
TaxonomyConfig { TaxonomyConfig { name: "test-taxonomy".to_string(), ..TaxonomyConfig::default() },
name: "test-taxonomy".to_string(), TaxonomyConfig { name: "test taxonomy".to_string(), ..TaxonomyConfig::default() },
lang: config.default_language.clone(), TaxonomyConfig { name: "test-taxonomy ".to_string(), ..TaxonomyConfig::default() },
..TaxonomyConfig::default() TaxonomyConfig { name: "Test-Taxonomy ".to_string(), ..TaxonomyConfig::default() },
},
TaxonomyConfig {
name: "test taxonomy".to_string(),
lang: config.default_language.clone(),
..TaxonomyConfig::default()
},
TaxonomyConfig {
name: "test-taxonomy ".to_string(),
lang: config.default_language.clone(),
..TaxonomyConfig::default()
},
TaxonomyConfig {
name: "Test-Taxonomy ".to_string(),
lang: config.default_language.clone(),
..TaxonomyConfig::default()
},
]; ];
let mut page1 = Page::default(); let mut page1 = Page::default();
@ -964,7 +894,7 @@ mod tests {
let tax = &taxonomies[0]; let tax = &taxonomies[0];
// if names are different permalinks should also be different so // if names are different permalinks should also be different so
// the tems are still accessable // the items are still accessible
for term1 in tax.items.iter() { for term1 in tax.items.iter() {
for term2 in tax.items.iter() { for term2 in tax.items.iter() {
assert!(term1.name == term2.name || term1.permalink != term2.permalink); assert!(term1.name == term2.name || term1.permalink != term2.permalink);

View file

@ -173,8 +173,12 @@ impl Site {
// which we can only decide to use after we've deserialised the section // which we can only decide to use after we've deserialised the section
// so it's kinda necessecary // so it's kinda necessecary
let mut dir_walker = WalkDir::new(format!("{}/{}", base_path, "content/")).into_iter(); let mut dir_walker = WalkDir::new(format!("{}/{}", base_path, "content/")).into_iter();
let mut allowed_index_filenames: Vec<_> = let mut allowed_index_filenames: Vec<_> = self
self.config.other_languages().iter().map(|(code, _)| format!("_index.{}.md", code)).collect(); .config
.other_languages()
.iter()
.map(|(code, _)| format!("_index.{}.md", code))
.collect();
allowed_index_filenames.push("_index.md".to_string()); allowed_index_filenames.push("_index.md".to_string());
loop { loop {
@ -240,11 +244,8 @@ impl Site {
.collect::<Vec<DirEntry>>(); .collect::<Vec<DirEntry>>();
for index_file in index_files { for index_file in index_files {
let section = Section::from_file( let section =
index_file.path(), Section::from_file(index_file.path(), &self.config, &self.base_path)?;
&self.config,
&self.base_path,
)?;
// if the section is drafted we can skip the enitre dir // if the section is drafted we can skip the enitre dir
if section.meta.draft && !self.include_drafts { if section.meta.draft && !self.include_drafts {
@ -794,8 +795,8 @@ impl Site {
ensure_directory_exists(&self.output_path)?; ensure_directory_exists(&self.output_path)?;
let mut components = Vec::new(); let mut components = Vec::new();
if taxonomy.kind.lang != self.config.default_language { if taxonomy.lang != self.config.default_language {
components.push(taxonomy.kind.lang.as_ref()); components.push(taxonomy.lang.as_ref());
} }
components.push(taxonomy.slug.as_ref()); components.push(taxonomy.slug.as_ref());
@ -829,11 +830,7 @@ impl Site {
self.render_feed( self.render_feed(
item.pages.iter().map(|p| library.get_page_by_key(*p)).collect(), item.pages.iter().map(|p| library.get_page_by_key(*p)).collect(),
Some(&PathBuf::from(format!("{}/{}", taxonomy.slug, item.slug))), Some(&PathBuf::from(format!("{}/{}", taxonomy.slug, item.slug))),
if self.config.is_multilingual() && !taxonomy.kind.lang.is_empty() { &taxonomy.lang,
&taxonomy.kind.lang
} else {
&self.config.default_language
},
|mut context: Context| { |mut context: Context| {
context.insert("taxonomy", &taxonomy.kind); context.insert("taxonomy", &taxonomy.kind);
context context

View file

@ -550,7 +550,6 @@ fn can_build_site_with_pagination_for_taxonomy() {
paginate_by: Some(2), paginate_by: Some(2),
paginate_path: None, paginate_path: None,
feed: true, feed: true,
lang: site.config.default_language.clone(),
}); });
site.load().unwrap(); site.load().unwrap();
{ {

View file

@ -358,7 +358,7 @@ impl GetTaxonomyUrl {
for item in &taxo.items { for item in &taxo.items {
items.insert(slugify_paths(&item.name.clone(), slugify), item.permalink.clone()); items.insert(slugify_paths(&item.name.clone(), slugify), item.permalink.clone());
} }
taxonomies.insert(format!("{}-{}", taxo.kind.name, taxo.kind.lang), items); taxonomies.insert(format!("{}-{}", taxo.kind.name, taxo.lang), items);
} }
Self { taxonomies, default_lang: default_lang.to_string(), slugify } Self { taxonomies, default_lang: default_lang.to_string(), slugify }
} }
@ -476,7 +476,7 @@ impl GetTaxonomy {
) -> Self { ) -> Self {
let mut taxonomies = HashMap::new(); let mut taxonomies = HashMap::new();
for taxo in all_taxonomies { for taxo in all_taxonomies {
taxonomies.insert(format!("{}-{}", taxo.kind.name, taxo.kind.lang), taxo); taxonomies.insert(format!("{}-{}", taxo.kind.name, taxo.lang), taxo);
} }
Self { taxonomies, library, default_lang: default_lang.to_string() } Self { taxonomies, library, default_lang: default_lang.to_string() }
} }
@ -587,20 +587,13 @@ mod tests {
fn can_get_taxonomy() { fn can_get_taxonomy() {
let mut config = Config::default(); let mut config = Config::default();
config.slugify.taxonomies = SlugifyStrategy::On; config.slugify.taxonomies = SlugifyStrategy::On;
let taxo_config = TaxonomyConfig { let taxo_config = TaxonomyConfig { name: "tags".to_string(), ..TaxonomyConfig::default() };
name: "tags".to_string(), let taxo_config_fr =
lang: config.default_language.clone(), TaxonomyConfig { name: "tags".to_string(), ..TaxonomyConfig::default() };
..TaxonomyConfig::default()
};
let taxo_config_fr = TaxonomyConfig {
name: "tags".to_string(),
lang: "fr".to_string(),
..TaxonomyConfig::default()
};
let library = Arc::new(RwLock::new(Library::new(0, 0, false))); let library = Arc::new(RwLock::new(Library::new(0, 0, false)));
let tag = TaxonomyItem::new( let tag = TaxonomyItem::new(
"Programming", "Programming",
&taxo_config, &config.default_language,
"tags", "tags",
&config, &config,
vec![], vec![],
@ -608,15 +601,24 @@ mod tests {
); );
let tag_fr = TaxonomyItem::new( let tag_fr = TaxonomyItem::new(
"Programmation", "Programmation",
&taxo_config_fr, "fr",
"tags", "tags",
&config, &config,
vec![], vec![],
&library.read().unwrap(), &library.read().unwrap(),
); );
let tags = Taxonomy { kind: taxo_config, slug: "tags".to_string(), items: vec![tag] }; let tags = Taxonomy {
let tags_fr = kind: taxo_config,
Taxonomy { kind: taxo_config_fr, slug: "tags".to_string(), items: vec![tag_fr] }; lang: config.default_language.clone(),
slug: "tags".to_string(),
items: vec![tag],
};
let tags_fr = Taxonomy {
kind: taxo_config_fr,
lang: "fr".to_owned(),
slug: "tags".to_string(),
items: vec![tag_fr],
};
let taxonomies = vec![tags.clone(), tags_fr.clone()]; let taxonomies = vec![tags.clone(), tags_fr.clone()];
let static_fn = let static_fn =
@ -668,23 +670,31 @@ mod tests {
fn can_get_taxonomy_url() { fn can_get_taxonomy_url() {
let mut config = Config::default(); let mut config = Config::default();
config.slugify.taxonomies = SlugifyStrategy::On; config.slugify.taxonomies = SlugifyStrategy::On;
let taxo_config = TaxonomyConfig { let taxo_config = TaxonomyConfig { name: "tags".to_string(), ..TaxonomyConfig::default() };
name: "tags".to_string(), let taxo_config_fr =
lang: config.default_language.clone(), TaxonomyConfig { name: "tags".to_string(), ..TaxonomyConfig::default() };
..TaxonomyConfig::default()
};
let taxo_config_fr = TaxonomyConfig {
name: "tags".to_string(),
lang: "fr".to_string(),
..TaxonomyConfig::default()
};
let library = Library::new(0, 0, false); let library = Library::new(0, 0, false);
let tag = TaxonomyItem::new("Programming", &taxo_config, "tags", &config, vec![], &library); let tag = TaxonomyItem::new(
let tag_fr = "Programming",
TaxonomyItem::new("Programmation", &taxo_config_fr, "tags", &config, vec![], &library); &config.default_language,
let tags = Taxonomy { kind: taxo_config, slug: "tags".to_string(), items: vec![tag] }; "tags",
let tags_fr = &config,
Taxonomy { kind: taxo_config_fr, slug: "tags".to_string(), items: vec![tag_fr] }; vec![],
&library,
);
let tag_fr = TaxonomyItem::new("Programmation", "fr", "tags", &config, vec![], &library);
let tags = Taxonomy {
kind: taxo_config,
lang: config.default_language.clone(),
slug: "tags".to_string(),
items: vec![tag],
};
let tags_fr = Taxonomy {
kind: taxo_config_fr,
lang: "fr".to_owned(),
slug: "tags".to_string(),
items: vec![tag_fr],
};
let taxonomies = vec![tags.clone(), tags_fr.clone()]; let taxonomies = vec![tags.clone(), tags_fr.clone()];
let static_fn = let static_fn =
@ -839,27 +849,23 @@ 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(TRANS_CONFIG).unwrap();
let static_fn = GetUrl::new(config.clone(), HashMap::new(), vec![TEST_CONTEXT.static_path.clone()]); let static_fn =
GetUrl::new(config.clone(), HashMap::new(), vec![TEST_CONTEXT.static_path.clone()]);
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());
assert_eq!( assert_eq!(static_fn.call(&args).unwrap(), "https://remplace-par-ton-url.fr/atom.xml");
static_fn.call(&args).unwrap(),
"https://remplace-par-ton-url.fr/atom.xml"
);
} }
#[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(TRANS_CONFIG).unwrap();
let static_fn = GetUrl::new(config.clone(), HashMap::new(), vec![TEST_CONTEXT.static_path.clone()]); let static_fn =
GetUrl::new(config.clone(), HashMap::new(), vec![TEST_CONTEXT.static_path.clone()]);
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());
assert_eq!( assert_eq!(static_fn.call(&args).unwrap(), "https://remplace-par-ton-url.fr/en/atom.xml");
static_fn.call(&args).unwrap(),
"https://remplace-par-ton-url.fr/en/atom.xml"
);
} }
#[test] #[test]

View file

@ -281,11 +281,7 @@ pub fn serve(
return Err(format!("Cannot start server on address {}.", address).into()); return Err(format!("Cannot start server on address {}.", address).into());
} }
let config_filename = config_file let config_filename = config_file.file_name().unwrap().to_str().unwrap_or("config.toml");
.file_name()
.unwrap()
.to_str()
.unwrap_or("config.toml");
// An array of (path, bool, bool) where the path should be watched for changes, and the boolean value // An array of (path, bool, bool) where the path should be watched for changes, and the boolean value
// indicates whether this file/folder must exist for zola serve to operate // indicates whether this file/folder must exist for zola serve to operate
@ -485,7 +481,7 @@ pub fn serve(
match rx.recv() { match rx.recv() {
Ok(event) => { Ok(event) => {
let can_do_fast_reload = !matches!(event, Remove(_)); let can_do_fast_reload = !matches!(event, Remove(_));
match event { match event {
// Intellij does weird things on edit, chmod is there to count those changes // Intellij does weird things on edit, chmod is there to count those changes
// https://github.com/passcod/notify/issues/150#issuecomment-494912080 // https://github.com/passcod/notify/issues/150#issuecomment-494912080

View file

@ -13,13 +13,15 @@ generate_feed = true
taxonomies = [ taxonomies = [
{name = "authors", feed = true}, {name = "authors", feed = true},
{name = "auteurs", lang = "fr"},
{name = "tags"}, {name = "tags"},
{name = "tags", lang = "fr"},
] ]
[languages.fr] [languages.fr]
generate_feed = true generate_feed = true
taxonomies = [
{name = "auteurs", lang = "fr"},
{name = "tags", lang = "fr"},
]
[languages.it] [languages.it]
build_search_index = true build_search_index = true

View file

@ -1,3 +1,3 @@
{% for tag in terms %} {% for tag in terms %}
{{ tag.name }} {{ tag.slug }} {{ tag.pages | length }} {{ taxonomy.lang }} {{ tag.name }} {{ tag.slug }} {{ tag.pages | length }} {{ lang }}
{% endfor %} {% endfor %}