jekyll-paginate-v2 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/Gemfile +8 -0
- data/LICENSE +22 -0
- data/README.md +248 -0
- data/jekyll-paginate-v2.gemspec +28 -0
- data/lib/jekyll-paginate-v2.rb +21 -0
- data/lib/jekyll-paginate-v2/defaults.rb +18 -0
- data/lib/jekyll-paginate-v2/pagination.rb +252 -0
- data/lib/jekyll-paginate-v2/paginator.rb +58 -0
- data/lib/jekyll-paginate-v2/utils.rb +58 -0
- data/lib/jekyll-paginate-v2/version.rb +5 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cd4827a1c9dd80de07ba232d75d61c573b52eeaf
|
4
|
+
data.tar.gz: a6238314308d5a386f8fab3f2b28f730b51ab8a7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 917b6eadca4c14048091ee608c8a284ba17ed3d5a8430c8723828b5cfda7918a64658dbbf7fccd53783ea25253a6e3edaf6432bce4c878c34d6a81884e151466
|
7
|
+
data.tar.gz: 72686ab7df0df3a8d2686f4c8141645df09c82248c547215f1fc2a5bbe4f4db40e19f2a672d8869abfac8a6408f36d0ce16aa983cc35736b35c50596ec93bc36
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Sverrir Sigmundarson
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,248 @@
|
|
1
|
+
# Jekyll::Paginate V2
|
2
|
+
|
3
|
+
Pagination plugin built specially for Jekyll 3 and newer.
|
4
|
+
|
5
|
+
Enhanced replacement for the previously built-in [jekyll-paginate gem](https://github.com/jekyll/jekyll-paginate).
|
6
|
+
|
7
|
+
The code was based on the original design of [jekyll-paginate](https://github.com/jekyll/jekyll-paginate) and features were mostly drawn from discussions from the issues pages (especially https://github.com/jekyll/jekyll-paginate/issues/27) and some from the excellent [Octopress::Paginate code](https://github.com/octopress/paginate).
|
8
|
+
|
9
|
+
Thanks everybody :heart:
|
10
|
+
|
11
|
+
## Features
|
12
|
+
|
13
|
+
In addition to all the features offered by the older [jekyll-paginate gem](https://github.com/jekyll/jekyll-paginate) this new pagination plugin features include
|
14
|
+
|
15
|
+
1. Works with any type of file ending (HTML, Markdown, etc) as long as the file has front-matter and the minimum page level pagination meta (see [page-configuration](#page-configuration)).
|
16
|
+
2. Paginated files can have any file name (not just index.html).
|
17
|
+
3. Supports category, tag and locale filtering.
|
18
|
+
4. Supports any combination of category, tag and locale filtering (e.g. _all posts in the 'ruby' category written for 'en\_US'_ or _all posts in 'car' and 'cycle' category tagged with 'cool' written for 'fr\_FR'_)
|
19
|
+
5. Sorting of posts by any field. Decending or Ascending.
|
20
|
+
6. Optional limits of number of pagenated pages (e.g. _only produce 15 pages_)
|
21
|
+
7. Fully customizable permalink format. E.g `/page:num/` or `/page/:num/` or `/:num/` or really anything you want.
|
22
|
+
8. Optional title suffix for paginated pages (e.g. _Index - Page 2_)
|
23
|
+
|
24
|
+
All this while being fully backwards compatible with the old [jekyll-paginate](https://github.com/jekyll/jekyll-paginate) gem (requires minimal additional front-matter, see [page-configuration](#page-configuration)).
|
25
|
+
|
26
|
+
## Installation
|
27
|
+
|
28
|
+
Currently this plugin is in develpment mode and is not yet distributed as a gem (mostly because I don't know how).
|
29
|
+
|
30
|
+
To install, simply copy the `lib\jekyll-paginate-v2.rb` file into the `_plugins` folder under your Jekyll site root.
|
31
|
+
> If the _plugins folder does not exist simply create it.
|
32
|
+
|
33
|
+
Then add the necessary [Site YML](#site-configuration) and [Page](#page-configuration) configuration elements.
|
34
|
+
|
35
|
+
Run `jekyll serve` and you should see the pagination plugin debug messages printed during site generation:
|
36
|
+
|
37
|
+
``` bash
|
38
|
+
Generating...
|
39
|
+
Pagination: found template: pictures/bestof.md
|
40
|
+
Pagination: found template: puffins/list.html
|
41
|
+
Pagination: found template: index.html
|
42
|
+
```
|
43
|
+
|
44
|
+
## Current state
|
45
|
+
|
46
|
+
Currently this code is in dire need of feedback, code review and testing.
|
47
|
+
|
48
|
+
I also would welcome guidance on how to write automated tests for this code so that I can publish it as a Gem.
|
49
|
+
|
50
|
+
Come to think of it, I currently have no idea on how to publish a Gem... :/
|
51
|
+
|
52
|
+
> Don't worry too much about the current structure, this is just the first iteration.
|
53
|
+
> The code is currently a single file `jekyll-paginate-v2.rb` only because it makes it faster to develop and debug. As soon as I and hopefully other people test and green-light the logic I intend to break this code into separate files and distribute as a gem.
|
54
|
+
|
55
|
+
## Contributing
|
56
|
+
|
57
|
+
1. Fork it ( https://github.com/sverrirs/jekyll-paginate-v2/fork )
|
58
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
59
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
60
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
61
|
+
5. Create new Pull Request
|
62
|
+
|
63
|
+
## Site configuration
|
64
|
+
|
65
|
+
The plugin can be configured in the site's `_config.yml` file by including the `pagination` configuration element
|
66
|
+
|
67
|
+
``` yml
|
68
|
+
############################################################
|
69
|
+
# Site configuration for the Jekyll 3 Pagination Plugin
|
70
|
+
# The values here represent the defaults if nothing is set
|
71
|
+
pagination:
|
72
|
+
|
73
|
+
# Site-wide kill switch, disabled here it doesn't run at all
|
74
|
+
enabled: true
|
75
|
+
|
76
|
+
# How many objects per paginated page, used to be `paginate` (default: 0, means all)
|
77
|
+
per_page: 10
|
78
|
+
|
79
|
+
# The permalink structure for the paginated pages (this can be any level deep)
|
80
|
+
permalink: '/page/:num/'
|
81
|
+
|
82
|
+
# Optional additional suffix for the title of the paginated pages (the prefix is inherited from the template page)
|
83
|
+
title_suffix: ' - page :num'
|
84
|
+
|
85
|
+
# Limit how many pagenated pages to create (default: 0, means all)
|
86
|
+
limit: 0
|
87
|
+
|
88
|
+
# Optional, defines the field that the posts should be sorted on (omit to default to 'date')
|
89
|
+
sort_field: 'date'
|
90
|
+
|
91
|
+
# Optional, sorts the posts in reverse order (omit to default decending or sort_reverse: true)
|
92
|
+
sort_reverse: true
|
93
|
+
|
94
|
+
# The default category to use, just leave this as 'posts' to get a backwards-compatible behavior (all posts)
|
95
|
+
category: 'posts'
|
96
|
+
|
97
|
+
# Optional, the default tag to use, omit to disable
|
98
|
+
tag: 'cool'
|
99
|
+
|
100
|
+
# Optional, the default locale to use, omit to disable (depends on a field 'locale' to be specified in the posts,
|
101
|
+
# in reality this can be any value, suggested are the Microsoft locale-codes (e.g. en_US, en_GB) or simply the ISO-639 language code )
|
102
|
+
locale: 'en_US'
|
103
|
+
|
104
|
+
############################################################
|
105
|
+
```
|
106
|
+
|
107
|
+
## Page configuration
|
108
|
+
|
109
|
+
To enable pagination on a page (i.e. make that page a template for pagination) then simply include the minimal pagination configuration in the page front-matter:
|
110
|
+
|
111
|
+
``` yml
|
112
|
+
pagination:
|
113
|
+
enabled: true
|
114
|
+
```
|
115
|
+
|
116
|
+
Then you can use the normal `paginator.posts` logic to iterate through the posts.
|
117
|
+
|
118
|
+
``` html
|
119
|
+
{% for post in paginator.posts %}
|
120
|
+
<h1>{{ post.title }}</h1>
|
121
|
+
{% endfor %}
|
122
|
+
```
|
123
|
+
|
124
|
+
And to display pagination links, simply
|
125
|
+
|
126
|
+
``` html
|
127
|
+
{% if paginator.total_pages > 1 %}
|
128
|
+
<ul class="pager">
|
129
|
+
{% if paginator.previous_page %}
|
130
|
+
<li class="previous">
|
131
|
+
<a href="{{ paginator.previous_page_path | prepend: site.baseurl | replace: '//', '/' }}">Newer Posts</a>
|
132
|
+
</li>
|
133
|
+
{% endif %}
|
134
|
+
{% if paginator.next_page %}
|
135
|
+
<li class="next">
|
136
|
+
<a href="{{ paginator.next_page_path | prepend: site.baseurl | replace: '//', '/' }}">Older Posts</a>
|
137
|
+
</li>
|
138
|
+
{% endif %}
|
139
|
+
</ul>
|
140
|
+
{% endif %}
|
141
|
+
```
|
142
|
+
|
143
|
+
The code is fully backwards compatible and you will have access to all the normal paginator variables defined in the [official jekyll documentation](https://jekyllrb.com/docs/pagination/#liquid-attributes-available).
|
144
|
+
|
145
|
+
Neat!
|
146
|
+
|
147
|
+
## Paginate categories, tags, locales
|
148
|
+
|
149
|
+
Enabling pagination for specific categories, tags or locales is as simple as adding values to the pagination template front-matter and corresponding values in the posts.
|
150
|
+
|
151
|
+
### Filtering categories
|
152
|
+
|
153
|
+
Filter single category 'software'
|
154
|
+
|
155
|
+
``` yml
|
156
|
+
pagination:
|
157
|
+
enabled: true
|
158
|
+
category: software
|
159
|
+
```
|
160
|
+
|
161
|
+
Filter multiple categories (lists only posts belonging to all categories)
|
162
|
+
|
163
|
+
``` yml
|
164
|
+
pagination:
|
165
|
+
enabled: true
|
166
|
+
category: software, ruby
|
167
|
+
```
|
168
|
+
|
169
|
+
> To define categories you can either specify them in the front-matter or through the [directory structure](http://jekyllrb.com/docs/variables/#page-variables) of your jekyll site (Categories are derived from the directory structure above the \_posts directory). You can actually use both approaches to assign your pages to multiple categories.
|
170
|
+
|
171
|
+
### Filtering tags
|
172
|
+
|
173
|
+
Filter on a single tag
|
174
|
+
|
175
|
+
``` yml
|
176
|
+
pagination:
|
177
|
+
enabled: true
|
178
|
+
tag: cool
|
179
|
+
```
|
180
|
+
|
181
|
+
Filter on multiple tags
|
182
|
+
|
183
|
+
``` yml
|
184
|
+
pagination:
|
185
|
+
enabled: true
|
186
|
+
tag: cool, life
|
187
|
+
```
|
188
|
+
|
189
|
+
### Filtering locales
|
190
|
+
|
191
|
+
In the case your site offers multiple languages you can include a `locale` item in your post front matter. The paginator can then use this value to filter on
|
192
|
+
|
193
|
+
The category page front-matter would look like this
|
194
|
+
|
195
|
+
``` yml
|
196
|
+
pagination:
|
197
|
+
enabled: true
|
198
|
+
locale: en_US
|
199
|
+
```
|
200
|
+
|
201
|
+
Then for the relevant posts, include the `locale` variable in their front-matter
|
202
|
+
|
203
|
+
``` yml
|
204
|
+
locale: en_US
|
205
|
+
```
|
206
|
+
|
207
|
+
## Paginate on combination of filters
|
208
|
+
|
209
|
+
Including only posts from categories 'ruby' and 'software' written in English
|
210
|
+
|
211
|
+
``` yml
|
212
|
+
pagination:
|
213
|
+
enabled: true
|
214
|
+
category: software, ruby
|
215
|
+
locale: en_US, en_GB, en_WW
|
216
|
+
```
|
217
|
+
|
218
|
+
Only showing posts tagged with 'cool' and in category 'cars'
|
219
|
+
|
220
|
+
``` yml
|
221
|
+
pagination:
|
222
|
+
enabled: true
|
223
|
+
category: cars
|
224
|
+
tag: cool
|
225
|
+
```
|
226
|
+
|
227
|
+
... and so on and so on
|
228
|
+
|
229
|
+
## Configuration overrides
|
230
|
+
|
231
|
+
All of the configuration elements from the `_config.yml` file can be overwritten in the pagination template pages. E.g. if you want one category page to have different permalink structure simply override the item like so
|
232
|
+
|
233
|
+
``` yml
|
234
|
+
pagination:
|
235
|
+
enabled: true
|
236
|
+
category: cars
|
237
|
+
permalink: '/cars/:num/'
|
238
|
+
```
|
239
|
+
|
240
|
+
Overriding sorting to sort by the post title in ascending order for another paginated template could be done like so
|
241
|
+
|
242
|
+
``` yml
|
243
|
+
pagination:
|
244
|
+
enabled: true
|
245
|
+
category: ruby
|
246
|
+
sort_field: 'title'
|
247
|
+
sort_reverse: false
|
248
|
+
```
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'jekyll-paginate-v2/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "jekyll-paginate-v2"
|
8
|
+
spec.version = Jekyll::PaginateV2::VERSION
|
9
|
+
spec.platform = Gem::Platform::RUBY
|
10
|
+
spec.date = '2016-11-18'
|
11
|
+
spec.authors = ["Sverrir Sigmundarson"]
|
12
|
+
spec.email = ["jekyll@sverrirs.com"]
|
13
|
+
spec.homepage = "https://github.com/sverrirs/jekyll-paginate-v2"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.summary = %q{Pagination Generator for Jekyll 3}
|
17
|
+
spec.description = %q{An enhanced in-place replacement for the previously built-in jekyll-paginate gem offering full backwards compatability as well as a slew of new frequently requested features}
|
18
|
+
|
19
|
+
spec.files = `git ls-files -z`.split("\x0")
|
20
|
+
#spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
|
+
#spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_development_dependency "jekyll", ">= 3.0"
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
26
|
+
spec.add_development_dependency "rake"
|
27
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
28
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Jekyll::Paginate V2 is a gem built for Jekyll 3 that generates pagiatation for posts, categories and tags.
|
2
|
+
#
|
3
|
+
# It is based on https://github.com/jekyll/jekyll-paginate, the original Jekyll paginator
|
4
|
+
# which was decommissioned in Jekyll 3 release onwards. This code is currently not officially
|
5
|
+
# supported on Jekyll versions < 3.0 (although it might work)
|
6
|
+
#
|
7
|
+
# Author: Sverrir Sigmundarson
|
8
|
+
# Site: https://github.com/sverrirs/jekyll-paginate-v2
|
9
|
+
# Distributed Under The MIT License (MIT) as described in the LICENSE file
|
10
|
+
# - https://opensource.org/licenses/MIT
|
11
|
+
|
12
|
+
require "jekyll-paginate-v2/version"
|
13
|
+
require "jekyll-paginate-v2/defaults"
|
14
|
+
require "jekyll-paginate-v2/utils"
|
15
|
+
require "jekyll-paginate-v2/paginator"
|
16
|
+
require "jekyll-paginate-v2/pagination"
|
17
|
+
|
18
|
+
module Jekyll
|
19
|
+
module PaginateV2
|
20
|
+
end # module PaginateV2
|
21
|
+
end # module Jekyll
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module PaginateV2
|
3
|
+
|
4
|
+
# The default configuration for the Paginator
|
5
|
+
DEFAULT = {
|
6
|
+
'enabled' => false,
|
7
|
+
'collection' => 'posts',
|
8
|
+
'per_page' => 10,
|
9
|
+
'permalink' => '/page:num/', # Supports :num as customizable elements
|
10
|
+
'title_suffix' => ' - page :num', # Supports :num as customizable elements
|
11
|
+
'page_num' => 1,
|
12
|
+
'sort_reverse' => false,
|
13
|
+
'sort_field' => 'date',
|
14
|
+
'limit' => 0 # Limit how many content objects to paginate (default: 0, means all)
|
15
|
+
}
|
16
|
+
|
17
|
+
end # module PaginateV2
|
18
|
+
end # module Jekyll
|
@@ -0,0 +1,252 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module PaginateV2
|
3
|
+
|
4
|
+
class PaginationV2 < Generator
|
5
|
+
# This generator is safe from arbitrary code execution.
|
6
|
+
safe true
|
7
|
+
|
8
|
+
# This generator should be passive with regard to its execution
|
9
|
+
priority :lowest
|
10
|
+
|
11
|
+
# Generate paginated pages if necessary (Default entry point)
|
12
|
+
# site - The Site.
|
13
|
+
#
|
14
|
+
# Returns nothing.
|
15
|
+
def generate(site)
|
16
|
+
|
17
|
+
# Retrieve and merge the folate configuration from the site yml file
|
18
|
+
default_config = DEFAULT.merge(site.config['pagination'] || {})
|
19
|
+
|
20
|
+
# If disabled then simply quit
|
21
|
+
if !default_config['enabled']
|
22
|
+
Jekyll.logger.info "Pagination:","disabled in site.config."
|
23
|
+
return
|
24
|
+
end
|
25
|
+
|
26
|
+
Jekyll.logger.debug "Pagination:","Starting"
|
27
|
+
|
28
|
+
# By default if pagination is enabled we attempt to find all index.html pages in the site
|
29
|
+
templates = self.discover_paginate_templates(site)
|
30
|
+
if( templates.size.to_i <= 0 )
|
31
|
+
Jekyll.logger.warn "Pagination:","is enabled, but I couldn't find " +
|
32
|
+
"any index.html page to use as the pagination template. Skipping pagination."
|
33
|
+
return
|
34
|
+
end
|
35
|
+
|
36
|
+
# Get all posts that will be generated (excluding hidden posts such as drafts)
|
37
|
+
all_posts = site.site_payload['site']['posts'].reject { |post| post['hidden'] }
|
38
|
+
|
39
|
+
# Create the necessary indexes for the posts
|
40
|
+
all_categories = self.index_posts_by(all_posts, 'categories')
|
41
|
+
all_categories['posts'] = all_posts; # Popuplate a category for all posts
|
42
|
+
# (this is a default and must not be used in the category system)
|
43
|
+
all_tags = self.index_posts_by(all_posts, 'tags')
|
44
|
+
all_locales = self.index_posts_by(all_posts, 'locale')
|
45
|
+
|
46
|
+
# Now for each template page generate the paginator for it
|
47
|
+
for template in templates
|
48
|
+
|
49
|
+
# All pages that should be paginated need to include the pagination config element
|
50
|
+
if template.data['pagination'].is_a?(Hash)
|
51
|
+
template_config = default_config.merge(template.data['pagination'])
|
52
|
+
|
53
|
+
# Only paginate the template if it is explicitly enabled
|
54
|
+
# requiring this makes the logic simpler as I don't need to determine which index pages
|
55
|
+
# were generated automatically and which weren't
|
56
|
+
if( template_config['enabled'] )
|
57
|
+
Jekyll.logger.info "Pagination:","found template: "+template.path
|
58
|
+
# Now construct the pagination data for this template page
|
59
|
+
self.paginate(site, template, template_config, all_posts, all_tags, all_categories, all_locales)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end #for
|
63
|
+
|
64
|
+
end # function generate
|
65
|
+
|
66
|
+
#
|
67
|
+
# Rolls through the entire site and finds all index.html pages available
|
68
|
+
#
|
69
|
+
# site - The Site.
|
70
|
+
#
|
71
|
+
def discover_paginate_templates(site)
|
72
|
+
candidates = []
|
73
|
+
site.pages.select do |page|
|
74
|
+
# If the page has the enabled config set, supports any type of file name html or md
|
75
|
+
if page.data['pagination'].is_a?(Hash) && page.data['pagination']['enabled']
|
76
|
+
candidates << page
|
77
|
+
end
|
78
|
+
end
|
79
|
+
return candidates
|
80
|
+
end # function discover_paginate_templates
|
81
|
+
|
82
|
+
#
|
83
|
+
# Create a hash index for all post based on a key in the post.data table
|
84
|
+
#
|
85
|
+
def index_posts_by(all_posts, index_key)
|
86
|
+
return nil if all_posts.nil?
|
87
|
+
return all_posts if index_key.nil?
|
88
|
+
index = {}
|
89
|
+
for post in all_posts
|
90
|
+
next if post.data.nil?
|
91
|
+
next if !post.data.has_key?(index_key)
|
92
|
+
next if post.data[index_key].nil?
|
93
|
+
next if post.data[index_key].size <= 0
|
94
|
+
next if post.data[index_key].to_s.strip.length == 0
|
95
|
+
|
96
|
+
# Only tags and categories come as premade arrays, locale does not, so convert any data
|
97
|
+
# elements that are strings into arrays
|
98
|
+
post_data = post.data[index_key]
|
99
|
+
if post_data.is_a?(String)
|
100
|
+
post_data = post_data.split(/;|,|\s/)
|
101
|
+
end
|
102
|
+
|
103
|
+
for key in post_data
|
104
|
+
key = key.downcase.strip
|
105
|
+
# If the key is a delimetered list of values
|
106
|
+
# (meaning the user didn't use an array but a string with commas)
|
107
|
+
for k_split in key.split(/;|,/)
|
108
|
+
k_split = k_split.downcase.strip #Clean whitespace and junk
|
109
|
+
if !index.has_key?(k_split)
|
110
|
+
index[k_split.to_s] = []
|
111
|
+
end
|
112
|
+
index[k_split.to_s] << post
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
return index
|
117
|
+
end # function index_posts_by
|
118
|
+
|
119
|
+
#
|
120
|
+
# Creates an intersection (only returns common elements)
|
121
|
+
# between multiple arrays
|
122
|
+
#
|
123
|
+
def intersect_arrays(first, *rest)
|
124
|
+
return nil if first.nil?
|
125
|
+
return nil if rest.nil?
|
126
|
+
|
127
|
+
intersect = first
|
128
|
+
rest.each do |item|
|
129
|
+
return [] if item.nil?
|
130
|
+
intersect = intersect & item
|
131
|
+
end
|
132
|
+
return intersect
|
133
|
+
end #function intersect_arrays
|
134
|
+
|
135
|
+
#
|
136
|
+
# Filters posts based on a keyed source_posts hash of indexed posts and performs a intersection of
|
137
|
+
# the two sets. Returns only posts that are common between all collections
|
138
|
+
#
|
139
|
+
def read_config_value_and_filter_posts(config, config_key, posts, source_posts)
|
140
|
+
return nil if posts.nil?
|
141
|
+
return nil if source_posts.nil? # If the source is empty then simply don't do anything
|
142
|
+
return posts if config.nil?
|
143
|
+
return posts if !config.has_key?(config_key)
|
144
|
+
return posts if config[config_key].nil?
|
145
|
+
|
146
|
+
# Get the filter values from the config (this is the cat/tag/locale values that should be filtered on)
|
147
|
+
config_value = config[config_key]
|
148
|
+
|
149
|
+
# If we're dealing with a delimitered string instead of an array then let's be forgiving
|
150
|
+
if( config_value.is_a?(String))
|
151
|
+
config_value = config_value.split(/;|,/)
|
152
|
+
end
|
153
|
+
|
154
|
+
# Now for all filter values for the config key, let's remove all items from the posts that
|
155
|
+
# aren't common for all collections that the user wants to filter on
|
156
|
+
for key in config_value
|
157
|
+
key = key.downcase.strip
|
158
|
+
posts = self.intersect_arrays(posts, source_posts[key])
|
159
|
+
end
|
160
|
+
|
161
|
+
# The fully filtered final post list
|
162
|
+
return posts
|
163
|
+
end #function read_config_value_and_filter_posts
|
164
|
+
|
165
|
+
#
|
166
|
+
# Sorting routine used for ordering posts by custom fields.
|
167
|
+
# Handles Strings separately as we want a case-insenstive sorting
|
168
|
+
#
|
169
|
+
def _sort_posts(a, b)
|
170
|
+
if a.is_a?(String)
|
171
|
+
return a.downcase <=> b.downcase
|
172
|
+
end
|
173
|
+
|
174
|
+
# By default use the built in sorting for the data type
|
175
|
+
return a <=> b
|
176
|
+
end
|
177
|
+
|
178
|
+
# Paginates the blog's posts. Renders the index.html file into paginated
|
179
|
+
# directories, e.g.: page2/index.html, page3/index.html, etc and adds more
|
180
|
+
# site-wide data.
|
181
|
+
#
|
182
|
+
# site - The Site.
|
183
|
+
# template - The index.html Page that requires pagination.
|
184
|
+
# config - The configuration settings that should be used
|
185
|
+
#
|
186
|
+
def paginate(site, template, config, all_posts, all_tags, all_categories, all_locales)
|
187
|
+
|
188
|
+
# By default paginate on all posts in the site
|
189
|
+
using_posts = all_posts
|
190
|
+
|
191
|
+
# Now start filtering out any posts that the user doesn't want included in the pagination
|
192
|
+
using_posts = self.read_config_value_and_filter_posts(config, 'category', using_posts, all_categories)
|
193
|
+
using_posts = self.read_config_value_and_filter_posts(config, 'tag', using_posts, all_tags)
|
194
|
+
using_posts = self.read_config_value_and_filter_posts(config, 'locale', using_posts, all_locales)
|
195
|
+
|
196
|
+
# Apply sorting to the posts if configured, any field for the post is available for sorting
|
197
|
+
if config['sort_field']
|
198
|
+
sort_field = config['sort_field'].to_s
|
199
|
+
using_posts.sort!{ |a,b| self._sort_posts(a.data[sort_field], b.data[sort_field]) }
|
200
|
+
|
201
|
+
if config['sort_reverse']
|
202
|
+
using_posts.reverse!
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
# Calculate the max number of pagination-pages based on the configured per page value
|
207
|
+
total_pages = self.calculate_number_of_pages(using_posts, config['per_page'])
|
208
|
+
|
209
|
+
# If a upper limit is set on the number of total pagination pages then impose that now
|
210
|
+
if config['limit'] && config['limit'].to_i > 0 && config['limit'].to_i < total_pages
|
211
|
+
total_pages = config['limit'].to_i
|
212
|
+
end
|
213
|
+
|
214
|
+
# Now for each pagination page create it and configure the ranges for the collection
|
215
|
+
# This .pager member is a built in thing in Jekyll and defines the paginator implementation
|
216
|
+
# Simpy override to use mine
|
217
|
+
(1..total_pages).each do |cur_page_nr|
|
218
|
+
pager = PaginatorV2.new( config, using_posts, cur_page_nr, total_pages, template )
|
219
|
+
if( cur_page_nr > 1)
|
220
|
+
newpage = Page.new( site, site.source, template.dir, template.name)
|
221
|
+
newpage.pager = pager
|
222
|
+
newpage.dir = Utils.paginate_path(template, cur_page_nr, config)
|
223
|
+
if( config.has_key?('title_suffix'))
|
224
|
+
if( !template.data['title'] )
|
225
|
+
tmp_title = site.config['title']
|
226
|
+
else
|
227
|
+
tmp_title = template.data['title']
|
228
|
+
end
|
229
|
+
|
230
|
+
newpage.data['title'] = "#{tmp_title}#{Utils.format_page_number(config['title_suffix'], cur_page_nr)}"
|
231
|
+
end
|
232
|
+
site.pages << newpage
|
233
|
+
else
|
234
|
+
template.pager = pager
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end # function paginate
|
238
|
+
|
239
|
+
# Calculate the number of pages.
|
240
|
+
#
|
241
|
+
# all_posts - The Array of all Posts.
|
242
|
+
# per_page - The Integer of entries per page.
|
243
|
+
#
|
244
|
+
# Returns the Integer number of pages.
|
245
|
+
def calculate_number_of_pages(all_posts, per_page)
|
246
|
+
(all_posts.size.to_f / per_page.to_i).ceil
|
247
|
+
end
|
248
|
+
|
249
|
+
end # class PaginationV2
|
250
|
+
|
251
|
+
end # module PaginateV2
|
252
|
+
end # module Jekyll
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module PaginateV2
|
3
|
+
|
4
|
+
#
|
5
|
+
# Handles the preparation of all the posts based on the current page index
|
6
|
+
#
|
7
|
+
class PaginatorV2
|
8
|
+
attr_reader :page, :per_page, :posts, :total_posts, :total_pages,
|
9
|
+
:previous_page, :previous_page_path, :next_page, :next_page_path
|
10
|
+
|
11
|
+
# Initialize a new Paginator.
|
12
|
+
#
|
13
|
+
# site - the Jekyll::Site object
|
14
|
+
# page_nr - The Integer page number.
|
15
|
+
# all_posts - The Array of all the site's Posts.
|
16
|
+
# num_pages - The Integer number of pages or nil if you'd like the number
|
17
|
+
# of pages calculated.
|
18
|
+
def initialize(config, posts, cur_page_nr, num_pages, template )
|
19
|
+
@page = cur_page_nr
|
20
|
+
@per_page = config['per_page'].to_i
|
21
|
+
@total_pages = num_pages
|
22
|
+
|
23
|
+
if @page > @total_pages
|
24
|
+
raise RuntimeError, "page number can't be greater than total pages: #{@page} > #{@total_pages}"
|
25
|
+
end
|
26
|
+
|
27
|
+
init = (@page - 1) * @per_page
|
28
|
+
offset = (init + @per_page - 1) >= posts.size ? posts.size : (init + @per_page - 1)
|
29
|
+
|
30
|
+
@total_posts = posts.size
|
31
|
+
@posts = posts[init..offset]
|
32
|
+
@previous_page = @page != 1 ? @page - 1 : nil
|
33
|
+
@previous_page_path = Utils.paginate_path(template, @previous_page, config)
|
34
|
+
@next_page = @page != @total_pages ? @page + 1 : nil
|
35
|
+
@next_page_path = Utils.paginate_path(template, @next_page, config)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Convert this Paginator's data to a Hash suitable for use by Liquid.
|
39
|
+
#
|
40
|
+
# Returns the Hash representation of this Paginator.
|
41
|
+
def to_liquid
|
42
|
+
{
|
43
|
+
'per_page' => per_page,
|
44
|
+
'posts' => posts,
|
45
|
+
'total_posts' => total_posts,
|
46
|
+
'total_pages' => total_pages,
|
47
|
+
'page' => page,
|
48
|
+
'previous_page' => previous_page,
|
49
|
+
'previous_page_path' => previous_page_path,
|
50
|
+
'next_page' => next_page,
|
51
|
+
'next_page_path' => next_page_path
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
end # class PaginatorV2
|
56
|
+
|
57
|
+
end # module PaginateV2
|
58
|
+
end # module Jekyll
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module PaginateV2
|
3
|
+
|
4
|
+
#
|
5
|
+
# Static utility functions that are used in the code and
|
6
|
+
# don't belong in once place in particular
|
7
|
+
#
|
8
|
+
class Utils
|
9
|
+
|
10
|
+
# Static: Return the pagination path of the page
|
11
|
+
#
|
12
|
+
# site - the Jekyll::Site object
|
13
|
+
# cur_page_nr - the pagination page number
|
14
|
+
# config - the current configuration in use
|
15
|
+
#
|
16
|
+
# Returns the pagination path as a string
|
17
|
+
def self.paginate_path(template, cur_page_nr, config)
|
18
|
+
return nil if cur_page_nr.nil?
|
19
|
+
return template.url if cur_page_nr <= 1
|
20
|
+
format = config['permalink']
|
21
|
+
if format.include?(":num")
|
22
|
+
format = Utils.format_page_number(format, cur_page_nr)
|
23
|
+
else
|
24
|
+
raise ArgumentError.new("Invalid pagination path: '#{format}'. It must include ':num'.")
|
25
|
+
end
|
26
|
+
Utils.ensure_leading_slash(format)
|
27
|
+
end #function paginate_path
|
28
|
+
|
29
|
+
# Static: returns a fully formatted string with the current page number if configured
|
30
|
+
#
|
31
|
+
def self.format_page_number(toFormat, cur_page_nr)
|
32
|
+
return toFormat.sub(':num', cur_page_nr.to_s)
|
33
|
+
end #function format_page_number
|
34
|
+
|
35
|
+
# Static: Return a String version of the input which has a leading slash.
|
36
|
+
# If the input already has a forward slash in position zero, it will be
|
37
|
+
# returned unchanged.
|
38
|
+
#
|
39
|
+
# path - a String path
|
40
|
+
#
|
41
|
+
# Returns the path with a leading slash
|
42
|
+
def self.ensure_leading_slash(path)
|
43
|
+
path[0..0] == "/" ? path : "/#{path}"
|
44
|
+
end
|
45
|
+
|
46
|
+
# Static: Return a String version of the input without a leading slash.
|
47
|
+
#
|
48
|
+
# path - a String path
|
49
|
+
#
|
50
|
+
# Returns the input without the leading slash
|
51
|
+
def self.remove_leading_slash(path)
|
52
|
+
path[0..0] == "/" ? path[1..-1] : path
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end # module PaginateV2
|
58
|
+
end # module Jekyll
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jekyll-paginate-v2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sverrir Sigmundarson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-11-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: jekyll
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.5'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.5'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
description: An enhanced in-place replacement for the previously built-in jekyll-paginate
|
70
|
+
gem offering full backwards compatability as well as a slew of new frequently requested
|
71
|
+
features
|
72
|
+
email:
|
73
|
+
- jekyll@sverrirs.com
|
74
|
+
executables: []
|
75
|
+
extensions: []
|
76
|
+
extra_rdoc_files: []
|
77
|
+
files:
|
78
|
+
- ".gitignore"
|
79
|
+
- Gemfile
|
80
|
+
- LICENSE
|
81
|
+
- README.md
|
82
|
+
- jekyll-paginate-v2.gemspec
|
83
|
+
- lib/jekyll-paginate-v2.rb
|
84
|
+
- lib/jekyll-paginate-v2/defaults.rb
|
85
|
+
- lib/jekyll-paginate-v2/pagination.rb
|
86
|
+
- lib/jekyll-paginate-v2/paginator.rb
|
87
|
+
- lib/jekyll-paginate-v2/utils.rb
|
88
|
+
- lib/jekyll-paginate-v2/version.rb
|
89
|
+
homepage: https://github.com/sverrirs/jekyll-paginate-v2
|
90
|
+
licenses:
|
91
|
+
- MIT
|
92
|
+
metadata: {}
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 2.4.8
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: Pagination Generator for Jekyll 3
|
113
|
+
test_files: []
|