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, indexes: None, 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 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 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 let Some(pages) = self.pages {
118 object.insert("pages".into(), liquid::model::Value::Array(pages));
119 }
120 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}