You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

713 lines
26KB

  1. use std::collections::HashMap;
  2. use serde_derive::Serialize;
  3. use slotmap::DefaultKey;
  4. use tera::{Context, Tera};
  5. use config::{Config, Taxonomy as TaxonomyConfig};
  6. use errors::{bail, Error, Result};
  7. use utils::templates::render_template;
  8. use crate::content::SerializingPage;
  9. use crate::library::Library;
  10. use crate::sorting::sort_pages_by_date;
  11. use utils::slugs::slugify_paths;
  12. #[derive(Debug, Clone, PartialEq, Serialize)]
  13. pub struct SerializedTaxonomyItem<'a> {
  14. name: &'a str,
  15. slug: &'a str,
  16. permalink: &'a str,
  17. pages: Vec<SerializingPage<'a>>,
  18. }
  19. impl<'a> SerializedTaxonomyItem<'a> {
  20. pub fn from_item(item: &'a TaxonomyItem, library: &'a Library) -> Self {
  21. let mut pages = vec![];
  22. for key in &item.pages {
  23. let page = library.get_page_by_key(*key);
  24. pages.push(page.to_serialized_basic(library));
  25. }
  26. SerializedTaxonomyItem {
  27. name: &item.name,
  28. slug: &item.slug,
  29. permalink: &item.permalink,
  30. pages,
  31. }
  32. }
  33. }
  34. /// A taxonomy with all its pages
  35. #[derive(Debug, Clone, PartialEq)]
  36. pub struct TaxonomyItem {
  37. pub name: String,
  38. pub slug: String,
  39. pub permalink: String,
  40. pub pages: Vec<DefaultKey>,
  41. }
  42. impl TaxonomyItem {
  43. pub fn new(
  44. name: &str,
  45. taxonomy: &TaxonomyConfig,
  46. config: &Config,
  47. keys: Vec<DefaultKey>,
  48. library: &Library,
  49. ) -> Self {
  50. // Taxonomy are almost always used for blogs so we filter by dates
  51. // and it's not like we can sort things across sections by anything other
  52. // than dates
  53. let data = keys
  54. .iter()
  55. .map(|k| {
  56. if let Some(page) = library.pages().get(*k) {
  57. (k, page.meta.datetime, page.permalink.as_ref())
  58. } else {
  59. unreachable!("Sorting got an unknown page")
  60. }
  61. })
  62. .collect();
  63. let (mut pages, ignored_pages) = sort_pages_by_date(data);
  64. let slug = slugify_paths(name, config.slugify.taxonomies);
  65. let permalink = if taxonomy.lang != config.default_language {
  66. config.make_permalink(&format!("/{}/{}/{}", taxonomy.lang, taxonomy.name, slug))
  67. } else {
  68. config.make_permalink(&format!("/{}/{}", taxonomy.name, slug))
  69. };
  70. // We still append pages without dates at the end
  71. pages.extend(ignored_pages);
  72. TaxonomyItem { name: name.to_string(), permalink, slug, pages }
  73. }
  74. pub fn serialize<'a>(&'a self, library: &'a Library) -> SerializedTaxonomyItem<'a> {
  75. SerializedTaxonomyItem::from_item(self, library)
  76. }
  77. }
  78. #[derive(Debug, Clone, PartialEq, Serialize)]
  79. pub struct SerializedTaxonomy<'a> {
  80. kind: &'a TaxonomyConfig,
  81. items: Vec<SerializedTaxonomyItem<'a>>,
  82. }
  83. impl<'a> SerializedTaxonomy<'a> {
  84. pub fn from_taxonomy(taxonomy: &'a Taxonomy, library: &'a Library) -> Self {
  85. let items: Vec<SerializedTaxonomyItem> =
  86. taxonomy.items.iter().map(|i| SerializedTaxonomyItem::from_item(i, library)).collect();
  87. SerializedTaxonomy { kind: &taxonomy.kind, items }
  88. }
  89. }
  90. /// All different taxonomies we have and their content
  91. #[derive(Debug, Clone, PartialEq)]
  92. pub struct Taxonomy {
  93. pub kind: TaxonomyConfig,
  94. // this vec is sorted by the count of item
  95. pub items: Vec<TaxonomyItem>,
  96. }
  97. impl Taxonomy {
  98. fn new(
  99. kind: TaxonomyConfig,
  100. config: &Config,
  101. items: HashMap<String, Vec<DefaultKey>>,
  102. library: &Library,
  103. ) -> Taxonomy {
  104. let mut sorted_items = vec![];
  105. for (name, pages) in items {
  106. sorted_items.push(TaxonomyItem::new(&name, &kind, config, pages, library));
  107. }
  108. sorted_items.sort_by(|a, b| a.name.cmp(&b.name));
  109. Taxonomy { kind, items: sorted_items }
  110. }
  111. pub fn len(&self) -> usize {
  112. self.items.len()
  113. }
  114. pub fn is_empty(&self) -> bool {
  115. self.len() == 0
  116. }
  117. pub fn render_term(
  118. &self,
  119. item: &TaxonomyItem,
  120. tera: &Tera,
  121. config: &Config,
  122. library: &Library,
  123. ) -> Result<String> {
  124. let mut context = Context::new();
  125. context.insert("config", config);
  126. context.insert("lang", &self.kind.lang);
  127. context.insert("term", &SerializedTaxonomyItem::from_item(item, library));
  128. context.insert("taxonomy", &self.kind);
  129. context.insert(
  130. "current_url",
  131. &config.make_permalink(&format!("{}/{}", self.kind.name, item.slug)),
  132. );
  133. context.insert("current_path", &format!("/{}/{}", self.kind.name, item.slug));
  134. render_template(&format!("{}/single.html", self.kind.name), tera, context, &config.theme)
  135. .map_err(|e| {
  136. Error::chain(format!("Failed to render single term {} page.", self.kind.name), e)
  137. })
  138. }
  139. pub fn render_all_terms(
  140. &self,
  141. tera: &Tera,
  142. config: &Config,
  143. library: &Library,
  144. ) -> Result<String> {
  145. let mut context = Context::new();
  146. context.insert("config", config);
  147. let terms: Vec<SerializedTaxonomyItem> =
  148. self.items.iter().map(|i| SerializedTaxonomyItem::from_item(i, library)).collect();
  149. context.insert("terms", &terms);
  150. context.insert("taxonomy", &self.kind);
  151. context.insert("current_url", &config.make_permalink(&self.kind.name));
  152. context.insert("current_path", &self.kind.name);
  153. render_template(&format!("{}/list.html", self.kind.name), tera, context, &config.theme)
  154. .map_err(|e| {
  155. Error::chain(format!("Failed to render a list of {} page.", self.kind.name), e)
  156. })
  157. }
  158. pub fn to_serialized<'a>(&'a self, library: &'a Library) -> SerializedTaxonomy<'a> {
  159. SerializedTaxonomy::from_taxonomy(self, library)
  160. }
  161. }
  162. pub fn find_taxonomies(config: &Config, library: &Library) -> Result<Vec<Taxonomy>> {
  163. let taxonomies_def = {
  164. let mut m = HashMap::new();
  165. for t in &config.taxonomies {
  166. m.insert(format!("{}-{}", t.name, t.lang), t);
  167. }
  168. m
  169. };
  170. let mut all_taxonomies = HashMap::new();
  171. for (key, page) in library.pages() {
  172. for (name, val) in &page.meta.taxonomies {
  173. let taxo_key = format!("{}-{}", name, page.lang);
  174. if taxonomies_def.contains_key(&taxo_key) {
  175. all_taxonomies.entry(taxo_key.clone()).or_insert_with(HashMap::new);
  176. for v in val {
  177. all_taxonomies
  178. .get_mut(&taxo_key)
  179. .unwrap()
  180. .entry(v.to_string())
  181. .or_insert_with(|| vec![])
  182. .push(key);
  183. }
  184. } else {
  185. bail!(
  186. "Page `{}` has taxonomy `{}` which is not defined in config.toml",
  187. page.file.path.display(),
  188. name
  189. );
  190. }
  191. }
  192. }
  193. let mut taxonomies = vec![];
  194. for (name, taxo) in all_taxonomies {
  195. taxonomies.push(Taxonomy::new(taxonomies_def[&name].clone(), config, taxo, library));
  196. }
  197. Ok(taxonomies)
  198. }
  199. #[cfg(test)]
  200. mod tests {
  201. use super::*;
  202. use std::collections::HashMap;
  203. use crate::content::Page;
  204. use crate::library::Library;
  205. use config::{Config, Language, Taxonomy as TaxonomyConfig};
  206. use utils::slugs::SlugifyStrategy;
  207. #[test]
  208. fn can_make_taxonomies() {
  209. let mut config = Config::default();
  210. let mut library = Library::new(2, 0, false);
  211. config.taxonomies = vec![
  212. TaxonomyConfig {
  213. name: "categories".to_string(),
  214. lang: config.default_language.clone(),
  215. ..TaxonomyConfig::default()
  216. },
  217. TaxonomyConfig {
  218. name: "tags".to_string(),
  219. lang: config.default_language.clone(),
  220. ..TaxonomyConfig::default()
  221. },
  222. TaxonomyConfig {
  223. name: "authors".to_string(),
  224. lang: config.default_language.clone(),
  225. ..TaxonomyConfig::default()
  226. },
  227. ];
  228. let mut page1 = Page::default();
  229. let mut taxo_page1 = HashMap::new();
  230. taxo_page1.insert("tags".to_string(), vec!["rust".to_string(), "db".to_string()]);
  231. taxo_page1.insert("categories".to_string(), vec!["Programming tutorials".to_string()]);
  232. page1.meta.taxonomies = taxo_page1;
  233. page1.lang = config.default_language.clone();
  234. library.insert_page(page1);
  235. let mut page2 = Page::default();
  236. let mut taxo_page2 = HashMap::new();
  237. taxo_page2.insert("tags".to_string(), vec!["rust".to_string(), "js".to_string()]);
  238. taxo_page2.insert("categories".to_string(), vec!["Other".to_string()]);
  239. page2.meta.taxonomies = taxo_page2;
  240. page2.lang = config.default_language.clone();
  241. library.insert_page(page2);
  242. let mut page3 = Page::default();
  243. let mut taxo_page3 = HashMap::new();
  244. taxo_page3.insert("tags".to_string(), vec!["js".to_string()]);
  245. taxo_page3.insert("authors".to_string(), vec!["Vincent Prouillet".to_string()]);
  246. page3.meta.taxonomies = taxo_page3;
  247. page3.lang = config.default_language.clone();
  248. library.insert_page(page3);
  249. let taxonomies = find_taxonomies(&config, &library).unwrap();
  250. let (tags, categories, authors) = {
  251. let mut t = None;
  252. let mut c = None;
  253. let mut a = None;
  254. for x in taxonomies {
  255. match x.kind.name.as_ref() {
  256. "tags" => t = Some(x),
  257. "categories" => c = Some(x),
  258. "authors" => a = Some(x),
  259. _ => unreachable!(),
  260. }
  261. }
  262. (t.unwrap(), c.unwrap(), a.unwrap())
  263. };
  264. assert_eq!(tags.items.len(), 3);
  265. assert_eq!(categories.items.len(), 2);
  266. assert_eq!(authors.items.len(), 1);
  267. assert_eq!(tags.items[0].name, "db");
  268. assert_eq!(tags.items[0].slug, "db");
  269. assert_eq!(tags.items[0].permalink, "http://a-website.com/tags/db/");
  270. assert_eq!(tags.items[0].pages.len(), 1);
  271. assert_eq!(tags.items[1].name, "js");
  272. assert_eq!(tags.items[1].slug, "js");
  273. assert_eq!(tags.items[1].permalink, "http://a-website.com/tags/js/");
  274. assert_eq!(tags.items[1].pages.len(), 2);
  275. assert_eq!(tags.items[2].name, "rust");
  276. assert_eq!(tags.items[2].slug, "rust");
  277. assert_eq!(tags.items[2].permalink, "http://a-website.com/tags/rust/");
  278. assert_eq!(tags.items[2].pages.len(), 2);
  279. assert_eq!(categories.items[0].name, "Other");
  280. assert_eq!(categories.items[0].slug, "other");
  281. assert_eq!(categories.items[0].permalink, "http://a-website.com/categories/other/");
  282. assert_eq!(categories.items[0].pages.len(), 1);
  283. assert_eq!(categories.items[1].name, "Programming tutorials");
  284. assert_eq!(categories.items[1].slug, "programming-tutorials");
  285. assert_eq!(
  286. categories.items[1].permalink,
  287. "http://a-website.com/categories/programming-tutorials/"
  288. );
  289. assert_eq!(categories.items[1].pages.len(), 1);
  290. }
  291. #[test]
  292. fn can_make_slugified_taxonomies() {
  293. let mut config = Config::default();
  294. let mut library = Library::new(2, 0, false);
  295. config.taxonomies = vec![
  296. TaxonomyConfig {
  297. name: "categories".to_string(),
  298. lang: config.default_language.clone(),
  299. ..TaxonomyConfig::default()
  300. },
  301. TaxonomyConfig {
  302. name: "tags".to_string(),
  303. lang: config.default_language.clone(),
  304. ..TaxonomyConfig::default()
  305. },
  306. TaxonomyConfig {
  307. name: "authors".to_string(),
  308. lang: config.default_language.clone(),
  309. ..TaxonomyConfig::default()
  310. },
  311. ];
  312. let mut page1 = Page::default();
  313. let mut taxo_page1 = HashMap::new();
  314. taxo_page1.insert("tags".to_string(), vec!["rust".to_string(), "db".to_string()]);
  315. taxo_page1.insert("categories".to_string(), vec!["Programming tutorials".to_string()]);
  316. page1.meta.taxonomies = taxo_page1;
  317. page1.lang = config.default_language.clone();
  318. library.insert_page(page1);
  319. let mut page2 = Page::default();
  320. let mut taxo_page2 = HashMap::new();
  321. taxo_page2.insert("tags".to_string(), vec!["rust".to_string(), "js".to_string()]);
  322. taxo_page2.insert("categories".to_string(), vec!["Other".to_string()]);
  323. page2.meta.taxonomies = taxo_page2;
  324. page2.lang = config.default_language.clone();
  325. library.insert_page(page2);
  326. let mut page3 = Page::default();
  327. let mut taxo_page3 = HashMap::new();
  328. taxo_page3.insert("tags".to_string(), vec!["js".to_string()]);
  329. taxo_page3.insert("authors".to_string(), vec!["Vincent Prouillet".to_string()]);
  330. page3.meta.taxonomies = taxo_page3;
  331. page3.lang = config.default_language.clone();
  332. library.insert_page(page3);
  333. let taxonomies = find_taxonomies(&config, &library).unwrap();
  334. let (tags, categories, authors) = {
  335. let mut t = None;
  336. let mut c = None;
  337. let mut a = None;
  338. for x in taxonomies {
  339. match x.kind.name.as_ref() {
  340. "tags" => t = Some(x),
  341. "categories" => c = Some(x),
  342. "authors" => a = Some(x),
  343. _ => unreachable!(),
  344. }
  345. }
  346. (t.unwrap(), c.unwrap(), a.unwrap())
  347. };
  348. assert_eq!(tags.items.len(), 3);
  349. assert_eq!(categories.items.len(), 2);
  350. assert_eq!(authors.items.len(), 1);
  351. assert_eq!(tags.items[0].name, "db");
  352. assert_eq!(tags.items[0].slug, "db");
  353. assert_eq!(tags.items[0].permalink, "http://a-website.com/tags/db/");
  354. assert_eq!(tags.items[0].pages.len(), 1);
  355. assert_eq!(tags.items[1].name, "js");
  356. assert_eq!(tags.items[1].slug, "js");
  357. assert_eq!(tags.items[1].permalink, "http://a-website.com/tags/js/");
  358. assert_eq!(tags.items[1].pages.len(), 2);
  359. assert_eq!(tags.items[2].name, "rust");
  360. assert_eq!(tags.items[2].slug, "rust");
  361. assert_eq!(tags.items[2].permalink, "http://a-website.com/tags/rust/");
  362. assert_eq!(tags.items[2].pages.len(), 2);
  363. assert_eq!(categories.items[0].name, "Other");
  364. assert_eq!(categories.items[0].slug, "other");
  365. assert_eq!(categories.items[0].permalink, "http://a-website.com/categories/other/");
  366. assert_eq!(categories.items[0].pages.len(), 1);
  367. assert_eq!(categories.items[1].name, "Programming tutorials");
  368. assert_eq!(categories.items[1].slug, "programming-tutorials");
  369. assert_eq!(
  370. categories.items[1].permalink,
  371. "http://a-website.com/categories/programming-tutorials/"
  372. );
  373. assert_eq!(categories.items[1].pages.len(), 1);
  374. }
  375. #[test]
  376. fn errors_on_unknown_taxonomy() {
  377. let mut config = Config::default();
  378. let mut library = Library::new(2, 0, false);
  379. config.taxonomies = vec![TaxonomyConfig {
  380. name: "authors".to_string(),
  381. lang: config.default_language.clone(),
  382. ..TaxonomyConfig::default()
  383. }];
  384. let mut page1 = Page::default();
  385. let mut taxo_page1 = HashMap::new();
  386. taxo_page1.insert("tags".to_string(), vec!["rust".to_string(), "db".to_string()]);
  387. page1.meta.taxonomies = taxo_page1;
  388. page1.lang = config.default_language.clone();
  389. library.insert_page(page1);
  390. let taxonomies = find_taxonomies(&config, &library);
  391. assert!(taxonomies.is_err());
  392. let err = taxonomies.unwrap_err();
  393. // no path as this is created by Default
  394. assert_eq!(
  395. format!("{}", err),
  396. "Page `` has taxonomy `tags` which is not defined in config.toml"
  397. );
  398. }
  399. #[test]
  400. fn can_make_taxonomies_in_multiple_languages() {
  401. let mut config = Config::default();
  402. config.languages.push(Language { rss: false, code: "fr".to_string(), search: false });
  403. let mut library = Library::new(2, 0, true);
  404. config.taxonomies = vec![
  405. TaxonomyConfig {
  406. name: "categories".to_string(),
  407. lang: config.default_language.clone(),
  408. ..TaxonomyConfig::default()
  409. },
  410. TaxonomyConfig {
  411. name: "tags".to_string(),
  412. lang: config.default_language.clone(),
  413. ..TaxonomyConfig::default()
  414. },
  415. TaxonomyConfig {
  416. name: "auteurs".to_string(),
  417. lang: "fr".to_string(),
  418. ..TaxonomyConfig::default()
  419. },
  420. TaxonomyConfig {
  421. name: "tags".to_string(),
  422. lang: "fr".to_string(),
  423. ..TaxonomyConfig::default()
  424. },
  425. ];
  426. let mut page1 = Page::default();
  427. let mut taxo_page1 = HashMap::new();
  428. taxo_page1.insert("tags".to_string(), vec!["rust".to_string(), "db".to_string()]);
  429. taxo_page1.insert("categories".to_string(), vec!["Programming tutorials".to_string()]);
  430. page1.meta.taxonomies = taxo_page1;
  431. page1.lang = config.default_language.clone();
  432. library.insert_page(page1);
  433. let mut page2 = Page::default();
  434. let mut taxo_page2 = HashMap::new();
  435. taxo_page2.insert("tags".to_string(), vec!["rust".to_string()]);
  436. taxo_page2.insert("categories".to_string(), vec!["Other".to_string()]);
  437. page2.meta.taxonomies = taxo_page2;
  438. page2.lang = config.default_language.clone();
  439. library.insert_page(page2);
  440. let mut page3 = Page::default();
  441. page3.lang = "fr".to_string();
  442. let mut taxo_page3 = HashMap::new();
  443. taxo_page3.insert("tags".to_string(), vec!["rust".to_string()]);
  444. taxo_page3.insert("auteurs".to_string(), vec!["Vincent Prouillet".to_string()]);
  445. page3.meta.taxonomies = taxo_page3;
  446. library.insert_page(page3);
  447. let taxonomies = find_taxonomies(&config, &library).unwrap();
  448. let (tags, categories, authors) = {
  449. let mut t = None;
  450. let mut c = None;
  451. let mut a = None;
  452. for x in taxonomies {
  453. match x.kind.name.as_ref() {
  454. "tags" => {
  455. if x.kind.lang == "en" {
  456. t = Some(x)
  457. }
  458. }
  459. "categories" => c = Some(x),
  460. "auteurs" => a = Some(x),
  461. _ => unreachable!(),
  462. }
  463. }
  464. (t.unwrap(), c.unwrap(), a.unwrap())
  465. };
  466. assert_eq!(tags.items.len(), 2);
  467. assert_eq!(categories.items.len(), 2);
  468. assert_eq!(authors.items.len(), 1);
  469. assert_eq!(tags.items[0].name, "db");
  470. assert_eq!(tags.items[0].slug, "db");
  471. assert_eq!(tags.items[0].permalink, "http://a-website.com/tags/db/");
  472. assert_eq!(tags.items[0].pages.len(), 1);
  473. assert_eq!(tags.items[1].name, "rust");
  474. assert_eq!(tags.items[1].slug, "rust");
  475. assert_eq!(tags.items[1].permalink, "http://a-website.com/tags/rust/");
  476. assert_eq!(tags.items[1].pages.len(), 2);
  477. assert_eq!(authors.items[0].name, "Vincent Prouillet");
  478. assert_eq!(authors.items[0].slug, "vincent-prouillet");
  479. assert_eq!(
  480. authors.items[0].permalink,
  481. "http://a-website.com/fr/auteurs/vincent-prouillet/"
  482. );
  483. assert_eq!(authors.items[0].pages.len(), 1);
  484. assert_eq!(categories.items[0].name, "Other");
  485. assert_eq!(categories.items[0].slug, "other");
  486. assert_eq!(categories.items[0].permalink, "http://a-website.com/categories/other/");
  487. assert_eq!(categories.items[0].pages.len(), 1);
  488. assert_eq!(categories.items[1].name, "Programming tutorials");
  489. assert_eq!(categories.items[1].slug, "programming-tutorials");
  490. assert_eq!(
  491. categories.items[1].permalink,
  492. "http://a-website.com/categories/programming-tutorials/"
  493. );
  494. assert_eq!(categories.items[1].pages.len(), 1);
  495. }
  496. #[test]
  497. fn can_make_utf8_taxonomies() {
  498. let mut config = Config::default();
  499. config.slugify.taxonomies = SlugifyStrategy::Safe;
  500. config.languages.push(Language {
  501. rss: false,
  502. code: "fr".to_string(),
  503. ..Language::default()
  504. });
  505. let mut library = Library::new(2, 0, true);
  506. config.taxonomies = vec![TaxonomyConfig {
  507. name: "catégories".to_string(),
  508. lang: "fr".to_string(),
  509. ..TaxonomyConfig::default()
  510. }];
  511. let mut page = Page::default();
  512. page.lang = "fr".to_string();
  513. let mut taxo_page = HashMap::new();
  514. taxo_page.insert("catégories".to_string(), vec!["Écologie".to_string()]);
  515. page.meta.taxonomies = taxo_page;
  516. library.insert_page(page);
  517. let taxonomies = find_taxonomies(&config, &library).unwrap();
  518. let categories = &taxonomies[0];
  519. assert_eq!(categories.items.len(), 1);
  520. assert_eq!(categories.items[0].name, "Écologie");
  521. assert_eq!(categories.items[0].permalink, "http://a-website.com/fr/catégories/Écologie/");
  522. assert_eq!(categories.items[0].pages.len(), 1);
  523. }
  524. #[test]
  525. fn can_make_slugified_taxonomies_in_multiple_languages() {
  526. let mut config = Config::default();
  527. config.slugify.taxonomies = SlugifyStrategy::On;
  528. config.languages.push(Language {
  529. rss: false,
  530. code: "fr".to_string(),
  531. ..Language::default()
  532. });
  533. let mut library = Library::new(2, 0, true);
  534. config.taxonomies = vec![
  535. TaxonomyConfig {
  536. name: "categories".to_string(),
  537. lang: config.default_language.clone(),
  538. ..TaxonomyConfig::default()
  539. },
  540. TaxonomyConfig {
  541. name: "tags".to_string(),
  542. lang: config.default_language.clone(),
  543. ..TaxonomyConfig::default()
  544. },
  545. TaxonomyConfig {
  546. name: "auteurs".to_string(),
  547. lang: "fr".to_string(),
  548. ..TaxonomyConfig::default()
  549. },
  550. TaxonomyConfig {
  551. name: "tags".to_string(),
  552. lang: "fr".to_string(),
  553. ..TaxonomyConfig::default()
  554. },
  555. ];
  556. let mut page1 = Page::default();
  557. let mut taxo_page1 = HashMap::new();
  558. taxo_page1.insert("tags".to_string(), vec!["rust".to_string(), "db".to_string()]);
  559. taxo_page1.insert("categories".to_string(), vec!["Programming tutorials".to_string()]);
  560. page1.meta.taxonomies = taxo_page1;
  561. page1.lang = config.default_language.clone();
  562. library.insert_page(page1);
  563. let mut page2 = Page::default();
  564. let mut taxo_page2 = HashMap::new();
  565. taxo_page2.insert("tags".to_string(), vec!["rust".to_string()]);
  566. taxo_page2.insert("categories".to_string(), vec!["Other".to_string()]);
  567. page2.meta.taxonomies = taxo_page2;
  568. page2.lang = config.default_language.clone();
  569. library.insert_page(page2);
  570. let mut page3 = Page::default();
  571. page3.lang = "fr".to_string();
  572. let mut taxo_page3 = HashMap::new();
  573. taxo_page3.insert("tags".to_string(), vec!["rust".to_string()]);
  574. taxo_page3.insert("auteurs".to_string(), vec!["Vincent Prouillet".to_string()]);
  575. page3.meta.taxonomies = taxo_page3;
  576. library.insert_page(page3);
  577. let taxonomies = find_taxonomies(&config, &library).unwrap();
  578. let (tags, categories, authors) = {
  579. let mut t = None;
  580. let mut c = None;
  581. let mut a = None;
  582. for x in taxonomies {
  583. match x.kind.name.as_ref() {
  584. "tags" => {
  585. if x.kind.lang == "en" {
  586. t = Some(x)
  587. }
  588. }
  589. "categories" => c = Some(x),
  590. "auteurs" => a = Some(x),
  591. _ => unreachable!(),
  592. }
  593. }
  594. (t.unwrap(), c.unwrap(), a.unwrap())
  595. };
  596. assert_eq!(tags.items.len(), 2);
  597. assert_eq!(categories.items.len(), 2);
  598. assert_eq!(authors.items.len(), 1);
  599. assert_eq!(tags.items[0].name, "db");
  600. assert_eq!(tags.items[0].slug, "db");
  601. assert_eq!(tags.items[0].permalink, "http://a-website.com/tags/db/");
  602. assert_eq!(tags.items[0].pages.len(), 1);
  603. assert_eq!(tags.items[1].name, "rust");
  604. assert_eq!(tags.items[1].slug, "rust");
  605. assert_eq!(tags.items[1].permalink, "http://a-website.com/tags/rust/");
  606. assert_eq!(tags.items[1].pages.len(), 2);
  607. assert_eq!(authors.items[0].name, "Vincent Prouillet");
  608. assert_eq!(authors.items[0].slug, "vincent-prouillet");
  609. assert_eq!(
  610. authors.items[0].permalink,
  611. "http://a-website.com/fr/auteurs/vincent-prouillet/"
  612. );
  613. assert_eq!(authors.items[0].pages.len(), 1);
  614. assert_eq!(categories.items[0].name, "Other");
  615. assert_eq!(categories.items[0].slug, "other");
  616. assert_eq!(categories.items[0].permalink, "http://a-website.com/categories/other/");
  617. assert_eq!(categories.items[0].pages.len(), 1);
  618. assert_eq!(categories.items[1].name, "Programming tutorials");
  619. assert_eq!(categories.items[1].slug, "programming-tutorials");
  620. assert_eq!(
  621. categories.items[1].permalink,
  622. "http://a-website.com/categories/programming-tutorials/"
  623. );
  624. assert_eq!(categories.items[1].pages.len(), 1);
  625. }
  626. }