jekyll-paginate-v2 1.7.3 → 1.7.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 16960246c340b15c1c92a75fff4edab91d9a87ce
4
- data.tar.gz: 19a9d469619d6411c76e223f1e133368c6ad25b0
3
+ metadata.gz: 4855434b556a103b8dc3c52c7b1ae326e6095b1c
4
+ data.tar.gz: e4294bf86b65b62ec44749ee5f8dba02f1b620e2
5
5
  SHA512:
6
- metadata.gz: 35b366f65415ad461745f24a004ab16da5048c52a8288659b996720b1e2853212ce6e189f0e8151086c39853ebf9488284f7f12e4125909a7213fddcded6f28a
7
- data.tar.gz: e72a69dcbc1b19d8bf61ad9d34d68127485f9c19690b2ce14251b3faa82c89f027575c8e233142fcd95cc2e5f5c6849afbdb876c7564ceb22ff746fb4a63088e
6
+ metadata.gz: ef1b03b89575d5ce47ca62c2095f09ab5f96165940102b550e4989316a781ad7d453379ba4a27b8e2309b885aeed5f21fc0fa409975cd7d611705bc8478489e5
7
+ data.tar.gz: d860729ffa770477ca05767e537c68949b6fb0f57f724c2d0e1b9c70ecc7a853407a56fa2a2ac77439d281d874928a55a9568754b54ca49bdc8c60cf76e9d0a4
@@ -57,7 +57,9 @@ pagination:
57
57
  per_page: 10
58
58
 
59
59
  # The permalink structure for the paginated pages (this can be any level deep)
60
- permalink: '/page/:num/'
60
+ permalink: '/page/:num/' # Pages are index.html inside this folder (default)
61
+ #permalink: '/page/:num.html' # Pages are simple html files
62
+ #permalink: '/page/:num' # Pages are html files, linked jekyll extensionless permalink style.
61
63
 
62
64
  # Optional the title format for the paginated pages (supports :title for original page title, :num for pagination page number, :max for total number of pages)
63
65
  title: ':title - page :num'
@@ -446,6 +448,7 @@ The `title` field in both the site.config and the front-matter configuration sup
446
448
  Each pagination page defines an information structure `pagination_info` that is available to the liquid templates. This structure contains meta information for the pagination process, such as current pagination page and the total number of paginated pages.
447
449
 
448
450
  The following fields are available
451
+
449
452
  | Field | Description |
450
453
  | --- | --- |
451
454
  | curr_page | The number of the current pagination page |
@@ -6,7 +6,7 @@ module Jekyll
6
6
  'enabled' => false,
7
7
  'tags' => {
8
8
  'layouts' => ['autopage_tags.html'],
9
- 'title' => 'Posts tagged with :tag`',
9
+ 'title' => 'Posts tagged with :tag',
10
10
  'permalink' => '/tag/:tag',
11
11
  'enabled' => true
12
12
 
@@ -26,4 +26,4 @@ module Jekyll
26
26
  }
27
27
 
28
28
  end # module PaginateV2::AutoPages
29
- end # module Jekyll
29
+ end # module Jekyll
@@ -1,327 +1,355 @@
1
- module Jekyll
2
- module PaginateV2::Generator
3
-
4
- #
5
- # The main model for the pagination, handles the orchestration of the pagination and calling all the necessary bits and bobs needed :)
6
- #
7
- class PaginationModel
8
-
9
- @debug = false # is debug output enabled?
10
- @logging_lambda = nil # The lambda to use for logging
11
- @page_add_lambda = nil # The lambda used to create pages and add them to the site
12
- @page_remove_lambda = nil # Lambda to remove a page from the site.pages collection
13
- @collection_by_name_lambda = nil # Lambda to get all documents/posts in a particular collection (by name)
14
-
15
- # ctor
16
- def initialize(logging_lambda, page_add_lambda, page_remove_lambda, collection_by_name_lambda)
17
- @logging_lambda = logging_lambda
18
- @page_add_lambda = page_add_lambda
19
- @page_remove_lambda = page_remove_lambda
20
- @collection_by_name_lambda = collection_by_name_lambda
21
- end
22
-
23
-
24
- def run(default_config, site_pages, site_title)
25
- # By default if pagination is enabled we attempt to find all index.html pages in the site
26
- templates = self.discover_paginate_templates(site_pages)
27
- if( templates.size.to_i <= 0 )
28
- @logging_lambda.call "Is enabled, but I couldn't find any pagination page. Skipping pagination. "+
29
- "Pages must have 'pagination: enabled: true' in their front-matter for pagination to work.", "warn"
30
- return
31
- end
32
-
33
- # Now for each template page generate the paginator for it
34
- for template in templates
35
- # All pages that should be paginated need to include the pagination config element
36
- if template.data['pagination'].is_a?(Hash)
37
- template_config = Jekyll::Utils.deep_merge_hashes(default_config, template.data['pagination'] || {})
38
-
39
- # Handling deprecation of configuration values
40
- self._fix_deprecated_config_features(template_config)
41
-
42
- @debug = template_config['debug'] # Is debugging enabled on the page level
43
-
44
- self._debug_print_config_info(template_config, template.path)
45
-
46
- # Only paginate the template if it is explicitly enabled
47
- # requiring this makes the logic simpler as I don't need to determine which index pages
48
- # were generated automatically and which weren't
49
- if( template_config['enabled'] )
50
- if !@debug
51
- @logging_lambda.call "found page: "+template.path, 'debug'
52
- end
53
-
54
- # Request all documents in all collections that the user has requested
55
- all_posts = self.get_docs_in_collections(template_config['collection'])
56
-
57
- # Create the necessary indexes for the posts
58
- all_categories = PaginationIndexer.index_posts_by(all_posts, 'categories')
59
- all_categories['posts'] = all_posts; # Populate a category for all posts (this is here for backward compatibility, do not use this as it will be decommissioned 2018-01-01)
60
- # (this is a default and must not be used in the category system)
61
- all_tags = PaginationIndexer.index_posts_by(all_posts, 'tags')
62
- all_locales = PaginationIndexer.index_posts_by(all_posts, 'locale')
63
-
64
- # TODO: NOTE!!! This whole request for posts and indexing results could be cached to improve performance, leaving like this for now during testing
65
-
66
- # Now construct the pagination data for this template page
67
- self.paginate(template, template_config, site_title, all_posts, all_tags, all_categories, all_locales)
68
- end
69
- end
70
- end #for
71
-
72
- # Return the total number of templates found
73
- return templates.size.to_i
74
- end # function run
75
-
76
- #
77
- # This function is here to retain the old compatability logic with the jekyll-paginate gem
78
- # no changes should be made to this function and it should be retired and deleted after 2018-01-01
79
- # (REMOVE AFTER 2018-01-01)
80
- #
81
- def run_compatability(legacy_config, site_pages, site_title, all_posts)
82
-
83
- # Decomissioning error
84
- if( date = Date.strptime("20180101","%Y%m%d") <= Date.today )
85
- raise ArgumentError.new("Legacy jekyll-paginate configuration compatibility mode has expired. Please upgrade to jekyll-paginate-v2 configuration.")
86
- end
87
-
88
- # Two month warning or general notification
89
- if( date = Date.strptime("20171101","%Y%m%d") <= Date.today )
90
- @logging_lambda.call "Legacy pagination logic will stop working on Jan 1st 2018, update your configs before that time.", "warn"
91
- else
92
- @logging_lambda.call "Detected legacy jekyll-paginate logic running. "+
93
- "Please update your configs to use the jekyll-paginate-v2 logic. This compatibility function "+
94
- "will stop working after Jan 1st 2018 and your site build will throw an error.", "warn"
95
- end
96
-
97
- if template = CompatibilityUtils.template_page(site_pages, legacy_config['legacy_source'], legacy_config['permalink'])
98
- CompatibilityUtils.paginate(legacy_config, all_posts, template, @page_add_lambda)
99
- else
100
- @logging_lambda.call "Legacy pagination is enabled, but I couldn't find " +
101
- "an index.html page to use as the pagination page. Skipping pagination.", "warn"
102
- end
103
- end # function run_compatability (REMOVE AFTER 2018-01-01)
104
-
105
- # Returns the combination of all documents in the collections that are specified
106
- # raw_collection_names can either be a list of collections separated by a ',' or ' ' or a single string
107
- def get_docs_in_collections(raw_collection_names)
108
- if raw_collection_names.is_a?(String)
109
- collection_names = raw_collection_names.split(/;|,|\s/)
110
- else
111
- collection_names = raw_collection_names
112
- end
113
-
114
- docs = []
115
- # Now for each of the collections get the docs
116
- for coll_name in collection_names
117
- # Request all the documents for the collection in question, and join it with the total collection
118
- docs += @collection_by_name_lambda.call(coll_name.downcase.strip)
119
- end
120
-
121
- return docs
122
- end
123
-
124
- def _fix_deprecated_config_features(config)
125
- keys_to_delete = []
126
-
127
- # As of v1.5.1 the title_suffix is deprecated and 'title' should be used
128
- # but only if title has not been defined already!
129
- if( !config['title_suffix'].nil? )
130
- if( config['title'].nil? )
131
- config['title'] = ":title" + config['title_suffix'].to_s # Migrate the old key to title
132
- end
133
- keys_to_delete << "title_suffix" # Always remove the depricated key if found
134
- end
135
-
136
- # Delete the depricated keys
137
- config.delete_if{ |k,| keys_to_delete.include? k }
138
- end
139
-
140
- def _debug_print_config_info(config, page_path)
141
- r = 20
142
- f = "Pagination: ".rjust(20)
143
- # Debug print the config
144
- if @debug
145
- puts f + "----------------------------"
146
- puts f + "Page: "+page_path.to_s
147
- puts f + " Active configuration"
148
- puts f + " Enabled: ".ljust(r) + config['enabled'].to_s
149
- puts f + " Items per page: ".ljust(r) + config['per_page'].to_s
150
- puts f + " Permalink: ".ljust(r) + config['permalink'].to_s
151
- puts f + " Title: ".ljust(r) + config['title'].to_s
152
- puts f + " Limit: ".ljust(r) + config['limit'].to_s
153
- puts f + " Sort by: ".ljust(r) + config['sort_field'].to_s
154
- puts f + " Sort reverse: ".ljust(r) + config['sort_reverse'].to_s
155
-
156
- puts f + " Active Filters"
157
- puts f + " Collection: ".ljust(r) + config['collection'].to_s
158
- puts f + " Category: ".ljust(r) + (config['category'].nil? || config['category'] == "posts" ? "[Not set]" : config['category'].to_s)
159
- puts f + " Tag: ".ljust(r) + (config['tag'].nil? ? "[Not set]" : config['tag'].to_s)
160
- puts f + " Locale: ".ljust(r) + (config['locale'].nil? ? "[Not set]" : config['locale'].to_s)
161
-
162
- if config['legacy']
163
- puts f + " Legacy Paginate Code Enabled"
164
- puts f + " Legacy Paginate: ".ljust(r) + config['per_page'].to_s
165
- puts f + " Legacy Source: ".ljust(r) + config['legacy_source'].to_s
166
- puts f + " Legacy Path: ".ljust(r) + config['paginate_path'].to_s
167
- end
168
- end
169
- end
170
-
171
- def _debug_print_filtering_info(filter_name, before_count, after_count)
172
- # Debug print the config
173
- if @debug
174
- puts "Pagination: ".rjust(20) + " Filtering by: "+filter_name.to_s.ljust(9) + " " + before_count.to_s.rjust(3) + " => " + after_count.to_s
175
- end
176
- end
177
-
178
- #
179
- # Rolls through all the pages passed in and finds all pages that have pagination enabled on them.
180
- # These pages will be used as templates
181
- #
182
- # site_pages - All pages in the site
183
- #
184
- def discover_paginate_templates(site_pages)
185
- candidates = []
186
- site_pages.select do |page|
187
- # If the page has the enabled config set, supports any type of file name html or md
188
- if page.data['pagination'].is_a?(Hash) && page.data['pagination']['enabled']
189
- candidates << page
190
- end
191
- end
192
- return candidates
193
- end # function discover_paginate_templates
194
-
195
- # Paginates the blog's posts. Renders the index.html file into paginated
196
- # directories, e.g.: page2/index.html, page3/index.html, etc and adds more
197
- # site-wide data.
198
- #
199
- # site - The Site.
200
- # template - The index.html Page that requires pagination.
201
- # config - The configuration settings that should be used
202
- #
203
- def paginate(template, config, site_title, all_posts, all_tags, all_categories, all_locales)
204
- # By default paginate on all posts in the site
205
- using_posts = all_posts
206
-
207
- # Now start filtering out any posts that the user doesn't want included in the pagination
208
- before = using_posts.size.to_i
209
- using_posts = PaginationIndexer.read_config_value_and_filter_posts(config, 'category', using_posts, all_categories)
210
- self._debug_print_filtering_info('Category', before, using_posts.size.to_i)
211
- before = using_posts.size.to_i
212
- using_posts = PaginationIndexer.read_config_value_and_filter_posts(config, 'tag', using_posts, all_tags)
213
- self._debug_print_filtering_info('Tag', before, using_posts.size.to_i)
214
- before = using_posts.size.to_i
215
- using_posts = PaginationIndexer.read_config_value_and_filter_posts(config, 'locale', using_posts, all_locales)
216
- self._debug_print_filtering_info('Locale', before, using_posts.size.to_i)
217
-
218
- # Apply sorting to the posts if configured, any field for the post is available for sorting
219
- if config['sort_field']
220
- sort_field = config['sort_field'].to_s
221
- using_posts.sort!{ |a,b| Utils.sort_values(Utils.sort_get_post_data(a.data, sort_field), Utils.sort_get_post_data(b.data, sort_field)) }
222
- if config['sort_reverse']
223
- using_posts.reverse!
224
- end
225
- end
226
-
227
- # Calculate the max number of pagination-pages based on the configured per page value
228
- total_pages = Utils.calculate_number_of_pages(using_posts, config['per_page'])
229
-
230
- # If a upper limit is set on the number of total pagination pages then impose that now
231
- if config['limit'] && config['limit'].to_i > 0 && config['limit'].to_i < total_pages
232
- total_pages = config['limit'].to_i
233
- end
234
-
235
- #### BEFORE STARTING REMOVE THE TEMPLATE PAGE FROM THE SITE LIST!
236
- @page_remove_lambda.call( template )
237
-
238
- # list of all newly created pages
239
- newpages = []
240
-
241
- # Now for each pagination page create it and configure the ranges for the collection
242
- # This .pager member is a built in thing in Jekyll and defines the paginator implementation
243
- # Simpy override to use mine
244
- (1..total_pages).each do |cur_page_nr|
245
-
246
- # 1. Create the in-memory page
247
- # External Proc call to create the actual page for us (this is passed in when the pagination is run)
248
- newpage = PaginationPage.new( template, cur_page_nr, total_pages )
249
-
250
- # 2. Create the url for the in-memory page (calc permalink etc), construct the title, set all page.data values needed
251
- paginated_page_url = config['permalink']
252
- first_index_page_url = ""
253
- if template.data['permalink']
254
- first_index_page_url = template.data['permalink']
255
- else
256
- first_index_page_url = template.dir
257
- end
258
- paginated_page_url = File.join(first_index_page_url, paginated_page_url)
259
-
260
- # 3. Create the pager logic for this page, pass in the prev and next page numbers, assign pager to in-memory page
261
- newpage.pager = Paginator.new( config['per_page'], first_index_page_url, paginated_page_url, using_posts, cur_page_nr, total_pages)
262
-
263
- # Create the url for the new page, make sure we prepend any permalinks that are defined in the template page before
264
- newpage.set_url(File.join(newpage.pager.page_path, 'index.html'))
265
- if( template.data['permalink'] )
266
- newpage.data['permalink'] = newpage.pager.page_path
267
- end
268
-
269
- # Transfer the title across to the new page
270
- if( !template.data['title'] )
271
- tmp_title = site_title
272
- else
273
- tmp_title = template.data['title']
274
- end
275
- # If the user specified a title suffix to be added then let's add that to all the pages except the first
276
- if( cur_page_nr > 1 && config.has_key?('title') )
277
- newpage.data['title'] = "#{Utils.format_page_title(config['title'], tmp_title, cur_page_nr, total_pages)}"
278
- else
279
- newpage.data['title'] = tmp_title
280
- end
281
-
282
- # Signals that this page is automatically generated by the pagination logic
283
- # (we don't do this for the first page as it is there to mask the one we removed)
284
- if cur_page_nr > 1
285
- newpage.data['autogen'] = "jekyll-paginate-v2"
286
- end
287
-
288
- # Add the page to the site
289
- @page_add_lambda.call( newpage )
290
-
291
- # Store the page in an internal list for later referencing if we need to generate a pagination number path later on
292
- newpages << newpage
293
- end #each.do total_pages
294
-
295
- # Now generate the pagination number path, e.g. so that the users can have a prev 1 2 3 4 5 next structure on their page
296
- # simplest is to include all of the links to the pages preceeding the current one
297
- # (e.g for page 1 you get the list 2, 3, 4.... and for page 2 you get the list 3,4,5...)
298
- if( config['trail'] && !config['trail'].nil? && newpages.size.to_i > 1 )
299
- trail_before = [config['trail']['before'].to_i, 0].max
300
- trail_after = [config['trail']['after'].to_i, 0].max
301
- trail_length = trail_before + trail_after + 1
302
-
303
- if( trail_before > 0 || trail_after > 0 )
304
- newpages.select do | npage |
305
- idx_start = [ npage.pager.page - trail_before - 1, 0].max # Selecting the beginning of the trail
306
- idx_end = [idx_start + trail_length, newpages.size.to_i].min # Selecting the end of the trail
307
-
308
- # Always attempt to maintain the max total of <trail_length> pages in the trail (it will look better if the trail doesn't shrink)
309
- if( idx_end - idx_start < trail_length )
310
- # Attempt to pad the beginning if we have enough pages
311
- idx_start = [idx_start - ( trail_length - (idx_end - idx_start) ), 0].max # Never go beyond the zero index
312
- end
313
-
314
- # Convert the newpages array into a two dimensional array that has [index, page_url] as items
315
- #puts( "Trail created for page #{npage.pager.page} (idx_start:#{idx_start} idx_end:#{idx_end})")
316
- npage.pager.page_trail = newpages[idx_start...idx_end].each_with_index.map {|ipage,idx| PageTrail.new(idx_start+idx+1, ipage.pager.page_path, ipage.data['title'])}
317
- #puts( npage.pager.page_trail )
318
- end #newpages.select
319
- end #if trail_before / trail_after
320
- end # if config['trail']
321
-
322
- end # function paginate
323
-
324
- end # class PaginationV2
325
-
326
- end # module PaginateV2
1
+ module Jekyll
2
+ module PaginateV2::Generator
3
+
4
+ #
5
+ # The main model for the pagination, handles the orchestration of the pagination and calling all the necessary bits and bobs needed :)
6
+ #
7
+ class PaginationModel
8
+
9
+ @debug = false # is debug output enabled?
10
+ @logging_lambda = nil # The lambda to use for logging
11
+ @page_add_lambda = nil # The lambda used to create pages and add them to the site
12
+ @page_remove_lambda = nil # Lambda to remove a page from the site.pages collection
13
+ @collection_by_name_lambda = nil # Lambda to get all documents/posts in a particular collection (by name)
14
+
15
+ # ctor
16
+ def initialize(logging_lambda, page_add_lambda, page_remove_lambda, collection_by_name_lambda)
17
+ @logging_lambda = logging_lambda
18
+ @page_add_lambda = page_add_lambda
19
+ @page_remove_lambda = page_remove_lambda
20
+ @collection_by_name_lambda = collection_by_name_lambda
21
+ end
22
+
23
+
24
+ def run(default_config, site_pages, site_title)
25
+ # By default if pagination is enabled we attempt to find all index.html pages in the site
26
+ templates = self.discover_paginate_templates(site_pages)
27
+ if( templates.size.to_i <= 0 )
28
+ @logging_lambda.call "Is enabled, but I couldn't find any pagination page. Skipping pagination. "+
29
+ "Pages must have 'pagination: enabled: true' in their front-matter for pagination to work.", "warn"
30
+ return
31
+ end
32
+
33
+ # Now for each template page generate the paginator for it
34
+ for template in templates
35
+ # All pages that should be paginated need to include the pagination config element
36
+ if template.data['pagination'].is_a?(Hash)
37
+ template_config = Jekyll::Utils.deep_merge_hashes(default_config, template.data['pagination'] || {})
38
+
39
+ # Handling deprecation of configuration values
40
+ self._fix_deprecated_config_features(template_config)
41
+
42
+ @debug = template_config['debug'] # Is debugging enabled on the page level
43
+
44
+ self._debug_print_config_info(template_config, template.path)
45
+
46
+ # Only paginate the template if it is explicitly enabled
47
+ # requiring this makes the logic simpler as I don't need to determine which index pages
48
+ # were generated automatically and which weren't
49
+ if( template_config['enabled'] )
50
+ if !@debug
51
+ @logging_lambda.call "found page: "+template.path, 'debug'
52
+ end
53
+
54
+ # Request all documents in all collections that the user has requested
55
+ all_posts = self.get_docs_in_collections(template_config['collection'])
56
+
57
+ # Create the necessary indexes for the posts
58
+ all_categories = PaginationIndexer.index_posts_by(all_posts, 'categories')
59
+ all_categories['posts'] = all_posts; # Populate a category for all posts (this is here for backward compatibility, do not use this as it will be decommissioned 2018-01-01)
60
+ # (this is a default and must not be used in the category system)
61
+ all_tags = PaginationIndexer.index_posts_by(all_posts, 'tags')
62
+ all_locales = PaginationIndexer.index_posts_by(all_posts, 'locale')
63
+
64
+ # TODO: NOTE!!! This whole request for posts and indexing results could be cached to improve performance, leaving like this for now during testing
65
+
66
+ # Now construct the pagination data for this template page
67
+ self.paginate(template, template_config, site_title, all_posts, all_tags, all_categories, all_locales)
68
+ end
69
+ end
70
+ end #for
71
+
72
+ # Return the total number of templates found
73
+ return templates.size.to_i
74
+ end # function run
75
+
76
+ #
77
+ # This function is here to retain the old compatability logic with the jekyll-paginate gem
78
+ # no changes should be made to this function and it should be retired and deleted after 2018-01-01
79
+ # (REMOVE AFTER 2018-01-01)
80
+ #
81
+ def run_compatability(legacy_config, site_pages, site_title, all_posts)
82
+
83
+ # Decomissioning error
84
+ if( date = Date.strptime("20180101","%Y%m%d") <= Date.today )
85
+ raise ArgumentError.new("Legacy jekyll-paginate configuration compatibility mode has expired. Please upgrade to jekyll-paginate-v2 configuration.")
86
+ end
87
+
88
+ # Two month warning or general notification
89
+ if( date = Date.strptime("20171101","%Y%m%d") <= Date.today )
90
+ @logging_lambda.call "Legacy pagination logic will stop working on Jan 1st 2018, update your configs before that time.", "warn"
91
+ else
92
+ @logging_lambda.call "Detected legacy jekyll-paginate logic running. "+
93
+ "Please update your configs to use the jekyll-paginate-v2 logic. This compatibility function "+
94
+ "will stop working after Jan 1st 2018 and your site build will throw an error.", "warn"
95
+ end
96
+
97
+ if template = CompatibilityUtils.template_page(site_pages, legacy_config['legacy_source'], legacy_config['permalink'])
98
+ CompatibilityUtils.paginate(legacy_config, all_posts, template, @page_add_lambda)
99
+ else
100
+ @logging_lambda.call "Legacy pagination is enabled, but I couldn't find " +
101
+ "an index.html page to use as the pagination page. Skipping pagination.", "warn"
102
+ end
103
+ end # function run_compatability (REMOVE AFTER 2018-01-01)
104
+
105
+ # Returns the combination of all documents in the collections that are specified
106
+ # raw_collection_names can either be a list of collections separated by a ',' or ' ' or a single string
107
+ def get_docs_in_collections(raw_collection_names)
108
+ if raw_collection_names.is_a?(String)
109
+ collection_names = raw_collection_names.split(/;|,|\s/)
110
+ else
111
+ collection_names = raw_collection_names
112
+ end
113
+
114
+ docs = []
115
+ # Now for each of the collections get the docs
116
+ for coll_name in collection_names
117
+ # Request all the documents for the collection in question, and join it with the total collection
118
+ docs += @collection_by_name_lambda.call(coll_name.downcase.strip)
119
+ end
120
+
121
+ return docs
122
+ end
123
+
124
+ def _fix_deprecated_config_features(config)
125
+ keys_to_delete = []
126
+
127
+ # As of v1.5.1 the title_suffix is deprecated and 'title' should be used
128
+ # but only if title has not been defined already!
129
+ if( !config['title_suffix'].nil? )
130
+ if( config['title'].nil? )
131
+ config['title'] = ":title" + config['title_suffix'].to_s # Migrate the old key to title
132
+ end
133
+ keys_to_delete << "title_suffix" # Always remove the depricated key if found
134
+ end
135
+
136
+ # Delete the depricated keys
137
+ config.delete_if{ |k,| keys_to_delete.include? k }
138
+ end
139
+
140
+ def _debug_print_config_info(config, page_path)
141
+ r = 20
142
+ f = "Pagination: ".rjust(20)
143
+ # Debug print the config
144
+ if @debug
145
+ puts f + "----------------------------"
146
+ puts f + "Page: "+page_path.to_s
147
+ puts f + " Active configuration"
148
+ puts f + " Enabled: ".ljust(r) + config['enabled'].to_s
149
+ puts f + " Items per page: ".ljust(r) + config['per_page'].to_s
150
+ puts f + " Permalink: ".ljust(r) + config['permalink'].to_s
151
+ puts f + " Title: ".ljust(r) + config['title'].to_s
152
+ puts f + " Limit: ".ljust(r) + config['limit'].to_s
153
+ puts f + " Sort by: ".ljust(r) + config['sort_field'].to_s
154
+ puts f + " Sort reverse: ".ljust(r) + config['sort_reverse'].to_s
155
+
156
+ puts f + " Active Filters"
157
+ puts f + " Collection: ".ljust(r) + config['collection'].to_s
158
+ puts f + " Category: ".ljust(r) + (config['category'].nil? || config['category'] == "posts" ? "[Not set]" : config['category'].to_s)
159
+ puts f + " Tag: ".ljust(r) + (config['tag'].nil? ? "[Not set]" : config['tag'].to_s)
160
+ puts f + " Locale: ".ljust(r) + (config['locale'].nil? ? "[Not set]" : config['locale'].to_s)
161
+
162
+ if config['legacy']
163
+ puts f + " Legacy Paginate Code Enabled"
164
+ puts f + " Legacy Paginate: ".ljust(r) + config['per_page'].to_s
165
+ puts f + " Legacy Source: ".ljust(r) + config['legacy_source'].to_s
166
+ puts f + " Legacy Path: ".ljust(r) + config['paginate_path'].to_s
167
+ end
168
+ end
169
+ end
170
+
171
+ def _debug_print_filtering_info(filter_name, before_count, after_count)
172
+ # Debug print the config
173
+ if @debug
174
+ puts "Pagination: ".rjust(20) + " Filtering by: "+filter_name.to_s.ljust(9) + " " + before_count.to_s.rjust(3) + " => " + after_count.to_s
175
+ end
176
+ end
177
+
178
+ #
179
+ # Rolls through all the pages passed in and finds all pages that have pagination enabled on them.
180
+ # These pages will be used as templates
181
+ #
182
+ # site_pages - All pages in the site
183
+ #
184
+ def discover_paginate_templates(site_pages)
185
+ candidates = []
186
+ site_pages.select do |page|
187
+ # If the page has the enabled config set, supports any type of file name html or md
188
+ if page.data['pagination'].is_a?(Hash) && page.data['pagination']['enabled']
189
+ candidates << page
190
+ end
191
+ end
192
+ return candidates
193
+ end # function discover_paginate_templates
194
+
195
+ # Paginates the blog's posts. Renders the index.html file into paginated
196
+ # directories, e.g.: page2/index.html, page3/index.html, etc and adds more
197
+ # site-wide data.
198
+ #
199
+ # site - The Site.
200
+ # template - The index.html Page that requires pagination.
201
+ # config - The configuration settings that should be used
202
+ #
203
+ def paginate(template, config, site_title, all_posts, all_tags, all_categories, all_locales)
204
+ # By default paginate on all posts in the site
205
+ using_posts = all_posts
206
+
207
+ # Now start filtering out any posts that the user doesn't want included in the pagination
208
+ before = using_posts.size.to_i
209
+ using_posts = PaginationIndexer.read_config_value_and_filter_posts(config, 'category', using_posts, all_categories)
210
+ self._debug_print_filtering_info('Category', before, using_posts.size.to_i)
211
+ before = using_posts.size.to_i
212
+ using_posts = PaginationIndexer.read_config_value_and_filter_posts(config, 'tag', using_posts, all_tags)
213
+ self._debug_print_filtering_info('Tag', before, using_posts.size.to_i)
214
+ before = using_posts.size.to_i
215
+ using_posts = PaginationIndexer.read_config_value_and_filter_posts(config, 'locale', using_posts, all_locales)
216
+ self._debug_print_filtering_info('Locale', before, using_posts.size.to_i)
217
+
218
+ # Apply sorting to the posts if configured, any field for the post is available for sorting
219
+ if config['sort_field']
220
+ sort_field = config['sort_field'].to_s
221
+
222
+ # There is an issue in Jekyll related to lazy initialized member variables that causes iterators to
223
+ # break when accessing an uninitialized value during iteration. This happens for document.rb when the <=> compaison function
224
+ # is called (as this function calls the 'date' field which for drafts are not initialized.)
225
+ # So to unblock this common issue for the date field I simply iterate once over every document and initialize the .date field explicitly
226
+ if @debug
227
+ puts "Pagination: ".rjust(20) + "Rolling through the date fields for all documents"
228
+ end
229
+ for p in using_posts
230
+ tmp_date = p.date
231
+ if( !tmp_date || tmp_date.nil? )
232
+ if @debug
233
+ puts "Pagination: ".rjust(20) + "Explicitly assigning date for doc: #{p.data['title']} | #{p.path}"
234
+ end
235
+ p.date = File.mtime(p.path)
236
+ end
237
+ end
238
+
239
+ using_posts.sort!{ |a,b| Utils.sort_values(Utils.sort_get_post_data(a.data, sort_field), Utils.sort_get_post_data(b.data, sort_field)) }
240
+
241
+ if config['sort_reverse']
242
+ using_posts.reverse!
243
+ end
244
+ end
245
+
246
+ # Calculate the max number of pagination-pages based on the configured per page value
247
+ total_pages = Utils.calculate_number_of_pages(using_posts, config['per_page'])
248
+
249
+ # If a upper limit is set on the number of total pagination pages then impose that now
250
+ if config['limit'] && config['limit'].to_i > 0 && config['limit'].to_i < total_pages
251
+ total_pages = config['limit'].to_i
252
+ end
253
+
254
+ #### BEFORE STARTING REMOVE THE TEMPLATE PAGE FROM THE SITE LIST!
255
+ @page_remove_lambda.call( template )
256
+
257
+ # list of all newly created pages
258
+ newpages = []
259
+
260
+ # Now for each pagination page create it and configure the ranges for the collection
261
+ # This .pager member is a built in thing in Jekyll and defines the paginator implementation
262
+ # Simpy override to use mine
263
+ (1..total_pages).each do |cur_page_nr|
264
+
265
+ # 1. Create the in-memory page
266
+ # External Proc call to create the actual page for us (this is passed in when the pagination is run)
267
+ newpage = PaginationPage.new( template, cur_page_nr, total_pages )
268
+
269
+ # 2. Create the url for the in-memory page (calc permalink etc), construct the title, set all page.data values needed
270
+ paginated_page_url = config['permalink']
271
+ first_index_page_url = ""
272
+ if template.data['permalink']
273
+ first_index_page_url = Utils.ensure_trailing_slash(template.data['permalink'])
274
+ else
275
+ first_index_page_url = Utils.ensure_trailing_slash(template.dir)
276
+ end
277
+ paginated_page_url = File.join(first_index_page_url, paginated_page_url)
278
+
279
+ # 3. Create the pager logic for this page, pass in the prev and next page numbers, assign pager to in-memory page
280
+ newpage.pager = Paginator.new( config['per_page'], first_index_page_url, paginated_page_url, using_posts, cur_page_nr, total_pages)
281
+
282
+ # Create the url for the new page, make sure we prepend any permalinks that are defined in the template page before
283
+ if newpage.pager.page_path.end_with? '/'
284
+ newpage.set_url(File.join(newpage.pager.page_path, 'index.html'))
285
+ elsif newpage.pager.page_path.end_with? '.html'
286
+ # Support for direct .html files
287
+ newpage.set_url(newpage.pager.page_path)
288
+ else
289
+ # Support for extensionless permalinks
290
+ newpage.set_url(newpage.pager.page_path+'.html')
291
+ end
292
+
293
+ if( template.data['permalink'] )
294
+ newpage.data['permalink'] = newpage.pager.page_path
295
+ end
296
+
297
+ # Transfer the title across to the new page
298
+ if( !template.data['title'] )
299
+ tmp_title = site_title
300
+ else
301
+ tmp_title = template.data['title']
302
+ end
303
+ # If the user specified a title suffix to be added then let's add that to all the pages except the first
304
+ if( cur_page_nr > 1 && config.has_key?('title') )
305
+ newpage.data['title'] = "#{Utils.format_page_title(config['title'], tmp_title, cur_page_nr, total_pages)}"
306
+ else
307
+ newpage.data['title'] = tmp_title
308
+ end
309
+
310
+ # Signals that this page is automatically generated by the pagination logic
311
+ # (we don't do this for the first page as it is there to mask the one we removed)
312
+ if cur_page_nr > 1
313
+ newpage.data['autogen'] = "jekyll-paginate-v2"
314
+ end
315
+
316
+ # Add the page to the site
317
+ @page_add_lambda.call( newpage )
318
+
319
+ # Store the page in an internal list for later referencing if we need to generate a pagination number path later on
320
+ newpages << newpage
321
+ end #each.do total_pages
322
+
323
+ # Now generate the pagination number path, e.g. so that the users can have a prev 1 2 3 4 5 next structure on their page
324
+ # simplest is to include all of the links to the pages preceeding the current one
325
+ # (e.g for page 1 you get the list 2, 3, 4.... and for page 2 you get the list 3,4,5...)
326
+ if( config['trail'] && !config['trail'].nil? && newpages.size.to_i > 1 )
327
+ trail_before = [config['trail']['before'].to_i, 0].max
328
+ trail_after = [config['trail']['after'].to_i, 0].max
329
+ trail_length = trail_before + trail_after + 1
330
+
331
+ if( trail_before > 0 || trail_after > 0 )
332
+ newpages.select do | npage |
333
+ idx_start = [ npage.pager.page - trail_before - 1, 0].max # Selecting the beginning of the trail
334
+ idx_end = [idx_start + trail_length, newpages.size.to_i].min # Selecting the end of the trail
335
+
336
+ # Always attempt to maintain the max total of <trail_length> pages in the trail (it will look better if the trail doesn't shrink)
337
+ if( idx_end - idx_start < trail_length )
338
+ # Attempt to pad the beginning if we have enough pages
339
+ idx_start = [idx_start - ( trail_length - (idx_end - idx_start) ), 0].max # Never go beyond the zero index
340
+ end
341
+
342
+ # Convert the newpages array into a two dimensional array that has [index, page_url] as items
343
+ #puts( "Trail created for page #{npage.pager.page} (idx_start:#{idx_start} idx_end:#{idx_end})")
344
+ npage.pager.page_trail = newpages[idx_start...idx_end].each_with_index.map {|ipage,idx| PageTrail.new(idx_start+idx+1, ipage.pager.page_path, ipage.data['title'])}
345
+ #puts( npage.pager.page_trail )
346
+ end #newpages.select
347
+ end #if trail_before / trail_after
348
+ end # if config['trail']
349
+
350
+ end # function paginate
351
+
352
+ end # class PaginationV2
353
+
354
+ end # module PaginateV2
327
355
  end # module Jekyll
@@ -52,6 +52,17 @@ module Jekyll
52
52
  def self.remove_leading_slash(path)
53
53
  path[0..0] == "/" ? path[1..-1] : path
54
54
  end
55
+
56
+ # Static: Return a String version of the input which has a trailing slash.
57
+ # If the input already has a forward slash at the end, it will be
58
+ # returned unchanged.
59
+ #
60
+ # path - a String path
61
+ #
62
+ # Returns the path with a trailing slash
63
+ def self.ensure_trailing_slash(path)
64
+ path[-1] == "/" ? path : "#{path}/"
65
+ end
55
66
 
56
67
  #
57
68
  # Sorting routine used for ordering posts by custom fields.
@@ -1,8 +1,8 @@
1
1
  module Jekyll
2
2
  module PaginateV2
3
- VERSION = "1.7.3"
3
+ VERSION = "1.7.4"
4
4
  # When modifying remember to issue a new tag command in git before committing, then push the new tag
5
- # git tag -a v1.7.3 -m "Gem v1.7.3"
5
+ # git tag -a v1.7.4 -m "Gem v1.7.4"
6
6
  # git push origin --tags
7
7
  # Yanking a published Gem
8
8
  # gem yank jekyll-paginate-v2 -v VERSION
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-paginate-v2
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.3
4
+ version: 1.7.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sverrir Sigmundarson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-03 00:00:00.000000000 Z
11
+ date: 2017-03-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll