Class: Bridgetown::Paginate::PaginationGenerator

Inherits:
Generator
  • Object
show all
Defined in:
lib/bridgetown-paginate/pagination_generator.rb

Overview

The main entry point into the generator, called by Bridgetown this function extracts all the necessary information from the Bridgetown end and passes it into the pagination logic. Additionally it also contains all site specific actions that the pagination logic needs access to (such as how to create new pages)

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.add_matching_template(template) ⇒ Object



21
22
23
# File 'lib/bridgetown-paginate/pagination_generator.rb', line 21

def self.add_matching_template(template)
  matching_templates << template
end

.matching_templatesSet<Bridgetown::Page, Bridgetown::Resource::Base>

Returns:

  • (Set<Bridgetown::Page, Bridgetown::Resource::Base>)


17
18
19
# File 'lib/bridgetown-paginate/pagination_generator.rb', line 17

def self.matching_templates
  @matching_templates ||= Set.new
end

Instance Method Details

#generate(site) ⇒ Object

Generate paginated pages if necessary (Default entry point) site - The Site.

Returns nothing.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/bridgetown-paginate/pagination_generator.rb', line 29

def generate(site) # rubocop:todo Metrics/AbcSize
  # Retrieve and merge the pagination configuration from the site yml file
  default_config = Bridgetown::Utils.deep_merge_hashes(
    DEFAULT,
    site.config["pagination"] || {}
  )

  # If disabled then simply quit
  unless default_config["enabled"]
    Bridgetown.logger.info "Pagination:", "disabled. Enable in site config " \
                                          "with pagination:\\n  enabled: true"
    return
  end

  Bridgetown.logger.debug "Pagination:", "Starting"

  # Get all matching pages in the site found by the init hooks, and ensure they're
  # still in the site.generated_pages array
  templates = self.class.matching_templates.select do |page|
    site.generated_pages.include?(page) || site.resources.include?(page)
  end

  # Get the default title of the site (used as backup when there is no
  # title available for pagination)
  site_title = site.data.dig("metadata", "title") || site.config["title"]

  # Specify the callback function that returns the correct docs/posts
  # based on the collection name
  # Posts collection is the default and if the user doesn't specify a
  # collection in their front-matter then that is the one we load
  # If the collection is not found then empty array is returned
  collection_by_name_lambda = ->(collection_name) do
    coll = []
    if collection_name == "all"
      # the 'all' collection_name is a special case and includes all
      # collections in the site (except posts!!)
      # this is useful when you want to list items across multiple collections
      site.collections.each do |coll_name, collection|
        next unless !collection.nil? && coll_name != "posts"

        # Exclude all pagination pages
        coll += collection.each.reject do |doc|
          doc.data.key?("pagination") || doc.data.key?("paginate")
        end
      end
    else
      # Just the one collection requested
      return [] unless site.collections.key?(collection_name)

      # Exclude all pagination pages
      coll = site.collections[collection_name].each.reject do |doc|
        doc.data.key?("pagination") || doc.data.key?("paginate")
      end
    end
    coll
  end

  # Create the proc that constructs the real-life site page
  # This is necessary to decouple the code from the Bridgetown site object
  page_add_lambda = ->(newpage) do
    site.add_generated_page newpage
    newpage # Return the site to the calling code
  end

  # lambda that removes a page from the site pages list
  page_remove_lambda = ->(page_to_remove) do
    if page_to_remove.is_a?(Bridgetown::Resource::Base)
      page_to_remove.collection.resources.delete(page_to_remove)
    else
      site.generated_pages.delete(page_to_remove)
    end
    page_to_remove.unmark_for_fast_refresh!
  end

  # Create a proc that will delegate logging
  # Decoupling Bridgetown specific logging
  logging_lambda = ->(message, type = "info") do
    case type
    when "debug"
      Bridgetown.logger.debug "Pagination:", message.to_s
    when "error"
      Bridgetown.logger.error "Pagination:", message.to_s
    when "warn"
      Bridgetown.logger.warn "Pagination:", message.to_s
    else
      Bridgetown.logger.info "Pagination:", message.to_s
    end
  end

  # Now create and call the model with the real-life page creation proc and site data
  model = PaginationModel.new(
    logging_lambda,
    page_add_lambda,
    page_remove_lambda,
    collection_by_name_lambda
  )
  count = model.run(default_config, templates, site_title)
  self.class.matching_templates.clear
  Bridgetown.logger.info "Pagination:", "Complete, processed #{count} pagination page(s)"
end