pagy 5.2.2 → 5.4.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.
@@ -1,23 +1,23 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/foundation
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/extras/shared'
4
+ require 'pagy/extras/frontend_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  # Frontend modules are specially optimized for performance.
8
8
  # The resulting code may not look very elegant, but produces the best benchmarks
9
9
  module FoundationExtra
10
10
  # Pagination for Foundation: it returns the html with the series of links to the pages
11
- def pagy_foundation_nav(pagy, pagy_id: nil, link_extra: '')
11
+ def pagy_foundation_nav(pagy, pagy_id: nil, link_extra: '', **vars)
12
12
  p_id = %( id="#{pagy_id}") if pagy_id
13
13
  link = pagy_link_proc(pagy, link_extra: link_extra)
14
14
 
15
15
  html = +%(<nav#{p_id} class="pagy-foundation-nav" aria-label="Pagination"><ul class="pagination">)
16
16
  html << pagy_foundation_prev_html(pagy, link)
17
- pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
17
+ pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
18
18
  html << case item
19
19
  when Integer then %(<li>#{link.call item}</li>) # page link
20
- when String then %(<li class="current">#{pagy_labeler(pagy, item)}</li>) # active page
20
+ when String then %(<li class="current">#{pagy.label_for(item)}</li>) # active page
21
21
  when :gap then %(<li class="ellipsis gap" aria-hidden="true"></li>) # page gap
22
22
  else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
23
23
  end
@@ -27,17 +27,17 @@ class Pagy # :nodoc:
27
27
  end
28
28
 
29
29
  # Javascript pagination for foundation: it returns a nav and a JSON tag used by the Pagy.nav javascript
30
- def pagy_foundation_nav_js(pagy, pagy_id: nil, link_extra: '', steps: nil)
30
+ def pagy_foundation_nav_js(pagy, pagy_id: nil, link_extra: '', **vars)
31
31
  p_id = %( id="#{pagy_id}") if pagy_id
32
32
  link = pagy_link_proc(pagy, link_extra: link_extra)
33
33
  tags = { 'before' => %(<ul class="pagination">#{pagy_foundation_prev_html pagy, link}),
34
- 'link' => %(<li>#{link.call PAGE_PLACEHOLDER}</li>),
35
- 'active' => %(<li class="current">#{pagy.page}</li>),
34
+ 'link' => %(<li>#{link.call(PAGE_PLACEHOLDER, LABEL_PLACEHOLDER)}</li>),
35
+ 'active' => %(<li class="current">#{LABEL_PLACEHOLDER}</li>),
36
36
  'gap' => %(<li class="ellipsis gap" aria-hidden="true"></li>),
37
37
  'after' => %(#{pagy_foundation_next_html pagy, link}</ul>) }
38
38
 
39
39
  %(<nav#{p_id} class="pagy-njs pagy-foundation-nav-js" aria-label="Pagination" #{
40
- pagy_json_attr(pagy, :nav, tags, pagy.sequels(steps))}></nav>)
40
+ pagy_json_attr(pagy, :nav, tags, (sequels = pagy.sequels(**vars)), pagy.label_sequels(sequels))}></nav>)
41
41
  end
42
42
 
43
43
  # Javascript combo pagination for Foundation: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
@@ -5,7 +5,8 @@ require 'digest'
5
5
  class Pagy # :nodoc:
6
6
  DEFAULT[:steps] = false # default false will use {0 => @vars[:size]}
7
7
 
8
- module SharedExtra
8
+ # Private module documented in the main classes
9
+ module FrontendHelpers
9
10
  # Additions for the Pagy class
10
11
  module Pagy
11
12
  # `Pagy` instance method used by the `pagy*_nav_js` helpers.
@@ -17,12 +18,25 @@ class Pagy # :nodoc:
17
18
  # "350" => [1, 2, :gap, 17, 18, 19, "20", 21, 22, 23, :gap, 49, 50],
18
19
  # "550" => [1, 2, 3, :gap, 16, 17, 18, 19, "20", 21, 22, 23, 24, :gap, 48, 49, 50] }
19
20
  # Notice: if :steps is false it will use the single {0 => @vars[:size]} size
20
- def sequels(steps = nil)
21
- steps ||= @vars[:steps] || { 0 => @vars[:size] }
21
+ def sequels(steps: @vars[:steps] || { 0 => @vars[:size] })
22
22
  raise VariableError.new(self, :steps, 'to define the 0 width', steps) unless steps.key?(0)
23
23
 
24
24
  {}.tap do |sequels|
25
- steps.each { |width, size| sequels[width.to_s] = series(size) }
25
+ steps.each { |width, step_size| sequels[width.to_s] = series(size: step_size) }
26
+ end
27
+ end
28
+
29
+ # Support for the Calendar API
30
+ def label_sequels(*); end
31
+ end
32
+
33
+ # Additions for Calendar class
34
+ module Calendar
35
+ def label_sequels(sequels = self.sequels)
36
+ {}.tap do |label_sequels|
37
+ sequels.each do |width, series|
38
+ label_sequels[width] = series.map { |item| item == :gap ? :gap : label_for(item) }
39
+ end
26
40
  end
27
41
  end
28
42
  end
@@ -50,6 +64,7 @@ class Pagy # :nodoc:
50
64
  end
51
65
  end
52
66
  end
53
- prepend SharedExtra::Pagy
54
- Frontend.prepend SharedExtra::Frontend
67
+ prepend FrontendHelpers::Pagy
68
+ Calendar.prepend FrontendHelpers::Calendar if defined?(Calendar)
69
+ Frontend.prepend FrontendHelpers::Frontend
55
70
  end
@@ -4,11 +4,22 @@
4
4
  class Pagy # :nodoc:
5
5
  # Use ::I18n gem
6
6
  module I18nExtra
7
- def pagy_t(key, **opts)
8
- ::I18n.t(key, **opts)
7
+ # Frontend overriding
8
+ module Frontend
9
+ def pagy_t(key, **opts)
10
+ ::I18n.t(key, **opts)
11
+ end
12
+ end
13
+
14
+ # Calendar overriding
15
+ module Calendar
16
+ def localize(time, opts)
17
+ ::I18n.l(time, **opts)
18
+ end
9
19
  end
10
20
  end
11
- Frontend.prepend I18nExtra
21
+ Frontend.prepend I18nExtra::Frontend
22
+ Calendar.prepend I18nExtra::Calendar if defined?(Calendar)
12
23
 
13
24
  # Add the pagy locales to the I18n.load_path
14
25
  ::I18n.load_path += Dir[Pagy.root.join('locales', '*.yml')]
@@ -1,7 +1,7 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/items
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/extras/shared'
4
+ require 'pagy/extras/frontend_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:items_param] = :items
@@ -1,20 +1,20 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/materialize
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/extras/shared'
4
+ require 'pagy/extras/frontend_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  # Frontend modules are specially optimized for performance.
8
8
  # The resulting code may not look very elegant, but produces the best benchmarks
9
9
  module MaterializeExtra
10
10
  # Pagination for materialize: it returns the html with the series of links to the pages
11
- def pagy_materialize_nav(pagy, pagy_id: nil, link_extra: '')
11
+ def pagy_materialize_nav(pagy, pagy_id: nil, link_extra: '', **vars)
12
12
  p_id = %( id="#{pagy_id}") if pagy_id
13
13
  link = pagy_link_proc(pagy, link_extra: link_extra)
14
14
 
15
15
  html = +%(<div#{p_id} class="pagy-materialize-nav pagination" role="navigation" aria-label="pager"><ul class="pagination">)
16
16
  html << pagy_materialize_prev_html(pagy, link)
17
- pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
17
+ pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
18
18
  html << case item
19
19
  when Integer then %(<li class="waves-effect">#{link.call item}</li>) # page link
20
20
  when String then %(<li class="active">#{link.call item}</li>) # active page
@@ -27,18 +27,18 @@ class Pagy # :nodoc:
27
27
  end
28
28
 
29
29
  # Javascript pagination for materialize: it returns a nav and a JSON tag used by the Pagy.nav javascript
30
- def pagy_materialize_nav_js(pagy, pagy_id: nil, link_extra: '', steps: nil)
30
+ def pagy_materialize_nav_js(pagy, pagy_id: nil, link_extra: '', **vars)
31
31
  p_id = %( id="#{pagy_id}") if pagy_id
32
32
  link = pagy_link_proc(pagy, link_extra: link_extra)
33
33
 
34
34
  tags = { 'before' => %(<ul class="pagination">#{pagy_materialize_prev_html pagy, link}),
35
- 'link' => %(<li class="waves-effect">#{mark = link.call(PAGE_PLACEHOLDER)}</li>),
35
+ 'link' => %(<li class="waves-effect">#{mark = link.call(PAGE_PLACEHOLDER, LABEL_PLACEHOLDER)}</li>),
36
36
  'active' => %(<li class="active">#{mark}</li>),
37
37
  'gap' => %(<li class="gap disabled"><a href="#">#{pagy_t 'pagy.nav.gap'}</a></li>),
38
38
  'after' => %(#{pagy_materialize_next_html pagy, link}</ul>) }
39
39
 
40
40
  %(<div#{p_id} class="pagy-njs pagy-materialize-nav-js" role="navigation" aria-label="pager" #{
41
- pagy_json_attr(pagy, :nav, tags, pagy.sequels(steps))}></div>)
41
+ pagy_json_attr(pagy, :nav, tags, (sequels = pagy.sequels(**vars)), pagy.label_sequels(sequels))}></div>)
42
42
  end
43
43
 
44
44
  # Javascript combo pagination for materialize: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
@@ -1,24 +1,24 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/navs
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/extras/shared'
4
+ require 'pagy/extras/frontend_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  # Frontend modules are specially optimized for performance.
8
8
  # The resulting code may not look very elegant, but produces the best benchmarks
9
9
  module NavsExtra
10
10
  # Javascript pagination: it returns a nav and a JSON tag used by the Pagy.nav javascript
11
- def pagy_nav_js(pagy, pagy_id: nil, link_extra: '', steps: nil)
11
+ def pagy_nav_js(pagy, pagy_id: nil, link_extra: '', **vars)
12
12
  p_id = %( id="#{pagy_id}") if pagy_id
13
13
  link = pagy_link_proc(pagy, link_extra: link_extra)
14
14
  tags = { 'before' => pagy_nav_prev_html(pagy, link),
15
- 'link' => %(<span class="page">#{link.call(PAGE_PLACEHOLDER)}</span> ),
16
- 'active' => %(<span class="page active">#{pagy.page}</span> ),
15
+ 'link' => %(<span class="page">#{link.call(PAGE_PLACEHOLDER, LABEL_PLACEHOLDER)}</span> ),
16
+ 'active' => %(<span class="page active">#{LABEL_PLACEHOLDER}</span> ),
17
17
  'gap' => %(<span class="page gap">#{pagy_t 'pagy.nav.gap'}</span> ),
18
18
  'after' => pagy_nav_next_html(pagy, link) }
19
19
 
20
20
  %(<nav#{p_id} class="pagy-njs pagy-nav-js pagination" aria-label="pager" #{
21
- pagy_json_attr(pagy, :nav, tags, pagy.sequels(steps))}></nav>)
21
+ pagy_json_attr(pagy, :nav, tags, (sequels = pagy.sequels(**vars)), pagy.label_sequels(sequels))}></nav>)
22
22
  end
23
23
 
24
24
  # Javascript combo pagination: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
@@ -15,25 +15,25 @@ class Pagy # :nodoc:
15
15
 
16
16
  # Add rescue clause for different behaviors
17
17
  def initialize(vars)
18
- @overflow ||= false # still true if :last_page re-run the method after an overflow
18
+ @overflow ||= false # still true if :last_page re-run the method after an overflow
19
19
  super
20
20
  rescue OverflowError
21
- @overflow = true # add the overflow flag
21
+ @overflow = true # add the overflow flag
22
22
  case @vars[:overflow]
23
23
  when :exception
24
- raise # same as without the extra
24
+ raise # same as without the extra
25
25
  when :last_page
26
- requested_page = @vars[:page] # save the requested page (even after re-run)
27
- initialize vars.merge!(page: @last) # re-run with the last page
28
- @vars[:page] = requested_page # restore the requested page
26
+ requested_page = @vars[:page] # save the requested page (even after re-run)
27
+ initialize vars.merge!(page: @last) # re-run with the last page
28
+ @vars[:page] = requested_page # restore the requested page
29
29
  when :empty_page
30
- @offset = @in = @from = @to = 0 # vars relative to the actual page
31
- if defined?(Calendar) && is_a?(Calendar) # only for Calendar instances
32
- edge = @order == :asc ? @final : @initial # get the edge of the overflow side (neat, but it would work with any time)
33
- @utc_from = @utc_to = edge.getutc # set both to the edge utc time (a query with >= && < will get no record)
30
+ @offset = @items = @from = @to = 0 # vars relative to the actual page
31
+ if defined?(Calendar) && is_a?(Calendar) # only for Calendar instances
32
+ edge = @time_order == :asc ? @final : @initial # get the edge of the overflow side (neat, but any time would do)
33
+ @utc_from = @utc_to = edge.getutc # set both to the edge utc time (a >=&&< query will get no records)
34
34
  end
35
- @prev = @last # prev relative to the actual page
36
- extend Series # special series for :empty_page
35
+ @prev = @last # prev relative to the actual page
36
+ extend Series # special series for :empty_page
37
37
  else
38
38
  raise VariableError.new(self, :overflow, 'to be in [:last_page, :empty_page, :exception]', @vars[:overflow])
39
39
  end
@@ -41,9 +41,9 @@ class Pagy # :nodoc:
41
41
 
42
42
  # Special series for empty page
43
43
  module Series
44
- def series(size = @vars[:size])
44
+ def series(*)
45
45
  @page = @last # series for last page
46
- super(size).tap do |s| # call original series
46
+ super.tap do |s| # call original series
47
47
  s[s.index(@page.to_s)] = @page # string to integer (i.e. no current page)
48
48
  @page = @vars[:page] # restore the actual page
49
49
  end
@@ -63,7 +63,7 @@ class Pagy # :nodoc:
63
63
  when :exception
64
64
  raise # same as without the extra
65
65
  when :empty_page
66
- @offset = @in = @from = @to = 0 # vars relative to the actual page
66
+ @offset = @items = @from = @to = 0 # vars relative to the actual page
67
67
  @vars[:size] = [] # no page in the series
68
68
  self
69
69
  else
@@ -1,23 +1,23 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/semantic
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/extras/shared'
4
+ require 'pagy/extras/frontend_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  # Frontend modules are specially optimized for performance.
8
8
  # The resulting code may not look very elegant, but produces the best benchmarks
9
9
  module SemanticExtra
10
10
  # Pagination for semantic: it returns the html with the series of links to the pages
11
- def pagy_semantic_nav(pagy, pagy_id: nil, link_extra: '')
11
+ def pagy_semantic_nav(pagy, pagy_id: nil, link_extra: '', **vars)
12
12
  p_id = %( id="#{pagy_id}") if pagy_id
13
13
  link = pagy_link_proc(pagy, link_extra: %(class="item" #{link_extra}))
14
14
 
15
15
  html = +%(<div#{p_id} class="pagy-semantic-nav ui pagination menu">)
16
16
  html << pagy_semantic_prev_html(pagy, link)
17
- pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
17
+ pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
18
18
  html << case item
19
19
  when Integer then link.call item
20
- when String then %(<a class="item active">#{pagy_labeler(pagy, item)}</a>)
20
+ when String then %(<a class="item active">#{pagy.label_for(item)}</a>)
21
21
  when :gap then %(<div class="disabled item">#{pagy_t 'pagy.nav.gap'}</div>)
22
22
  else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
23
23
  end
@@ -27,17 +27,17 @@ class Pagy # :nodoc:
27
27
  end
28
28
 
29
29
  # Javascript pagination for semantic: it returns a nav and a JSON tag used by the Pagy.nav javascript
30
- def pagy_semantic_nav_js(pagy, pagy_id: nil, link_extra: '', steps: nil)
30
+ def pagy_semantic_nav_js(pagy, pagy_id: nil, link_extra: '', **vars)
31
31
  p_id = %( id="#{pagy_id}") if pagy_id
32
32
  link = pagy_link_proc(pagy, link_extra: %(class="item" #{link_extra}))
33
33
  tags = { 'before' => pagy_semantic_prev_html(pagy, link),
34
- 'link' => link.call(PAGE_PLACEHOLDER),
35
- 'active' => %(<a class="item active">#{pagy.page}</a>),
34
+ 'link' => link.call(PAGE_PLACEHOLDER, LABEL_PLACEHOLDER),
35
+ 'active' => %(<a class="item active">#{LABEL_PLACEHOLDER}</a>),
36
36
  'gap' => %(<div class="disabled item">#{pagy_t('pagy.nav.gap')}</div>),
37
37
  'after' => pagy_semantic_next_html(pagy, link) }
38
38
 
39
39
  %(<div#{p_id} class="pagy-njs pagy-semantic-nav-js ui pagination menu" role="navigation" #{
40
- pagy_json_attr(pagy, :nav, tags, pagy.sequels(steps))}></div>)
40
+ pagy_json_attr(pagy, :nav, tags, (sequels = pagy.sequels(**vars)), pagy.label_sequels(sequels))}></div>)
41
41
  end
42
42
 
43
43
  # Combo pagination for semantic: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
@@ -37,15 +37,18 @@ class Pagy # :nodoc:
37
37
  # it works exactly as the regular #pagy_url_for, relying on the params method and Rack.
38
38
  # If there is a defined pagy.vars[:url] variable it does not need the params method nor Rack.
39
39
  def pagy_url_for(pagy, page, absolute: nil)
40
- vars = pagy.vars
41
- return super unless (url = vars[:url])
40
+ return super unless pagy.vars[:url]
42
41
 
43
- params = vars[:params].clone # safe when it gets reused
44
- params[vars[:page_param]] = page
45
- params[vars[:items_param]] = vars[:items] if vars[:items_extra]
46
-
47
- query_string = "?#{QueryUtils.build_nested_query(pagy_massage_params(params))}"
48
- "#{url}#{query_string}#{vars[:fragment]}"
42
+ vars = pagy.vars
43
+ page_param = vars[:page_param].to_s
44
+ items_param = vars[:items_param].to_s
45
+ params = pagy.params.is_a?(Hash) ? pagy.params.clone : {} # safe when it gets reused
46
+ params[page_param] = page
47
+ params[items_param] = vars[:items] if vars[:items_extra]
48
+ query_string = "?#{QueryUtils.build_nested_query(pagy_deprecated_params(pagy, params))}" # remove in 6.0
49
+ # params = pagy.params.call(params) if pagy.params.is_a?(Proc) # add in 6.0
50
+ # query_string = "?#{Rack::Utils.build_nested_query(params)}" # add in 6.0
51
+ "#{vars[:url]}#{query_string}#{vars[:fragment]}"
49
52
  end
50
53
  end
51
54
  # In ruby 3+ `UrlHelpers.prepend StandaloneExtra` would be enough instead of using the next 2 lines
@@ -12,9 +12,9 @@ class Pagy # :nodoc:
12
12
  link_proc = super(pagy, link_extra: link_extra)
13
13
  return link_proc unless pagy.vars[:trim_extra]
14
14
 
15
- lambda do |num, text = num, extra = ''|
16
- link = +link_proc.call(num, text, extra)
17
- return link unless num == 1
15
+ lambda do |page, text = pagy.label_for(page), extra = ''|
16
+ link = +link_proc.call(page, text, extra)
17
+ return link unless page == 1
18
18
 
19
19
  pagy_trim(pagy, link)
20
20
  end
@@ -1,22 +1,22 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/uikit
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/extras/shared'
4
+ require 'pagy/extras/frontend_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  # Frontend modules are specially optimized for performance.
8
8
  # The resulting code may not look very elegant, but produces the best benchmarks
9
9
  module UikitExtra
10
10
  # Pagination for uikit: it returns the html with the series of links to the pages
11
- def pagy_uikit_nav(pagy, pagy_id: nil, link_extra: '')
11
+ def pagy_uikit_nav(pagy, pagy_id: nil, link_extra: '', **vars)
12
12
  p_id = %( id="#{pagy_id}") if pagy_id
13
13
  link = pagy_link_proc(pagy, link_extra: link_extra)
14
14
 
15
15
  html = +%(<ul#{p_id} class="pagy-uikit-nav uk-pagination uk-flex-center">#{pagy_uikit_prev_html pagy, link})
16
- pagy.series.each do |item|
16
+ pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
17
17
  html << case item
18
18
  when Integer then %(<li>#{link.call item}</li>)
19
- when String then %(<li class="uk-active"><span>#{pagy_labeler(pagy, item)}</span></li>)
19
+ when String then %(<li class="uk-active"><span>#{pagy.label_for(item)}</span></li>)
20
20
  when :gap then %(<li class="uk-disabled"><span>#{pagy_t 'pagy.nav.gap'}</span></li>)
21
21
  else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
22
22
  end
@@ -26,17 +26,17 @@ class Pagy # :nodoc:
26
26
  end
27
27
 
28
28
  # Javascript pagination for uikit: it returns a nav and a JSON tag used by the Pagy.nav javascript
29
- def pagy_uikit_nav_js(pagy, pagy_id: nil, link_extra: '', steps: nil)
29
+ def pagy_uikit_nav_js(pagy, pagy_id: nil, link_extra: '', **vars)
30
30
  p_id = %( id="#{pagy_id}") if pagy_id
31
31
  link = pagy_link_proc(pagy, link_extra: link_extra)
32
32
  tags = { 'before' => pagy_uikit_prev_html(pagy, link),
33
- 'link' => %(<li>#{link.call(PAGE_PLACEHOLDER)}</li>),
34
- 'active' => %(<li class="uk-active"><span>#{PAGE_PLACEHOLDER}</span></li>),
33
+ 'link' => %(<li>#{link.call(PAGE_PLACEHOLDER, LABEL_PLACEHOLDER)}</li>),
34
+ 'active' => %(<li class="uk-active"><span>#{LABEL_PLACEHOLDER}</span></li>),
35
35
  'gap' => %(<li class="uk-disabled"><span>#{pagy_t 'pagy.nav.gap'}</span></li>),
36
36
  'after' => pagy_uikit_next_html(pagy, link) }
37
37
 
38
38
  %(<ul#{p_id} class="pagy-njs pagy-uikit-nav-js uk-pagination uk-flex-center" #{
39
- pagy_json_attr(pagy, :nav, tags, pagy.sequels(steps))}></ul>)
39
+ pagy_json_attr(pagy, :nav, tags, (sequels = pagy.sequels(**vars)), pagy.label_sequels(sequels))}></ul>)
40
40
  end
41
41
 
42
42
  # Javascript combo pagination for uikit: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
data/lib/pagy/frontend.rb CHANGED
@@ -6,7 +6,8 @@ require 'pagy/i18n'
6
6
 
7
7
  class Pagy
8
8
  # Used for search and replace, hardcoded also in the pagy.js file
9
- PAGE_PLACEHOLDER = '__pagy_page__'
9
+ PAGE_PLACEHOLDER = '__pagy_page__'
10
+ LABEL_PLACEHOLDER = '__pagy_label__'
10
11
 
11
12
  # Frontend modules are specially optimized for performance.
12
13
  # The resulting code may not look very elegant, but produces the best benchmarks
@@ -14,7 +15,7 @@ class Pagy
14
15
  include UrlHelpers
15
16
 
16
17
  # Generic pagination: it returns the html with the series of links to the pages
17
- def pagy_nav(pagy, pagy_id: nil, link_extra: '')
18
+ def pagy_nav(pagy, pagy_id: nil, link_extra: '', **vars)
18
19
  p_id = %( id="#{pagy_id}") if pagy_id
19
20
  link = pagy_link_proc(pagy, link_extra: link_extra)
20
21
  p_prev = pagy.prev
@@ -26,10 +27,10 @@ class Pagy
26
27
  else
27
28
  %(<span class="page prev disabled">#{pagy_t('pagy.nav.prev')}</span> )
28
29
  end
29
- pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
30
+ pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
30
31
  html << case item
31
32
  when Integer then %(<span class="page">#{link.call item}</span> )
32
- when String then %(<span class="page active">#{pagy_labeler(pagy, item)}</span> )
33
+ when String then %(<span class="page active">#{pagy.label_for(item)}</span> )
33
34
  when :gap then %(<span class="page gap">#{pagy_t('pagy.nav.gap')}</span> )
34
35
  else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
35
36
  end
@@ -64,20 +65,15 @@ class Pagy
64
65
  p_next = pagy.next
65
66
  left, right = %(<a href="#{pagy_url_for pagy, PAGE_PLACEHOLDER}" #{
66
67
  pagy.vars[:link_extra]} #{link_extra}).split(PAGE_PLACEHOLDER, 2)
67
- lambda do |num, text = pagy_labeler(pagy, num), extra_attrs = ''|
68
- %(#{left}#{num}#{right}#{ case num
69
- when p_prev then ' rel="prev"'
70
- when p_next then ' rel="next"'
71
- else ''
72
- end } #{extra_attrs}>#{text}</a>)
68
+ lambda do |page, text = pagy.label_for(page), extra_attrs = ''|
69
+ %(#{left}#{page}#{right}#{ case page
70
+ when p_prev then ' rel="prev"'
71
+ when p_next then ' rel="next"'
72
+ else ''
73
+ end } #{extra_attrs}>#{text}</a>)
73
74
  end
74
75
  end
75
76
 
76
- # Allow customization of the output by overriding (used by the calendar extra)
77
- def pagy_labeler(_pagy, num)
78
- num
79
- end
80
-
81
77
  # Similar to I18n.t: just ~18x faster using ~10x less memory
82
78
  # (@pagy_locale explicitly initialized in order to avoid warning)
83
79
  def pagy_t(key, **opts)
@@ -7,18 +7,32 @@ class Pagy
7
7
  # It supports all Rack-based frameworks (Sinatra, Padrino, Rails, ...).
8
8
  # For non-rack environments you can use the standalone extra
9
9
  def pagy_url_for(pagy, page, absolute: nil)
10
- vars = pagy.vars
11
- params = request.GET.merge(vars[:params].transform_keys(&:to_s))
12
- params[vars[:page_param].to_s] = page
13
- params[vars[:items_param].to_s] = vars[:items] if vars[:items_extra]
14
-
15
- query_string = "?#{Rack::Utils.build_nested_query(pagy_massage_params(params))}"
10
+ vars = pagy.vars
11
+ page_param = vars[:page_param].to_s
12
+ items_param = vars[:items_param].to_s
13
+ params = pagy.params.is_a?(Hash) ? pagy.params.transform_keys(&:to_s) : {}
14
+ params = request.GET.merge(params)
15
+ params[page_param] = page
16
+ params[items_param] = vars[:items] if vars[:items_extra]
17
+ query_string = "?#{Rack::Utils.build_nested_query(pagy_deprecated_params(pagy, params))}" # remove in 6.0
18
+ # params = pagy.params.call(params) if pagy.params.is_a?(Proc) # add in 6.0
19
+ # query_string = "?#{Rack::Utils.build_nested_query(params)}" # add in 6.0
16
20
  "#{request.base_url if absolute}#{request.path}#{query_string}#{vars[:fragment]}"
17
21
  end
18
22
 
19
- # Sub-method called only by #pagy_url_for: here for easy customization of params by overriding
20
- def pagy_massage_params(params)
21
- params
23
+ private
24
+
25
+ # Transitional code to handle params deprecations. It will be removed in version 6.0
26
+ def pagy_deprecated_params(pagy, params) # remove in 6.0
27
+ if pagy.params.is_a?(Proc) # new code
28
+ pagy.params.call(params)
29
+ elsif respond_to?(:pagy_massage_params) # deprecated code
30
+ Warning.warn '[PAGY WARNING] The pagy_massage_params method has been deprecated and it will be ignored from version 6. ' \
31
+ 'Set the :params variable to a Proc with the same code as the pagy_massage_params method.'
32
+ pagy_massage_params(params)
33
+ else
34
+ params # no massage params
35
+ end
22
36
  end
23
37
  end
24
38
  end
data/lib/pagy.rb CHANGED
@@ -5,7 +5,7 @@ require 'pathname'
5
5
 
6
6
  # Core class
7
7
  class Pagy
8
- VERSION = '5.2.2'
8
+ VERSION = '5.4.0'
9
9
 
10
10
  # Root pathname to get the path of Pagy files like templates or dictionaries
11
11
  def self.root
@@ -24,7 +24,7 @@ class Pagy
24
24
  i18n_key: 'pagy.item_name',
25
25
  cycle: false }
26
26
 
27
- attr_reader :count, :page, :items, :vars, :pages, :last, :offset, :in, :from, :to, :prev, :next
27
+ attr_reader :count, :page, :items, :vars, :pages, :last, :offset, :in, :from, :to, :prev, :next, :params
28
28
 
29
29
  # Merge and validate the options, do some simple arithmetic and set the instance variables
30
30
  def initialize(vars)
@@ -32,6 +32,7 @@ class Pagy
32
32
  setup_vars(count: 0, page: 1, outset: 0)
33
33
  setup_items_var
34
34
  setup_pages_var
35
+ setup_params_var
35
36
  raise OverflowError.new(self, :page, "in 1..#{@last}", @page) if @page > @last
36
37
 
37
38
  @offset = (@items * (@page - 1)) + @outset
@@ -43,7 +44,7 @@ class Pagy
43
44
  end
44
45
 
45
46
  # Return the array of page numbers and :gap items e.g. [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
46
- def series(size = @vars[:size])
47
+ def series(size: @vars[:size])
47
48
  return [] if size.empty?
48
49
  raise VariableError.new(self, :size, 'to contain 4 items >= 0', size) \
49
50
  unless size.is_a?(Array) && size.size == 4 && size.all? { |num| !num.negative? rescue false } # rubocop:disable Style/RescueModifier
@@ -70,6 +71,15 @@ class Pagy
70
71
  series
71
72
  end
72
73
 
74
+ # Allow the customization of the output (overridden by the calendar extra)
75
+ def label_for(page)
76
+ page.to_s
77
+ end
78
+
79
+ def label
80
+ @page.to_s
81
+ end
82
+
73
83
  protected
74
84
 
75
85
  # Apply defaults, cleanup blanks and set @vars
@@ -94,6 +104,12 @@ class Pagy
94
104
  def setup_pages_var
95
105
  @pages = @last = [(@count.to_f / @items).ceil, 1].max
96
106
  end
107
+
108
+ # Setup and validates the params
109
+ def setup_params_var
110
+ raise VariableError.new(self, :params, 'must be a Hash or a Proc', @params) \
111
+ unless (@params = @vars[:params]).is_a?(Hash) || @params.is_a?(Proc)
112
+ end
97
113
  end
98
114
 
99
115
  require 'pagy/backend'
@@ -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"><%= pagy_labeler(pagy, 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
- = pagy_labeler(pagy, 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
- = pagy_labeler(pagy, item)
25
+ = pagy.label_for(item)
26
26
 
27
27
  - elsif item == :gap # page gap
28
28
  li.ellipsis.gap aria-hidden="true"
@@ -5,7 +5,7 @@
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><%== pagy_labeler(pagy, 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 -%>
@@ -14,7 +14,7 @@
14
14
 
15
15
  - elsif item.is_a?(String)
16
16
  %li.uk-active
17
- %span!= pagy_labeler(pagy, item)
17
+ %span!= pagy.label_for(item)
18
18
 
19
19
  - elsif item == :gap
20
20
  %li.uk-disabled