cobalt/pagination/
tags.rs1use std::collections::HashMap;
2
3use crate::cobalt_model::pagination::PaginationConfig;
4use crate::cobalt_model::slug;
5use crate::document::Document;
6
7use super::{Result, ValueView, create_all_paginators, helpers, paginator, sort_posts};
8use helpers::extract_tags;
9use paginator::Paginator;
10
11#[allow(clippy::bind_instead_of_map)]
12pub(crate) fn create_tags_paginators(
13 all_posts: &[&liquid::model::Value],
14 doc: &Document,
15 pagination_cfg: &PaginationConfig,
16) -> Result<Vec<Paginator>> {
17 let mut per_tags = distribute_posts_by_tags(all_posts)?;
18
19 let mut tag_paginators: TagPaginators = per_tags
21 .iter_mut()
22 .try_fold(TagPaginators::default(), |mut acc, (tag, posts)| {
23 sort_posts(posts, pagination_cfg);
24 let cur_tag_paginators = create_all_paginators(
25 posts,
26 doc,
27 pagination_cfg,
28 Some(&liquid::model::Value::scalar(tag.to_owned())),
29 )?;
30 acc.firsts_of_tags.push(cur_tag_paginators[0].clone());
31 acc.paginators.extend(cur_tag_paginators.into_iter());
32 Ok(acc)
33 })
34 .or_else(std::result::Result::<_, anyhow::Error>::Err)?;
35
36 tag_paginators.firsts_of_tags.sort_unstable_by_key(|p| {
37 p.index_title
38 .as_ref()
39 .map(|index_title| slug::slugify(index_title.to_kstr()).to_lowercase())
40 });
41 let first = Paginator {
42 indexes: Some(tag_paginators.firsts_of_tags),
43 ..Default::default()
44 };
45 tag_paginators.paginators.insert(0, first);
46 Ok(tag_paginators.paginators)
47}
48
49fn distribute_posts_by_tags<'a>(
50 all_posts: &[&'a liquid::model::Value],
51) -> Result<HashMap<String, Vec<&'a liquid::model::Value>>> {
52 let mut per_tags: HashMap<String, Vec<&'a liquid::model::Value>> = HashMap::new();
53 for post in all_posts {
54 if let Some(tags) = extract_tags(post.as_view()) {
55 for tag in tags.values() {
56 let tag = tag
57 .as_scalar()
58 .ok_or_else(|| anyhow::format_err!("Should have string tags"))?
59 .to_kstr()
60 .into_string();
61 let cur_tag = per_tags.entry(tag).or_default();
62 cur_tag.push(post);
63 }
64 }
65 }
66 Ok(per_tags)
67}
68
69#[derive(Default, Debug)]
70struct TagPaginators {
71 firsts_of_tags: Vec<Paginator>,
72 paginators: Vec<Paginator>,
73}