pagy 6.5.0 → 7.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/lib/config/pagy.rb +18 -16
  4. data/lib/javascripts/pagy-dev.js +10 -11
  5. data/lib/javascripts/pagy-module.js +9 -10
  6. data/lib/javascripts/pagy.js +1 -1
  7. data/lib/locales/ar.yml +14 -10
  8. data/lib/locales/be.yml +11 -10
  9. data/lib/locales/bg.yml +9 -10
  10. data/lib/locales/bs.yml +11 -10
  11. data/lib/locales/ca.yml +11 -10
  12. data/lib/locales/ckb.yml +8 -10
  13. data/lib/locales/cs.yml +13 -12
  14. data/lib/locales/da.yml +11 -10
  15. data/lib/locales/de.yml +9 -10
  16. data/lib/locales/en.yml +9 -10
  17. data/lib/locales/es.yml +9 -10
  18. data/lib/locales/fr.yml +9 -10
  19. data/lib/locales/hr.yml +11 -10
  20. data/lib/locales/id.yml +9 -10
  21. data/lib/locales/it.yml +9 -10
  22. data/lib/locales/ja.yml +9 -10
  23. data/lib/locales/km.yml +9 -9
  24. data/lib/locales/ko.yml +9 -10
  25. data/lib/locales/nb.yml +9 -10
  26. data/lib/locales/nl.yml +9 -10
  27. data/lib/locales/nn.yml +9 -10
  28. data/lib/locales/pl.yml +11 -10
  29. data/lib/locales/pt-BR.yml +9 -10
  30. data/lib/locales/pt.yml +9 -10
  31. data/lib/locales/ru.yml +13 -10
  32. data/lib/locales/sr.yml +11 -9
  33. data/lib/locales/sv-SE.yml +10 -12
  34. data/lib/locales/sv.yml +10 -12
  35. data/lib/locales/sw.yml +11 -10
  36. data/lib/locales/ta.yml +11 -10
  37. data/lib/locales/tr.yml +9 -10
  38. data/lib/locales/uk.yml +11 -10
  39. data/lib/locales/vi.yml +7 -10
  40. data/lib/locales/zh-CN.yml +9 -10
  41. data/lib/locales/zh-HK.yml +9 -10
  42. data/lib/locales/zh-TW.yml +9 -10
  43. data/lib/pagy/backend.rb +3 -2
  44. data/lib/pagy/calendar/day.rb +3 -2
  45. data/lib/pagy/calendar/helper.rb +3 -7
  46. data/lib/pagy/calendar/month.rb +3 -2
  47. data/lib/pagy/calendar/quarter.rb +3 -2
  48. data/lib/pagy/calendar/year.rb +2 -1
  49. data/lib/pagy/extras/bootstrap.rb +45 -30
  50. data/lib/pagy/extras/bulma.rb +44 -33
  51. data/lib/pagy/extras/calendar.rb +7 -8
  52. data/lib/pagy/extras/elasticsearch_rails.rb +6 -6
  53. data/lib/pagy/extras/foundation.rb +46 -33
  54. data/lib/pagy/extras/frontend_helpers.rb +8 -8
  55. data/lib/pagy/extras/headers.rb +9 -9
  56. data/lib/pagy/extras/i18n.rb +4 -4
  57. data/lib/pagy/extras/items.rb +11 -10
  58. data/lib/pagy/extras/jsonapi.rb +2 -7
  59. data/lib/pagy/extras/materialize.rb +41 -29
  60. data/lib/pagy/extras/meilisearch.rb +7 -7
  61. data/lib/pagy/extras/metadata.rb +6 -6
  62. data/lib/pagy/extras/navs.rb +26 -38
  63. data/lib/pagy/extras/overflow.rb +7 -5
  64. data/lib/pagy/extras/searchkick.rb +6 -6
  65. data/lib/pagy/extras/semantic.rb +40 -27
  66. data/lib/pagy/extras/standalone.rb +4 -7
  67. data/lib/pagy/extras/support.rb +18 -32
  68. data/lib/pagy/extras/trim.rb +2 -2
  69. data/lib/pagy/extras/uikit.rb +44 -31
  70. data/lib/pagy/frontend.rb +59 -28
  71. data/lib/pagy/i18n.rb +0 -2
  72. data/lib/pagy/url_helpers.rb +1 -2
  73. data/lib/pagy.rb +16 -14
  74. data/lib/stylesheets/pagy.css +61 -0
  75. data/lib/stylesheets/pagy.scss +50 -0
  76. data/lib/stylesheets/pagy.tailwind.scss +24 -0
  77. metadata +7 -19
  78. data/lib/templates/bootstrap_nav.html.erb +0 -24
  79. data/lib/templates/bootstrap_nav.html.haml +0 -34
  80. data/lib/templates/bootstrap_nav.html.slim +0 -34
  81. data/lib/templates/bulma_nav.html.erb +0 -24
  82. data/lib/templates/bulma_nav.html.haml +0 -32
  83. data/lib/templates/bulma_nav.html.slim +0 -32
  84. data/lib/templates/foundation_nav.html.erb +0 -24
  85. data/lib/templates/foundation_nav.html.haml +0 -34
  86. data/lib/templates/foundation_nav.html.slim +0 -34
  87. data/lib/templates/nav.html.erb +0 -22
  88. data/lib/templates/nav.html.haml +0 -30
  89. data/lib/templates/nav.html.slim +0 -29
  90. data/lib/templates/uikit_nav.html.erb +0 -15
  91. data/lib/templates/uikit_nav.html.haml +0 -28
  92. data/lib/templates/uikit_nav.html.slim +0 -28
@@ -8,18 +8,24 @@ class Pagy # :nodoc:
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: '', **vars)
11
+ def pagy_foundation_nav(pagy, pagy_id: nil, link_extra: '',
12
+ nav_aria_label: nil, nav_i18n_key: nil, **vars)
12
13
  p_id = %( id="#{pagy_id}") if pagy_id
13
- link = pagy_link_proc(pagy, link_extra: link_extra)
14
+ link = pagy_link_proc(pagy, link_extra:)
14
15
 
15
- html = +%(<nav#{p_id} class="pagy-foundation-nav" aria-label="Pagination"><ul class="pagination">)
16
- html << pagy_foundation_prev_html(pagy, link)
16
+ html = +%(<nav#{p_id} class="pagy-foundation-nav" #{
17
+ nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)}><ul class="pagination">)
18
+ html << foundation_prev_html(pagy, link)
17
19
  pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
18
20
  html << case item
19
- when Integer then %(<li>#{link.call item}</li>) # page link
20
- when String then %(<li class="current">#{pagy.label_for(item)}</li>) # active page
21
- when :gap then %(<li class="ellipsis gap" aria-hidden="true"></li>) # page gap
22
- else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
21
+ when Integer
22
+ %(<li>#{link.call item}</li>)
23
+ when String
24
+ %(<li class="current" role="link" aria-current="page" aria-disabled="true">#{pagy.label_for(item)}</li>)
25
+ when :gap
26
+ %(<li class="ellipsis gap"></li>)
27
+ else
28
+ raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
23
29
  end
24
30
  end
25
31
  html << pagy_foundation_next_html(pagy, link)
@@ -27,64 +33,71 @@ class Pagy # :nodoc:
27
33
  end
28
34
 
29
35
  # Javascript pagination for foundation: it returns a nav and a JSON tag used by the pagy.js file
30
- def pagy_foundation_nav_js(pagy, pagy_id: nil, link_extra: '', **vars)
36
+ def pagy_foundation_nav_js(pagy, pagy_id: nil, link_extra: '',
37
+ nav_aria_label: nil, nav_i18n_key: nil, **vars)
31
38
  sequels = pagy.sequels(**vars)
32
39
  p_id = %( id="#{pagy_id}") if pagy_id
33
- link = pagy_link_proc(pagy, link_extra: link_extra)
34
- tags = { 'before' => %(<ul class="pagination">#{pagy_foundation_prev_html pagy, link}),
35
- 'link' => %(<li>#{link.call(PAGE_PLACEHOLDER, LABEL_PLACEHOLDER)}</li>),
36
- 'active' => %(<li class="current">#{LABEL_PLACEHOLDER}</li>),
37
- 'gap' => %(<li class="ellipsis gap" aria-hidden="true"></li>),
40
+ link = pagy_link_proc(pagy, link_extra:)
41
+ tags = { 'before' => %(<ul class="pagination">#{foundation_prev_html pagy, link}),
42
+ 'link' => %(<li>#{link.call(PAGE_TOKEN, LABEL_TOKEN)}</li>),
43
+ 'active' => %(<li class="current" role="link" aria-current="page" aria-disabled="true">#{LABEL_TOKEN}</li>),
44
+ 'gap' => %(<li class="ellipsis gap"></li>),
38
45
  'after' => %(#{pagy_foundation_next_html pagy, link}</ul>) }
39
46
 
40
- %(<nav#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-foundation-nav-js" aria-label="Pagination" #{
41
- pagy_data(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></nav>)
47
+ %(<nav#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-foundation-nav-js" #{
48
+ nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)} #{
49
+ pagy_data(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></nav>)
42
50
  end
43
51
 
44
52
  # Javascript combo pagination for Foundation: it returns a nav and a JSON tag used by the pagy.js file
45
- def pagy_foundation_combo_nav_js(pagy, pagy_id: nil, link_extra: '')
53
+ def pagy_foundation_combo_nav_js(pagy, pagy_id: nil, link_extra: '',
54
+ nav_aria_label: nil, nav_i18n_key: nil)
46
55
  p_id = %( id="#{pagy_id}") if pagy_id
47
- link = pagy_link_proc(pagy, link_extra: link_extra)
56
+ link = pagy_link_proc(pagy, link_extra:)
48
57
  p_page = pagy.page
49
58
  p_pages = pagy.pages
50
59
  input = %(<input class="input-group-field cell shrink" type="number" min="1" max="#{
51
60
  p_pages}" value="#{p_page}" style="width: #{
52
- p_pages.to_s.length + 1}rem; padding: 0 0.3rem; margin: 0 0.3rem;">)
61
+ p_pages.to_s.length + 1}rem; padding: 0 0.3rem; margin: 0 0.3rem;" aria-current="page">)
53
62
 
54
- %(<nav#{p_id} class="pagy-foundation-combo-nav-js" aria-label="Pagination"><div class="input-group" #{
55
- pagy_data(pagy, :combo, pagy_marked_link(link))}>#{
56
- if (p_prev = pagy.prev)
57
- link.call p_prev, pagy_t('pagy.nav.prev'),
58
- 'style="margin-bottom: 0" aria-label="previous" class="prev button primary"'
63
+ %(<nav#{p_id} class="pagy-foundation-combo-nav-js" #{
64
+ nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)} #{
65
+ pagy_data(pagy, :combo, pagy_marked_link(link))}><div class="input-group">#{
66
+ if (p_prev = pagy.prev)
67
+ link.call(p_prev, pagy_t('pagy.prev'),
68
+ %(style="margin-bottom: 0" class="prev button primary" #{prev_aria_label_attr}))
59
69
  else
60
- %(<a style="margin-bottom: 0" class="prev button primary disabled" href="#">#{pagy_t 'pagy.nav.prev'}</a>)
70
+ %(<a style="margin-bottom: 0" class="prev button primary disabled" role="link" aria-disabled="true" #{
71
+ prev_aria_label_attr}>#{pagy_t('pagy.prev')}</a>)
61
72
  end
62
73
  }#{
63
74
  pagy_t('pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages)
64
75
  .sub!('<label>', '<label class="input-group-label">')}#{ # add the class to the official dictionary string
65
- if (p_next = pagy.next)
66
- link.call p_next, pagy_t('pagy.nav.next'), 'style="margin-bottom: 0" aria-label="next" class="next button primary"'
76
+ if (p_next = pagy.next)
77
+ link.call(p_next, pagy_t('pagy.next'),
78
+ %(style="margin-bottom: 0" class="next button primary" #{next_aria_label_attr}))
67
79
  else
68
- %(<a style="margin-bottom: 0" class="next button primary disabled" href="#">#{pagy_t 'pagy.nav.next'}</a>)
80
+ %(<a style="margin-bottom: 0" class="next button primary disabled" role="link" aria-disabled="true" #{
81
+ next_aria_label_attr}>#{pagy_t 'pagy.next'}</a>)
69
82
  end
70
83
  }</div></nav>)
71
84
  end
72
85
 
73
86
  private
74
87
 
75
- def pagy_foundation_prev_html(pagy, link)
88
+ def foundation_prev_html(pagy, link)
76
89
  if (p_prev = pagy.prev)
77
- %(<li class="prev">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'}</li>)
90
+ %(<li class="prev">#{link.call(p_prev, pagy_t('pagy.prev'), prev_aria_label_attr)}</li>)
78
91
  else
79
- %(<li class="prev disabled">#{pagy_t 'pagy.nav.prev'}</li>)
92
+ %(<li class="prev disabled" role="link" aria-disabled="true" #{prev_aria_label_attr}>#{pagy_t('pagy.prev')}</li>)
80
93
  end
81
94
  end
82
95
 
83
96
  def pagy_foundation_next_html(pagy, link)
84
97
  if (p_next = pagy.next)
85
- %(<li class="next">#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'}</li>)
98
+ %(<li class="next">#{link.call(p_next, pagy_t('pagy.next'), next_aria_label_attr)}</li>)
86
99
  else
87
- %(<li class="next disabled">#{pagy_t 'pagy.nav.next'}</li>)
100
+ %(<li class="next disabled" role="link" aria-disabled="true" #{next_aria_label_attr}>#{pagy_t('pagy.next')}</li>)
88
101
  end
89
102
  end
90
103
  end
@@ -6,7 +6,7 @@ class Pagy # :nodoc:
6
6
  # Private module documented in the main classes
7
7
  module FrontendHelpers
8
8
  # Additions for the Pagy class
9
- module Pagy
9
+ module PagyAddOn
10
10
  # `Pagy` instance method used by the `pagy*_nav_js` helpers.
11
11
  # It returns the sequels of width/series generated from the :steps hash
12
12
  # Example:
@@ -27,9 +27,10 @@ class Pagy # :nodoc:
27
27
  # Support for the Calendar API
28
28
  def label_sequels(*); end
29
29
  end
30
+ Pagy.prepend PagyAddOn
30
31
 
31
32
  # Additions for Calendar class
32
- module Calendar
33
+ module CalendarOverride
33
34
  def label_sequels(sequels = self.sequels)
34
35
  {}.tap do |label_sequels|
35
36
  sequels.each do |width, series|
@@ -38,9 +39,10 @@ class Pagy # :nodoc:
38
39
  end
39
40
  end
40
41
  end
42
+ Calendar.prepend CalendarOverride if defined?(Calendar)
41
43
 
42
44
  # Additions for the Frontend
43
- module Frontend
45
+ module FrontendAddOn
44
46
  if defined?(Oj)
45
47
  # Return a data tag with the base64 encoded JSON-serialized args generated with the faster oj gem
46
48
  # Base64 encoded JSON is smaller than HTML escaped JSON
@@ -60,13 +62,11 @@ class Pagy # :nodoc:
60
62
  end
61
63
  end
62
64
 
63
- # Return the marked link to used by pagy.js
65
+ # Return the marked link used by pagy.js
64
66
  def pagy_marked_link(link)
65
- link.call PAGE_PLACEHOLDER, '', 'style="display: none;"'
67
+ link.call PAGE_TOKEN, '', 'style="display: none;"'
66
68
  end
67
69
  end
70
+ Frontend.prepend FrontendAddOn
68
71
  end
69
- prepend FrontendHelpers::Pagy
70
- Calendar.prepend FrontendHelpers::Calendar if defined?(Calendar)
71
- Frontend.prepend FrontendHelpers::Frontend
72
72
  end
@@ -4,10 +4,10 @@
4
4
  require 'pagy/url_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
- DEFAULT[:headers] = { page: 'Current-Page',
8
- items: 'Page-Items',
9
- count: 'Total-Count',
10
- pages: 'Total-Pages' }
7
+ DEFAULT[:headers] = { page: 'current-page',
8
+ items: 'page-items',
9
+ count: 'total-count',
10
+ pages: 'total-pages' }
11
11
  # Add specialized backend methods to add pagination response headers
12
12
  module HeadersExtra
13
13
  include UrlHelpers
@@ -22,7 +22,7 @@ class Pagy # :nodoc:
22
22
  # Generate a hash of RFC-8288 compliant http headers
23
23
  def pagy_headers(pagy)
24
24
  pagy_headers_hash(pagy).tap do |hash|
25
- hash['Link'] = hash['Link'].map { |rel, link| %(<#{link}>; rel="#{rel}") }.join(', ')
25
+ hash['link'] = hash['link'].map { |rel, link| %(<#{link}>; rel="#{rel}") }.join(', ')
26
26
  end
27
27
  end
28
28
 
@@ -31,12 +31,12 @@ class Pagy # :nodoc:
31
31
  countless = defined?(Countless) && pagy.is_a?(Countless)
32
32
  rel = { 'first' => 1, 'prev' => pagy.prev, 'next' => pagy.next }
33
33
  rel['last'] = pagy.last unless countless
34
- url_str = pagy_url_for(pagy, PAGE_PLACEHOLDER, absolute: true)
35
- link = rel.map do |r, num| # filter_map if ruby >=2.7
34
+ url_str = pagy_url_for(pagy, PAGE_TOKEN, absolute: true)
35
+ link = rel.filter_map do |r, num|
36
36
  next unless num # rubocop:disable Layout/EmptyLineAfterGuardClause
37
- [r, url_str.sub(PAGE_PLACEHOLDER, num.to_s)]
37
+ [r, url_str.sub(PAGE_TOKEN, num.to_s)]
38
38
  end.compact.to_h
39
- hash = { 'Link' => link }
39
+ hash = { 'link' => link }
40
40
  headers = pagy.vars[:headers]
41
41
  hash[headers[:page]] = pagy.page.to_s if headers[:page]
42
42
  if headers[:items] && !(defined?(Calendar) && pagy.is_a?(Calendar)) # items is not for Calendar
@@ -5,21 +5,21 @@ class Pagy # :nodoc:
5
5
  # Use ::I18n gem
6
6
  module I18nExtra
7
7
  # Frontend overriding for translation
8
- module Frontend
8
+ module FrontendOverride
9
9
  def pagy_t(key, **opts)
10
10
  ::I18n.t(key, **opts)
11
11
  end
12
12
  end
13
+ Frontend.prepend I18nExtra::FrontendOverride
13
14
 
14
15
  # Calendar overriding for localization (see also the block in the calendar section of the config/pagy.rb initializer)
15
- module Calendar
16
+ module CalendarOverride
16
17
  def localize(time, opts)
17
18
  ::I18n.l(time, **opts)
18
19
  end
19
20
  end
20
21
  end
21
- Frontend.prepend I18nExtra::Frontend
22
- Calendar.prepend I18nExtra::Calendar if defined?(Calendar)
22
+ Calendar.prepend I18nExtra::CalendarOverride if defined?(Calendar)
23
23
 
24
24
  # Add the pagy locales to the I18n.load_path
25
25
  ::I18n.load_path += Dir[Pagy.root.join('locales', '*.yml')]
@@ -11,7 +11,7 @@ class Pagy # :nodoc:
11
11
  # Allow the client to request a custom number of items per page with an optional selector UI
12
12
  module ItemsExtra
13
13
  # Additions for the Backend module
14
- module Backend
14
+ module BackendAddOn
15
15
  private
16
16
 
17
17
  # Set the items variable considering the params and other pagy variables
@@ -29,32 +29,33 @@ class Pagy # :nodoc:
29
29
  params[vars[:items_param] || DEFAULT[:items_param]]
30
30
  end
31
31
  end
32
+ Backend.prepend ItemsExtra::BackendAddOn
32
33
 
33
34
  # Additions for the Frontend module
34
- module Frontend
35
+ module FrontendAddOn
35
36
  ITEMS_PLACEHOLDER = '__pagy_items__'
36
37
 
37
38
  # Return the items selector HTML. For example "Show [20] items per page"
38
- def pagy_items_selector_js(pagy, pagy_id: nil, item_name: nil, i18n_key: nil, link_extra: '')
39
+ def pagy_items_selector_js(pagy, pagy_id: nil, item_name: nil, item_i18n_key: nil, link_extra: '')
39
40
  return '' unless pagy.vars[:items_extra]
40
41
 
41
42
  p_id = %( id="#{pagy_id}") if pagy_id
42
43
  p_vars = pagy.vars
43
44
  p_items = p_vars[:items]
44
45
  p_vars[:items] = ITEMS_PLACEHOLDER
45
- link = pagy_marked_link(pagy_link_proc(pagy, link_extra: link_extra))
46
+ link = pagy_marked_link(pagy_link_proc(pagy, link_extra:))
46
47
  p_vars[:items] = p_items # restore the items
47
48
 
48
- html = +%(<span#{p_id} class="pagy-items-selector-js" #{pagy_data(pagy, :selector, pagy.from, link)}>)
49
+ html = +%(<span#{p_id} class="pagy pagy-items-selector-js" #{pagy_data(pagy, :selector, pagy.from, link)}>)
49
50
  input = %(<input type="number" min="1" max="#{p_vars[:max_items]}" value="#{
50
51
  p_items}" style="padding: 0; text-align: center; width: #{p_items.to_s.length + 1}rem;">)
51
- html << pagy_t('pagy.items_selector_js', item_name: item_name || pagy_t(i18n_key || p_vars[:i18n_key], count: p_items),
52
- items_input: input,
53
- count: p_items)
52
+ html << pagy_t('pagy.items_selector_js',
53
+ item_name: item_name || pagy_t(item_i18n_key || p_vars[:item_i18n_key], count: p_items),
54
+ items_input: input,
55
+ count: p_items)
54
56
  html << %(</span>)
55
57
  end
56
58
  end
59
+ Frontend.prepend ItemsExtra::FrontendAddOn
57
60
  end
58
- Backend.prepend ItemsExtra::Backend
59
- Frontend.prepend ItemsExtra::Frontend
60
61
  end
@@ -59,10 +59,8 @@ class Pagy # :nodoc:
59
59
  params[:page][vars[:items_param] || DEFAULT[:items_param]]
60
60
  end
61
61
  end
62
- # Swap the next lines in ruby 3.0+ baseline
63
- # ItemsExtra::Backend.prepend ItemsExtraOverride if defined?(ItemsExtra::Backend)
64
62
  # :nocov:
65
- Backend.prepend ItemsExtraOverride if defined?(ItemsExtra::Backend)
63
+ ItemsExtra::BackendAddOn.prepend ItemsExtraOverride if defined?(ItemsExtra::BackendAddOn)
66
64
  # :nocov:
67
65
 
68
66
  # Module overriding UrlHelper
@@ -76,9 +74,6 @@ class Pagy # :nodoc:
76
74
  params['page'][vars[:items_param].to_s] = vars[:items] if vars[:items_extra]
77
75
  end
78
76
  end
79
- # Swap the next lines in ruby 3.0+ baseline
80
- # UrlHelpers.prepend UrlHelperOverride
81
- Backend.prepend UrlHelperOverride
82
- Frontend.prepend UrlHelperOverride
77
+ UrlHelpers.prepend UrlHelperOverride
83
78
  end
84
79
  end
@@ -8,75 +8,87 @@ class Pagy # :nodoc:
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: '', **vars)
11
+ def pagy_materialize_nav(pagy, pagy_id: nil, link_extra: '',
12
+ nav_aria_label: nil, nav_i18n_key: nil, **vars)
12
13
  p_id = %( id="#{pagy_id}") if pagy_id
13
- link = pagy_link_proc(pagy, link_extra: link_extra)
14
+ link = pagy_link_proc(pagy, link_extra:)
14
15
 
15
- html = +%(<div#{p_id} class="pagy-materialize-nav pagination" role="navigation"><ul class="pagination">)
16
- html << pagy_materialize_prev_html(pagy, link)
16
+ html = +%(<div#{p_id} class="pagy-materialize-nav pagination" role="navigation" #{
17
+ nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)}><ul class="pagination">)
18
+ html << materialize_prev_html(pagy, link)
17
19
  pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
18
20
  html << case item
19
- when Integer then %(<li class="waves-effect">#{link.call item}</li>) # page link
20
- when String then %(<li class="active">#{link.call item}</li>) # active page
21
- when :gap then %(<li class="gap disabled"><a href="#">#{pagy_t 'pagy.nav.gap'}</a></li>) # page gap
22
- else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
21
+ when Integer
22
+ %(<li class="waves-effect">#{link.call(item)}</li>)
23
+ when String
24
+ %(<li class="active"><a role="link" aria-current="page" aria-disabled="true">#{pagy.label_for(item)}</a></li>)
25
+ when :gap
26
+ %(<li class="gap disabled"><a role="link" aria-disabled="true">#{pagy_t 'pagy.gap'}</a></li>)
27
+ else
28
+ raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
23
29
  end
24
30
  end
25
- html << pagy_materialize_next_html(pagy, link)
31
+ html << materialize_next_html(pagy, link)
26
32
  html << %(</ul></div>)
27
33
  end
28
34
 
29
35
  # Javascript pagination for materialize: it returns a nav and a JSON tag used by the pagy.js file
30
- def pagy_materialize_nav_js(pagy, pagy_id: nil, link_extra: '', **vars)
36
+ def pagy_materialize_nav_js(pagy, pagy_id: nil, link_extra: '',
37
+ nav_aria_label: nil, nav_i18n_key: nil, **vars)
31
38
  sequels = pagy.sequels(**vars)
32
39
  p_id = %( id="#{pagy_id}") if pagy_id
33
- link = pagy_link_proc(pagy, link_extra: link_extra)
40
+ link = pagy_link_proc(pagy, link_extra:)
34
41
 
35
- tags = { 'before' => %(<ul class="pagination">#{pagy_materialize_prev_html pagy, link}),
36
- 'link' => %(<li class="waves-effect">#{mark = link.call(PAGE_PLACEHOLDER, LABEL_PLACEHOLDER)}</li>),
37
- 'active' => %(<li class="active">#{mark}</li>),
38
- 'gap' => %(<li class="gap disabled"><a href="#">#{pagy_t 'pagy.nav.gap'}</a></li>),
39
- 'after' => %(#{pagy_materialize_next_html pagy, link}</ul>) }
42
+ tags = { 'before' => %(<ul class="pagination">#{materialize_prev_html pagy, link}),
43
+ 'link' => %(<li class="waves-effect">#{link.call(PAGE_TOKEN, LABEL_TOKEN)}</li>),
44
+ 'active' => %(<li class="active"><a role="link" aria-current="page" aria-disabled="true">#{LABEL_TOKEN}</a></li>),
45
+ 'gap' => %(<li class="gap disabled"><a role="link" aria-disabled="true">#{pagy_t 'pagy.gap'}</a></li>),
46
+ 'after' => %(#{materialize_next_html pagy, link}</ul>) }
40
47
 
41
48
  %(<div#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-materialize-nav-js" role="navigation" #{
42
- pagy_data(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></div>)
49
+ nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)} #{
50
+ pagy_data(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></div>)
43
51
  end
44
52
 
45
53
  # Javascript combo pagination for materialize: it returns a nav and a JSON tag used by the pagy.js file
46
- def pagy_materialize_combo_nav_js(pagy, pagy_id: nil, link_extra: '')
54
+ def pagy_materialize_combo_nav_js(pagy, pagy_id: nil, link_extra: '',
55
+ nav_aria_label: nil, nav_i18n_key: nil)
47
56
  p_id = %( id="#{pagy_id}") if pagy_id
48
- link = pagy_link_proc(pagy, link_extra: link_extra)
57
+ link = pagy_link_proc(pagy, link_extra:)
49
58
  p_page = pagy.page
50
59
  p_pages = pagy.pages
51
60
  style = ' style="vertical-align: middle"'
52
61
  input = %(<input type="number" class="browser-default" min="1" max="#{p_pages}" value="#{
53
- p_page}" style="text-align: center; width: #{p_pages.to_s.length + 1}rem;">)
62
+ p_page}" style="text-align: center; width: #{p_pages.to_s.length + 1}rem;" aria-current="page">)
54
63
 
55
- html = %(<ul#{p_id} class="pagy-materialize-combo-nav-js pagination chip" role="navigation")
64
+ html = %(<ul#{p_id} class="pagy-materialize-combo-nav-js pagination chip" role="navigation" #{
65
+ nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)})
56
66
  %(#{html} style="padding-right: 0" #{
57
67
  pagy_data(pagy, :combo, pagy_marked_link(link))}>#{
58
- pagy_materialize_prev_html pagy, link, style}<li class="pagy-combo-input">#{
68
+ materialize_prev_html pagy, link, style}<li class="pagy-combo-input">#{
59
69
  pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages}</li>#{
60
- pagy_materialize_next_html pagy, link, style}</ul>)
70
+ materialize_next_html pagy, link, style}</ul>)
61
71
  end
62
72
 
63
73
  private
64
74
 
65
- def pagy_materialize_prev_html(pagy, link, style = '')
75
+ def materialize_prev_html(pagy, link, style = '')
66
76
  if (p_prev = pagy.prev)
67
77
  %(<li class="waves-effect prev"#{style}>#{
68
- link.call p_prev, '<i class="material-icons">chevron_left</i>', 'aria-label="previous"'}</li>)
78
+ link.call(p_prev, '<i class="material-icons">chevron_left</i>', prev_aria_label_attr)}</li>)
69
79
  else
70
- %(<li class="prev disabled"#{style}><a href="#"><i class="material-icons">chevron_left</i></a></li>)
80
+ %(<li class="prev disabled"#{style}><a role="link" aria-disabled="true" #{
81
+ prev_aria_label_attr}><i class="material-icons">chevron_left</i></a></li>)
71
82
  end
72
83
  end
73
84
 
74
- def pagy_materialize_next_html(pagy, link, style = '')
85
+ def materialize_next_html(pagy, link, style = '')
75
86
  if (p_next = pagy.next)
76
87
  %(<li class="waves-effect next"#{style}>#{
77
- link.call p_next, '<i class="material-icons">chevron_right</i>', 'aria-label="next"'}</li>)
88
+ link.call(p_next, '<i class="material-icons">chevron_right</i>', next_aria_label_attr)}</li>)
78
89
  else
79
- %(<li class="next disabled"#{style}><a href="#"><i class="material-icons">chevron_right</i></a></li>)
90
+ %(<li class="next disabled"#{style}><a role="link" aria-disabled="true" #{
91
+ next_aria_label_attr}><i class="material-icons">chevron_right</i></a></li>)
80
92
  end
81
93
  end
82
94
  end
@@ -7,7 +7,7 @@ class Pagy # :nodoc:
7
7
 
8
8
  # Paginate Meilisearch results
9
9
  module MeilisearchExtra
10
- module Meilisearch # :nodoc:
10
+ module ModelExtension # :nodoc:
11
11
  # Return an array used to delay the call of #search
12
12
  # after the pagination variables are merged to the options
13
13
  def pagy_meilisearch(query, params = {})
@@ -15,9 +15,10 @@ class Pagy # :nodoc:
15
15
  end
16
16
  alias_method DEFAULT[:meilisearch_pagy_search], :pagy_meilisearch
17
17
  end
18
+ Pagy::Meilisearch = ModelExtension
18
19
 
19
- # Additions for the Pagy class
20
- module Pagy
20
+ # Extension for the Pagy class
21
+ module PagyExtension
21
22
  # Create a Pagy object from a Meilisearch results
22
23
  def new_from_meilisearch(results, vars = {})
23
24
  vars[:items] = results.raw_answer['hitsPerPage']
@@ -27,9 +28,10 @@ class Pagy # :nodoc:
27
28
  new(vars)
28
29
  end
29
30
  end
31
+ Pagy.extend PagyExtension
30
32
 
31
33
  # Add specialized backend methods to paginate Meilisearch results
32
- module Backend
34
+ module BackendAddOn
33
35
  private
34
36
 
35
37
  # Return Pagy object and results
@@ -58,8 +60,6 @@ class Pagy # :nodoc:
58
60
  vars
59
61
  end
60
62
  end
63
+ Backend.prepend BackendAddOn
61
64
  end
62
- Meilisearch = MeilisearchExtra::Meilisearch
63
- extend MeilisearchExtra::Pagy
64
- Backend.prepend MeilisearchExtra::Backend
65
65
  end
@@ -15,17 +15,17 @@ class Pagy # :nodoc:
15
15
 
16
16
  # Return the metadata hash
17
17
  def pagy_metadata(pagy, absolute: nil)
18
- scaffold_url = pagy_url_for(pagy, PAGE_PLACEHOLDER, absolute: absolute)
18
+ scaffold_url = pagy_url_for(pagy, PAGE_TOKEN, absolute:)
19
19
  {}.tap do |metadata|
20
20
  keys = defined?(Calendar) && pagy.is_a?(Calendar) ? pagy.vars[:metadata] - %i[count items] : pagy.vars[:metadata]
21
21
  keys.each do |key|
22
22
  metadata[key] = case key
23
23
  when :scaffold_url then scaffold_url
24
- when :first_url then scaffold_url.sub(PAGE_PLACEHOLDER, 1.to_s)
25
- when :prev_url then scaffold_url.sub(PAGE_PLACEHOLDER, pagy.prev.to_s)
26
- when :page_url then scaffold_url.sub(PAGE_PLACEHOLDER, pagy.page.to_s)
27
- when :next_url then scaffold_url.sub(PAGE_PLACEHOLDER, pagy.next.to_s)
28
- when :last_url then scaffold_url.sub(PAGE_PLACEHOLDER, pagy.last.to_s)
24
+ when :first_url then scaffold_url.sub(PAGE_TOKEN, 1.to_s)
25
+ when :prev_url then scaffold_url.sub(PAGE_TOKEN, pagy.prev.to_s)
26
+ when :page_url then scaffold_url.sub(PAGE_TOKEN, pagy.page.to_s)
27
+ when :next_url then scaffold_url.sub(PAGE_TOKEN, pagy.next.to_s)
28
+ when :last_url then scaffold_url.sub(PAGE_TOKEN, pagy.last.to_s)
29
29
  else pagy.send(key)
30
30
  end
31
31
  rescue NoMethodError
@@ -8,56 +8,44 @@ class Pagy # :nodoc:
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.js file
11
- def pagy_nav_js(pagy, pagy_id: nil, link_extra: '', **vars)
11
+ def pagy_nav_js(pagy, pagy_id: nil, link_extra: '',
12
+ nav_aria_label: nil, nav_i18n_key: nil, **vars)
12
13
  sequels = pagy.sequels(**vars)
13
14
  p_id = %( id="#{pagy_id}") if pagy_id
14
- link = pagy_link_proc(pagy, link_extra: link_extra)
15
- tags = { 'before' => pagy_nav_prev_html(pagy, link),
16
- 'link' => %(<span class="page">#{link.call(PAGE_PLACEHOLDER, LABEL_PLACEHOLDER)}</span> ),
17
- 'active' => %(<span class="page active">#{LABEL_PLACEHOLDER}</span> ),
18
- 'gap' => %(<span class="page gap">#{pagy_t 'pagy.nav.gap'}</span> ),
19
- 'after' => pagy_nav_next_html(pagy, link) }
20
-
21
- %(<nav#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-nav-js pagination" #{
22
- pagy_data(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></nav>)
15
+ link = pagy_link_proc(pagy, link_extra:)
16
+ tags = { 'before' => prev_html(pagy, link),
17
+ 'link' => %(<span class="page">#{link.call(PAGE_TOKEN, LABEL_TOKEN)}</span>),
18
+ 'active' => %(<span class="page active">) +
19
+ %(<a role="link" aria-current="page" aria-disabled="true">#{LABEL_TOKEN}</a></span>),
20
+ 'gap' => %(<span class="page gap">#{pagy_t 'pagy.gap'}</span>),
21
+ 'after' => next_html(pagy, link) }
22
+
23
+ %(<nav#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy pagy-nav-js pagination" #{
24
+ nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)} #{
25
+ pagy_data(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))
26
+ }></nav>)
23
27
  end
24
28
 
25
29
  # Javascript combo pagination: it returns a nav and a JSON tag used by the pagy.js file
26
- def pagy_combo_nav_js(pagy, pagy_id: nil, link_extra: '')
30
+ def pagy_combo_nav_js(pagy, pagy_id: nil, link_extra: '',
31
+ nav_aria_label: nil, nav_i18n_key: nil)
27
32
  p_id = %( id="#{pagy_id}") if pagy_id
28
- link = pagy_link_proc(pagy, link_extra: link_extra)
33
+ link = pagy_link_proc(pagy, link_extra:)
29
34
  p_page = pagy.page
30
35
  p_pages = pagy.pages
31
- input = %(<input type="number" min="1" max="#{p_pages}" value="#{
32
- p_page}" style="padding: 0; text-align: center; width: #{p_pages.to_s.length + 1}rem;">)
36
+ input = %(<input type="number" min="1" max="#{p_pages}" value="#{p_page}" ) +
37
+ %(style="padding: 0; text-align: center; width: #{p_pages.to_s.length + 1}rem;" aria-current="page">)
33
38
 
34
- %(<nav#{p_id} class="pagy-combo-nav-js pagination" #{
39
+ %(<nav#{p_id} class="pagy pagy-combo-nav-js pagination" #{
40
+ nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)} #{
35
41
  pagy_data(pagy, :combo, pagy_marked_link(link))}>#{
36
- pagy_nav_prev_html pagy, link
37
- }<span class="pagy-combo-input" style="margin: 0 0.6rem;">#{
38
- pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages
39
- }</span> #{
40
- pagy_nav_next_html pagy, link
42
+ prev_html(pagy, link)
43
+ }<span class="pagy-combo-input">#{
44
+ pagy_t('pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages)
45
+ }</span>#{
46
+ next_html(pagy, link)
41
47
  }</nav>)
42
48
  end
43
-
44
- private
45
-
46
- def pagy_nav_prev_html(pagy, link)
47
- if (p_prev = pagy.prev)
48
- %(<span class="page prev">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'}</span> )
49
- else
50
- %(<span class="page prev disabled">#{pagy_t 'pagy.nav.prev'}</span> )
51
- end
52
- end
53
-
54
- def pagy_nav_next_html(pagy, link)
55
- if (p_next = pagy.next)
56
- %(<span class="page next">#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'}</span>)
57
- else
58
- %(<span class="page next disabled">#{pagy_t 'pagy.nav.next'}</span>)
59
- end
60
- end
61
49
  end
62
50
  Frontend.prepend NavsExtra
63
51
  end
@@ -7,7 +7,7 @@ class Pagy # :nodoc:
7
7
  # Handles OverflowError exceptions for different classes with different options
8
8
  module OverflowExtra
9
9
  # Support for Pagy class
10
- module Pagy
10
+ module PagyOverride
11
11
  # Is the requested page overflowing?
12
12
  def overflow?
13
13
  @overflow
@@ -50,9 +50,11 @@ class Pagy # :nodoc:
50
50
  end
51
51
  end
52
52
  end
53
+ Pagy.prepend PagyOverride
54
+ Pagy::Calendar.prepend PagyOverride if defined?(Calendar)
53
55
 
54
56
  # Support for Pagy::Countless class
55
- module Countless
57
+ module CountlessOverride
56
58
  # Add rescue clause for different behaviors
57
59
  def finalize(items)
58
60
  @overflow = false
@@ -71,8 +73,8 @@ class Pagy # :nodoc:
71
73
  end
72
74
  end
73
75
  end
76
+ # :nocov:
77
+ Pagy::Countless.prepend CountlessOverride if defined?(Countless)
78
+ # :nocov:
74
79
  end
75
- prepend OverflowExtra::Pagy
76
- Calendar.prepend OverflowExtra::Pagy if defined?(Calendar)
77
- Countless.prepend OverflowExtra::Countless if defined?(Countless)
78
80
  end