pagy 5.7.5 → 8.6.2

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.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/apps/calendar.ru +745 -0
  4. data/apps/demo.ru +435 -0
  5. data/apps/rails.ru +213 -0
  6. data/apps/repro.ru +177 -0
  7. data/apps/tmp/calendar.sqlite3 +0 -0
  8. data/apps/tmp/calendar.sqlite3-shm +0 -0
  9. data/apps/tmp/calendar.sqlite3-wal +0 -0
  10. data/apps/tmp/local_secret.txt +1 -0
  11. data/bin/pagy +100 -0
  12. data/{lib/config → config}/pagy.rb +72 -96
  13. data/javascripts/pagy-module.js +100 -0
  14. data/javascripts/pagy.d.ts +5 -0
  15. data/javascripts/pagy.js +4 -0
  16. data/javascripts/pagy.min.js +4 -0
  17. data/javascripts/pagy.min.js.map +10 -0
  18. data/javascripts/pagy.mjs +100 -0
  19. data/lib/optimist.rb +1022 -0
  20. data/lib/pagy/backend.rb +16 -4
  21. data/lib/pagy/calendar/day.rb +22 -10
  22. data/lib/pagy/calendar/month.rb +35 -9
  23. data/lib/pagy/calendar/quarter.rb +36 -10
  24. data/lib/pagy/calendar/unit.rb +106 -0
  25. data/lib/pagy/calendar/week.rb +16 -16
  26. data/lib/pagy/calendar/year.rb +15 -9
  27. data/lib/pagy/calendar.rb +60 -68
  28. data/lib/pagy/console.rb +3 -3
  29. data/lib/pagy/countless.rb +17 -12
  30. data/lib/pagy/exceptions.rb +1 -1
  31. data/lib/pagy/extras/arel.rb +2 -2
  32. data/lib/pagy/extras/array.rb +2 -2
  33. data/lib/pagy/extras/bootstrap.rb +57 -53
  34. data/lib/pagy/extras/bulma.rb +53 -57
  35. data/lib/pagy/extras/calendar.rb +54 -37
  36. data/lib/pagy/extras/countless.rb +3 -3
  37. data/lib/pagy/extras/elasticsearch_rails.rb +12 -11
  38. data/lib/pagy/extras/foundation.rb +59 -54
  39. data/lib/pagy/extras/gearbox.rb +32 -19
  40. data/lib/pagy/extras/headers.rb +11 -11
  41. data/lib/pagy/extras/i18n.rb +5 -5
  42. data/lib/pagy/extras/items.rb +34 -24
  43. data/lib/pagy/extras/{frontend_helpers.rb → js_tools.rb} +24 -24
  44. data/lib/pagy/extras/jsonapi.rb +79 -0
  45. data/lib/pagy/extras/materialize.rb +63 -47
  46. data/lib/pagy/extras/meilisearch.rb +26 -22
  47. data/lib/pagy/extras/metadata.rb +13 -9
  48. data/lib/pagy/extras/overflow.rb +13 -10
  49. data/lib/pagy/extras/pagy.rb +82 -0
  50. data/lib/pagy/extras/searchkick.rb +12 -11
  51. data/lib/pagy/extras/semantic.rb +57 -45
  52. data/lib/pagy/extras/size.rb +40 -0
  53. data/lib/pagy/extras/standalone.rb +12 -16
  54. data/lib/pagy/extras/trim.rb +13 -13
  55. data/lib/pagy/extras/uikit.rb +60 -46
  56. data/lib/pagy/frontend.rb +62 -45
  57. data/lib/pagy/i18n.rb +4 -3
  58. data/lib/pagy/url_helpers.rb +13 -25
  59. data/lib/pagy.rb +61 -59
  60. data/locales/ar.yml +28 -0
  61. data/locales/be.yml +25 -0
  62. data/locales/bg.yml +21 -0
  63. data/locales/bs.yml +25 -0
  64. data/locales/ca.yml +21 -0
  65. data/locales/ckb.yml +18 -0
  66. data/locales/cs.yml +23 -0
  67. data/locales/da.yml +21 -0
  68. data/locales/de.yml +21 -0
  69. data/locales/en.yml +21 -0
  70. data/locales/es.yml +21 -0
  71. data/locales/fr.yml +21 -0
  72. data/locales/hr.yml +25 -0
  73. data/locales/id.yml +19 -0
  74. data/locales/it.yml +21 -0
  75. data/locales/ja.yml +19 -0
  76. data/locales/km.yml +19 -0
  77. data/locales/ko.yml +17 -0
  78. data/locales/nb.yml +21 -0
  79. data/locales/nl.yml +21 -0
  80. data/locales/nn.yml +21 -0
  81. data/locales/pl.yml +25 -0
  82. data/locales/pt-BR.yml +21 -0
  83. data/locales/pt.yml +21 -0
  84. data/locales/ru.yml +25 -0
  85. data/locales/sr.yml +25 -0
  86. data/locales/sv-SE.yml +21 -0
  87. data/locales/sv.yml +21 -0
  88. data/locales/sw.yml +23 -0
  89. data/locales/ta.yml +23 -0
  90. data/locales/tr.yml +19 -0
  91. data/locales/uk.yml +25 -0
  92. data/locales/vi.yml +17 -0
  93. data/locales/zh-CN.yml +19 -0
  94. data/locales/zh-HK.yml +19 -0
  95. data/locales/zh-TW.yml +19 -0
  96. data/stylesheets/pagy.css +46 -0
  97. data/stylesheets/pagy.scss +48 -0
  98. data/stylesheets/pagy.tailwind.css +21 -0
  99. metadata +79 -66
  100. data/lib/javascripts/pagy-dev.js +0 -118
  101. data/lib/javascripts/pagy-module.d.ts +0 -30
  102. data/lib/javascripts/pagy-module.js +0 -117
  103. data/lib/javascripts/pagy.js +0 -1
  104. data/lib/locales/ar.yml +0 -26
  105. data/lib/locales/bg.yml +0 -22
  106. data/lib/locales/bs.yml +0 -24
  107. data/lib/locales/ca.yml +0 -22
  108. data/lib/locales/cs.yml +0 -22
  109. data/lib/locales/da.yml +0 -22
  110. data/lib/locales/de.yml +0 -22
  111. data/lib/locales/en.yml +0 -22
  112. data/lib/locales/es.yml +0 -22
  113. data/lib/locales/fr.yml +0 -22
  114. data/lib/locales/hr.yml +0 -24
  115. data/lib/locales/id.yml +0 -20
  116. data/lib/locales/it.yml +0 -22
  117. data/lib/locales/ja.yml +0 -20
  118. data/lib/locales/km.yml +0 -19
  119. data/lib/locales/ko.yml +0 -20
  120. data/lib/locales/nb.yml +0 -22
  121. data/lib/locales/nl.yml +0 -22
  122. data/lib/locales/pl.yml +0 -24
  123. data/lib/locales/pt-BR.yml +0 -22
  124. data/lib/locales/pt.yml +0 -22
  125. data/lib/locales/ru.yml +0 -24
  126. data/lib/locales/sr.yml +0 -23
  127. data/lib/locales/sv-SE.yml +0 -23
  128. data/lib/locales/sv.yml +0 -23
  129. data/lib/locales/sw.yml +0 -22
  130. data/lib/locales/ta.yml +0 -22
  131. data/lib/locales/tr.yml +0 -20
  132. data/lib/locales/uk.yml +0 -24
  133. data/lib/locales/zh-CN.yml +0 -20
  134. data/lib/locales/zh-HK.yml +0 -20
  135. data/lib/locales/zh-TW.yml +0 -20
  136. data/lib/pagy/calendar/month_mixin.rb +0 -49
  137. data/lib/pagy/extras/navs.rb +0 -63
  138. data/lib/pagy/extras/support.rb +0 -54
  139. data/lib/templates/bootstrap_nav.html.erb +0 -24
  140. data/lib/templates/bootstrap_nav.html.haml +0 -34
  141. data/lib/templates/bootstrap_nav.html.slim +0 -34
  142. data/lib/templates/bulma_nav.html.erb +0 -24
  143. data/lib/templates/bulma_nav.html.haml +0 -32
  144. data/lib/templates/bulma_nav.html.slim +0 -32
  145. data/lib/templates/foundation_nav.html.erb +0 -24
  146. data/lib/templates/foundation_nav.html.haml +0 -34
  147. data/lib/templates/foundation_nav.html.slim +0 -34
  148. data/lib/templates/nav.html.erb +0 -22
  149. data/lib/templates/nav.html.haml +0 -30
  150. data/lib/templates/nav.html.slim +0 -29
  151. data/lib/templates/uikit_nav.html.erb +0 -15
  152. data/lib/templates/uikit_nav.html.haml +0 -28
  153. data/lib/templates/uikit_nav.html.slim +0 -28
@@ -1,82 +1,98 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/materialize
2
1
  # frozen_string_literal: true
3
2
 
4
- require 'pagy/extras/frontend_helpers'
3
+ warn '[PAGY WARNING] The materialize extra has been discontinued and it will be removed in v9 ' \
4
+ '(https://github.com/ddnexus/pagy/discussions/672#discussioncomment-9212328)'
5
+
6
+ require_relative 'js_tools'
5
7
 
6
8
  class Pagy # :nodoc:
7
9
  # Frontend modules are specially optimized for performance.
8
10
  # The resulting code may not look very elegant, but produces the best benchmarks
9
11
  module MaterializeExtra
10
12
  # 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)
12
- p_id = %( id="#{pagy_id}") if pagy_id
13
- link = pagy_link_proc(pagy, link_extra: link_extra)
13
+ def pagy_materialize_nav(pagy, id: nil, aria_label: nil, **vars)
14
+ id = %( id="#{id}") if id
15
+ a = pagy_anchor(pagy)
14
16
 
15
- html = +%(<div#{p_id} class="pagy-materialize-nav pagination" role="navigation" aria-label="pager"><ul class="pagination">)
16
- html << pagy_materialize_prev_html(pagy, link)
17
+ html = +%(<div#{id} class="pagy-materialize nav pagination" role="navigation" #{
18
+ nav_aria_label(pagy, aria_label:)}><ul class="pagination">#{
19
+ materialize_prev_html(pagy, a)})
17
20
  pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
18
21
  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}"
22
+ when Integer
23
+ %(<li class="waves-effect">#{a.(item)}</li>)
24
+ when String
25
+ %(<li class="active"><a role="link" aria-current="page" aria-disabled="true">#{pagy.label_for(item)}</a></li>)
26
+ when :gap
27
+ %(<li class="gap disabled"><a role="link" aria-disabled="true">#{pagy_t 'pagy.gap'}</a></li>)
28
+ else
29
+ raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
23
30
  end
24
31
  end
25
- html << pagy_materialize_next_html(pagy, link)
26
- html << %(</ul></div>)
32
+ html << %(#{materialize_next_html(pagy, a)}</ul></div>)
27
33
  end
28
34
 
29
- # 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)
35
+ # Javascript pagination for materialize: it returns a nav with a data-pagy attribute used by the pagy.js file
36
+ def pagy_materialize_nav_js(pagy, id: nil, aria_label: nil, **vars)
31
37
  sequels = pagy.sequels(**vars)
32
- p_id = %( id="#{pagy_id}") if pagy_id
33
- link = pagy_link_proc(pagy, link_extra: link_extra)
38
+ id = %( id="#{id}") if id
39
+ a = pagy_anchor(pagy)
34
40
 
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>) }
41
+ tokens = { 'before' => %(<ul class="pagination">#{materialize_prev_html pagy, a}),
42
+ 'a' => %(<li class="waves-effect">#{a.(PAGE_TOKEN, LABEL_TOKEN)}</li>),
43
+ 'current' => %(<li class="active"><a role="link" aria-current="page" aria-disabled="true">#{
44
+ 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, a}</ul>) }
40
47
 
41
- %(<div#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-materialize-nav-js" role="navigation" aria-label="pager" #{
42
- pagy_json_attr(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></div>)
48
+ %(<div#{id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-materialize nav-js" role="navigation" #{
49
+ nav_aria_label(pagy, aria_label:)} #{
50
+ pagy_data(pagy, :nav, tokens, sequels, pagy.label_sequels(sequels))
51
+ }></div>)
43
52
  end
44
53
 
45
- # 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: '')
47
- p_id = %( id="#{pagy_id}") if pagy_id
48
- link = pagy_link_proc(pagy, link_extra: link_extra)
49
- p_page = pagy.page
50
- p_pages = pagy.pages
51
- style = ' style="vertical-align: middle"'
52
- 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;">)
54
+ # Javascript combo pagination for materialize: it returns a nav with a data-pagy attribute used by the pagy.js file
55
+ def pagy_materialize_combo_nav_js(pagy, id: nil, aria_label: nil)
56
+ id = %( id="#{id}") if id
57
+ a = pagy_anchor(pagy)
58
+ pages = pagy.pages
59
+
60
+ page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page" ) <<
61
+ %(style="text-align: center; width: #{pages.to_s.length + 1}rem; height: 1.5rem; font-size: 1.2rem; ) <<
62
+ %(border: none; border-radius: 2px; color: white; background-color: #ee6e73;" class="browser-default"> ) <<
63
+ JSTools::A_TAG
54
64
 
55
- html = %(<ul#{p_id} class="pagy-materialize-combo-nav-js pagination chip" role="navigation")
56
- %(#{html} aria-label="pager" style="padding-right: 0" #{
57
- pagy_json_attr pagy, :combo, pagy_marked_link(link)}>#{
58
- pagy_materialize_prev_html pagy, link, style}<li class="pagy-combo-input">#{
59
- 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>)
65
+ %(<ul#{id} class="pagy-materialize combo-nav-js pagination" role="navigation" style="padding-right: 0;" #{
66
+ nav_aria_label(pagy, aria_label:)} #{
67
+ pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))
68
+ }>#{
69
+ materialize_prev_html(pagy, a)
70
+ }<li style="vertical-align: -webkit-baseline-middle;"><label style="font-size: 1.2rem;">#{
71
+ pagy_t('pagy.combo_nav_js', page_input:, pages:)
72
+ }</label></li>#{
73
+ materialize_next_html(pagy, a)
74
+ }</ul>)
61
75
  end
62
76
 
63
77
  private
64
78
 
65
- def pagy_materialize_prev_html(pagy, link, style = '')
79
+ def materialize_prev_html(pagy, a)
66
80
  if (p_prev = pagy.prev)
67
- %(<li class="waves-effect prev"#{style}>#{
68
- link.call p_prev, '<i class="material-icons">chevron_left</i>', 'aria-label="previous"'}</li>)
81
+ %(<li class="waves-effect prev">#{
82
+ a.(p_prev, '<i class="material-icons">chevron_left</i>', aria_label: pagy_t('pagy.aria_label.prev'))}</li>)
69
83
  else
70
- %(<li class="prev disabled"#{style}><a href="#"><i class="material-icons">chevron_left</i></a></li>)
84
+ %(<li class="prev disabled"><a role="link" aria-disabled="true" aria-label="#{
85
+ pagy_t('pagy.aria_label.prev')}"><i class="material-icons">chevron_left</i></a></li>)
71
86
  end
72
87
  end
73
88
 
74
- def pagy_materialize_next_html(pagy, link, style = '')
89
+ def materialize_next_html(pagy, a)
75
90
  if (p_next = pagy.next)
76
- %(<li class="waves-effect next"#{style}>#{
77
- link.call p_next, '<i class="material-icons">chevron_right</i>', 'aria-label="next"'}</li>)
91
+ %(<li class="waves-effect next">#{
92
+ a.(p_next, '<i class="material-icons">chevron_right</i>', aria_label: pagy_t('pagy.aria_label.next'))}</li>)
78
93
  else
79
- %(<li class="next disabled"#{style}><a href="#"><i class="material-icons">chevron_right</i></a></li>)
94
+ %(<li class="next disabled"#><a role="link" aria-disabled="true" aria-label="#{
95
+ pagy_t('pagy.aria_label.next')}><i class="material-icons">chevron_right</i></a></li>)
80
96
  end
81
97
  end
82
98
  end
@@ -1,43 +1,49 @@
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/meilisearch
1
2
  # frozen_string_literal: true
2
3
 
3
4
  class Pagy # :nodoc:
4
- DEFAULT[:meilisearch_search_method] ||= :pagy_search
5
+ DEFAULT[:meilisearch_search] ||= :ms_search
6
+ DEFAULT[:meilisearch_pagy_search] ||= :pagy_search
5
7
 
6
8
  # Paginate Meilisearch results
7
9
  module MeilisearchExtra
8
- module Meilisearch # :nodoc:
10
+ module ModelExtension # :nodoc:
9
11
  # Return an array used to delay the call of #search
10
12
  # after the pagination variables are merged to the options
11
- def pagy_meilisearch(term = nil, **vars)
12
- [self, term, vars]
13
+ def pagy_meilisearch(query, params = {})
14
+ [self, query, params]
13
15
  end
14
- alias_method DEFAULT[:meilisearch_search_method], :pagy_meilisearch
16
+ alias_method DEFAULT[:meilisearch_pagy_search], :pagy_meilisearch
15
17
  end
18
+ Pagy::Meilisearch = ModelExtension
16
19
 
17
- # Additions for the Pagy class
18
- module Pagy
20
+ # Extension for the Pagy class
21
+ module PagyExtension
19
22
  # Create a Pagy object from a Meilisearch results
20
23
  def new_from_meilisearch(results, vars = {})
21
- vars[:items] = results.raw_answer['limit']
22
- vars[:page] = [results.raw_answer['offset'] / vars[:items], 1].max
23
- vars[:count] = results.raw_answer['nbHits']
24
+ vars[:items] = results.raw_answer['hitsPerPage']
25
+ vars[:page] = results.raw_answer['page']
26
+ vars[:count] = results.raw_answer['totalHits']
27
+
24
28
  new(vars)
25
29
  end
26
30
  end
31
+ Pagy.extend PagyExtension
27
32
 
28
33
  # Add specialized backend methods to paginate Meilisearch results
29
- module Backend
34
+ module BackendAddOn
30
35
  private
31
36
 
32
37
  # Return Pagy object and results
33
38
  def pagy_meilisearch(pagy_search_args, vars = {})
34
- model, term, options = pagy_search_args
35
- vars = pagy_meilisearch_get_vars(nil, vars)
36
- options[:limit] = vars[:items]
37
- options[:offset] = (vars[:page] - 1) * vars[:items]
38
- results = model.search(term, **options)
39
- vars[:count] = results.raw_answer['nbHits']
40
- pagy = ::Pagy.new(vars)
39
+ model, term, options = pagy_search_args
40
+ vars = pagy_meilisearch_get_vars(nil, vars)
41
+ options[:hits_per_page] = vars[:items]
42
+ options[:page] = vars[:page]
43
+ results = model.send(:ms_search, term, options)
44
+ vars[:count] = results.raw_answer['totalHits']
45
+
46
+ pagy = ::Pagy.new(vars)
41
47
  # with :last_page overflow we need to re-run the method in order to get the hits
42
48
  return pagy_meilisearch(pagy_search_args, vars.merge(page: pagy.page)) \
43
49
  if defined?(::Pagy::OverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page
@@ -50,12 +56,10 @@ class Pagy # :nodoc:
50
56
  def pagy_meilisearch_get_vars(_collection, vars)
51
57
  pagy_set_items_from_params(vars) if defined?(ItemsExtra)
52
58
  vars[:items] ||= DEFAULT[:items]
53
- vars[:page] ||= (params[vars[:page_param] || DEFAULT[:page_param]] || 1).to_i
59
+ vars[:page] ||= pagy_get_page(vars)
54
60
  vars
55
61
  end
56
62
  end
63
+ Backend.prepend BackendAddOn
57
64
  end
58
- Meilisearch = MeilisearchExtra::Meilisearch
59
- extend MeilisearchExtra::Pagy
60
- Backend.prepend MeilisearchExtra::Backend
61
65
  end
@@ -1,7 +1,7 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/metadata
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/metadata
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/url_helpers'
4
+ require_relative '../url_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:metadata] = %i[ scaffold_url first_url prev_url page_url next_url last_url
@@ -15,17 +15,21 @@ 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
- keys = defined?(Calendar) && pagy.is_a?(Calendar) ? pagy.vars[:metadata] - %i[count items] : pagy.vars[:metadata]
20
+ keys = if defined?(Calendar::Unit) && pagy.is_a?(Calendar::Unit)
21
+ pagy.vars[:metadata] - %i[count items]
22
+ else
23
+ pagy.vars[:metadata]
24
+ end
21
25
  keys.each do |key|
22
26
  metadata[key] = case key
23
27
  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)
28
+ when :first_url then scaffold_url.sub(PAGE_TOKEN, 1.to_s)
29
+ when :prev_url then scaffold_url.sub(PAGE_TOKEN, pagy.prev.to_s)
30
+ when :page_url then scaffold_url.sub(PAGE_TOKEN, pagy.page.to_s)
31
+ when :next_url then scaffold_url.sub(PAGE_TOKEN, pagy.next.to_s)
32
+ when :last_url then scaffold_url.sub(PAGE_TOKEN, pagy.last.to_s)
29
33
  else pagy.send(key)
30
34
  end
31
35
  rescue NoMethodError
@@ -1,4 +1,4 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/overflow
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/overflow
2
2
  # frozen_string_literal: true
3
3
 
4
4
  class Pagy # :nodoc:
@@ -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
@@ -27,8 +27,9 @@ class Pagy # :nodoc:
27
27
  initialize vars.merge!(page: @last) # re-run with the last page
28
28
  @vars[:page] = requested_page # restore the requested page
29
29
  when :empty_page
30
- @offset = @items = @from = @to = 0 # vars relative to the actual page
31
- if defined?(Calendar) && is_a?(Calendar) # only for Calendar instances
30
+ @offset = @items = @in = @from = @to = 0 # vars relative to the actual page
31
+ if defined?(Calendar::Unit) \
32
+ && is_a?(Calendar::Unit) # only for Calendar::Units instances
32
33
  edge = @order == :asc ? @final : @initial # get the edge of the overflow side (neat, but any time would do)
33
34
  @from = @to = edge # set both to the edge utc time (a >=&&< query will get no records)
34
35
  end
@@ -41,7 +42,7 @@ class Pagy # :nodoc:
41
42
 
42
43
  # Special series for empty page
43
44
  module Series
44
- def series(*)
45
+ def series(*, **)
45
46
  @page = @last # series for last page
46
47
  super.tap do |s| # call original series
47
48
  s[s.index(@page.to_s)] = @page # string to integer (i.e. no current page)
@@ -50,9 +51,11 @@ class Pagy # :nodoc:
50
51
  end
51
52
  end
52
53
  end
54
+ Pagy.prepend PagyOverride
55
+ Pagy::Calendar::Unit.prepend PagyOverride if defined?(Calendar::Unit)
53
56
 
54
57
  # Support for Pagy::Countless class
55
- module Countless
58
+ module CountlessOverride
56
59
  # Add rescue clause for different behaviors
57
60
  def finalize(items)
58
61
  @overflow = false
@@ -64,15 +67,15 @@ class Pagy # :nodoc:
64
67
  raise # same as without the extra
65
68
  when :empty_page
66
69
  @offset = @items = @from = @to = 0 # vars relative to the actual page
67
- @vars[:size] = [] # no page in the series
70
+ @vars[:size] = 0 # no page in the series
68
71
  self
69
72
  else
70
73
  raise VariableError.new(self, :overflow, 'to be in [:empty_page, :exception]', @vars[:overflow])
71
74
  end
72
75
  end
73
76
  end
77
+ # :nocov:
78
+ Pagy::Countless.prepend CountlessOverride if defined?(Countless)
79
+ # :nocov:
74
80
  end
75
- prepend OverflowExtra::Pagy
76
- Calendar.prepend OverflowExtra::Pagy if defined?(Calendar)
77
- Countless.prepend OverflowExtra::Countless if defined?(Countless)
78
81
  end
@@ -0,0 +1,82 @@
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/pagy
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'js_tools'
5
+
6
+ class Pagy # :nodoc:
7
+ # Frontend modules are specially optimized for performance.
8
+ # The resulting code may not look very elegant, but produces the best benchmarks
9
+ module PagyExtra
10
+ # pagy_nav is defined in the Frontend itself
11
+ # Javascript pagination: it returns a nav with a data-pagy attribute used by the pagy.js file
12
+ def pagy_nav_js(pagy, id: nil, aria_label: nil, **vars)
13
+ sequels = pagy.sequels(**vars)
14
+ id = %( id="#{id}") if id
15
+ a = pagy_anchor(pagy)
16
+ tokens = { 'before' => prev_a(pagy, a),
17
+ 'a' => a.(PAGE_TOKEN, LABEL_TOKEN),
18
+ 'current' => %(<a class="current" role="link" aria-current="page" aria-disabled="true">#{
19
+ LABEL_TOKEN}</a>),
20
+ 'gap' => %(<a class="gap" role="link" aria-disabled="true">#{pagy_t('pagy.gap')}</a>),
21
+ 'after' => next_a(pagy, a) }
22
+
23
+ %(<nav#{id} class="#{'pagy-rjs ' if sequels.size > 1}pagy nav-js" #{
24
+ nav_aria_label(pagy, aria_label:)} #{
25
+ pagy_data(pagy, :nav, tokens, sequels, pagy.label_sequels(sequels))
26
+ }></nav>)
27
+ end
28
+
29
+ # Javascript combo pagination: it returns a nav with a data-pagy attribute used by the pagy.js file
30
+ def pagy_combo_nav_js(pagy, id: nil, aria_label: nil)
31
+ id = %( id="#{id}") if id
32
+ a = pagy_anchor(pagy)
33
+ pages = pagy.pages
34
+
35
+ page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page" ) <<
36
+ %(style="text-align: center; width: #{pages.to_s.length + 1}rem; padding: 0;">#{JSTools::A_TAG})
37
+
38
+ %(<nav#{id} class="pagy combo-nav-js" #{
39
+ nav_aria_label(pagy, aria_label:)} #{
40
+ pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))}>#{
41
+ prev_a(pagy, a)
42
+ }<label>#{
43
+ pagy_t('pagy.combo_nav_js', page_input:, pages:)
44
+ }</label>#{
45
+ next_a(pagy, a)
46
+ }</nav>)
47
+ end
48
+
49
+ # Return the previous page URL string or nil
50
+ def pagy_prev_url(pagy, absolute: false)
51
+ pagy_url_for(pagy, pagy.prev, absolute:) if pagy.prev
52
+ end
53
+
54
+ # Return the next page URL string or nil
55
+ def pagy_next_url(pagy, absolute: false)
56
+ pagy_url_for(pagy, pagy.next, absolute:) if pagy.next
57
+ end
58
+
59
+ # Return the enabled/disabled previous page anchor tag
60
+ def pagy_prev_a(pagy, text: pagy_t('pagy.prev'), aria_label: pagy_t('pagy.aria_label.prev'))
61
+ a = pagy_anchor(pagy)
62
+ prev_a(pagy, a, text:, aria_label:)
63
+ end
64
+
65
+ # Return the enabled/disabled next page anchor tag
66
+ def pagy_next_a(pagy, text: pagy_t('pagy.next'), aria_label: pagy_t('pagy.aria_label.next'))
67
+ a = pagy_anchor(pagy)
68
+ next_a(pagy, a, text:, aria_label:)
69
+ end
70
+
71
+ # Conditionally return the previous page link tag
72
+ def pagy_prev_link(pagy, absolute: false)
73
+ %(<link href="#{pagy_url_for(pagy, pagy.prev, absolute:)}"/>) if pagy.prev
74
+ end
75
+
76
+ # Conditionally return the next page link tag
77
+ def pagy_next_link(pagy, absolute: false)
78
+ %(<link href="#{pagy_url_for(pagy, pagy.next, absolute:)}"/>) if pagy.next
79
+ end
80
+ end
81
+ Frontend.prepend PagyExtra
82
+ end
@@ -1,12 +1,13 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/searchkick
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/searchkick
2
2
  # frozen_string_literal: true
3
3
 
4
4
  class Pagy # :nodoc:
5
- DEFAULT[:searchkick_search_method] ||= :pagy_search
5
+ DEFAULT[:searchkick_search] ||= :search
6
+ DEFAULT[:searchkick_pagy_search] ||= :pagy_search
6
7
 
7
8
  # Paginate Searchkick::Results objects
8
9
  module SearchkickExtra
9
- module Searchkick # :nodoc:
10
+ module ModelExtension # :nodoc:
10
11
  # Return an array used to delay the call of #search
11
12
  # after the pagination variables are merged to the options.
12
13
  # It also pushes to the same array an optional method call.
@@ -15,11 +16,12 @@ class Pagy # :nodoc:
15
16
  args.define_singleton_method(:method_missing) { |*a| args += a }
16
17
  end
17
18
  end
18
- alias_method Pagy::DEFAULT[:searchkick_search_method], :pagy_searchkick
19
+ alias_method Pagy::DEFAULT[:searchkick_pagy_search], :pagy_searchkick
19
20
  end
21
+ Pagy::Searchkick = ModelExtension
20
22
 
21
23
  # Additions for the Pagy class
22
- module Pagy
24
+ module PagyExtension
23
25
  # Create a Pagy object from a Searchkick::Results object
24
26
  def new_from_searchkick(results, vars = {})
25
27
  vars[:items] = results.options[:per_page]
@@ -28,9 +30,10 @@ class Pagy # :nodoc:
28
30
  new(vars)
29
31
  end
30
32
  end
33
+ Pagy.extend PagyExtension
31
34
 
32
35
  # Add specialized backend methods to paginate Searchkick::Results
33
- module Backend
36
+ module BackendAddOn
34
37
  private
35
38
 
36
39
  # Return Pagy object and results
@@ -39,7 +42,7 @@ class Pagy # :nodoc:
39
42
  vars = pagy_searchkick_get_vars(nil, vars)
40
43
  options[:per_page] = vars[:items]
41
44
  options[:page] = vars[:page]
42
- results = model.search(term, **options, &block)
45
+ results = model.send(DEFAULT[:searchkick_search], term, **options, &block)
43
46
  vars[:count] = results.total_count
44
47
 
45
48
  pagy = ::Pagy.new(vars)
@@ -55,12 +58,10 @@ class Pagy # :nodoc:
55
58
  def pagy_searchkick_get_vars(_collection, vars)
56
59
  pagy_set_items_from_params(vars) if defined?(ItemsExtra)
57
60
  vars[:items] ||= DEFAULT[:items]
58
- vars[:page] ||= (params[vars[:page_param] || DEFAULT[:page_param]] || 1).to_i
61
+ vars[:page] ||= pagy_get_page(vars)
59
62
  vars
60
63
  end
61
64
  end
65
+ Backend.prepend BackendAddOn
62
66
  end
63
- Searchkick = SearchkickExtra::Searchkick
64
- extend SearchkickExtra::Pagy
65
- Backend.prepend SearchkickExtra::Backend
66
67
  end
@@ -1,80 +1,92 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/semantic
2
1
  # frozen_string_literal: true
3
2
 
4
- require 'pagy/extras/frontend_helpers'
3
+ warn '[PAGY WARNING] The semantic extra has been discontinued and it will be removed in v9 ' \
4
+ '(https://github.com/ddnexus/pagy/discussions/672#discussioncomment-9212328)'
5
+
6
+ require_relative 'js_tools'
5
7
 
6
8
  class Pagy # :nodoc:
7
9
  # Frontend modules are specially optimized for performance.
8
10
  # The resulting code may not look very elegant, but produces the best benchmarks
9
11
  module SemanticExtra
10
12
  # 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: '', **vars)
12
- p_id = %( id="#{pagy_id}") if pagy_id
13
- link = pagy_link_proc(pagy, link_extra: %(class="item" #{link_extra}))
13
+ def pagy_semantic_nav(pagy, id: nil, aria_label: nil, **vars)
14
+ id = %( id="#{id}") if id
15
+ a = pagy_anchor(pagy)
14
16
 
15
- html = +%(<div#{p_id} class="pagy-semantic-nav ui pagination menu">)
16
- html << pagy_semantic_prev_html(pagy, link)
17
+ html = %(<div#{id} role="navigation" class="pagy-semantic nav ui pagination menu" #{
18
+ nav_aria_label(pagy, aria_label:)}>#{semantic_prev_html(pagy, a)})
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 link.call item
20
- when String then %(<a class="item active">#{pagy.label_for(item)}</a>)
21
- when :gap then %(<div class="disabled item">#{pagy_t 'pagy.nav.gap'}</div>)
22
- else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
21
+ when Integer
22
+ a.(item, pagy.label_for(item), classes: 'item')
23
+ when String
24
+ %(<a role="link" class="item active" aria-current="page" aria-disabled="true">#{pagy.label_for(item)}</a>)
25
+ when :gap
26
+ %(<div class="disabled item">#{pagy_t 'pagy.gap'}</div>)
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_semantic_next_html(pagy, link)
26
- html << %(</div>)
31
+ html << %(#{semantic_next_html(pagy, a)}</div>)
27
32
  end
28
33
 
29
- # Javascript pagination for semantic: it returns a nav and a JSON tag used by the pagy.js file
30
- def pagy_semantic_nav_js(pagy, pagy_id: nil, link_extra: '', **vars)
34
+ # Javascript pagination for semantic: it returns a nav with a data-pagy attribute used by the pagy.js file
35
+ def pagy_semantic_nav_js(pagy, id: nil, aria_label: nil, **vars)
31
36
  sequels = pagy.sequels(**vars)
32
- p_id = %( id="#{pagy_id}") if pagy_id
33
- link = pagy_link_proc(pagy, link_extra: %(class="item" #{link_extra}))
34
- tags = { 'before' => pagy_semantic_prev_html(pagy, link),
35
- 'link' => link.call(PAGE_PLACEHOLDER, LABEL_PLACEHOLDER),
36
- 'active' => %(<a class="item active">#{LABEL_PLACEHOLDER}</a>),
37
- 'gap' => %(<div class="disabled item">#{pagy_t('pagy.nav.gap')}</div>),
38
- 'after' => pagy_semantic_next_html(pagy, link) }
37
+ id = %( id="#{id}") if id
38
+ a = pagy_anchor(pagy)
39
+ tokens = { 'before' => semantic_prev_html(pagy, a),
40
+ 'a' => a.(PAGE_TOKEN, LABEL_TOKEN, classes: 'item'),
41
+ 'current' => %(<a role="link" class="item active" aria-current="page" aria-disabled="true">#{LABEL_TOKEN}</a>),
42
+ 'gap' => %(<div class="disabled item">#{pagy_t('pagy.gap')}</div>),
43
+ 'after' => semantic_next_html(pagy, a) }
39
44
 
40
- %(<div#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-semantic-nav-js ui pagination menu" role="navigation" #{
41
- pagy_json_attr(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></div>)
45
+ %(<div#{id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-semantic nav-js ui pagination menu" role="navigation" #{
46
+ nav_aria_label(pagy, aria_label:)} #{
47
+ pagy_data(pagy, :nav, tokens, sequels, pagy.label_sequels(sequels))
48
+ }></div>)
42
49
  end
43
50
 
44
- # Combo pagination for semantic: it returns a nav and a JSON tag used by the pagy.js file
45
- def pagy_semantic_combo_nav_js(pagy, pagy_id: nil, link_extra: '')
46
- p_id = %( id="#{pagy_id}") if pagy_id
47
- link = pagy_link_proc(pagy, link_extra: %(class="item" #{link_extra}))
48
- p_page = pagy.page
49
- p_pages = pagy.pages
50
- input = %(<input type="number" min="1" max="#{p_pages}" value="#{
51
- p_page}" style="padding: 0; text-align: center; width: #{p_pages.to_s.length + 1}rem; margin: 0 0.3rem">)
51
+ # Combo pagination for semantic: it returns a nav with a data-pagy attribute used by the pagy.js file
52
+ def pagy_semantic_combo_nav_js(pagy, id: nil, aria_label: nil)
53
+ id = %( id="#{id}") if id
54
+ a = pagy_anchor(pagy)
55
+ pages = pagy.pages
56
+
57
+ page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page") <<
58
+ %(style="text-align: center; width: #{pages.to_s.length + 1}rem; padding: 0; margin: 0 0.3rem">) <<
59
+ JSTools::A_TAG
52
60
 
53
- %(<div#{p_id} class="pagy-semantic-combo-nav-js ui compact menu" role="navigation" #{
54
- pagy_json_attr pagy, :combo, pagy_marked_link(link)}>#{
55
- pagy_semantic_prev_html pagy, link
56
- }<div class="pagy-combo-input item">#{
57
- pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages
58
- }</div> #{
59
- pagy_semantic_next_html pagy, link
61
+ %(<div#{id} class="pagy-semantic combo-nav-js ui compact menu" role="navigation" #{
62
+ nav_aria_label(pagy, aria_label:)} #{
63
+ pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))
64
+ }>#{
65
+ semantic_prev_html(pagy, a)
66
+ }<div class="item"><label>#{
67
+ pagy_t('pagy.combo_nav_js', page_input:, pages:)
68
+ }</label></div> #{
69
+ semantic_next_html(pagy, a)
60
70
  }</div>)
61
71
  end
62
72
 
63
73
  private
64
74
 
65
- def pagy_semantic_prev_html(pagy, link)
75
+ def semantic_prev_html(pagy, a)
66
76
  if (p_prev = pagy.prev)
67
- link.call p_prev, '<i class="left small chevron icon"></i>', 'aria-label="previous"'
77
+ a.(p_prev, pagy_t('pagy.prev'), classes: 'item', aria_label: pagy_t('pagy.aria_label.prev'))
68
78
  else
69
- +%(<div class="item disabled"><i class="left small chevron icon"></i></div>)
79
+ %(<div class="item disabled" role="a" aria-disabled="true" aria-label="#{
80
+ pagy_t('pagy.aria_label.prev')}">#{pagy_t('pagy.prev')}</div>)
70
81
  end
71
82
  end
72
83
 
73
- def pagy_semantic_next_html(pagy, link)
84
+ def semantic_next_html(pagy, a)
74
85
  if (p_next = pagy.next)
75
- link.call p_next, '<i class="right small chevron icon"></i>', 'aria-label="next"'
86
+ a.(p_next, pagy_t('pagy.next'), classes: 'item', aria_label: pagy_t('pagy.aria_label.next'))
76
87
  else
77
- +%(<div class="item disabled"><i class="right small chevron icon"></i></div>)
88
+ %(<div class="item disabled" role="link" aria-disabled="true" aria=label="#{
89
+ pagy_t('pagy.aria_label.prev')}">#{pagy_t('pagy.next')}</div>)
78
90
  end
79
91
  end
80
92
  end