bridgetown-paginate 0.11.0 → 0.11.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,198 +2,197 @@
2
2
 
3
3
  module Bridgetown
4
4
  module Paginate
5
- module Generator
6
- #
7
- # The main model for the pagination, handles the orchestration of the
8
- # pagination and calling all the necessary bits and bobs needed :)
9
- #
10
- class PaginationModel
11
- @debug = false # is debug output enabled?
12
- # The lambda to use for logging
13
- @logging_lambda = nil
14
- # The lambda used to create pages and add them to the site
15
- @page_add_lambda = nil
16
- # Lambda to remove a page from the site.pages collection
17
- @page_remove_lambda = nil
18
- # Lambda to get all documents/posts in a particular collection (by name)
19
- @collection_by_name_lambda = nil
20
-
21
- def initialize(
22
- logging_lambda,
23
- page_add_lambda,
24
- page_remove_lambda,
25
- collection_by_name_lambda
26
- )
27
- @logging_lambda = logging_lambda
28
- @page_add_lambda = page_add_lambda
29
- @page_remove_lambda = page_remove_lambda
30
- @collection_by_name_lambda = collection_by_name_lambda
5
+ #
6
+ # The main model for the pagination, handles the orchestration of the
7
+ # pagination and calling all the necessary bits and bobs needed :)
8
+ #
9
+ class PaginationModel
10
+ @debug = false # is debug output enabled?
11
+ # The lambda to use for logging
12
+ @logging_lambda = nil
13
+ # The lambda used to create pages and add them to the site
14
+ @page_add_lambda = nil
15
+ # Lambda to remove a page from the site.pages collection
16
+ @page_remove_lambda = nil
17
+ # Lambda to get all documents/posts in a particular collection (by name)
18
+ @collection_by_name_lambda = nil
19
+
20
+ def initialize(
21
+ logging_lambda,
22
+ page_add_lambda,
23
+ page_remove_lambda,
24
+ collection_by_name_lambda
25
+ )
26
+ @logging_lambda = logging_lambda
27
+ @page_add_lambda = page_add_lambda
28
+ @page_remove_lambda = page_remove_lambda
29
+ @collection_by_name_lambda = collection_by_name_lambda
30
+ end
31
+
32
+ # rubocop:disable Metrics/BlockLength
33
+ def run(default_config, templates, site_title)
34
+ if templates.size.to_i <= 0
35
+ @logging_lambda.call "is enabled in the config, but no paginated pages found." \
36
+ " Add 'pagination:\\n enabled: true' to the front-matter of a page.", "warn"
37
+ return
31
38
  end
32
39
 
33
- # rubocop:disable Metrics/BlockLength
34
- def run(default_config, site_pages, site_title)
35
- # By default if pagination is enabled we attempt to find all index.html
36
- # pages in the site
37
- templates = discover_paginate_templates(site_pages)
38
- if templates.size.to_i <= 0
39
- @logging_lambda.call "is enabled in the config, but no paginated pages found." \
40
- " Add 'pagination:\\n enabled: true' to the front-matter of a page.", "warn"
41
- return
42
- end
40
+ @docs_by_collection_cache = {}
43
41
 
44
- # Now for each template page generate the paginator for it
45
- templates.each do |template|
46
- # All pages that should be paginated need to include the pagination
47
- # config element
48
- if template.data["pagination"].is_a?(Hash)
49
- template_config = Bridgetown::Utils.deep_merge_hashes(
50
- default_config,
51
- template.data["pagination"] || {}
52
- )
42
+ # Now for each template page generate the paginator for it
43
+ templates.each do |template|
44
+ # All pages that should be paginated need to include the pagination
45
+ # config element
46
+ if template.data["pagination"].is_a?(Hash)
47
+ template_config = Bridgetown::Utils.deep_merge_hashes(
48
+ default_config,
49
+ template.data["pagination"] || {}
50
+ )
53
51
 
54
- # Is debugging enabled on the page level
55
- @debug = template_config["debug"]
56
-
57
- _debug_print_config_info(template_config, template.path)
58
-
59
- # Only paginate the template if it is explicitly enabled
60
- # requiring this makes the logic simpler as I don't need to
61
- # determine which index pages were generated automatically and
62
- # which weren't
63
- if template_config["enabled"]
64
- @logging_lambda.call "found page: " + template.path, "debug" unless @debug
65
-
66
- # Request all documents in all collections that the user has requested
67
- all_posts = get_docs_in_collections(template_config["collection"])
68
-
69
- # Create the necessary indexes for the posts
70
- all_categories = PaginationIndexer.index_documents_by(all_posts, "categories")
71
- all_tags = PaginationIndexer.index_documents_by(all_posts, "tags")
72
- all_locales = PaginationIndexer.index_documents_by(all_posts, "locale")
73
-
74
- # Load in custom query index, if specified
75
- all_where_matches = if template_config["where_query"]
76
- PaginationIndexer.index_documents_by(
77
- all_posts, template_config["where_query"]
78
- )
79
- end
80
-
81
- documents_payload = {
82
- posts: all_posts,
83
- tags: all_tags,
84
- categories: all_categories,
85
- locales: all_locales,
86
- where_matches: all_where_matches,
87
- }
88
-
89
- # TODO: NOTE!!! This whole request for posts and indexing results
90
- # could be cached to improve performance, leaving like this for
91
- # now during testing
92
-
93
- # Now construct the pagination data for this template page
94
- paginate(
95
- template,
96
- template_config,
97
- site_title,
98
- documents_payload
99
- )
100
- end
52
+ # Is debugging enabled on the page level
53
+ @debug = template_config["debug"]
54
+
55
+ _debug_print_config_info(template_config, template.path)
56
+
57
+ # Only paginate the template if it is explicitly enabled
58
+ # requiring this makes the logic simpler as I don't need to
59
+ # determine which index pages were generated automatically and
60
+ # which weren't
61
+ if template_config["enabled"]
62
+ @logging_lambda.call "found page: " + template.path, "debug" unless @debug
63
+
64
+ # Request all documents in all collections that the user has requested
65
+ all_posts = get_docs_in_collections(template_config["collection"])
66
+
67
+ # Create the necessary indexes for the posts
68
+ all_categories = if template_config["category"]
69
+ PaginationIndexer.index_documents_by(all_posts, "categories")
70
+ end
71
+ all_tags = if template_config["tag"]
72
+ PaginationIndexer.index_documents_by(all_posts, "tags")
73
+ end
74
+ all_locales = if template_config["locale"]
75
+ PaginationIndexer.index_documents_by(all_posts, "locale")
76
+ end
77
+
78
+ # Load in custom query index, if specified
79
+ all_where_matches = if template_config["where_query"]
80
+ PaginationIndexer.index_documents_by(
81
+ all_posts, template_config["where_query"]
82
+ )
83
+ end
84
+
85
+ documents_payload = {
86
+ posts: all_posts,
87
+ tags: all_tags,
88
+ categories: all_categories,
89
+ locales: all_locales,
90
+ where_matches: all_where_matches,
91
+ }
92
+
93
+ # TODO: NOTE!!! This whole request for posts and indexing results
94
+ # could be cached to improve performance, leaving like this for
95
+ # now during testing
96
+
97
+ # Now construct the pagination data for this template page
98
+ paginate(
99
+ template,
100
+ template_config,
101
+ site_title,
102
+ documents_payload
103
+ )
101
104
  end
102
105
  end
103
-
104
- # Return the total number of templates found
105
- templates.size.to_i
106
106
  end
107
- # rubocop:enable Metrics/BlockLength
108
107
 
109
- # Returns the combination of all documents in the collections that are
110
- # specified
111
- # raw_collection_names can either be a list of collections separated by a
112
- # ',' or ' ' or a single string
113
- def get_docs_in_collections(raw_collection_names)
114
- collection_names = if raw_collection_names.is_a?(String)
115
- raw_collection_names.split %r!/;|,|\s/!
116
- else
117
- raw_collection_names
118
- end
119
-
120
- docs = []
121
- # Now for each of the collections get the docs
122
- collection_names.each do |coll_name|
123
- # Request all the documents for the collection in question, and join
124
- # it with the total collection
125
- docs += @collection_by_name_lambda.call coll_name.downcase.strip
126
- end
108
+ # Return the total number of templates found
109
+ templates.size.to_i
110
+ end
111
+ # rubocop:enable Metrics/BlockLength
112
+
113
+ # Returns the combination of all documents in the collections that are
114
+ # specified
115
+ # raw_collection_names can either be a list of collections separated by a
116
+ # ',' or ' ' or a single string
117
+ def get_docs_in_collections(raw_collection_names)
118
+ if @docs_by_collection_cache[raw_collection_names]
119
+ return @docs_by_collection_cache[raw_collection_names]
120
+ end
127
121
 
128
- # Hidden documents should not not be processed anywhere.
129
- docs = docs.reject { |doc| doc["hidden"] }
122
+ collection_names = if raw_collection_names.is_a?(String)
123
+ raw_collection_names.split %r!/;|,|\s/!
124
+ else
125
+ raw_collection_names
126
+ end
130
127
 
131
- docs
128
+ docs = []
129
+ # Now for each of the collections get the docs
130
+ collection_names.each do |coll_name|
131
+ # Request all the documents for the collection in question, and join
132
+ # it with the total collection
133
+ docs += @collection_by_name_lambda.call coll_name.downcase.strip
132
134
  end
133
135
 
134
- # rubocop:disable Layout/LineLength
135
- def _debug_print_config_info(config, page_path)
136
- r = 20
137
- f = "Pagination: ".rjust(20)
138
- # Debug print the config
139
- if @debug
140
- puts f + "----------------------------"
141
- puts f + "Page: " + page_path.to_s
142
- puts f + " Active configuration"
143
- puts f + " Enabled: ".ljust(r) + config["enabled"].to_s
144
- puts f + " Items per page: ".ljust(r) + config["per_page"].to_s
145
- puts f + " Permalink: ".ljust(r) + config["permalink"].to_s
146
- puts f + " Title: ".ljust(r) + config["title"].to_s
147
- puts f + " Limit: ".ljust(r) + config["limit"].to_s
148
- puts f + " Sort by: ".ljust(r) + config["sort_field"].to_s
149
- puts f + " Sort reverse: ".ljust(r) + config["sort_reverse"].to_s
150
-
151
- puts f + " Active Filters"
152
- puts f + " Collection: ".ljust(r) + config["collection"].to_s
153
- puts f + " Offset: ".ljust(r) + config["offset"].to_s
154
- puts f + " Category: ".ljust(r) + (config["category"].nil? || config["category"] == "posts" ? "[Not set]" : config["category"].to_s)
155
- puts f + " Tag: ".ljust(r) + (config["tag"].nil? ? "[Not set]" : config["tag"].to_s)
156
- puts f + " Locale: ".ljust(r) + (config["locale"].nil? ? "[Not set]" : config["locale"].to_s)
157
- end
158
- end
159
- # rubocop:enable Layout/LineLength
136
+ # Hidden documents should not not be processed anywhere.
137
+ docs = docs.reject { |doc| doc["hidden"] }
160
138
 
161
- # rubocop:disable Layout/LineLength
162
- def _debug_print_filtering_info(filter_name, before_count, after_count)
163
- # Debug print the config
164
- if @debug
165
- puts "Pagination: ".rjust(20) + " Filtering by: " + filter_name.to_s.ljust(9) + " " + before_count.to_s.rjust(3) + " => " + after_count.to_s
166
- end
139
+ @docs_by_collection_cache[raw_collection_names] = docs
140
+
141
+ docs
142
+ end
143
+
144
+ # rubocop:disable Layout/LineLength
145
+ def _debug_print_config_info(config, page_path)
146
+ r = 20
147
+ f = "Pagination: ".rjust(20)
148
+ # Debug print the config
149
+ if @debug
150
+ puts f + "----------------------------"
151
+ puts f + "Page: " + page_path.to_s
152
+ puts f + " Active configuration"
153
+ puts f + " Enabled: ".ljust(r) + config["enabled"].to_s
154
+ puts f + " Items per page: ".ljust(r) + config["per_page"].to_s
155
+ puts f + " Permalink: ".ljust(r) + config["permalink"].to_s
156
+ puts f + " Title: ".ljust(r) + config["title"].to_s
157
+ puts f + " Limit: ".ljust(r) + config["limit"].to_s
158
+ puts f + " Sort by: ".ljust(r) + config["sort_field"].to_s
159
+ puts f + " Sort reverse: ".ljust(r) + config["sort_reverse"].to_s
160
+
161
+ puts f + " Active Filters"
162
+ puts f + " Collection: ".ljust(r) + config["collection"].to_s
163
+ puts f + " Offset: ".ljust(r) + config["offset"].to_s
164
+ puts f + " Category: ".ljust(r) + (config["category"].nil? || config["category"] == "posts" ? "[Not set]" : config["category"].to_s)
165
+ puts f + " Tag: ".ljust(r) + (config["tag"].nil? ? "[Not set]" : config["tag"].to_s)
166
+ puts f + " Locale: ".ljust(r) + (config["locale"].nil? ? "[Not set]" : config["locale"].to_s)
167
167
  end
168
- # rubocop:enable Layout/LineLength
169
-
170
- #
171
- # Rolls through all the pages passed in and finds all pages that have
172
- # pagination enabled on them.
173
- # These pages will be used as templates
174
- #
175
- # site_pages - All pages in the site
176
- #
177
- def discover_paginate_templates(site_pages)
178
- site_pages.select do |page|
179
- page.data["pagination"].is_a?(Hash) && page.data["pagination"]["enabled"]
180
- end
168
+ end
169
+ # rubocop:enable Layout/LineLength
170
+
171
+ # rubocop:disable Layout/LineLength
172
+ def _debug_print_filtering_info(filter_name, before_count, after_count)
173
+ # Debug print the config
174
+ if @debug
175
+ puts "Pagination: ".rjust(20) + " Filtering by: " + filter_name.to_s.ljust(9) + " " + before_count.to_s.rjust(3) + " => " + after_count.to_s
181
176
  end
177
+ end
178
+ # rubocop:enable Layout/LineLength
179
+
180
+ # Paginates the blog's posts. Renders the index.html file into paginated
181
+ # directories, e.g.: page2/index.html, page3/index.html, etc and adds more
182
+ # site-wide data.
183
+ #
184
+ # site - The Site.
185
+ # template - The index.html Page that requires pagination.
186
+ # config - The configuration settings that should be used
187
+ #
188
+ def paginate(template, config, site_title, documents_payload)
189
+ # By default paginate on all posts in the site
190
+ using_posts = documents_payload[:posts]
191
+
192
+ # Now start filtering out any posts that the user doesn't want included
193
+ # in the pagination
182
194
 
183
- # Paginates the blog's posts. Renders the index.html file into paginated
184
- # directories, e.g.: page2/index.html, page3/index.html, etc and adds more
185
- # site-wide data.
186
- #
187
- # site - The Site.
188
- # template - The index.html Page that requires pagination.
189
- # config - The configuration settings that should be used
190
- #
191
- def paginate(template, config, site_title, documents_payload)
192
- # By default paginate on all posts in the site
193
- using_posts = documents_payload[:posts]
194
-
195
- # Now start filtering out any posts that the user doesn't want included
196
- # in the pagination
195
+ if config["category"]
197
196
  before = using_posts.size.to_i
198
197
  using_posts = PaginationIndexer.read_config_value_and_filter_documents(
199
198
  config,
@@ -202,7 +201,9 @@ module Bridgetown
202
201
  documents_payload[:categories]
203
202
  )
204
203
  _debug_print_filtering_info("Category", before, using_posts.size.to_i)
204
+ end
205
205
 
206
+ if config["tag"]
206
207
  before = using_posts.size.to_i
207
208
  using_posts = PaginationIndexer.read_config_value_and_filter_documents(
208
209
  config,
@@ -211,7 +212,9 @@ module Bridgetown
211
212
  documents_payload[:tags]
212
213
  )
213
214
  _debug_print_filtering_info("Tag", before, using_posts.size.to_i)
215
+ end
214
216
 
217
+ if config["locale"]
215
218
  before = using_posts.size.to_i
216
219
  using_posts = PaginationIndexer.read_config_value_and_filter_documents(
217
220
  config,
@@ -220,219 +223,223 @@ module Bridgetown
220
223
  documents_payload[:locales]
221
224
  )
222
225
  _debug_print_filtering_info("Locale", before, using_posts.size.to_i)
226
+ end
223
227
 
224
- if config["where_query"]
225
- before = using_posts.size.to_i
226
- using_posts = PaginationIndexer.read_config_value_and_filter_documents(
227
- config,
228
- "where_query",
229
- using_posts,
230
- documents_payload[:where_matches]
231
- )
232
- _debug_print_filtering_info(
233
- "Where Query (#{config["where_query"]})",
234
- before,
235
- using_posts.size.to_i
236
- )
237
- end
228
+ if config["where_query"]
229
+ before = using_posts.size.to_i
230
+ using_posts = PaginationIndexer.read_config_value_and_filter_documents(
231
+ config,
232
+ "where_query",
233
+ using_posts,
234
+ documents_payload[:where_matches]
235
+ )
236
+ _debug_print_filtering_info(
237
+ "Where Query (#{config["where_query"]})",
238
+ before,
239
+ using_posts.size.to_i
240
+ )
241
+ end
238
242
 
239
- # Apply sorting to the posts if configured, any field for the post is
240
- # available for sorting
241
- if config["sort_field"]
242
- sort_field = config["sort_field"].to_s
243
-
244
- # There is an issue in Bridgetown related to lazy initialized member
245
- # variables that causes iterators to
246
- # break when accessing an uninitialized value during iteration. This
247
- # happens for document.rb when the <=> comparison function
248
- # is called (as this function calls the 'date' field which for drafts
249
- # are not initialized.)
250
- # So to unblock this common issue for the date field I simply iterate
251
- # once over every document and initialize the .date field explicitly
252
- if @debug
253
- puts "Pagination: ".rjust(20) + "Rolling through the date fields for all documents"
254
- end
255
- using_posts.each do |u_post|
256
- next unless u_post.respond_to?("date")
257
-
258
- tmp_date = u_post.date
259
- if !tmp_date || tmp_date.nil?
260
- if @debug
261
- puts "Pagination: ".rjust(20) +
262
- "Explicitly assigning date for doc: #{u_post.data["title"]} | #{u_post.path}"
263
- end
264
- u_post.date = File.mtime(u_post.path)
243
+ # Apply sorting to the posts if configured, any field for the post is
244
+ # available for sorting
245
+ if config["sort_field"]
246
+ sort_field = config["sort_field"].to_s
247
+
248
+ # There is an issue in Bridgetown related to lazy initialized member
249
+ # variables that causes iterators to
250
+ # break when accessing an uninitialized value during iteration. This
251
+ # happens for document.rb when the <=> comparison function
252
+ # is called (as this function calls the 'date' field which for drafts
253
+ # are not initialized.)
254
+ # So to unblock this common issue for the date field I simply iterate
255
+ # once over every document and initialize the .date field explicitly
256
+ if @debug
257
+ puts "Pagination: ".rjust(20) + "Rolling through the date fields for all documents"
258
+ end
259
+ using_posts.each do |u_post|
260
+ next unless u_post.respond_to?("date")
261
+
262
+ tmp_date = u_post.date
263
+ if !tmp_date || tmp_date.nil?
264
+ if @debug
265
+ puts "Pagination: ".rjust(20) +
266
+ "Explicitly assigning date for doc: #{u_post.data["title"]} | #{u_post.path}"
265
267
  end
268
+ u_post.date = File.mtime(u_post.path)
266
269
  end
270
+ end
267
271
 
268
- using_posts.sort! do |a, b|
269
- Utils.sort_values(
270
- Utils.sort_get_post_data(a.data, sort_field),
271
- Utils.sort_get_post_data(b.data, sort_field)
272
- )
273
- end
272
+ using_posts.sort! do |a, b|
273
+ Utils.sort_values(
274
+ Utils.sort_get_post_data(a.data, sort_field),
275
+ Utils.sort_get_post_data(b.data, sort_field)
276
+ )
277
+ end
274
278
 
275
- # Remove the first x entries
276
- offset_post_count = [0, config["offset"].to_i].max
277
- using_posts.pop(offset_post_count)
279
+ # Remove the first x entries
280
+ offset_post_count = [0, config["offset"].to_i].max
281
+ using_posts.pop(offset_post_count)
278
282
 
279
- using_posts.reverse! if config["sort_reverse"]
280
- end
283
+ using_posts.reverse! if config["sort_reverse"]
284
+ end
281
285
 
282
- # Calculate the max number of pagination-pages based on the configured per page value
283
- total_pages = Utils.calculate_number_of_pages(using_posts, config["per_page"])
286
+ # Calculate the max number of pagination-pages based on the configured per page value
287
+ total_pages = Utils.calculate_number_of_pages(using_posts, config["per_page"])
284
288
 
285
- # If a upper limit is set on the number of total pagination pages then impose that now
286
- if config["limit"].to_i.positive? && config["limit"].to_i < total_pages
287
- total_pages = config["limit"].to_i
288
- end
289
+ # If a upper limit is set on the number of total pagination pages then impose that now
290
+ if config["limit"].to_i.positive? && config["limit"].to_i < total_pages
291
+ total_pages = config["limit"].to_i
292
+ end
289
293
 
290
- #### BEFORE STARTING REMOVE THE TEMPLATE PAGE FROM THE SITE LIST!
291
- @page_remove_lambda.call template
294
+ #### BEFORE STARTING REMOVE THE TEMPLATE PAGE FROM THE SITE LIST!
295
+ @page_remove_lambda.call template
292
296
 
293
- # list of all newly created pages
294
- newpages = []
297
+ # list of all newly created pages
298
+ newpages = []
295
299
 
296
- # Consider the index page name and extension
297
- # By default, they will be nil and the Page object will infer
298
- # it from the template used
299
- index_page_name = config["indexpage"].split(".")[0] unless config["indexpage"].nil?
300
- index_page_ext = unless index_page_name.nil? || config["extension"].nil?
301
- Utils.ensure_leading_dot(config["extension"])
302
- end
303
- index_page_with_ext = index_page_name + index_page_ext if index_page_name
304
-
305
- # In case there are no (visible) posts, generate the index file anyway
306
- total_pages = 1 if total_pages.zero?
307
-
308
- # Now for each pagination page create it and configure the ranges for
309
- # the collection
310
- # The .pager member is a built in thing in Bridgetown and references the
311
- # paginator implementation
312
- # rubocop:disable Metrics/BlockLength
313
- (1..total_pages).each do |cur_page_nr|
314
- # 1. Create the in-memory page
315
- # External Proc call to create the actual page for us (this is
316
- # passed in when the pagination is run)
317
- newpage = PaginationPage.new(
318
- template,
319
- cur_page_nr,
320
- total_pages,
321
- index_page_with_ext,
322
- template.ext
323
- )
300
+ # Consider the index page name and extension
301
+ # By default, they will be nil and the Page object will infer
302
+ # it from the template used
303
+ index_page_name = config["indexpage"].split(".")[0] unless config["indexpage"].nil?
304
+ index_page_ext = unless index_page_name.nil? || config["extension"].nil?
305
+ Utils.ensure_leading_dot(config["extension"])
306
+ end
307
+ index_page_with_ext = index_page_name + index_page_ext if index_page_name
308
+
309
+ # In case there are no (visible) posts, generate the index file anyway
310
+ total_pages = 1 if total_pages.zero?
311
+
312
+ # Now for each pagination page create it and configure the ranges for
313
+ # the collection
314
+ # The .pager member is a built in thing in Bridgetown and references the
315
+ # paginator implementation
316
+ # rubocop:disable Metrics/BlockLength
317
+ (1..total_pages).each do |cur_page_nr|
318
+ # 1. Create the in-memory page
319
+ # External Proc call to create the actual page for us (this is
320
+ # passed in when the pagination is run)
321
+ newpage = PaginationPage.new(
322
+ template,
323
+ cur_page_nr,
324
+ total_pages,
325
+ index_page_with_ext,
326
+ template.ext
327
+ )
328
+
329
+ # 2. Create the url for the in-memory page (calc permalink etc),
330
+ # construct the title, set all page.data values needed
331
+ paginated_page_url = config["permalink"]
332
+ first_index_page_url = if template.data["permalink"]
333
+ Utils.ensure_trailing_slash(
334
+ template.data["permalink"]
335
+ )
336
+ else
337
+ Utils.ensure_trailing_slash(template.dir)
338
+ end
339
+ paginated_page_url = File.join(first_index_page_url, paginated_page_url)
340
+
341
+ # 3. Create the pager logic for this page, pass in the prev and next
342
+ # page numbers, assign pager to in-memory page
343
+ newpage.pager = Paginator.new(
344
+ config["per_page"],
345
+ first_index_page_url,
346
+ paginated_page_url,
347
+ using_posts,
348
+ cur_page_nr,
349
+ total_pages,
350
+ index_page_name,
351
+ index_page_ext
352
+ )
353
+
354
+ # Create the url for the new page, make sure we prepend any permalinks
355
+ # that are defined in the template page before
356
+ if newpage.pager.page_path.end_with? "/"
357
+ newpage.set_url(File.join(newpage.pager.page_path, index_page_with_ext))
358
+ elsif newpage.pager.page_path.end_with? index_page_ext.to_s
359
+ # Support for direct .html files
360
+ newpage.set_url(newpage.pager.page_path)
361
+ else
362
+ # Support for extensionless permalinks
363
+ newpage.set_url(newpage.pager.page_path + index_page_ext.to_s)
364
+ end
324
365
 
325
- # 2. Create the url for the in-memory page (calc permalink etc),
326
- # construct the title, set all page.data values needed
327
- paginated_page_url = config["permalink"]
328
- first_index_page_url = if template.data["permalink"]
329
- Utils.ensure_trailing_slash(
330
- template.data["permalink"]
331
- )
332
- else
333
- Utils.ensure_trailing_slash(template.dir)
334
- end
335
- paginated_page_url = File.join(first_index_page_url, paginated_page_url)
336
-
337
- # 3. Create the pager logic for this page, pass in the prev and next
338
- # page numbers, assign pager to in-memory page
339
- newpage.pager = Paginator.new(
340
- config["per_page"],
341
- first_index_page_url,
342
- paginated_page_url,
343
- using_posts,
366
+ newpage.data["permalink"] = newpage.pager.page_path if template.data["permalink"]
367
+
368
+ # Transfer the title across to the new page
369
+ tmp_title = if !template.data["title"]
370
+ site_title
371
+ else
372
+ template.data["title"]
373
+ end
374
+
375
+ # If the user specified a title suffix to be added then let's add that
376
+ # to all the pages except the first
377
+ if cur_page_nr > 1 && config.key?("title")
378
+ newtitle = Utils.format_page_title(
379
+ config["title"],
380
+ tmp_title,
344
381
  cur_page_nr,
345
- total_pages,
346
- index_page_name,
347
- index_page_ext
382
+ total_pages
348
383
  )
384
+ newpage.data["title"] = newtitle.to_s
385
+ else
386
+ newpage.data["title"] = tmp_title
387
+ end
349
388
 
350
- # Create the url for the new page, make sure we prepend any permalinks
351
- # that are defined in the template page before
352
- if newpage.pager.page_path.end_with? "/"
353
- newpage.set_url(File.join(newpage.pager.page_path, index_page_with_ext))
354
- elsif newpage.pager.page_path.end_with? index_page_ext.to_s
355
- # Support for direct .html files
356
- newpage.set_url(newpage.pager.page_path)
357
- else
358
- # Support for extensionless permalinks
359
- newpage.set_url(newpage.pager.page_path + index_page_ext.to_s)
360
- end
389
+ # Signals that this page is automatically generated by the pagination logic
390
+ # (we don't do this for the first page as it is there to mask the one we removed)
391
+ newpage.data["autogen"] = "bridgetown-paginate" if cur_page_nr > 1
361
392
 
362
- newpage.data["permalink"] = newpage.pager.page_path if template.data["permalink"]
363
-
364
- # Transfer the title across to the new page
365
- tmp_title = if !template.data["title"]
366
- site_title
367
- else
368
- template.data["title"]
369
- end
370
-
371
- # If the user specified a title suffix to be added then let's add that
372
- # to all the pages except the first
373
- if cur_page_nr > 1 && config.key?("title")
374
- newtitle = Utils.format_page_title(
375
- config["title"],
376
- tmp_title,
377
- cur_page_nr,
378
- total_pages
379
- )
380
- newpage.data["title"] = newtitle.to_s
381
- else
382
- newpage.data["title"] = tmp_title
383
- end
393
+ # If there's only one post (like on a per_page: 1 scenario), let's be
394
+ # helpful and supply a document variable
395
+ newpage.data["document"] = using_posts.first if using_posts.size == 1
396
+
397
+ # Add the page to the site
398
+ @page_add_lambda.call newpage
384
399
 
385
- # Signals that this page is automatically generated by the pagination logic
386
- # (we don't do this for the first page as it is there to mask the one we removed)
387
- newpage.data["autogen"] = "bridgetown-paginate" if cur_page_nr > 1
400
+ # Store the page in an internal list for later referencing if we need
401
+ # to generate a pagination number path later on
402
+ newpages << newpage
403
+ end
404
+ # rubocop:enable Metrics/BlockLength
388
405
 
389
- # Add the page to the site
390
- @page_add_lambda.call newpage
406
+ # Now generate the pagination number path, e.g. so that the users can
407
+ # have a prev 1 2 3 4 5 next structure on their page
408
+ # simplest is to include all of the links to the pages preceeding the
409
+ # current one (e.g for page 1 you get the list 2, 3, 4.... and for
410
+ # page 2 you get the list 3,4,5...)
411
+ if config["trail"] && !config["trail"].nil? && newpages.size.to_i.positive?
412
+ trail_before = [config["trail"]["before"].to_i, 0].max
413
+ trail_after = [config["trail"]["after"].to_i, 0].max
414
+ trail_length = trail_before + trail_after + 1
415
+
416
+ if trail_before.positive? || trail_after.positive?
417
+ newpages.select do |npage|
418
+ # Selecting the beginning of the trail
419
+ idx_start = [npage.pager.page - trail_before - 1, 0].max
420
+ # Selecting the end of the trail
421
+ idx_end = [idx_start + trail_length, newpages.size.to_i].min
422
+
423
+ # Always attempt to maintain the max total of <trail_length> pages
424
+ # in the trail (it will look better if the trail doesn't shrink)
425
+ if idx_end - idx_start < trail_length
426
+ # Attempt to pad the beginning if we have enough pages
427
+ # Never go beyond the zero index
428
+ idx_start = [
429
+ idx_start - (trail_length - (idx_end - idx_start)),
430
+ 0,
431
+ ].max
432
+ end
391
433
 
392
- # Store the page in an internal list for later referencing if we need
393
- # to generate a pagination number path later on
394
- newpages << newpage
395
- end
396
- # rubocop:enable Metrics/BlockLength
397
-
398
- # Now generate the pagination number path, e.g. so that the users can
399
- # have a prev 1 2 3 4 5 next structure on their page
400
- # simplest is to include all of the links to the pages preceeding the
401
- # current one (e.g for page 1 you get the list 2, 3, 4.... and for
402
- # page 2 you get the list 3,4,5...)
403
- if config["trail"] && !config["trail"].nil? && newpages.size.to_i.positive?
404
- trail_before = [config["trail"]["before"].to_i, 0].max
405
- trail_after = [config["trail"]["after"].to_i, 0].max
406
- trail_length = trail_before + trail_after + 1
407
-
408
- if trail_before.positive? || trail_after.positive?
409
- newpages.select do |npage|
410
- # Selecting the beginning of the trail
411
- idx_start = [npage.pager.page - trail_before - 1, 0].max
412
- # Selecting the end of the trail
413
- idx_end = [idx_start + trail_length, newpages.size.to_i].min
414
-
415
- # Always attempt to maintain the max total of <trail_length> pages
416
- # in the trail (it will look better if the trail doesn't shrink)
417
- if idx_end - idx_start < trail_length
418
- # Attempt to pad the beginning if we have enough pages
419
- # Never go beyond the zero index
420
- idx_start = [
421
- idx_start - (trail_length - (idx_end - idx_start)),
422
- 0,
423
- ].max
424
- end
425
-
426
- # Convert the newpages array into a two dimensional array that has
427
- # [index, page_url] as items
428
- npage.pager.page_trail = newpages[idx_start...idx_end] \
429
- .each_with_index.map do |ipage, idx|
430
- PageTrail.new(
431
- idx_start + idx + 1,
432
- ipage.pager.page_path,
433
- ipage.data["title"]
434
- )
435
- end
434
+ # Convert the newpages array into a two dimensional array that has
435
+ # [index, page_url] as items
436
+ npage.pager.page_trail = newpages[idx_start...idx_end] \
437
+ .each_with_index.map do |ipage, idx|
438
+ PageTrail.new(
439
+ idx_start + idx + 1,
440
+ ipage.pager.page_path,
441
+ ipage.data["title"]
442
+ )
436
443
  end
437
444
  end
438
445
  end