cobalt/pagination/
paginator.rs

1use crate::document::Document;
2
3use super::{PaginationConfig, Result, interpret_permalink};
4
5#[derive(Default, Clone, Debug)]
6pub(crate) struct Paginator {
7    pub(crate) pages: Option<Vec<liquid::model::Value>>,
8    pub(crate) indexes: Option<Vec<Paginator>>,
9    pub(crate) index: usize,
10    pub(crate) index_title: Option<liquid::model::Value>,
11    pub(crate) index_permalink: String,
12    pub(crate) previous_index: usize,
13    pub(crate) previous_index_permalink: Option<String>,
14    pub(crate) next_index: usize,
15    pub(crate) next_index_permalink: Option<String>,
16    pub(crate) first_index_permalink: String,
17    pub(crate) last_index_permalink: String,
18    pub(crate) total_indexes: usize,
19    pub(crate) total_pages: usize,
20}
21
22impl Paginator {
23    pub(crate) fn new(total_indexes: usize, total_pages: usize) -> Paginator {
24        Paginator {
25            pages: None,   // pages in current index
26            indexes: None, // list of the available indexes, use when include is tags for instance
27            index: 0,
28            index_permalink: String::new(),
29            index_title: None,
30            previous_index: 0,
31            previous_index_permalink: None,
32            next_index: 0,
33            next_index_permalink: None,
34            first_index_permalink: String::new(),
35            last_index_permalink: String::new(),
36            total_indexes,
37            total_pages,
38        }
39    }
40
41    pub(crate) fn set_first_last(
42        &mut self,
43        doc: &Document,
44        config: &PaginationConfig,
45        total_pages: usize,
46        index_title: Option<&liquid::model::Value>,
47    ) -> Result<()> {
48        self.first_index_permalink = doc.url_path.to_string();
49        self.last_index_permalink = interpret_permalink(config, doc, total_pages, index_title)?;
50        Ok(())
51    }
52
53    pub(crate) fn set_current_index_info(
54        &mut self,
55        index: usize,
56        all_pages: &[&liquid::model::Value],
57        config: &PaginationConfig,
58        doc: &Document,
59        index_title: Option<&liquid::model::Value>,
60    ) -> Result<()> {
61        self.index = index;
62        self.pages = Some(all_pages.iter().map(|p| (*p).clone()).collect());
63        self.index_title = index_title.cloned();
64        self.index_permalink = interpret_permalink(config, doc, index, index_title)?;
65        Ok(())
66    }
67
68    pub(crate) fn set_previous_next_info(
69        &mut self,
70        index: usize,
71        total_indexes: usize,
72        doc: &Document,
73        config: &PaginationConfig,
74        index_title: Option<&liquid::model::Value>,
75    ) -> Result<()> {
76        if index > 1 {
77            // we have a previous index
78            self.previous_index_permalink =
79                Some(interpret_permalink(config, doc, index - 1, index_title)?);
80            self.previous_index = index - 1;
81        }
82
83        if index < total_indexes {
84            // we have a next index
85            self.next_index = index + 1;
86            self.next_index_permalink =
87                Some(interpret_permalink(config, doc, index + 1, index_title)?);
88        }
89        Ok(())
90    }
91}
92
93pub(crate) fn create_paginator(
94    i: usize,
95    total_indexes: usize,
96    total_pages: usize,
97    config: &PaginationConfig,
98    doc: &Document,
99    all_posts: &[&liquid::model::Value],
100    index_title: Option<&liquid::model::Value>,
101) -> Result<Paginator> {
102    let index = i + 1;
103    let mut paginator = Paginator::new(total_indexes, total_pages);
104
105    paginator.set_first_last(doc, config, total_indexes, index_title)?;
106    paginator.set_current_index_info(index, all_posts, config, doc, index_title)?;
107    paginator.set_previous_next_info(index, total_indexes, doc, config, index_title)?;
108
109    Ok(paginator)
110}
111
112#[allow(clippy::from_over_into)]
113impl Into<liquid::Object> for Paginator {
114    fn into(self) -> liquid::Object {
115        let mut object = liquid::Object::new();
116        // if no pages, means we have indexes instead, `tags` like cases for example
117        if let Some(pages) = self.pages {
118            object.insert("pages".into(), liquid::model::Value::Array(pages));
119        }
120        // list of available indexes, in `tags` like cases
121        if let Some(indexes) = self.indexes {
122            object.insert(
123                "indexes".into(),
124                liquid::model::Value::Array(
125                    indexes
126                        .into_iter()
127                        .map(|paginator| {
128                            let v: liquid::Object = paginator.into();
129                            liquid::model::Value::Object(v)
130                        })
131                        .collect(),
132                ),
133            );
134        }
135        object.insert(
136            "index".into(),
137            liquid::model::Value::scalar(self.index as i32),
138        );
139        object.insert(
140            "index_permalink".into(),
141            liquid::model::Value::scalar(self.index_permalink),
142        );
143        if let Some(index_title) = self.index_title {
144            object.insert("index_title".into(), index_title);
145        }
146        if let Some(previous_index_permalink) = self.previous_index_permalink {
147            object.insert(
148                "previous_index".into(),
149                liquid::model::Value::scalar(self.previous_index as i32),
150            );
151            object.insert(
152                "previous_index_permalink".into(),
153                liquid::model::Value::scalar(previous_index_permalink),
154            );
155        }
156        if let Some(next_index_permalink) = self.next_index_permalink {
157            object.insert(
158                "next_index".into(),
159                liquid::model::Value::scalar(self.next_index as i32),
160            );
161            object.insert(
162                "next_index_permalink".into(),
163                liquid::model::Value::scalar(next_index_permalink),
164            );
165        }
166        object.insert(
167            "first_index_permalink".into(),
168            liquid::model::Value::scalar(self.first_index_permalink),
169        );
170        object.insert(
171            "last_index_permalink".into(),
172            liquid::model::Value::scalar(self.last_index_permalink),
173        );
174        object.insert(
175            "total_indexes".into(),
176            liquid::model::Value::scalar(self.total_indexes as i32),
177        );
178        object.insert(
179            "total_pages".into(),
180            liquid::model::Value::scalar(self.total_pages as i32),
181        );
182        object
183    }
184}