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, all, 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 config: &PaginationConfig,
16) -> Result<Vec<Paginator>> {
17 let mut per_tags = distribute_posts_by_tags(all_posts)?;
18 walk_tags(&mut per_tags, config, doc)
19}
20
21fn distribute_posts_by_tags<'a>(
22 all_posts: &[&'a liquid::model::Value],
23) -> Result<HashMap<String, Vec<&'a liquid::model::Value>>> {
24 let mut per_tags: HashMap<String, Vec<&'a liquid::model::Value>> = HashMap::new();
25 for post in all_posts {
26 if let Some(tags) = extract_tags(post.as_view()) {
27 for tag in tags.values() {
28 let tag = tag
29 .as_scalar()
30 .ok_or_else(|| anyhow::format_err!("Should have string tags"))?
31 .to_kstr()
32 .into_string();
33 let cur_tag = per_tags.entry(tag).or_default();
34 cur_tag.push(post);
35 }
36 }
37 }
38 Ok(per_tags)
39}
40
41#[derive(Default, Debug)]
42struct TagPaginators {
43 firsts_of_tags: Vec<Paginator>,
44 paginators: Vec<Paginator>,
45}
46
47fn walk_tags(
48 per_tags: &mut HashMap<String, Vec<&liquid::model::Value>>,
49 config: &PaginationConfig,
50 doc: &Document,
51) -> Result<Vec<Paginator>> {
52 let mut tag_paginators = TagPaginators::default();
54 for (tag, posts) in per_tags.iter_mut() {
55 sort_posts(posts, config);
56 let cur_tag_paginators = all::create_all_paginators(
57 posts,
58 doc,
59 config,
60 Some(&liquid::model::Value::scalar(tag.to_owned())),
61 )?;
62 tag_paginators
63 .firsts_of_tags
64 .push(cur_tag_paginators[0].clone());
65 tag_paginators
66 .paginators
67 .extend(cur_tag_paginators.into_iter());
68 }
69
70 tag_paginators.firsts_of_tags.sort_unstable_by_key(|p| {
71 p.index_title
72 .as_ref()
73 .map(|index_title| slug::slugify(index_title.to_kstr()).to_lowercase())
74 });
75 let first = Paginator {
76 indexes: Some(tag_paginators.firsts_of_tags),
77 ..Default::default()
78 };
79 tag_paginators.paginators.insert(0, first);
80 Ok(tag_paginators.paginators)
81}