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.

715 lines
26KB

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