pagy 4.11.0 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/lib/config/pagy.rb +119 -58
  4. data/lib/javascripts/pagy-dev.js +114 -0
  5. data/lib/javascripts/pagy-module.d.ts +5 -0
  6. data/lib/javascripts/pagy-module.js +113 -0
  7. data/lib/javascripts/pagy.js +1 -121
  8. data/lib/locales/de.yml +1 -1
  9. data/lib/locales/ko.yml +1 -1
  10. data/lib/locales/nn.yml +22 -0
  11. data/lib/locales/ta.yml +22 -0
  12. data/lib/pagy/backend.rb +10 -13
  13. data/lib/pagy/calendar/day.rb +39 -0
  14. data/lib/pagy/calendar/helper.rb +61 -0
  15. data/lib/pagy/calendar/month.rb +40 -0
  16. data/lib/pagy/calendar/quarter.rb +47 -0
  17. data/lib/pagy/calendar/week.rb +39 -0
  18. data/lib/pagy/calendar/year.rb +33 -0
  19. data/lib/pagy/calendar.rb +100 -0
  20. data/lib/pagy/console.rb +6 -4
  21. data/lib/pagy/countless.rb +22 -23
  22. data/lib/pagy/exceptions.rb +14 -16
  23. data/lib/pagy/extras/arel.rb +11 -7
  24. data/lib/pagy/extras/array.rb +9 -9
  25. data/lib/pagy/extras/bootstrap.rb +45 -38
  26. data/lib/pagy/extras/bulma.rb +50 -38
  27. data/lib/pagy/extras/calendar.rb +49 -0
  28. data/lib/pagy/extras/countless.rb +15 -18
  29. data/lib/pagy/extras/elasticsearch_rails.rb +67 -48
  30. data/lib/pagy/extras/foundation.rb +39 -35
  31. data/lib/pagy/extras/frontend_helpers.rb +72 -0
  32. data/lib/pagy/extras/gearbox.rb +54 -0
  33. data/lib/pagy/extras/headers.rb +30 -20
  34. data/lib/pagy/extras/i18n.rb +15 -13
  35. data/lib/pagy/extras/items.rb +42 -40
  36. data/lib/pagy/extras/materialize.rb +40 -38
  37. data/lib/pagy/extras/meilisearch.rb +53 -44
  38. data/lib/pagy/extras/metadata.rb +15 -20
  39. data/lib/pagy/extras/navs.rb +35 -34
  40. data/lib/pagy/extras/overflow.rb +62 -61
  41. data/lib/pagy/extras/searchkick.rb +54 -46
  42. data/lib/pagy/extras/semantic.rb +42 -40
  43. data/lib/pagy/extras/standalone.rb +50 -46
  44. data/lib/pagy/extras/support.rb +24 -16
  45. data/lib/pagy/extras/trim.rb +15 -14
  46. data/lib/pagy/extras/uikit.rb +41 -38
  47. data/lib/pagy/frontend.rb +36 -59
  48. data/lib/pagy/i18n.rb +164 -0
  49. data/lib/pagy/url_helpers.rb +24 -0
  50. data/lib/pagy.rb +90 -31
  51. data/lib/templates/bootstrap_nav.html.erb +2 -2
  52. data/lib/templates/bootstrap_nav.html.haml +2 -2
  53. data/lib/templates/bootstrap_nav.html.slim +2 -2
  54. data/lib/templates/foundation_nav.html.erb +1 -1
  55. data/lib/templates/foundation_nav.html.haml +1 -1
  56. data/lib/templates/foundation_nav.html.slim +1 -1
  57. data/lib/templates/nav.html.erb +1 -1
  58. data/lib/templates/nav.html.haml +1 -1
  59. data/lib/templates/nav.html.slim +1 -1
  60. data/lib/templates/uikit_nav.html.erb +2 -2
  61. data/lib/templates/uikit_nav.html.haml +1 -1
  62. data/lib/templates/uikit_nav.html.slim +2 -2
  63. metadata +29 -13
  64. data/lib/locales/utils/i18n.rb +0 -17
  65. data/lib/locales/utils/loader.rb +0 -31
  66. data/lib/locales/utils/p11n.rb +0 -112
  67. data/lib/pagy/deprecation.rb +0 -27
  68. data/lib/pagy/extras/shared.rb +0 -52
data/lib/pagy/i18n.rb ADDED
@@ -0,0 +1,164 @@
1
+ # See Pagy::I18n API documentation https://ddnexus.github.io/pagy/api/i18n
2
+ # frozen_string_literal: true
3
+
4
+ require 'yaml'
5
+
6
+ class Pagy
7
+ # Pagy i18n implementation, compatible with the I18n gem, just a lot faster and lighter
8
+ module I18n
9
+ extend self
10
+
11
+ # Pluralization rules
12
+ module P11n
13
+ # Pluralization variables
14
+ from0to1 = (0..1).to_a.freeze
15
+ from2to4 = (2..4).to_a.freeze
16
+ from3to10 = (3..10).to_a.freeze
17
+ from5to9 = (5..9).to_a.freeze
18
+ from11to14 = (11..14).to_a.freeze
19
+ from11to99 = (11..99).to_a.freeze
20
+ from12to14 = (12..14).to_a.freeze
21
+
22
+ from0to1_from5to9 = from0to1 + from5to9
23
+
24
+ # Store the proc defining each pluralization RULE
25
+ # Logic adapted from https://github.com/svenfuchs/rails-i18n
26
+ RULE = {
27
+ arabic:
28
+ lambda do |n = 0|
29
+ mod100 = n % 100
30
+ case
31
+ when n == 0 then 'zero' # rubocop:disable Style/NumericPredicate
32
+ when n == 1 then 'one'
33
+ when n == 2 then 'two'
34
+ when from3to10.include?(mod100) then 'few'
35
+ when from11to99.include?(mod100) then 'many'
36
+ else 'other'
37
+ end
38
+ end,
39
+
40
+ east_slavic:
41
+ lambda do |n = 0|
42
+ mod10 = n % 10
43
+ mod100 = n % 100
44
+ case
45
+ when mod10 == 1 && mod100 != 11 then 'one'
46
+ when from2to4.include?(mod10) && !from12to14.include?(mod100) then 'few'
47
+ when mod10 == 0 || from5to9.include?(mod10) || from11to14.include?(mod100) then 'many' # rubocop:disable Style/NumericPredicate
48
+ else 'other'
49
+ end
50
+ end,
51
+
52
+ one_other:
53
+ ->(n) { n == 1 ? 'one' : 'other' }, # default RULE
54
+
55
+ one_two_other:
56
+ lambda do |n|
57
+ case n
58
+ when 1 then 'one'
59
+ when 2 then 'two'
60
+ else 'other'
61
+ end
62
+ end,
63
+
64
+ one_upto_two_other:
65
+ ->(n) { n && n >= 0 && n < 2 ? 'one' : 'other' },
66
+
67
+ other:
68
+ ->(*) { 'other' },
69
+
70
+ polish:
71
+ lambda do |n = 0|
72
+ mod10 = n % 10
73
+ mod100 = n % 100
74
+ case
75
+ when n == 1 then 'one'
76
+ when from2to4.include?(mod10) && !from12to14.include?(mod100) then 'few'
77
+ when from0to1_from5to9.include?(mod10) || from12to14.include?(mod100) then 'many'
78
+ else 'other'
79
+ end
80
+ end,
81
+
82
+ west_slavic:
83
+ lambda do |n|
84
+ case n
85
+ when 1 then 'one'
86
+ when *from2to4 then 'few'
87
+ else 'other'
88
+ end
89
+ end
90
+
91
+ }.freeze
92
+
93
+ # Store the RULE to apply to each LOCALE
94
+ # the :one_other RULE is the default for locales missing from this list
95
+ LOCALE = Hash.new(RULE[:one_other]).tap do |hash|
96
+ hash['ar'] = RULE[:arabic]
97
+ hash['bs'] = RULE[:east_slavic]
98
+ hash['cs'] = RULE[:west_slavic]
99
+ hash['id'] = RULE[:other]
100
+ hash['fr'] = RULE[:one_upto_two_other]
101
+ hash['hr'] = RULE[:east_slavic]
102
+ hash['ja'] = RULE[:other]
103
+ hash['km'] = RULE[:other]
104
+ hash['ko'] = RULE[:other]
105
+ hash['pl'] = RULE[:polish]
106
+ hash['ru'] = RULE[:east_slavic]
107
+ hash['sr'] = RULE[:east_slavic]
108
+ hash['sv'] = RULE[:one_two_other]
109
+ hash['sv-SE'] = RULE[:one_two_other]
110
+ hash['tr'] = RULE[:other]
111
+ hash['uk'] = RULE[:east_slavic]
112
+ hash['zh-CN'] = RULE[:other]
113
+ hash['zh-HK'] = RULE[:other]
114
+ hash['zh-TW'] = RULE[:other]
115
+ end.freeze
116
+ end
117
+
118
+ # Stores the i18n DATA structure for each loaded locale
119
+ # default on the first locale DATA
120
+ DATA = Hash.new { |hash, _| hash.first[1] }
121
+
122
+ private
123
+
124
+ # Create a flat hash with dotted notation keys
125
+ def flatten(initial, prefix = '')
126
+ initial.each.reduce({}) do |hash, (key, value)|
127
+ hash.merge!(value.is_a?(Hash) ? flatten(value, "#{prefix}#{key}.") : { "#{prefix}#{key}" => value })
128
+ end
129
+ end
130
+
131
+ # Build the DATA hash out of the passed locales
132
+ def build(*locales)
133
+ locales.each do |locale|
134
+ locale[:filepath] ||= Pagy.root.join('locales', "#{locale[:locale]}.yml")
135
+ locale[:pluralize] ||= P11n::LOCALE[locale[:locale]]
136
+ dictionary = YAML.safe_load(File.read(locale[:filepath], encoding: 'UTF-8'))
137
+ raise I18nError, %(expected :locale "#{locale[:locale]}" not found in :filepath "#{locale[:filepath].inspect}") \
138
+ unless dictionary.key?(locale[:locale])
139
+
140
+ DATA[locale[:locale]] = [flatten(dictionary[locale[:locale]]), locale[:pluralize]]
141
+ end
142
+ end
143
+ # Build the default at require time
144
+ build(locale: 'en')
145
+
146
+ public
147
+
148
+ # Public method to configure the locales: overrides the default, build the DATA and freezes it
149
+ def load(*locales)
150
+ DATA.clear
151
+ build(*locales)
152
+ DATA.freeze
153
+ end
154
+
155
+ # Translate and pluralize the key with the locale DATA
156
+ def translate(locale, key, opts = {})
157
+ data, pluralize = DATA[locale]
158
+ translation = data[key] || (opts[:count] && data[key += ".#{pluralize.call(opts[:count])}"]) \
159
+ or return %([translation missing: "#{key}"])
160
+ translation.gsub(/%{[^}]+?}/) { |match| opts[:"#{match[2..-2]}"] || match }
161
+ end
162
+ alias t translate
163
+ end
164
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pagy
4
+ # Provide the helpers to handle the url in frontend and backend
5
+ module UrlHelpers
6
+ # Return the URL for the page, relying on the params method and Rack by default.
7
+ # It supports all Rack-based frameworks (Sinatra, Padrino, Rails, ...).
8
+ # For non-rack environments you can use the standalone extra
9
+ def pagy_url_for(pagy, page, absolute: false, html_escaped: false)
10
+ vars = pagy.vars
11
+ request_path = vars[:request_path].to_s.empty? ? request.path : vars[:request_path]
12
+ page_param = vars[:page_param].to_s
13
+ items_param = vars[:items_param].to_s
14
+ params = pagy.params.is_a?(Hash) ? pagy.params.transform_keys(&:to_s) : {}
15
+ params = request.GET.merge(params)
16
+ params[page_param] = page
17
+ params[items_param] = vars[:items] if vars[:items_extra]
18
+ params = pagy.params.call(params) if pagy.params.is_a?(Proc)
19
+ query_string = "?#{Rack::Utils.build_nested_query(params)}"
20
+ query_string = query_string.gsub('&', '&amp;') if html_escaped # the only unescaped entity
21
+ "#{request.base_url if absolute}#{request_path}#{query_string}#{vars[:fragment]}"
22
+ end
23
+ end
24
+ end
data/lib/pagy.rb CHANGED
@@ -3,64 +3,69 @@
3
3
 
4
4
  require 'pathname'
5
5
 
6
- # main class
6
+ # Core class
7
7
  class Pagy
8
- VERSION = '4.11.0'
8
+ VERSION = '6.0.0'
9
9
 
10
10
  # Root pathname to get the path of Pagy files like templates or dictionaries
11
11
  def self.root
12
12
  @root ||= Pathname.new(__dir__).freeze
13
13
  end
14
14
 
15
- # default vars
16
- VARS = { page: 1, items: 20, outset: 0, size: [1, 4, 4, 1], page_param: :page, # rubocop:disable Style/MutableConstant
17
- params: {}, fragment: '', link_extra: '', i18n_key: 'pagy.item_name', cycle: false }
15
+ # Default core vars: constant for easy access, but mutable for customizable defaults
16
+ DEFAULT = { page: 1, # rubocop:disable Style/MutableConstant
17
+ items: 20,
18
+ outset: 0,
19
+ size: [1, 4, 4, 1],
20
+ page_param: :page,
21
+ params: {},
22
+ fragment: '',
23
+ link_extra: '',
24
+ i18n_key: 'pagy.item_name',
25
+ cycle: false,
26
+ request_path: '' }
18
27
 
19
- attr_reader :count, :page, :items, :vars, :pages, :last, :offset, :from, :to, :prev, :next
20
-
21
- INSTANCE_VARS_MIN = { count: 0, items: 1, page: 1, outset: 0 }.freeze
28
+ attr_reader :count, :page, :items, :vars, :pages, :last, :offset, :in, :from, :to, :prev, :next, :params, :request_path
22
29
 
23
30
  # Merge and validate the options, do some simple arithmetic and set the instance variables
24
31
  def initialize(vars)
25
- @vars = VARS.merge( vars.delete_if{|k,v| VARS.key?(k) && (v.nil? || v == '') } )
26
- @vars[:fragment] = Pagy.deprecated_var(:anchor, @vars[:anchor], :fragment, @vars[:fragment]) if @vars[:anchor]
27
-
28
- INSTANCE_VARS_MIN.each do |name,min|
29
- raise VariableError.new(self), "expected :#{name} >= #{min}; got #{@vars[name].inspect}" \
30
- unless @vars[name] && instance_variable_set(:"@#{name}", @vars[name].to_i) >= min
31
- end
32
- @pages = @last = [(@count.to_f / @items).ceil, 1].max
33
- raise OverflowError.new(self), "expected :page in 1..#{@last}; got #{@page.inspect}" \
34
- if @page > @last
32
+ normalize_vars(vars)
33
+ setup_vars(count: 0, page: 1, outset: 0)
34
+ setup_items_var
35
+ setup_pages_var
36
+ setup_offset_var
37
+ setup_params_var
38
+ setup_request_path_var
39
+ raise OverflowError.new(self, :page, "in 1..#{@last}", @page) if @page > @last
35
40
 
36
- @offset = @items * (@page - 1) + @outset
37
- @items = @count - ((@pages - 1) * @items) if @page == @last && @count.positive?
38
- @from = @count.zero? ? 0 : @offset + 1 - @outset
39
- @to = @count.zero? ? 0 : @offset + @items - @outset
41
+ @from = [@offset - @outset + 1, @count].min
42
+ @to = [@offset - @outset + @items, @count].min
43
+ @in = [@to - @from + 1, @count].min
40
44
  @prev = (@page - 1 unless @page == 1)
41
45
  @next = @page == @last ? (1 if @vars[:cycle]) : @page + 1
42
46
  end
43
47
 
44
48
  # Return the array of page numbers and :gap items e.g. [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
45
- def series(size=@vars[:size])
49
+ def series(size: @vars[:size], **_)
46
50
  return [] if size.empty?
47
- raise VariableError.new(self), "expected 4 items >= 0 in :size; got #{size.inspect}" \
48
- unless size.size == 4 && size.all?{ |num| !num.negative? rescue false } # rubocop:disable Style/RescueModifier
51
+ raise VariableError.new(self, :size, 'to contain 4 items >= 0', size) \
52
+ unless size.is_a?(Array) && size.size == 4 && size.all? { |num| !num.negative? rescue false } # rubocop:disable Style/RescueModifier
53
+
49
54
  # This algorithm is up to ~5x faster and ~2.3x lighter than the previous one (pagy < 4.3)
50
- left_gap_start = 1 + size[0]
55
+ left_gap_start = 1 + size[0] # rubocop:disable Layout/ExtraSpacing, Layout/SpaceAroundOperators
51
56
  left_gap_end = @page - size[1] - 1
52
57
  right_gap_start = @page + size[2] + 1
53
58
  right_gap_end = @last - size[3]
54
59
  left_gap_end = right_gap_end if left_gap_end > right_gap_end
55
60
  right_gap_start = left_gap_start if left_gap_start > right_gap_start
56
- series = []
57
- start = 1
61
+ series = []
62
+ start = 1
58
63
  if (left_gap_end - left_gap_start).positive?
59
- series.push(*start..(left_gap_start - 1), :gap)
64
+ series.push(*start...left_gap_start, :gap)
60
65
  start = left_gap_end + 1
61
66
  end
62
67
  if (right_gap_end - right_gap_start).positive?
63
- series.push(*start..(right_gap_start - 1), :gap)
68
+ series.push(*start...right_gap_start, :gap)
64
69
  start = right_gap_end + 1
65
70
  end
66
71
  series.push(*start..@last)
@@ -68,9 +73,63 @@ class Pagy
68
73
  series
69
74
  end
70
75
 
76
+ # Allow the customization of the output (overridden by the calendar extra)
77
+ def label_for(page)
78
+ page.to_s
79
+ end
80
+
81
+ # Allow the customization of the output (overridden by the calendar extra)
82
+ def label
83
+ @page.to_s
84
+ end
85
+
86
+ protected
87
+
88
+ # Apply defaults, cleanup blanks and set @vars
89
+ def normalize_vars(vars)
90
+ @vars = DEFAULT.merge(vars.delete_if { |k, v| DEFAULT.key?(k) && (v.nil? || v == '') })
91
+ end
92
+
93
+ # Setup and validates the passed vars: var must be present and value.to_i must be >= to min
94
+ def setup_vars(name_min)
95
+ name_min.each do |name, min|
96
+ raise VariableError.new(self, name, ">= #{min}", @vars[name]) \
97
+ unless @vars[name]&.respond_to?(:to_i) && instance_variable_set(:"@#{name}", @vars[name].to_i) >= min
98
+ end
99
+ end
100
+
101
+ # Setup @items (overridden by the gearbox extra)
102
+ def setup_items_var
103
+ setup_vars(items: 1)
104
+ end
105
+
106
+ # Setup @pages and @last (overridden by the gearbox extra)
107
+ def setup_pages_var
108
+ @pages = @last = [(@count.to_f / @items).ceil, 1].max
109
+ end
110
+
111
+ # Setup @offset based on the :gearbox_items variable
112
+ def setup_offset_var
113
+ @offset = (@items * (@page - 1)) + @outset # may be already set from gear_box
114
+ end
115
+
116
+ # Setup and validate @params
117
+ def setup_params_var
118
+ raise VariableError.new(self, :params, 'must be a Hash or a Proc', @params) \
119
+ unless (@params = @vars[:params]).is_a?(Hash) || @params.is_a?(Proc)
120
+ end
121
+
122
+ def setup_request_path_var
123
+ request_path = @vars[:request_path]
124
+ return if request_path.to_s.empty?
125
+
126
+ raise VariableError.new(self, :request_path, 'must be a bare path like "/foo"', request_path) \
127
+ if !request_path.start_with?('/') || request_path.include?('?')
128
+
129
+ @request_path = request_path
130
+ end
71
131
  end
72
132
 
73
- require 'pagy/deprecation'
74
133
  require 'pagy/backend'
75
134
  require 'pagy/frontend'
76
135
  require 'pagy/exceptions'
@@ -5,8 +5,8 @@
5
5
  The link variable is set to a proc that returns the link tag.
6
6
  Usage: link.call( page_number [, text [, extra_attributes_string ]])
7
7
  -%>
8
- <% link = pagy_link_proc(pagy, 'class="page-link"') -%>
9
- <%# -%><nav aria-label="pager" class="pagy-bootstrap-nav" role="navigation">
8
+ <% link = pagy_link_proc(pagy, link_extra: 'class="page-link"') -%>
9
+ <%# -%><nav class="pagy-bootstrap-nav" role="navigation">
10
10
  <%# -%> <ul class="pagination">
11
11
  <% if pagy.prev -%> <li class="page-item prev"><%== link.call(pagy.prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"') %></li>
12
12
  <% else -%> <li class="page-item prev disabled"><a href="#" class="page-link"><%== pagy_t('pagy.nav.prev') %></a></li>
@@ -4,9 +4,9 @@
4
4
  -# The link variable is set to a proc that returns the link tag.
5
5
  -# Usage: link.call( page_number [, text [, extra_attributes_string ]])
6
6
 
7
- - link = pagy_link_proc(pagy, 'class="page-link"')
7
+ - link = pagy_link_proc(pagy, link_extra: 'class="page-link"')
8
8
 
9
- %nav.pagy-bootstrap-nav{"aria-label" => "pager", :role => "navigation"}
9
+ %nav.pagy-bootstrap-nav{:role => "navigation"}
10
10
 
11
11
  %ul.pagination
12
12
 
@@ -4,9 +4,9 @@
4
4
  / The link variable is set to a proc that returns the link tag.
5
5
  / Usage: link.call( page_number [, text [, extra_attributes_string ]])
6
6
 
7
- - link = pagy_link_proc(pagy, 'class="page-link"')
7
+ - link = pagy_link_proc(pagy, link_extra: 'class="page-link"')
8
8
 
9
- nav.pagy-bootstrap-nav role="navigation" aria-label="pager"
9
+ nav.pagy-bootstrap-nav role="navigation"
10
10
 
11
11
  ul.pagination
12
12
 
@@ -13,7 +13,7 @@
13
13
  <% end -%>
14
14
  <% pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36] -%>
15
15
  <% if item.is_a?(Integer) -%> <li><%== link.call(item) %></li>
16
- <% elsif item.is_a?(String) -%> <li class="current"><%= item %></li>
16
+ <% elsif item.is_a?(String) -%> <li class="current"><%= pagy.label_for(item) %></li>
17
17
  <% elsif item == :gap -%> <li class="ellipsis gap" aria-hidden="true"></li>
18
18
  <% end -%>
19
19
  <% end -%>
@@ -22,7 +22,7 @@
22
22
 
23
23
  - elsif item.is_a?(String) # current page
24
24
  %li.current
25
- = item
25
+ = pagy.label_for(item)
26
26
 
27
27
  - elsif item == :gap # page gap
28
28
  %li.ellipsis.gap{"aria-hidden" => true}
@@ -22,7 +22,7 @@ nav.pagy-foundation-nav role="navigation" aria-label="Pagination"
22
22
 
23
23
  - elsif item.is_a?(String) # current page
24
24
  li.current
25
- = item
25
+ = pagy.label_for(item)
26
26
 
27
27
  - elsif item == :gap # page gap
28
28
  li.ellipsis.gap aria-hidden="true"
@@ -6,7 +6,7 @@
6
6
  Usage: link.call( page_number [, text [, extra_attributes_string ]])
7
7
  -%>
8
8
  <% link = pagy_link_proc(pagy) -%>
9
- <%# -%><nav aria-label="pager" class="pagy_nav pagination" role="navigation">
9
+ <%# -%><nav class="pagy_nav pagination" role="navigation">
10
10
  <% if pagy.prev -%> <span class="page prev"><%== link.call(pagy.prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"') %></span>
11
11
  <% else -%> <span class="page prev disabled"><%== pagy_t('pagy.nav.prev') %></span>
12
12
  <% end -%>
@@ -6,7 +6,7 @@
6
6
 
7
7
  - link = pagy_link_proc(pagy)
8
8
 
9
- %nav.pagy_nav.pagination{"aria-label" => "pager", :role => "navigation"}
9
+ %nav.pagy_nav.pagination{:role => "navigation"}
10
10
 
11
11
  - if pagy.prev
12
12
  %span.page.prev!= link.call(pagy.prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"')
@@ -6,7 +6,7 @@
6
6
 
7
7
  - link = pagy_link_proc(pagy)
8
8
 
9
- nav.pagy_nav.pagination role="navigation" aria-label="pager"
9
+ nav.pagy_nav.pagination role="navigation"
10
10
 
11
11
  - if pagy.prev
12
12
  span.page.prev ==> link.call(pagy.prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"')
@@ -5,11 +5,11 @@
5
5
  <% end -%>
6
6
  <% pagy.series.each do |item| -%>
7
7
  <% if item.is_a?(Integer) -%> <li><%== link.call(item) %></li>
8
- <% elsif item.is_a?(String) -%> <li class="uk-active"><span><%== item %></span></li>
8
+ <% elsif item.is_a?(String) -%> <li class="uk-active"><span><%== pagy.label_for(item) %></span></li>
9
9
  <% elsif item == :gap -%> <li class="uk-disabled"><span><%== pagy_t('pagy.nav.gap') %></span></li>
10
10
  <% end -%>
11
11
  <% end -%>
12
- <% if pagy.next -%> <li><%== link.call(p_next, "<span uk-pagination-next>#{pagy_t('pagy.nav.next')}</span>") %></li>
12
+ <% if pagy.next -%> <li><%== link.call(pagy.next, "<span uk-pagination-next>#{pagy_t('pagy.nav.next')}</span>") %></li>
13
13
  <% else -%> <li class="uk-disabled"><a href="#"><span uk-pagination-next><%== pagy_t('pagy.nav.next') %></span></a></li>
14
14
  <% end -%>
15
15
  <%# -%> </ul>
@@ -14,7 +14,7 @@
14
14
 
15
15
  - elsif item.is_a?(String)
16
16
  %li.uk-active
17
- %span!= item
17
+ %span!= pagy.label_for(item)
18
18
 
19
19
  - elsif item == :gap
20
20
  %li.uk-disabled
@@ -14,14 +14,14 @@ ul.uk-pagination.uk-flex-center
14
14
 
15
15
  - elsif item.is_a?(String)
16
16
  li.uk-active
17
- span== item
17
+ span== pagy.label_for(item)
18
18
 
19
19
  - elsif item == :gap
20
20
  li.uk-disabled
21
21
  span== pagy_t('pagy.nav.gap')
22
22
 
23
23
  - if pagy.next
24
- li== link.call(p_next, "<span uk-pagination-next>#{pagy_t('pagy.nav.next')}</span>")
24
+ li== link.call(pagy.next, "<span uk-pagination-next>#{pagy_t('pagy.nav.next')}</span>")
25
25
  - else
26
26
  li.uk-disabled
27
27
  a href="#"
metadata CHANGED
@@ -1,18 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pagy
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.11.0
4
+ version: 6.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Domizio Demichelis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-20 00:00:00.000000000 Z
11
+ date: 2022-12-22 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: 'Agnostic pagination in plain ruby: it works with any framework, ORM
14
- and DB type, with all kinds of collections, even pre-paginated, scopes, Arrays,
15
- JSON data... Easy, powerful, fast and light.'
13
+ description: Agnostic pagination in plain ruby. It does it all. Better.
16
14
  email:
17
15
  - dd.nexus@gmail.com
18
16
  executables: []
@@ -21,6 +19,9 @@ extra_rdoc_files: []
21
19
  files:
22
20
  - LICENSE.txt
23
21
  - lib/config/pagy.rb
22
+ - lib/javascripts/pagy-dev.js
23
+ - lib/javascripts/pagy-module.d.ts
24
+ - lib/javascripts/pagy-module.js
24
25
  - lib/javascripts/pagy.js
25
26
  - lib/locales/ar.yml
26
27
  - lib/locales/bg.yml
@@ -40,6 +41,7 @@ files:
40
41
  - lib/locales/ko.yml
41
42
  - lib/locales/nb.yml
42
43
  - lib/locales/nl.yml
44
+ - lib/locales/nn.yml
43
45
  - lib/locales/pl.yml
44
46
  - lib/locales/pt-BR.yml
45
47
  - lib/locales/pt.yml
@@ -48,27 +50,34 @@ files:
48
50
  - lib/locales/sv-SE.yml
49
51
  - lib/locales/sv.yml
50
52
  - lib/locales/sw.yml
53
+ - lib/locales/ta.yml
51
54
  - lib/locales/tr.yml
52
55
  - lib/locales/uk.yml
53
- - lib/locales/utils/i18n.rb
54
- - lib/locales/utils/loader.rb
55
- - lib/locales/utils/p11n.rb
56
56
  - lib/locales/zh-CN.yml
57
57
  - lib/locales/zh-HK.yml
58
58
  - lib/locales/zh-TW.yml
59
59
  - lib/pagy.rb
60
60
  - lib/pagy/backend.rb
61
+ - lib/pagy/calendar.rb
62
+ - lib/pagy/calendar/day.rb
63
+ - lib/pagy/calendar/helper.rb
64
+ - lib/pagy/calendar/month.rb
65
+ - lib/pagy/calendar/quarter.rb
66
+ - lib/pagy/calendar/week.rb
67
+ - lib/pagy/calendar/year.rb
61
68
  - lib/pagy/console.rb
62
69
  - lib/pagy/countless.rb
63
- - lib/pagy/deprecation.rb
64
70
  - lib/pagy/exceptions.rb
65
71
  - lib/pagy/extras/arel.rb
66
72
  - lib/pagy/extras/array.rb
67
73
  - lib/pagy/extras/bootstrap.rb
68
74
  - lib/pagy/extras/bulma.rb
75
+ - lib/pagy/extras/calendar.rb
69
76
  - lib/pagy/extras/countless.rb
70
77
  - lib/pagy/extras/elasticsearch_rails.rb
71
78
  - lib/pagy/extras/foundation.rb
79
+ - lib/pagy/extras/frontend_helpers.rb
80
+ - lib/pagy/extras/gearbox.rb
72
81
  - lib/pagy/extras/headers.rb
73
82
  - lib/pagy/extras/i18n.rb
74
83
  - lib/pagy/extras/items.rb
@@ -79,12 +88,13 @@ files:
79
88
  - lib/pagy/extras/overflow.rb
80
89
  - lib/pagy/extras/searchkick.rb
81
90
  - lib/pagy/extras/semantic.rb
82
- - lib/pagy/extras/shared.rb
83
91
  - lib/pagy/extras/standalone.rb
84
92
  - lib/pagy/extras/support.rb
85
93
  - lib/pagy/extras/trim.rb
86
94
  - lib/pagy/extras/uikit.rb
87
95
  - lib/pagy/frontend.rb
96
+ - lib/pagy/i18n.rb
97
+ - lib/pagy/url_helpers.rb
88
98
  - lib/templates/bootstrap_nav.html.erb
89
99
  - lib/templates/bootstrap_nav.html.haml
90
100
  - lib/templates/bootstrap_nav.html.slim
@@ -103,7 +113,13 @@ files:
103
113
  homepage: https://github.com/ddnexus/pagy
104
114
  licenses:
105
115
  - MIT
106
- metadata: {}
116
+ metadata:
117
+ rubygems_mfa_required: 'true'
118
+ homepage_uri: https://github.com/ddnexus/pagy
119
+ documentation_uri: https://ddnexus.github.io/pagy
120
+ bug_tracker_uri: https://github.com/ddnexus/pagy/issues
121
+ changelog_uri: https://github.com/ddnexus/pagy/blob/master/CHANGELOG.md
122
+ support: https://github.com/ddnexus/pagy/discussions/categories/q-a
107
123
  post_install_message:
108
124
  rdoc_options: []
109
125
  require_paths:
@@ -119,8 +135,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
135
  - !ruby/object:Gem::Version
120
136
  version: '0'
121
137
  requirements: []
122
- rubygems_version: 3.2.3
138
+ rubygems_version: 3.2.33
123
139
  signing_key:
124
140
  specification_version: 4
125
- summary: The Ultimate Pagination Ruby Gem
141
+ summary: The kick-ass pagination ruby gem
126
142
  test_files: []
@@ -1,17 +0,0 @@
1
- # See https://ddnexus.github.io/pagy/api/frontend#i18n
2
- # frozen_string_literal: true
3
-
4
- # this file returns the I18n hash used as default alternative to the i18n gem
5
-
6
- Hash.new{|h,_| h.first[1]}.tap do |i18n_hash| # first loaded locale used as default
7
- i18n_hash.define_singleton_method(:load) do |*load_args|
8
- # eval: we don't need to keep the loader proc in memory
9
- eval(Pagy.root.join('locales', 'utils', 'loader.rb').read).call(i18n_hash, *load_args) #rubocop:disable Security/Eval
10
- end
11
- i18n_hash.define_singleton_method(:t) do |locale, key, **opts|
12
- data, pluralize = self[locale]
13
- translate = data[key] || opts[:count] && data[key+=".#{pluralize.call(opts[:count])}"] or return %([translation missing: "#{key}"])
14
- translate.call(opts)
15
- end
16
- i18n_hash.load(locale: 'en')
17
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # the whole file will be eval'ed/executed and gc-collected after returning/executing the loader proc
4
-
5
- # eval: no need for the whole file in memory
6
- plurals, = eval Pagy.root.join('locales', 'utils', 'p11n.rb').read # rubocop:disable Security/Eval
7
-
8
- # flatten the dictionary file nested keys
9
- # convert each value to a simple ruby interpolation proc
10
- flatten = lambda do |hash, key=''|
11
- hash.each.reduce({}) do |h, (k, v)|
12
- if v.is_a?(Hash)
13
- h.merge! flatten.call(v, "#{key}#{k}.")
14
- else
15
- code = %({"#{key}#{k}" => lambda{|vars|"#{v.gsub(/%{[^}]+?}/){|m| "\#{vars[:#{m[2..-2]}]||'#{m}'}" }}"}})
16
- h.merge! eval(code) # rubocop:disable Security/Eval
17
- end
18
- end
19
- end
20
-
21
- # loader proc
22
- lambda do |i18n, *args|
23
- i18n.clear
24
- args.each do |arg|
25
- arg[:filepath] ||= Pagy.root.join('locales', "#{arg[:locale]}.yml")
26
- arg[:pluralize] ||= plurals[arg[:locale]]
27
- hash = YAML.load(File.read(arg[:filepath], encoding: 'UTF-8')) #rubocop:disable Security/YAMLLoad
28
- hash.key?(arg[:locale]) or raise VariableError, %(expected :locale "#{arg[:locale]}" not found in :filepath "#{arg[:filepath].inspect}")
29
- i18n[arg[:locale]] = [flatten.call(hash[arg[:locale]]), arg[:pluralize]]
30
- end
31
- end