jekyll-paginate-v2 1.5.2 → 1.6.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.
@@ -7,6 +7,7 @@ Gem::Specification.new do |spec|
7
7
  spec.name = "jekyll-paginate-v2"
8
8
  spec.version = Jekyll::PaginateV2::VERSION
9
9
  spec.platform = Gem::Platform::RUBY
10
+ spec.required_ruby_version = '>= 2.0.0' # Same as Jekyll
10
11
  spec.date = DateTime.now.strftime('%Y-%m-%d')
11
12
  spec.authors = ["Sverrir Sigmundarson"]
12
13
  spec.email = ["jekyll@sverrirs.com"]
@@ -14,16 +15,18 @@ Gem::Specification.new do |spec|
14
15
  spec.license = "MIT"
15
16
 
16
17
  spec.summary = %q{Pagination Generator for Jekyll 3}
17
- spec.description = %q{An enhanced zero-configuration in-place replacement for the now decomissioned built-in jekyll-paginate gem. This pagination gem offers full backwards compatability as well as a slew of new frequently requested features with minimal additional site and page configuration.}
18
+ spec.description = %q{An enhanced zero-configuration in-place replacement for the now decomissioned built-in jekyll-paginate gem. This pagination gem offers full backwards compatability as well as a slew of new frequently requested features with minimal additional site and page configuration. Optional features include auto-generation of paginated collection, tag and category pages.}
18
19
 
19
- #spec.files = `git ls-files -z`.split("\x0")
20
- spec.files = Dir['CODE_OF_CONDUCT.md', 'README.md', 'LICENSE', 'Rakefile', '*.gemspec', 'Gemfile', 'lib/**/*', 'spec/**/*']
21
- #spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.files = Dir['CODE_OF_CONDUCT.md', 'README*.md', 'LICENSE', 'Rakefile', '*.gemspec', 'Gemfile', 'lib/**/*', 'spec/**/*']
22
21
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
22
  spec.require_paths = ["lib"]
24
23
 
25
- spec.add_development_dependency "jekyll", ">= 3.0"
24
+ # Gem requires Jekyll to work
25
+ # ~> is the pessimistic operator and is equivalent to '>= 3.0', '< 4.0'
26
+ spec.add_runtime_dependency "jekyll", "~> 3.0"
27
+
28
+ # Development requires more
26
29
  spec.add_development_dependency "bundler", "~> 1.5"
27
- spec.add_development_dependency "rake"
28
- spec.add_development_dependency "minitest", '~> 5.4', '>= 5.4.3'
30
+ spec.add_development_dependency "rake", "~> 10.4"
31
+ spec.add_development_dependency "minitest", '~> 5.4'
29
32
  end
@@ -20,7 +20,13 @@ require "jekyll-paginate-v2/generator/paginationPage"
20
20
  require "jekyll-paginate-v2/generator/paginationModel"
21
21
  require "jekyll-paginate-v2/generator/paginationGenerator"
22
22
  # Files needed for the auto category and tag pages
23
-
23
+ require "jekyll-paginate-v2/autopages/utils"
24
+ require "jekyll-paginate-v2/autopages/defaults"
25
+ require "jekyll-paginate-v2/autopages/autoPages"
26
+ require "jekyll-paginate-v2/autopages/pages/baseAutoPage"
27
+ require "jekyll-paginate-v2/autopages/pages/categoryAutoPage"
28
+ require "jekyll-paginate-v2/autopages/pages/collectionAutoPage"
29
+ require "jekyll-paginate-v2/autopages/pages/tagAutoPage"
24
30
 
25
31
  module Jekyll
26
32
  module PaginateV2
@@ -0,0 +1,77 @@
1
+ module Jekyll
2
+ module PaginateV2::AutoPages
3
+
4
+ #
5
+ # When the site has been read then go a head an generate the necessary extra pages
6
+ # This code is adapted from Stephen Crosby's code https://github.com/stevecrozz
7
+ Jekyll::Hooks.register :site, :post_read do |site|
8
+
9
+ # Get the configuration for the auto pages
10
+ autopage_config = Jekyll::Utils.deep_merge_hashes(DEFAULT, site.config['autopages'] || {})
11
+ pagination_config = Jekyll::Utils.deep_merge_hashes(Jekyll::PaginateV2::Generator::DEFAULT, site.config['pagination'] || {})
12
+
13
+ # If disabled then don't do anything
14
+ if !autopage_config['enabled'] || autopage_config['enabled'].nil?
15
+ Jekyll.logger.info "AutoPages:","Disabled/Not configured in site.config."
16
+ next ## Break the loop, could be an issue if the hook is called again though??
17
+ end
18
+
19
+ # TODO: Should I detect here and disable if we're running the legacy paginate code???!
20
+
21
+ # Simply gather all documents across all pages/posts/collections that we have
22
+ # we could be generating quite a few empty pages but the logic is just vastly simpler than trying to
23
+ # figure out what tag/category belong to which collection.
24
+ posts_to_use = Utils.collect_all_docs(site.collections)
25
+
26
+ ###############################################
27
+ # Generate the Tag pages if enabled
28
+ createtagpage_lambda = lambda do | autopage_tag_config, pagination_config, layout_name, tag |
29
+ site.pages << TagAutoPage.new(site, site.dest, autopage_tag_config, pagination_config, layout_name, tag)
30
+ end
31
+ autopage_create(autopage_config, pagination_config, posts_to_use, 'tags', 'tags', createtagpage_lambda) # Call the actual function
32
+
33
+
34
+ ###############################################
35
+ # Generate the category pages if enabled
36
+ createcatpage_lambda = lambda do | autopage_cat_config, pagination_config, layout_name, category |
37
+ site.pages << CategoryAutoPage.new(site, site.dest, autopage_cat_config, pagination_config, layout_name, category)
38
+ end
39
+ autopage_create(autopage_config, pagination_config,posts_to_use, 'categories', 'categories', createcatpage_lambda) # Call the actual function
40
+
41
+ ###############################################
42
+ # Generate the Collection pages if enabled
43
+ createcolpage_lambda = lambda do | autopage_col_config, pagination_config, layout_name, coll_name |
44
+ site.pages << CollectionAutoPage.new(site, site.dest, autopage_col_config, pagination_config, layout_name, coll_name)
45
+ end
46
+ autopage_create(autopage_config, pagination_config,posts_to_use, 'collections', '__coll', createcolpage_lambda) # Call the actual function
47
+
48
+ end # Jekyll::Hooks
49
+
50
+
51
+ # STATIC: this function actually performs the steps to generate the autopages. It uses a lambda function to delegate the creation of the individual
52
+ # page types to the calling code (this way all features can reuse the logic).
53
+ #
54
+ def self.autopage_create(autopage_config, pagination_config, posts_to_use, configkey_name, indexkey_name, createpage_lambda )
55
+ if !autopage_config[configkey_name].nil?
56
+ ap_sub_config = autopage_config[configkey_name]
57
+ if ap_sub_config ['enabled']
58
+ Jekyll.logger.info "AutoPages:","Generating #{configkey_name} pages"
59
+
60
+ # Roll through all documents in the posts collection and extract the tags
61
+ index_keys = Utils.index_posts_by(posts_to_use, indexkey_name).keys # Cannot use just the posts here, must use all things.. posts, collections...
62
+
63
+ index_keys.each do |index_key|
64
+ # Iterate over each layout specified in the config
65
+ ap_sub_config ['layouts'].each do | layout_name |
66
+ # Use site.dest here as these pages are never created in the actual source but only inside the _site folder
67
+ createpage_lambda.call(ap_sub_config, pagination_config, layout_name, index_key)
68
+ end
69
+ end
70
+ else
71
+ Jekyll.logger.info "AutoPages:","#{configkey_name} pages are disabled/not configured in site.config."
72
+ end
73
+ end
74
+ end
75
+
76
+ end # module PaginateV2
77
+ end # module Jekyll
@@ -1,26 +1,29 @@
1
1
  module Jekyll
2
2
  module PaginateV2::AutoPages
3
3
 
4
- # Construct an extended version of the pagination config for the tag pages
5
- tagDefaults = Jekyll::PaginateV2::Generator::DEFAULT.merge({
6
- 'layout' => 'autopage_tags.html',
7
- 'title' => 'Posts tagged with :tag',
8
- 'permalink' => '/tags/:tag'
9
- })
10
-
11
- # Extend the pagination config for the categories as well
12
- catDefaults = Jekyll::PaginateV2::Generator::DEFAULT.merge({
13
- 'layout' => 'autopage_category.html',
14
- 'title' => 'Posts in category :cat',
15
- 'permalink' => '/category/:cat'
16
- })
17
-
18
4
  # The default configuration for the AutoPages
19
5
  DEFAULT = {
20
- 'enabled' => false,
21
- 'tags' => tagDefaults,
22
- 'category'=> catDefaults
6
+ 'enabled' => false,
7
+ 'tags' => {
8
+ 'layouts' => ['autopage_tags.html'],
9
+ 'title' => 'Posts tagged with :tag`',
10
+ 'permalink' => '/tag/:tag',
11
+ 'enabled' => true
12
+
13
+ },
14
+ 'categories' => {
15
+ 'layouts' => ['autopage_category.html'],
16
+ 'title' => 'Posts in category :cat',
17
+ 'permalink' => '/category/:cat',
18
+ 'enabled' => true
19
+ },
20
+ 'collections' => {
21
+ 'layouts' => ['autopage_collection.html'],
22
+ 'title' => 'Posts in collection :coll',
23
+ 'permalink' => '/collection/:coll',
24
+ 'enabled' => true
25
+ }
23
26
  }
24
27
 
25
- end # module PaginateV2
28
+ end # module PaginateV2::AutoPages
26
29
  end # module Jekyll
@@ -0,0 +1,60 @@
1
+ module Jekyll
2
+ module PaginateV2::AutoPages
3
+
4
+ class BaseAutoPage < Jekyll::Page
5
+ def initialize(site, base, autopage_config, pagination_config, layout_name, set_autopage_data_lambda, get_autopage_permalink_lambda, get_autopage_title_lambda)
6
+ @site = site
7
+ @base = base
8
+ @name = 'index.html'
9
+
10
+ layout_dir = '_layouts'
11
+
12
+ # Path is only used by the convertible module and accessed below when calling read_yaml
13
+ # Handling themes stored in a gem
14
+ @path = if site.in_theme_dir(site.source) == site.source # we're in a theme
15
+ site.in_theme_dir(site.source, layout_dir, layout_name)
16
+ else
17
+ site.in_source_dir(site.source, layout_dir, layout_name)
18
+ end
19
+
20
+ self.process(@name) # Creates the base name and extension
21
+ self.read_yaml(File.join(site.source, layout_dir), layout_name)
22
+
23
+ # Merge the config with any config that might already be defined in the layout
24
+ pagination_layout_config = Jekyll::Utils.deep_merge_hashes( pagination_config, self.data['pagination'] || {} )
25
+
26
+ # Read any possible autopage overrides in the layout page
27
+ autopage_layout_config = Jekyll::Utils.deep_merge_hashes( autopage_config, self.data['autopages'] || {} )
28
+
29
+ # Now set the page specific pagination data
30
+ set_autopage_data_lambda.call(pagination_layout_config)
31
+
32
+ # Get permalink structure
33
+ permalink_formatted = get_autopage_permalink_lambda.call(autopage_layout_config['permalink'])
34
+
35
+ # Construct the title
36
+ page_title = autopage_layout_config['title']
37
+
38
+ # NOTE: Should we set this before calling read_yaml as that function validates the permalink structure
39
+ self.data['permalink'] = permalink_formatted
40
+ @url = File.join(permalink_formatted, @name)
41
+ @dir = permalink_formatted
42
+
43
+ self.data['layout'] = File.basename(layout_name, File.extname(layout_name))
44
+ self.data['title'] = get_autopage_title_lambda.call( page_title )
45
+ self.data['pagination'] = pagination_layout_config # Store the pagination configuration
46
+
47
+ # Add the auto page flag in there to be able to detect the page (necessary when figuring out where to load it from)
48
+ # TODO: Need to re-think this variable!!!
49
+ self.data['autopage'] = {"layout_path" => File.join( layout_dir, layout_name ) }
50
+
51
+ data.default_proc = proc do |_, key|
52
+ site.frontmatter_defaults.find(File.join(layout_dir, layout_name), type, key)
53
+ end
54
+
55
+ # Trigger a page event
56
+ #Jekyll::Hooks.trigger :pages, :post_init, self
57
+ end #function initialize
58
+ end #class BaseAutoPage
59
+ end # module PaginateV2
60
+ end # module Jekyll
@@ -0,0 +1,28 @@
1
+ module Jekyll
2
+ module PaginateV2::AutoPages
3
+
4
+ class CategoryAutoPage < BaseAutoPage
5
+ def initialize(site, base, autopage_config, pagination_config, layout_name, category)
6
+
7
+ # Construc the lambda function to set the config values
8
+ # this function received the pagination config hash and manipulates it
9
+ set_autopage_data_lambda = lambda do | in_config |
10
+ in_config['category'] = category
11
+ end
12
+
13
+ get_autopage_permalink_lambda = lambda do |permalink_pattern|
14
+ return Utils.format_cat_macro(permalink_pattern, category)
15
+ end
16
+
17
+ get_autopage_title_lambda = lambda do |title_pattern|
18
+ return Utils.format_cat_macro(title_pattern, category)
19
+ end
20
+
21
+ # Call the super constuctor with our custom lambda
22
+ super(site, base, autopage_config, pagination_config, layout_name, set_autopage_data_lambda, get_autopage_permalink_lambda, get_autopage_title_lambda)
23
+
24
+ end #function initialize
25
+
26
+ end #class CategoryAutoPage
27
+ end # module PaginateV2
28
+ end # module Jekyll
@@ -0,0 +1,28 @@
1
+ module Jekyll
2
+ module PaginateV2::AutoPages
3
+
4
+ class CollectionAutoPage < BaseAutoPage
5
+ def initialize(site, base, autopage_config, pagination_config, layout_name, collection)
6
+
7
+ # Construc the lambda function to set the config values
8
+ # this function received the pagination config hash and manipulates it
9
+ set_autopage_data_lambda = lambda do | in_config |
10
+ in_config['collection'] = collection
11
+ end
12
+
13
+ get_autopage_permalink_lambda = lambda do |permalink_pattern|
14
+ return Utils.format_coll_macro(permalink_pattern, collection)
15
+ end
16
+
17
+ get_autopage_title_lambda = lambda do |title_pattern|
18
+ return Utils.format_coll_macro(title_pattern, collection)
19
+ end
20
+
21
+ # Call the super constuctor with our custom lambda
22
+ super(site, base, autopage_config, pagination_config, layout_name, set_autopage_data_lambda, get_autopage_permalink_lambda, get_autopage_title_lambda)
23
+
24
+ end #function initialize
25
+
26
+ end #class CollectionAutoPage
27
+ end # module PaginateV2
28
+ end # module Jekyll
@@ -0,0 +1,28 @@
1
+ module Jekyll
2
+ module PaginateV2::AutoPages
3
+
4
+ class TagAutoPage < BaseAutoPage
5
+ def initialize(site, base, autopage_config, pagination_config, layout_name, tag)
6
+
7
+ # Construc the lambda function to set the config values,
8
+ # this function received the pagination config hash and manipulates it
9
+ set_autopage_data_lambda = lambda do | config |
10
+ config['tag'] = tag
11
+ end
12
+
13
+ get_autopage_permalink_lambda = lambda do |permalink_pattern|
14
+ return Utils.format_tag_macro(permalink_pattern, tag)
15
+ end
16
+
17
+ get_autopage_title_lambda = lambda do |title_pattern|
18
+ return Utils.format_tag_macro(title_pattern, tag)
19
+ end
20
+
21
+ # Call the super constuctor with our custom lambda
22
+ super(site, base, autopage_config, pagination_config, layout_name, set_autopage_data_lambda, get_autopage_permalink_lambda, get_autopage_title_lambda)
23
+
24
+ end #function initialize
25
+
26
+ end #class TagAutoPage
27
+ end # module PaginateV2
28
+ end # module Jekyll
@@ -6,14 +6,66 @@ module Jekyll
6
6
  # Static: returns a fully formatted string with the tag macro (:tag) replaced
7
7
  #
8
8
  def self.format_tag_macro(toFormat, tag)
9
- return toFormat.sub(':tag', Jekyll::Utils.slugify(tag.to_s)
9
+ return toFormat.sub(':tag', Jekyll::Utils.slugify(tag.to_s))
10
10
  end #function format_tag_macro
11
11
 
12
12
  # Static: returns a fully formatted string with the category macro (:cat) replaced
13
13
  #
14
14
  def self.format_cat_macro(toFormat, category)
15
15
  return toFormat.sub(':cat', Jekyll::Utils.slugify(category.to_s))
16
- end #function format_tag_macro
16
+ end #function format_cat_macro
17
+
18
+ # Static: returns a fully formatted string with the collection macro (:coll) replaced
19
+ #
20
+ def self.format_coll_macro(toFormat, collection)
21
+ return toFormat.sub(':coll', Jekyll::Utils.slugify(collection.to_s))
22
+ end #function format_coll_macro
23
+
24
+ # Static: returns all documents from all collections defined in the hash of collections passed in
25
+ # excludes all pagination pages though
26
+ def self.collect_all_docs(site_collections)
27
+ coll = []
28
+ for coll_name, coll_data in site_collections
29
+ if !coll_data.nil?
30
+ coll += coll_data.docs.select { |doc| !doc.data.has_key?('pagination') }.each{ |doc| doc.data['__coll'] = coll_name } # Exclude all pagination pages and then for every page store it's collection name
31
+ end
32
+ end
33
+ return coll
34
+ end
35
+
36
+ def self.index_posts_by(all_posts, index_key)
37
+ return nil if all_posts.nil?
38
+ return all_posts if index_key.nil?
39
+ index = {}
40
+ for post in all_posts
41
+ next if post.data.nil?
42
+ next if !post.data.has_key?(index_key)
43
+ next if post.data[index_key].nil?
44
+ next if post.data[index_key].size <= 0
45
+ next if post.data[index_key].to_s.strip.length == 0
46
+
47
+ # Only tags and categories come as premade arrays, locale does not, so convert any data
48
+ # elements that are strings into arrays
49
+ post_data = post.data[index_key]
50
+ if post_data.is_a?(String)
51
+ post_data = post_data.split(/;|,|\s/)
52
+ end
53
+
54
+ for key in post_data
55
+ key = key.downcase.strip
56
+ # If the key is a delimetered list of values
57
+ # (meaning the user didn't use an array but a string with commas)
58
+ for k_split in key.split(/;|,/)
59
+ k_split = k_split.downcase.strip #Clean whitespace and junk
60
+ if !index.has_key?(k_split)
61
+ index[k_split.to_s] = []
62
+ end
63
+ index[k_split.to_s] << post
64
+ end
65
+ end
66
+ end
67
+ return index
68
+ end # function index_posts_by
17
69
 
18
70
  end # class Utils
19
71
 
@@ -1,6 +1,35 @@
1
1
  module Jekyll
2
2
  module PaginateV2::Generator
3
3
 
4
+ class CompatibilityPaginationPage < Page
5
+ def initialize(site, base, dir, template_path)
6
+ @site = site
7
+ @base = base
8
+ @dir = dir
9
+ @template = template_path
10
+ @name = 'index.html'
11
+
12
+ templ_dir = File.dirname(template_path)
13
+ templ_file = File.basename(template_path)
14
+
15
+ # Path is only used by the convertible module and accessed below when calling read_yaml
16
+ # in our case we have the path point to the original template instead of our faux new pagination page
17
+ @path = if site.in_theme_dir(base) == base # we're in a theme
18
+ site.in_theme_dir(base, templ_dir, templ_file)
19
+ else
20
+ site.in_source_dir(base, templ_dir, templ_file)
21
+ end
22
+
23
+ self.process(@name)
24
+ self.read_yaml(templ_dir, templ_file)
25
+
26
+ data.default_proc = proc do |_, key|
27
+ site.frontmatter_defaults.find(File.join(templ_dir, templ_file), type, key)
28
+ end
29
+
30
+ end
31
+ end # class CompatibilityPaginationPage
32
+
4
33
  #
5
34
  # Static utility functions that provide backwards compatibility with the old
6
35
  # jekyll-paginate gem that this new version superseeds (this code is here to ensure)
@@ -50,21 +79,43 @@ module Jekyll
50
79
  # directories, e.g.: page2/index.html, page3/index.html, etc and adds more
51
80
  # site-wide data.
52
81
  #
53
- def self.paginate(legacy_config, all_posts, page, page_create_lambda )
82
+ def self.paginate(legacy_config, all_posts, page, page_add_lambda )
54
83
  pages = Utils.calculate_number_of_pages(all_posts, legacy_config['per_page'].to_i)
55
84
  (1..pages).each do |num_page|
56
- pager = Paginator.new( legacy_config['per_page'], legacy_config['permalink'], all_posts, num_page, pages, page.url, page.path )
85
+ pager = Paginator.new( legacy_config['per_page'], page.url, legacy_config['permalink'], all_posts, num_page, pages )
57
86
  if num_page > 1
58
- newpage = page_create_lambda.call( page.path )
87
+ template_full_path = File.join(page.site.source, page.path)
88
+ template_dir = File.dirname(page.path)
89
+ newpage = CompatibilityPaginationPage.new(page.site, page.site.source, template_dir, template_full_path)
59
90
  newpage.pager = pager
60
- newpage.dir = Utils.paginate_path(page.url, page.path, num_page, legacy_config['permalink'])
91
+ newpage.dir = CompatibilityUtils.paginate_path(page.url, num_page, legacy_config['permalink'])
61
92
  newpage.data['autogen'] = "jekyll-paginate-v2" # Signals that this page is automatically generated by the pagination logic
93
+ page_add_lambda.call(newpage)
62
94
  else
63
95
  page.pager = pager
64
96
  end
65
97
  end
66
98
  end
67
99
 
100
+ # Static: Return the pagination path of the page
101
+ #
102
+ # site - the Jekyll::Site object
103
+ # cur_page_nr - the pagination page number
104
+ # config - the current configuration in use
105
+ #
106
+ # Returns the pagination path as a string
107
+ def self.paginate_path(template_url, cur_page_nr, permalink_format)
108
+ return nil if cur_page_nr.nil?
109
+ return template_url if cur_page_nr <= 1
110
+ if permalink_format.include?(":num")
111
+ permalink_format = Utils.format_page_number(permalink_format, cur_page_nr)
112
+ else
113
+ raise ArgumentError.new("Invalid pagination path: '#{permalink_format}'. It must include ':num'.")
114
+ end
115
+
116
+ Utils.ensure_leading_slash(permalink_format)
117
+ end #function paginate_path
118
+
68
119
  end # class CompatibilityUtils
69
120
  end # module PaginateV2
70
121
  end # module Jekyll