@@ -7,7 +7,7 @@ use url::Url;
77
88use crate :: site:: { ServusMetadata , Site } ;
99
10- #[ derive( Clone , Copy , PartialEq , Serialize ) ]
10+ #[ derive( Clone , Copy , Debug , PartialEq , Serialize ) ]
1111pub enum ResourceKind {
1212 Post ,
1313 Page ,
@@ -99,7 +99,9 @@ impl Renderable for Page {
9999
100100 Ok ( Self {
101101 title,
102- permalink : site. config . make_permalink ( & site. domain , & resource_url) ,
102+ permalink : site
103+ . config
104+ . make_permalink ( & site. domain , & resource_url, None ) ,
103105 url : resource_url. clone ( ) ,
104106 slug : resource. slug . to_owned ( ) ,
105107 path : Some ( resource_url) ,
@@ -187,6 +189,7 @@ pub struct Section<T> {
187189 pages : Vec < Page > ,
188190 content : String ,
189191 description : Option < String > ,
192+ paginator : Paginator ,
190193 _phantom : PhantomData < T > ,
191194}
192195
@@ -198,27 +201,77 @@ where
198201 let Some ( resource_url) = resource. get_resource_url ( ) else {
199202 bail ! ( "Cannot render a resource without URL" ) ;
200203 } ;
204+
205+ let current_index = resource. page_number . unwrap_or ( 1 ) ;
206+ let paginate_by = site
207+ . config
208+ . sections
209+ . iter ( )
210+ . find ( |s| s. name == resource. slug )
211+ . map_or ( 0 , |s| s. paginate_by . unwrap_or ( 0 ) ) ;
212+
201213 let Ok ( resources) = site. resources . read ( ) else {
202214 bail ! ( "Cannot access resources" ) ;
203215 } ;
204- let mut resources_list = resources. values ( ) . collect :: < Vec < & Resource > > ( ) ;
205- resources_list. sort_by ( |a, b| b. date . cmp ( & a. date ) ) ;
206- let pages_list = resources_list
216+ let mut resources = resources. values ( ) . collect :: < Vec < & Resource > > ( ) ;
217+ resources. sort_by ( |a, b| b. date . cmp ( & a. date ) ) ;
218+
219+ let mut all_pages = Vec :: new ( ) ;
220+ let mut current_pager_pages = Vec :: new ( ) ;
221+ let pager_start = ( current_index - 1 ) * paginate_by;
222+ let pager_end = pager_start + paginate_by;
223+ for ( i, page) in resources
207224 . into_iter ( )
208225 . filter ( |r| T :: filter ( r. kind ) )
209226 . map ( |r| Page :: from_resource ( r, site) )
210227 . filter_map ( Result :: ok)
211- . collect :: < Vec < Page > > ( ) ;
228+ . enumerate ( )
229+ {
230+ if i >= pager_start && i < pager_end || paginate_by == 0 {
231+ current_pager_pages. push ( page. clone ( ) ) ;
232+ }
233+ all_pages. push ( page) ;
234+ }
235+
236+ let number_pagers = match paginate_by {
237+ 0 => 0 ,
238+ _ => all_pages. len ( ) . div_ceil ( paginate_by) ,
239+ } ;
212240
213241 Ok ( Self {
214242 title : None ,
215- permalink : site. config . make_permalink ( & site. domain , & resource_url) ,
243+ permalink : site
244+ . config
245+ . make_permalink ( & site. domain , & resource_url, Some ( current_index) ) ,
216246 url : resource_url,
217247 slug : resource. slug . to_owned ( ) ,
218248 path : None , // TODO
219249 description : None , // TODO
220250 content : String :: new ( ) ,
221- pages : pages_list,
251+ pages : all_pages,
252+ paginator : Paginator {
253+ current_index,
254+ number_pagers,
255+ previous : if current_index > 1 {
256+ Some ( site. config . make_permalink (
257+ & site. domain ,
258+ & resource. slug ,
259+ Some ( current_index - 1 ) ,
260+ ) )
261+ } else {
262+ None
263+ } ,
264+ next : if current_index < number_pagers {
265+ Some ( site. config . make_permalink (
266+ & site. domain ,
267+ & resource. slug ,
268+ Some ( current_index + 1 ) ,
269+ ) )
270+ } else {
271+ None
272+ } ,
273+ pages : current_pager_pages,
274+ } ,
222275 _phantom : PhantomData ,
223276 } )
224277 }
@@ -238,19 +291,8 @@ where
238291
239292 extra_context. insert ( "config" , & site. config ) ;
240293
241- // NB: some themes expect to iterate over section.pages, others look for paginator.pages.
242- // We are currently passing both in all cases, so all themes will find the pages.
243294 extra_context. insert ( "section" , & self ) ;
244-
245- // TODO: paginator.pages should be paginated, but it is not.
246- extra_context. insert (
247- "paginator" ,
248- & Paginator {
249- current_index : 1 ,
250- number_pagers : 1 ,
251- pages : self . pages . clone ( ) ,
252- } ,
253- ) ;
295+ extra_context. insert ( "paginator" , & self . paginator ) ;
254296
255297 // https://www.getzola.org/documentation/templates/pages-sections/
256298 let template = match self . slug . as_str ( ) {
@@ -273,15 +315,18 @@ where
273315struct Paginator {
274316 current_index : usize ,
275317 number_pagers : usize ,
318+ previous : Option < String > ,
319+ next : Option < String > ,
276320 pages : Vec < Page > ,
277321}
278322
279- #[ derive( Clone , Serialize ) ]
323+ #[ derive( Clone , Debug , Serialize ) ]
280324pub struct Resource {
281325 pub kind : ResourceKind ,
282326 pub slug : String ,
283327 pub date : NaiveDateTime , // this is nice to have here for sorting
284328 pub event_id : Option < String > ,
329+ pub page_number : Option < usize > ,
285330}
286331
287332impl Resource {
0 commit comments