pagy 3.11.0 → 4.3.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,13 +1,21 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/searchkick
2
- # encoding: utf-8
3
2
  # frozen_string_literal: true
4
3
 
5
- require 'pagy/extras/pagy_search'
6
-
7
4
  class Pagy
8
5
 
9
- # used by the items extra
10
- SEARCHKICK = true
6
+ VARS[:searchkick_search_method] ||= :pagy_search
7
+
8
+ module Searchkick
9
+ # returns an array used to delay the call of #search
10
+ # after the pagination variables are merged to the options
11
+ # it also pushes to the same array an eventually called method
12
+ def pagy_searchkick(term = '*', **options, &block)
13
+ [self, term, options, block].tap do |args|
14
+ args.define_singleton_method(:method_missing){|*a| args += a}
15
+ end
16
+ end
17
+ alias_method VARS[:searchkick_search_method], :pagy_searchkick
18
+ end
11
19
 
12
20
  # create a Pagy object from a Searchkick::Results object
13
21
  def self.new_from_searchkick(results, vars={})
@@ -18,22 +26,24 @@ class Pagy
18
26
  end
19
27
 
20
28
  # Add specialized backend methods to paginate Searchkick::Results
21
- module Backend ; private
29
+ module Backend
30
+ private
22
31
 
23
32
  # Return Pagy object and results
24
33
  def pagy_searchkick(pagy_search_args, vars={})
25
- model, search_args, block, *called = pagy_search_args
26
- vars = pagy_searchkick_get_vars(nil, vars)
27
- search_args[-1][:per_page] = vars[:items]
28
- search_args[-1][:page] = vars[:page]
29
- results = model.search(*search_args, &block)
30
- vars[:count] = results.total_count
34
+ model, term, options, block, *called = pagy_search_args
35
+ vars = pagy_searchkick_get_vars(nil, vars)
36
+ options[:per_page] = vars[:items]
37
+ options[:page] = vars[:page]
38
+ results = model.search(term, **options, &block)
39
+ vars[:count] = results.total_count
40
+
31
41
  pagy = Pagy.new(vars)
32
42
  # with :last_page overflow we need to re-run the method in order to get the hits
33
- if defined?(OVERFLOW) && pagy.overflow? && pagy.vars[:overflow] == :last_page
34
- return pagy_searchkick(pagy_search_args, vars.merge(page: pagy.page))
35
- end
36
- return pagy, called.empty? ? results : results.send(*called)
43
+ return pagy_searchkick(pagy_search_args, vars.merge(page: pagy.page)) \
44
+ if defined?(Pagy::UseOverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page
45
+
46
+ [ pagy, called.empty? ? results : results.send(*called) ]
37
47
  end
38
48
 
39
49
  # Sub-method called only by #pagy_searchkick: here for easy customization of variables by overriding
@@ -1,5 +1,4 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/semantic
2
- # encoding: utf-8
3
2
  # frozen_string_literal: true
4
3
 
5
4
  require 'pagy/extras/shared'
@@ -9,47 +8,69 @@ class Pagy
9
8
 
10
9
  # Pagination for semantic: it returns the html with the series of links to the pages
11
10
  def pagy_semantic_nav(pagy)
12
- link, p_prev, p_next = pagy_link_proc(pagy, 'class="item"'), pagy.prev, pagy.next
11
+ link = pagy_link_proc(pagy, 'class="item"')
13
12
 
14
- html = EMPTY + (p_prev ? %(#{link.call p_prev, '<i class="left small chevron icon"></i>', 'aria-label="previous"'})
15
- : %(<div class="item disabled"><i class="left small chevron icon"></i></div>))
13
+ html = +%(<div class="pagy-semantic-nav ui pagination menu" aria-label="pager">)
14
+ html << pagy_semantic_prev_html(pagy, link)
16
15
  pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
17
- html << if item.is_a?(Integer); %(#{link.call item}) # page link
18
- elsif item.is_a?(String) ; %(<a class="item active">#{item}</a>) # current page
19
- elsif item == :gap ; %(<div class="disabled item">...</div>) # page gap
16
+ html << case item
17
+ when Integer then link.call item # page link
18
+ when String then %(<a class="item active">#{item}</a>) # current page
19
+ when :gap then %(<div class="disabled item">...</div>) # page gap
20
20
  end
21
21
  end
22
- html << (p_next ? %(#{link.call p_next, '<i class="right small chevron icon"></i>', 'aria-label="next"'})
23
- : %(<div class="item disabled"><i class="right small chevron icon"></i></div>))
24
- %(<div class="pagy-semantic-nav ui pagination menu" aria-label="pager">#{html}</div>)
22
+ html << pagy_semantic_next_html(pagy, link)
23
+ html << %(</div>)
25
24
  end
26
25
 
27
26
  # Javascript pagination for semantic: it returns a nav and a JSON tag used by the Pagy.nav javascript
28
27
  def pagy_semantic_nav_js(pagy, id=pagy_id)
29
- link, p_prev, p_next = pagy_link_proc(pagy, 'class="item"'), pagy.prev, pagy.next
30
- tags = { 'before' => (p_prev ? %(#{link.call(p_prev, '<i class="left small chevron icon"></i>', 'aria-label="previous"')})
31
- : %(<div class="item disabled"><i class="left small chevron icon"></i></div>)),
32
- 'link' => %(#{link.call(PAGE_PLACEHOLDER)}),
28
+ link = pagy_link_proc(pagy, 'class="item"')
29
+ tags = { 'before' => pagy_semantic_prev_html(pagy, link),
30
+ 'link' => link.call(PAGE_PLACEHOLDER),
33
31
  'active' => %(<a class="item active">#{pagy.page}</a>),
34
32
  'gap' => %(<div class="disabled item">#{pagy_t('pagy.nav.gap')}</div>),
35
- 'after' => (p_next ? %(#{link.call(p_next, '<i class="right small chevron icon"></i>', 'aria-label="next"')})
36
- : %(<div class="item disabled"><i class="right small chevron icon"></i></div>)) }
37
- %(<div id="#{id}" class="pagy-semantic-nav-js ui pagination menu" role="navigation" aria-label="pager"></div>#{pagy_json_tag(:nav, id, tags, pagy.sequels, defined?(TRIM) && pagy.vars[:page_param])})
33
+ 'after' => pagy_semantic_next_html(pagy, link) }
34
+
35
+ html = %(<div id="#{id}" class="pagy-semantic-nav-js ui pagination menu" role="navigation" aria-label="pager"></div>)
36
+ html << pagy_json_tag(pagy, :nav, id, tags, pagy.sequels)
38
37
  end
39
38
 
40
39
  # Combo pagination for semantic: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
41
40
  def pagy_semantic_combo_nav_js(pagy, id=pagy_id)
42
- link, p_prev, p_next, p_page, p_pages = pagy_link_proc(pagy, 'class="item"'), pagy.prev, pagy.next, pagy.page, pagy.pages
43
-
44
- html = EMPTY + %(<div id="#{id}" class="pagy-semantic-combo-nav-js ui compact menu" role="navigation" aria-label="pager">)
45
- html << (p_prev ? %(#{link.call p_prev, '<i class="left small chevron icon"></i>', 'aria-label="previous"'})
46
- : %(<div class="item disabled"><i class="left small chevron icon"></i></div>))
47
- input = %(<input type="number" min="1" max="#{p_pages}" value="#{p_page}" style="padding: 0; text-align: center; width: #{p_pages.to_s.length+1}rem; margin: 0 0.3rem">)
48
- html << %(<div class="pagy-combo-input item">#{pagy_t('pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages)}</div> )
49
- html << (p_next ? %(#{link.call p_next, '<i class="right small chevron icon"></i>', 'aria-label="next"'})
50
- : %(<div class="item disabled"><i class="right small chevron icon"></i></div>))
51
- html << %(</div>#{pagy_json_tag(:combo_nav, id, p_page, pagy_marked_link(link), defined?(TRIM) && pagy.vars[:page_param])})
41
+ link = pagy_link_proc(pagy, 'class="item"')
42
+ p_page = pagy.page
43
+ p_pages = pagy.pages
44
+ input = %(<input type="number" min="1" max="#{p_pages}" value="#{p_page}" style="padding: 0; text-align: center; width: #{p_pages.to_s.length+1}rem; margin: 0 0.3rem">)
45
+
46
+ %(<div id="#{id}" class="pagy-semantic-combo-nav-js ui compact menu" role="navigation" aria-label="pager">#{
47
+ pagy_semantic_prev_html pagy, link
48
+ }<div class="pagy-combo-input item">#{
49
+ pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages
50
+ }</div> #{
51
+ pagy_semantic_next_html pagy, link
52
+ }</div>#{
53
+ pagy_json_tag pagy, :combo_nav, id, p_page, pagy_marked_link(link)
54
+ })
52
55
  end
53
56
 
57
+ private
58
+
59
+ def pagy_semantic_prev_html(pagy, link)
60
+ if (p_prev = pagy.prev)
61
+ link.call p_prev, '<i class="left small chevron icon"></i>', 'aria-label="previous"'
62
+ else
63
+ +%(<div class="item disabled"><i class="left small chevron icon"></i></div>)
64
+ end
65
+ end
66
+
67
+ def pagy_semantic_next_html(pagy, link)
68
+ if (p_next = pagy.next)
69
+ link.call p_next, '<i class="right small chevron icon"></i>', 'aria-label="next"'
70
+ else
71
+ +%(<div class="item disabled"><i class="right small chevron icon"></i></div>)
72
+ end
73
+ end
74
+
54
75
  end
55
76
  end
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require 'digest'
@@ -19,21 +18,26 @@ class Pagy
19
18
  # Notice: if :steps is false it will use the single {0 => @vars[:size]} size
20
19
  def sequels
21
20
  steps = @vars[:steps] || {0 => @vars[:size]}
22
- steps.key?(0) or raise(VariableError.new(self), "expected :steps to define the 0 width; got #{steps.inspect}")
23
- sequels = {}; steps.each {|width, size| sequels[width.to_s] = series(size)}; sequels
21
+ raise VariableError.new(self), "expected :steps to define the 0 width; got #{steps.inspect}" \
22
+ unless steps.key?(0)
23
+ {}.tap do |sequels|
24
+ steps.each {|width, size| sequels[width.to_s] = series(size)}
25
+ end
24
26
  end
25
27
 
26
28
  module Frontend
27
29
 
28
30
  if defined?(Oj)
29
31
  # it returns a script tag with the JSON-serialized args generated with the faster oj gem
30
- def pagy_json_tag(*args)
32
+ def pagy_json_tag(pagy, *args)
33
+ args << pagy.vars[:page_param] if pagy.vars[:trim]
31
34
  %(<script type="application/json" class="pagy-json">#{Oj.dump(args, mode: :strict)}</script>)
32
35
  end
33
36
  else
34
37
  require 'json'
35
38
  # it returns a script tag with the JSON-serialized args generated with the slower to_json
36
- def pagy_json_tag(*args)
39
+ def pagy_json_tag(pagy, *args)
40
+ args << pagy.vars[:page_param] if pagy.vars[:trim]
37
41
  %(<script type="application/json" class="pagy-json">#{args.to_json}</script>)
38
42
  end
39
43
  end
@@ -45,7 +49,7 @@ class Pagy
45
49
 
46
50
  # it returns the marked link to used by pagy.js
47
51
  def pagy_marked_link(link)
48
- link.call(PAGE_PLACEHOLDER, '', 'style="display: none;"')
52
+ link.call PAGE_PLACEHOLDER, '', 'style="display: none;"'
49
53
  end
50
54
 
51
55
  end
@@ -1,5 +1,4 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/support
2
- # encoding: utf-8
3
2
  # frozen_string_literal: true
4
3
 
5
4
  class Pagy
@@ -15,13 +14,19 @@ class Pagy
15
14
  end
16
15
 
17
16
  def pagy_prev_link(pagy, text = pagy_t('pagy.nav.prev'), link_extra = '')
18
- pagy.prev ? %(<span class="page prev"><a href="#{pagy_url_for(pagy.prev, pagy)}" rel="prev" aria-label="previous" #{pagy.vars[:link_extra]} #{link_extra}>#{text}</a></span>)
19
- : %(<span class="page prev disabled">#{text}</span>)
17
+ if pagy.prev
18
+ %(<span class="page prev"><a href="#{pagy_url_for(pagy.prev, pagy)}" rel="prev" aria-label="previous" #{pagy.vars[:link_extra]} #{link_extra}>#{text}</a></span>)
19
+ else
20
+ %(<span class="page prev disabled">#{text}</span>)
21
+ end
20
22
  end
21
23
 
22
24
  def pagy_next_link(pagy, text = pagy_t('pagy.nav.next'), link_extra = '')
23
- pagy.next ? %(<span class="page next"><a href="#{pagy_url_for(pagy.next, pagy)}" rel="next" aria-label="next" #{pagy.vars[:link_extra]} #{link_extra}>#{text}</a></span>)
24
- : %(<span class="page next disabled">#{text}</span>)
25
+ if pagy.next
26
+ %(<span class="page next"><a href="#{pagy_url_for(pagy.next, pagy)}" rel="next" aria-label="next" #{pagy.vars[:link_extra]} #{link_extra}>#{text}</a></span>)
27
+ else
28
+ %(<span class="page next disabled">#{text}</span>)
29
+ end
25
30
  end
26
31
 
27
32
  def pagy_prev_link_tag(pagy)
@@ -1,23 +1,23 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/trim
2
- # encoding: utf-8
3
2
  # frozen_string_literal: true
4
3
 
5
4
  class Pagy
6
5
 
7
- module Frontend
6
+ VARS[:trim] = true
8
7
 
9
- TRIM = true # boolean used by *_js helpers
8
+ module UseTrimExtra
10
9
 
11
- alias_method :pagy_link_proc_without_trim, :pagy_link_proc
12
- def pagy_link_proc_with_trim(pagy, link_extra='')
13
- link_proc = pagy_link_proc_without_trim(pagy, link_extra)
14
- re = /[?&]#{pagy.vars[:page_param]}=1\b(?!&)|\b#{pagy.vars[:page_param]}=1&/
15
- lambda do |n, text=n, extra=''|
16
- link = link_proc.call(n, text, extra)
17
- n == 1 ? link.sub(re, '') : link
10
+ def pagy_link_proc(pagy, link_extra='')
11
+ link_proc = super(pagy, link_extra)
12
+ return link_proc unless pagy.vars[:trim]
13
+ lambda do |num, text=num, extra=''|
14
+ link = link_proc.call(num, text, extra)
15
+ return link unless num == 1
16
+ link.sub!(/[?&]#{pagy.vars[:page_param]}=1\b(?!&)|\b#{pagy.vars[:page_param]}=1&/, '')
18
17
  end
19
18
  end
20
- alias_method :pagy_link_proc, :pagy_link_proc_with_trim
21
19
 
22
20
  end
21
+ Frontend.prepend UseTrimExtra
22
+
23
23
  end
@@ -1,5 +1,4 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/uikit
2
- # encoding: utf-8
3
2
  # frozen_string_literal: true
4
3
 
5
4
  require 'pagy/extras/shared'
@@ -9,54 +8,80 @@ class Pagy
9
8
 
10
9
  # Pagination for uikit: it returns the html with the series of links to the pages
11
10
  def pagy_uikit_nav(pagy)
12
- link, p_prev, p_next = pagy_link_proc(pagy), pagy.prev, pagy.next
11
+ link = pagy_link_proc(pagy)
13
12
 
14
- previous_span = "<span uk-pagination-previous>#{pagy_t('pagy.nav.prev')}</span>"
15
- html = EMPTY + (p_prev ? %(<li>#{link.call p_prev, previous_span}</li>)
16
- : %(<li class="uk-disabled"><a href="#">#{previous_span}</a></li>))
13
+ html = %(<ul class="pagy-uikit-nav uk-pagination uk-flex-center">#{pagy_uikit_prev_html pagy, link})
17
14
  pagy.series.each do |item|
18
- html << if item.is_a?(Integer); %(<li>#{link.call item}</li>)
19
- elsif item.is_a?(String) ; %(<li class="uk-active"><span>#{item}</span></li>)
20
- elsif item == :gap ; %(<li class="uk-disabled"><span>#{pagy_t('pagy.nav.gap')}</span></li>)
15
+ html << case item
16
+ when Integer then %(<li>#{link.call item}</li>)
17
+ when String then %(<li class="uk-active"><span>#{item}</span></li>)
18
+ when :gap then %(<li class="uk-disabled"><span>#{pagy_t 'pagy.nav.gap'}</span></li>)
21
19
  end
22
20
  end
23
- next_span = "<span uk-pagination-next>#{pagy_t('pagy.nav.next')}</span>"
24
- html << (p_next ? %(<li>#{link.call p_next, next_span}</li>)
25
- : %(<li class="uk-disabled"><a href="#">#{next_span}</a></li>))
26
- %(<ul class="pagy-uikit-nav uk-pagination uk-flex-center">#{html}</ul>)
21
+ html << pagy_uikit_next_html(pagy, link)
22
+ html << %(</ul>)
27
23
  end
28
24
 
29
25
  # Javascript pagination for uikit: it returns a nav and a JSON tag used by the Pagy.nav javascript
30
26
  def pagy_uikit_nav_js(pagy, id=pagy_id)
31
- link, p_prev, p_next = pagy_link_proc(pagy), pagy.prev, pagy.next
32
- previous_span = "<span uk-pagination-previous>#{pagy_t('pagy.nav.prev')}</span>"
33
- next_span = "<span uk-pagination-next>#{pagy_t('pagy.nav.next')}</span>"
34
- tags = { 'before' => p_prev ? %(<li>#{link.call p_prev, previous_span}</li>)
35
- : %(<li class="uk-disabled"><a href="#">#{previous_span}</a></li>),
27
+ link = pagy_link_proc(pagy)
28
+ tags = { 'before' => pagy_uikit_prev_html(pagy, link),
36
29
  'link' => %(<li>#{link.call(PAGE_PLACEHOLDER)}</li>),
37
30
  'active' => %(<li class="uk-active"><span>#{PAGE_PLACEHOLDER}</span></li>),
38
31
  'gap' => %(<li class="uk-disabled"><span>#{pagy_t('pagy.nav.gap')}</span></li>),
39
- 'after' => p_next ? %(<li>#{link.call p_next, next_span}</li>)
40
- : %(<li class="uk-disabled"><a href="#">#{next_span}</a></li>) }
41
- %(<ul id="#{id}" class="pagy-uikit-nav-js uk-pagination uk-flex-center"></ul>#{pagy_json_tag(:nav, id, tags, pagy.sequels, defined?(TRIM) && pagy.vars[:page_param])})
32
+ 'after' => pagy_uikit_next_html(pagy, link) }
33
+
34
+ html = %(<ul id="#{id}" class="pagy-uikit-nav-js uk-pagination uk-flex-center"></ul>)
35
+ html << pagy_json_tag(pagy, :nav, id, tags, pagy.sequels)
42
36
  end
43
37
 
44
38
  # Javascript combo pagination for uikit: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
45
39
  def pagy_uikit_combo_nav_js(pagy, id=pagy_id)
46
- link, p_prev, p_next, p_page, p_pages = pagy_link_proc(pagy), pagy.prev, pagy.next, pagy.page, pagy.pages
40
+ link = pagy_link_proc(pagy)
41
+ p_page = pagy.page
42
+ p_pages = pagy.pages
43
+ input = %(<input type="number" min="1" max="#{p_pages}" value="#{p_page}" class="uk-input" style="padding: 0; text-align: center; width: #{p_pages.to_s.length+1}rem;">)
44
+
45
+ %(<div id="#{id}" class="pagy-uikit-combo-nav-js uk-button-group">#{
46
+ if (p_prev = pagy.prev)
47
+ link.call p_prev, pagy_t('pagy.nav.prev'), 'class="uk-button uk-button-default"'
48
+ else
49
+ %(<button class="uk-button uk-button-default" disabled>#{pagy_t 'pagy.nav.prev'}</button>)
50
+ end
51
+ }<div class="uk-text-middle uk-margin-left uk-margin-right">#{
52
+ pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages
53
+ }</div>#{
54
+ if (p_next = pagy.next)
55
+ link.call p_next, pagy_t('pagy.nav.next'), 'class="uk-button uk-button-default"'
56
+ else
57
+ %(<button class="uk-button uk-button-default" disabled>#{pagy_t 'pagy.nav.next'}</button>)
58
+ end
59
+ }</div>#{
60
+ pagy_json_tag pagy, :combo_nav, id, p_page, pagy_marked_link(link)
61
+ })
62
+ end
47
63
 
48
- html = %(<div id="#{id}" class="pagy-uikit-combo-nav-js uk-button-group">)
49
- html = html + (p_prev ? link.call(p_prev, pagy_t('pagy.nav.prev'), 'class="uk-button uk-button-default"')
50
- : %(<button class="uk-button uk-button-default" disabled>#{pagy_t('pagy.nav.prev')}</button>))
51
64
 
52
- html << %(<div class="uk-text-middle uk-margin-left uk-margin-right">)
53
- input = %(<input type="number" min="1" max="#{p_pages}" value="#{p_page}" class="uk-input" style="padding: 0; text-align: center; width: #{p_pages.to_s.length+1}rem;">)
54
- html << pagy_t('pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages) + '</div>'
55
65
 
56
- html << (p_next ? link.call(p_next, pagy_t('pagy.nav.next'), 'class="uk-button uk-button-default"')
57
- : %(<button class="uk-button uk-button-default" disabled>#{pagy_t('pagy.nav.next')}</button>))
66
+ private
67
+
68
+ def pagy_uikit_prev_html(pagy, link)
69
+ previous_span = %(<span uk-pagination-previous>#{pagy_t 'pagy.nav.prev'}</span>)
70
+ if (p_prev = pagy.prev)
71
+ %(<li>#{link.call p_prev, previous_span}</li>)
72
+ else
73
+ %(<li class="uk-disabled"><a href="#">#{previous_span}</a></li>)
74
+ end
75
+ end
76
+
77
+ def pagy_uikit_next_html(pagy, link)
78
+ next_span = %(<span uk-pagination-next>#{pagy_t 'pagy.nav.next'}</span>)
79
+ if (p_next = pagy.next)
80
+ %(<li>#{link.call p_next, next_span}</li>)
81
+ else
82
+ %(<li class="uk-disabled"><a href="#">#{next_span}</a></li>)
83
+ end
84
+ end
58
85
 
59
- html << %(</div>#{pagy_json_tag(:combo_nav, id, p_page, pagy_marked_link(link), defined?(TRIM) && pagy.vars[:page_param])})
60
- end
61
86
  end
62
87
  end
data/lib/pagy/frontend.rb CHANGED
@@ -1,26 +1,27 @@
1
1
  # See Pagy::Frontend API documentation: https://ddnexus.github.io/pagy/api/frontend
2
- # encoding: utf-8
3
2
  # frozen_string_literal: true
4
3
 
5
4
  require 'yaml'
6
5
 
7
6
  class Pagy
8
7
 
9
- PAGE_PLACEHOLDER = '__pagy_page__' # string used for search and replace, hardcoded also in the pagy.js file
8
+ PAGE_PLACEHOLDER = '__pagy_page__' # string used for search and replace, hardcoded also in the pagy.js file
10
9
 
11
10
  # I18n static hash loaded at startup, used as default alternative to the i18n gem.
12
11
  # see https://ddnexus.github.io/pagy/api/frontend#i18n
13
- I18n = eval(Pagy.root.join('locales', 'utils', 'i18n.rb').read) #rubocop:disable Security/Eval
12
+ I18n = eval Pagy.root.join('locales', 'utils', 'i18n.rb').read #rubocop:disable Security/Eval
14
13
 
15
14
  module Helpers
16
15
  # This works with all Rack-based frameworks (Sinatra, Padrino, Rails, ...)
17
- def pagy_url_for(page, pagy, url=false)
18
- p_vars = pagy.vars; params = request.GET.merge(p_vars[:params]); params[p_vars[:page_param].to_s] = page
16
+ def pagy_url_for(page, pagy, url=nil)
17
+ p_vars = pagy.vars
18
+ params = request.GET.merge(p_vars[:params])
19
+ params[p_vars[:page_param].to_s] = page
19
20
  "#{request.base_url if url}#{request.path}?#{Rack::Utils.build_nested_query(pagy_get_params(params))}#{p_vars[:anchor]}"
20
21
  end
21
22
 
22
23
  # Sub-method called only by #pagy_url_for: here for easy customization of params by overriding
23
- def pagy_get_params(params) params end
24
+ def pagy_get_params(params) = params
24
25
  end
25
26
 
26
27
  # All the code here has been optimized for performance: it may not look very pretty
@@ -29,47 +30,64 @@ class Pagy
29
30
 
30
31
  include Helpers
31
32
 
32
- EMPTY = '' # EMPTY + 'string' is almost as fast as +'string' but is also 1.9 compatible
33
- MARK = PAGE_PLACEHOLDER # backward compatibility in case of helper-overriding in legacy apps
34
-
35
33
  # Generic pagination: it returns the html with the series of links to the pages
36
34
  def pagy_nav(pagy)
37
- link, p_prev, p_next = pagy_link_proc(pagy), pagy.prev, pagy.next
35
+ link = pagy_link_proc(pagy)
36
+ p_prev = pagy.prev
37
+ p_next = pagy.next
38
38
 
39
- html = EMPTY + (p_prev ? %(<span class="page prev">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'}</span> )
40
- : %(<span class="page prev disabled">#{pagy_t('pagy.nav.prev')}</span> ))
39
+ html = +%(<nav class="pagy-nav pagination" role="navigation" aria-label="pager">)
40
+ html << if p_prev
41
+ %(<span class="page prev">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'}</span> )
42
+ else
43
+ %(<span class="page prev disabled">#{pagy_t('pagy.nav.prev')}</span> )
44
+ end
41
45
  pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
42
- html << if item.is_a?(Integer); %(<span class="page">#{link.call item}</span> ) # page link
43
- elsif item.is_a?(String) ; %(<span class="page active">#{item}</span> ) # current page
44
- elsif item == :gap ; %(<span class="page gap">#{pagy_t('pagy.nav.gap')}</span> ) # page gap
46
+ html << case item
47
+ when Integer then %(<span class="page">#{link.call item}</span> ) # page link
48
+ when String then %(<span class="page active">#{item}</span> ) # current page
49
+ when :gap then %(<span class="page gap">#{pagy_t('pagy.nav.gap')}</span> ) # page gap
45
50
  end
46
51
  end
47
- html << (p_next ? %(<span class="page next">#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'}</span>)
48
- : %(<span class="page next disabled">#{pagy_t('pagy.nav.next')}</span>))
49
- %(<nav class="pagy-nav pagination" role="navigation" aria-label="pager">#{html}</nav>)
52
+ html << if p_next
53
+ %(<span class="page next">#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'}</span>)
54
+ else
55
+ %(<span class="page next disabled">#{pagy_t('pagy.nav.next')}</span>)
56
+ end
57
+ html << %(</nav>)
50
58
  end
51
59
 
52
60
  # Return examples: "Displaying items 41-60 of 324 in total" of "Displaying Products 41-60 of 324 in total"
53
61
  def pagy_info(pagy, item_name=nil)
54
- path = if (count = pagy.count) == 0 ; 'pagy.info.no_items'
55
- else pagy.pages == 1 ? 'pagy.info.single_page' : 'pagy.info.multiple_pages'
56
- end
57
- pagy_t(path, item_name: item_name || pagy_t(pagy.vars[:i18n_key], count: count), count: count, from: pagy.from, to: pagy.to)
62
+ count = pagy.count
63
+ key = if count.zero? then 'pagy.info.no_items'
64
+ elsif pagy.pages == 1 then 'pagy.info.single_page'
65
+ else 'pagy.info.multiple_pages'
66
+ end
67
+ pagy_t key, item_name: item_name || pagy_t(pagy.vars[:i18n_key], count: count),
68
+ count: count, from: pagy.from, to: pagy.to
58
69
  end
59
70
 
60
71
  # Returns a performance optimized proc to generate the HTML links
61
72
  # Benchmarked on a 20 link nav: it is ~22x faster and uses ~18x less memory than rails' link_to
62
73
  def pagy_link_proc(pagy, link_extra='')
63
- p_prev, p_next = pagy.prev, pagy.next
64
- a, b = %(<a href="#{pagy_url_for(PAGE_PLACEHOLDER, pagy)}" #{pagy.vars[:link_extra]} #{link_extra}).split(PAGE_PLACEHOLDER, 2)
65
- lambda {|n, text=n, extra=''| "#{a}#{n}#{b}#{ if n == p_prev ; ' rel="prev"'
66
- elsif n == p_next ; ' rel="next"'
67
- else '' end } #{extra}>#{text}</a>"}
74
+ p_prev = pagy.prev
75
+ p_next = pagy.next
76
+ left, right = %(<a href="#{pagy_url_for PAGE_PLACEHOLDER, pagy}" #{pagy.vars[:link_extra]} #{link_extra}).split(PAGE_PLACEHOLDER, 2)
77
+ lambda do |num, text=num, extra=''|
78
+ %(#{left}#{num}#{right}#{ case num
79
+ when p_prev then ' rel="prev"'
80
+ when p_next then ' rel="next"'
81
+ else ''
82
+ end } #{extra}>#{text}</a>)
83
+ end
68
84
  end
69
85
 
70
86
  # Similar to I18n.t: just ~18x faster using ~10x less memory
71
- # (@pagy_locale explicitly initilized in order to avoid warning)
72
- def pagy_t(path, vars={}) Pagy::I18n.t(@pagy_locale||=nil, path, vars) end
87
+ # (@pagy_locale explicitly initialized in order to avoid warning)
88
+ def pagy_t(key, **opts)
89
+ Pagy::I18n.t @pagy_locale||=nil, key, **opts
90
+ end
73
91
 
74
92
  end
75
93
  end