pagy 9.4.0 → 43.5.5

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 (176) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/apps/calendar.ru +566 -562
  4. data/apps/demo.ru +246 -182
  5. data/apps/enable_rails_page_segment.rb +56 -0
  6. data/apps/index.rb +4 -2
  7. data/apps/keynav+root_key.ru +316 -0
  8. data/apps/keynav.ru +255 -0
  9. data/apps/{keyset_ar.ru → keyset.ru} +33 -42
  10. data/apps/{keyset_s.ru → keyset_sequel.ru} +32 -40
  11. data/apps/rails.ru +57 -58
  12. data/apps/repro.ru +54 -51
  13. data/bin/pagy +2 -95
  14. data/config/pagy.rb +33 -207
  15. data/javascripts/ai_widget.js +90 -0
  16. data/javascripts/pagy.js +166 -0
  17. data/javascripts/pagy.min.js +2 -4
  18. data/javascripts/pagy.mjs +126 -67
  19. data/javascripts/wand.js +1172 -0
  20. data/lib/pagy/classes/calendar/calendar.rb +101 -0
  21. data/lib/pagy/{calendar → classes/calendar}/day.rb +7 -11
  22. data/lib/pagy/{calendar → classes/calendar}/month.rb +5 -10
  23. data/lib/pagy/{calendar → classes/calendar}/quarter.rb +10 -15
  24. data/lib/pagy/classes/calendar/unit.rb +93 -0
  25. data/lib/pagy/{calendar → classes/calendar}/week.rb +5 -9
  26. data/lib/pagy/{calendar → classes/calendar}/year.rb +5 -6
  27. data/lib/pagy/classes/exceptions.rb +26 -0
  28. data/lib/pagy/classes/keyset/adapters/active_record.rb +50 -0
  29. data/lib/pagy/classes/keyset/adapters/sequel.rb +62 -0
  30. data/lib/pagy/classes/keyset/keynav.rb +85 -0
  31. data/lib/pagy/classes/keyset/keyset.rb +155 -0
  32. data/lib/pagy/classes/offset/countish.rb +17 -0
  33. data/lib/pagy/classes/offset/countless.rb +63 -0
  34. data/lib/pagy/classes/offset/offset.rb +63 -0
  35. data/lib/pagy/classes/offset/search.rb +34 -0
  36. data/lib/pagy/classes/request.rb +48 -0
  37. data/lib/pagy/cli.rb +122 -0
  38. data/lib/pagy/console.rb +5 -20
  39. data/lib/pagy/deprecated.rb +84 -0
  40. data/lib/pagy/modules/abilities/configurable.rb +37 -0
  41. data/lib/pagy/modules/abilities/countable.rb +23 -0
  42. data/lib/pagy/modules/abilities/linkable.rb +72 -0
  43. data/lib/pagy/modules/abilities/rangeable.rb +14 -0
  44. data/lib/pagy/modules/abilities/shiftable.rb +12 -0
  45. data/lib/pagy/{b64.rb → modules/b64.rb} +4 -2
  46. data/lib/pagy/modules/console.rb +33 -0
  47. data/lib/pagy/modules/i18n/i18n.rb +72 -0
  48. data/lib/pagy/modules/i18n/p11n/arabic.rb +30 -0
  49. data/lib/pagy/modules/i18n/p11n/east_slavic.rb +27 -0
  50. data/lib/pagy/modules/i18n/p11n/one_other.rb +15 -0
  51. data/lib/pagy/modules/i18n/p11n/one_upto_two_other.rb +15 -0
  52. data/lib/pagy/modules/i18n/p11n/other.rb +13 -0
  53. data/lib/pagy/modules/i18n/p11n/polish.rb +27 -0
  54. data/lib/pagy/modules/i18n/p11n/west_slavic.rb +22 -0
  55. data/lib/pagy/modules/i18n/p11n.rb +16 -0
  56. data/lib/pagy/modules/searcher.rb +20 -0
  57. data/lib/pagy/next.rb +25 -0
  58. data/lib/pagy/tasks/sync.rb +20 -0
  59. data/lib/pagy/toolbox/helpers/anchor_tags.rb +19 -0
  60. data/lib/pagy/toolbox/helpers/bootstrap/input_nav_js.rb +28 -0
  61. data/lib/pagy/toolbox/helpers/bootstrap/previous_next_html.rb +19 -0
  62. data/lib/pagy/toolbox/helpers/bootstrap/series_nav.rb +32 -0
  63. data/lib/pagy/toolbox/helpers/bootstrap/series_nav_js.rb +24 -0
  64. data/lib/pagy/toolbox/helpers/bulma/input_nav_js.rb +25 -0
  65. data/lib/pagy/toolbox/helpers/bulma/previous_next_html.rb +20 -0
  66. data/lib/pagy/toolbox/helpers/bulma/series_nav.rb +31 -0
  67. data/lib/pagy/toolbox/helpers/bulma/series_nav_js.rb +23 -0
  68. data/lib/pagy/toolbox/helpers/data_hash.rb +29 -0
  69. data/lib/pagy/toolbox/helpers/headers_hash.rb +30 -0
  70. data/lib/pagy/toolbox/helpers/info_tag.rb +30 -0
  71. data/lib/pagy/toolbox/helpers/input_nav_js.rb +22 -0
  72. data/lib/pagy/toolbox/helpers/limit_tag_js.rb +25 -0
  73. data/lib/pagy/toolbox/helpers/loaders.rb +58 -0
  74. data/lib/pagy/toolbox/helpers/page_url.rb +16 -0
  75. data/lib/pagy/toolbox/helpers/series_nav.rb +30 -0
  76. data/lib/pagy/toolbox/helpers/series_nav_js.rb +20 -0
  77. data/lib/pagy/toolbox/helpers/support/a_lambda.rb +36 -0
  78. data/lib/pagy/toolbox/helpers/support/data_pagy_attribute.rb +19 -0
  79. data/lib/pagy/toolbox/helpers/support/nav_aria_label_attribute.rb +10 -0
  80. data/lib/pagy/toolbox/helpers/support/series.rb +37 -0
  81. data/lib/pagy/toolbox/helpers/support/wrap_input_nav_js.rb +18 -0
  82. data/lib/pagy/toolbox/helpers/support/wrap_series_nav.rb +15 -0
  83. data/lib/pagy/toolbox/helpers/support/wrap_series_nav_js.rb +38 -0
  84. data/lib/pagy/toolbox/helpers/urls_hash.rb +12 -0
  85. data/lib/pagy/toolbox/paginators/calendar.rb +34 -0
  86. data/lib/pagy/toolbox/paginators/countish.rb +38 -0
  87. data/lib/pagy/toolbox/paginators/countless.rb +22 -0
  88. data/lib/pagy/toolbox/paginators/elasticsearch_rails.rb +56 -0
  89. data/lib/pagy/toolbox/paginators/keynav_js.rb +26 -0
  90. data/lib/pagy/toolbox/paginators/keyset.rb +15 -0
  91. data/lib/pagy/toolbox/paginators/meilisearch.rb +34 -0
  92. data/lib/pagy/toolbox/paginators/method.rb +38 -0
  93. data/lib/pagy/toolbox/paginators/offset.rb +24 -0
  94. data/lib/pagy/toolbox/paginators/searchkick.rb +34 -0
  95. data/lib/pagy/toolbox/paginators/typesense_rails.rb +34 -0
  96. data/lib/pagy.rb +79 -89
  97. data/locales/ar.yml +9 -6
  98. data/locales/be.yml +9 -6
  99. data/locales/bg.yml +9 -6
  100. data/locales/bs.yml +9 -6
  101. data/locales/ca.yml +9 -6
  102. data/locales/ckb.yml +8 -6
  103. data/locales/cs.yml +9 -6
  104. data/locales/da.yml +9 -6
  105. data/locales/de.yml +9 -6
  106. data/locales/dz.yml +9 -6
  107. data/locales/en.yml +9 -6
  108. data/locales/es.yml +9 -6
  109. data/locales/fr.yml +9 -6
  110. data/locales/hr.yml +9 -6
  111. data/locales/hu.yml +24 -0
  112. data/locales/id.yml +10 -9
  113. data/locales/it.yml +9 -6
  114. data/locales/ja.yml +10 -9
  115. data/locales/km.yml +10 -9
  116. data/locales/ko.yml +9 -6
  117. data/locales/nb.yml +9 -6
  118. data/locales/nl.yml +9 -6
  119. data/locales/nn.yml +9 -6
  120. data/locales/pl.yml +9 -6
  121. data/locales/pt-BR.yml +10 -7
  122. data/locales/pt.yml +10 -7
  123. data/locales/ru.yml +9 -6
  124. data/locales/sk.yml +9 -6
  125. data/locales/sr.yml +9 -6
  126. data/locales/sv-SE.yml +9 -6
  127. data/locales/sv.yml +9 -6
  128. data/locales/sw.yml +12 -9
  129. data/locales/ta.yml +9 -6
  130. data/locales/tr.yml +17 -12
  131. data/locales/uk.yml +9 -6
  132. data/locales/vi.yml +9 -6
  133. data/locales/zh-CN.yml +9 -6
  134. data/locales/zh-HK.yml +9 -6
  135. data/locales/zh-TW.yml +9 -6
  136. data/stylesheets/pagy-tailwind.css +68 -0
  137. data/stylesheets/pagy.css +64 -27
  138. metadata +134 -53
  139. data/javascripts/pagy.min.js.map +0 -10
  140. data/lib/optimist.rb +0 -1022
  141. data/lib/pagy/backend.rb +0 -44
  142. data/lib/pagy/calendar/unit.rb +0 -103
  143. data/lib/pagy/calendar.rb +0 -84
  144. data/lib/pagy/countless.rb +0 -38
  145. data/lib/pagy/exceptions.rb +0 -25
  146. data/lib/pagy/extras/arel.rb +0 -28
  147. data/lib/pagy/extras/array.rb +0 -19
  148. data/lib/pagy/extras/bootstrap.rb +0 -97
  149. data/lib/pagy/extras/bulma.rb +0 -93
  150. data/lib/pagy/extras/calendar.rb +0 -79
  151. data/lib/pagy/extras/countless.rb +0 -32
  152. data/lib/pagy/extras/elasticsearch_rails.rb +0 -71
  153. data/lib/pagy/extras/gearbox.rb +0 -55
  154. data/lib/pagy/extras/headers.rb +0 -54
  155. data/lib/pagy/extras/i18n.rb +0 -26
  156. data/lib/pagy/extras/js_tools.rb +0 -70
  157. data/lib/pagy/extras/jsonapi.rb +0 -88
  158. data/lib/pagy/extras/keyset.rb +0 -30
  159. data/lib/pagy/extras/limit.rb +0 -63
  160. data/lib/pagy/extras/meilisearch.rb +0 -57
  161. data/lib/pagy/extras/metadata.rb +0 -42
  162. data/lib/pagy/extras/overflow.rb +0 -81
  163. data/lib/pagy/extras/pagy.rb +0 -82
  164. data/lib/pagy/extras/searchkick.rb +0 -59
  165. data/lib/pagy/extras/size.rb +0 -40
  166. data/lib/pagy/extras/standalone.rb +0 -60
  167. data/lib/pagy/extras/trim.rb +0 -29
  168. data/lib/pagy/frontend.rb +0 -99
  169. data/lib/pagy/i18n.rb +0 -167
  170. data/lib/pagy/keyset/active_record.rb +0 -44
  171. data/lib/pagy/keyset/sequel.rb +0 -57
  172. data/lib/pagy/keyset.rb +0 -118
  173. data/lib/pagy/shared_methods.rb +0 -26
  174. data/lib/pagy/url_helpers.rb +0 -26
  175. data/stylesheets/pagy.scss +0 -48
  176. data/stylesheets/pagy.tailwind.css +0 -21
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../modules/searcher'
4
+
5
+ class Pagy
6
+ module ElasticsearchRailsPaginator
7
+ module_function
8
+
9
+ def paginate(search, options)
10
+ if search.is_a?(Search::Arguments) # Active mode
11
+
12
+ Searcher.wrap(search, options) do
13
+ model, arguments, search_options = search
14
+
15
+ search_options[:size] = options[:limit]
16
+ search_options[:from] = options[:limit] * ((options[:page] || 1) - 1)
17
+
18
+ method = options[:search_method] || ElasticsearchRails::DEFAULT[:search_method]
19
+ response_object = model.send(method, *arguments, **search_options)
20
+ options[:count] = total_count_from(response_object)
21
+
22
+ [ElasticsearchRails.new(**options), response_object]
23
+ end
24
+
25
+ else # Passive mode
26
+ from, size = pagination_params_from(search)
27
+ options[:limit] = size
28
+ options[:page] = ((from || 0) / options[:limit]) + 1
29
+ options[:count] = total_count_from(search)
30
+
31
+ ElasticsearchRails.new(**options)
32
+ end
33
+ end
34
+
35
+ # Support different versions of ElasticsearchRails
36
+ def pagination_params_from(response_object)
37
+ definition = response_object.search.definition
38
+ definition = definition.to_hash if definition.respond_to?(:to_hash)
39
+ container = (definition.is_a?(Hash) && (definition[:body] || definition)) || response_object.search.options
40
+ from = (container[:from] || container['from']).to_i
41
+ size = (container[:size] || container['size']).to_i
42
+ size = 10 if size.zero?
43
+
44
+ [from, size]
45
+ end
46
+
47
+ # Support different versions of ElasticsearchRails
48
+ def total_count_from(response_object)
49
+ total = response_object.instance_eval do
50
+ respond_to?(:response) ? response['hits']['total'] : raw_response['hits']['total']
51
+ end
52
+
53
+ total.is_a?(Hash) ? total['value'] : total
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../pagy/modules/b64'
4
+
5
+ class Pagy
6
+ module KeynavJsPaginator
7
+ module_function
8
+
9
+ def paginate(set, options)
10
+ page = options[:request].resolve_page(force_integer: false) # allow nil
11
+
12
+ return CountlessPaginator.paginate(set, page:, **options) if page&.match(' ') # countless fallback
13
+
14
+ if page.is_a?(String) && (page_arguments = Keyset.decode(page))
15
+ # Restart the pagination from page 1/nil if the url has been requested from another browser
16
+ options[:page] = page_arguments \
17
+ if options[:request].cookie == page_arguments.shift # rubocop:disable Style/SoleNestedConditional
18
+ end
19
+
20
+ options[:limit] = options[:request].resolve_limit
21
+
22
+ pagy = Keyset::Keynav.new(set, **options)
23
+ [pagy, pagy.records]
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pagy
4
+ module KeysetPaginator
5
+ module_function
6
+
7
+ def paginate(set, options)
8
+ options[:page] ||= options[:request].resolve_page(force_integer: false) # allow nil
9
+ options[:limit] = options[:request].resolve_limit
10
+
11
+ pagy = Keyset.new(set, **options)
12
+ [pagy, pagy.records]
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../modules/searcher'
4
+
5
+ class Pagy
6
+ module MeilisearchPaginator
7
+ module_function
8
+
9
+ def paginate(search, options)
10
+ if search.is_a?(Search::Arguments) # Active mode
11
+
12
+ Searcher.wrap(search, options) do
13
+ model, arguments, search_options = search
14
+
15
+ search_options[:hits_per_page] = options[:limit]
16
+ search_options[:page] = options[:page]
17
+
18
+ method = options[:search_method] || Meilisearch::DEFAULT[:search_method]
19
+ results = model.send(method, *arguments, search_options)
20
+ options[:count] = results.raw_answer['totalHits']
21
+
22
+ [Meilisearch.new(**options), results]
23
+ end
24
+
25
+ else # Passive mode
26
+ options[:limit] = search.raw_answer['hitsPerPage']
27
+ options[:page] = search.raw_answer['page']
28
+ options[:count] = search.raw_answer['totalHits']
29
+
30
+ Meilisearch.new(**options)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../classes/request'
4
+
5
+ class Pagy
6
+ paginators = { offset: :OffsetPaginator,
7
+ countless: :CountlessPaginator,
8
+ countish: :CountishPaginator,
9
+ keyset: :KeysetPaginator,
10
+ keynav_js: :KeynavJsPaginator,
11
+ calendar: :CalendarPaginator,
12
+ elasticsearch_rails: :ElasticsearchRailsPaginator,
13
+ meilisearch: :MeilisearchPaginator,
14
+ searchkick: :SearchkickPaginator,
15
+ typesense_rails: :TypesenseRailsPaginator }.freeze
16
+
17
+ path = Pathname.new(__dir__)
18
+ paginators.each { |symbol, name| autoload name, path.join(symbol.to_s) }
19
+
20
+ # Pagy::Method defines the #pagy method to be included in the app controller/view.
21
+ Method = Module.new do
22
+ protected
23
+
24
+ define_method :pagy do |paginator = :offset, collection, **options|
25
+ arguments = if paginator == :calendar
26
+ [self, collection, options]
27
+ else
28
+ [collection, options = Pagy::OPTIONS.merge(options)]
29
+ end
30
+
31
+ options[:root_key] = 'page' if options[:jsonapi] # enforce 'page' root_key for JSON:API
32
+ options[:request] ||= request # custom request Hash or self.request
33
+ options[:request] = Request.new(options) # Pagy::Request
34
+
35
+ Pagy.const_get(paginators[paginator]).paginate(*arguments)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../modules/abilities/countable'
4
+
5
+ class Pagy
6
+ module OffsetPaginator
7
+ module_function
8
+
9
+ def paginate(collection, options)
10
+ options[:page] ||= options[:request].resolve_page
11
+ options[:limit] = options[:request].resolve_limit
12
+ options[:count] ||= Countable.get_count(collection, options)
13
+
14
+ pagy = Offset.new(**options)
15
+ records = if collection.instance_of?(Array)
16
+ collection[pagy.offset, pagy.limit]
17
+ else
18
+ pagy.records(collection)
19
+ end
20
+
21
+ [pagy, records]
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../modules/searcher'
4
+
5
+ class Pagy
6
+ module SearchkickPaginator
7
+ module_function
8
+
9
+ def paginate(search, options)
10
+ if search.is_a?(Search::Arguments) # Active mode
11
+
12
+ Searcher.wrap(search, options) do
13
+ model, arguments, search_options, block = search
14
+
15
+ search_options[:per_page] = options[:limit]
16
+ search_options[:page] = options[:page]
17
+
18
+ method = options[:search_method] || Searchkick::DEFAULT[:search_method]
19
+ results = model.send(method, *arguments || '*', **search_options, &block)
20
+ options[:count] = results.total_count
21
+
22
+ [Searchkick.new(**options), results]
23
+ end
24
+
25
+ else # Passive mode
26
+ options[:limit] = search.respond_to?(:options) ? search.options[:per_page] : search.per_page
27
+ options[:page] = search.respond_to?(:options) ? search.options[:page] : search.current_page
28
+ options[:count] = search.total_count
29
+
30
+ Searchkick.new(**options)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../modules/searcher'
4
+
5
+ class Pagy
6
+ module TypesenseRailsPaginator
7
+ module_function
8
+
9
+ def paginate(search, options)
10
+ if search.is_a?(Search::Arguments) # Active mode
11
+
12
+ Searcher.wrap(search, options) do
13
+ model, arguments, search_options = search
14
+
15
+ search_options[:per_page] = options[:limit]
16
+ search_options[:page] = options[:page]
17
+
18
+ method = options[:search_method] || TypesenseRails::DEFAULT[:search_method]
19
+ results = model.send(method, *arguments, search_options)
20
+ options[:count] = results.raw_answer['found']
21
+
22
+ [TypesenseRails.new(**options), results]
23
+ end
24
+
25
+ else # Passive mode
26
+ options[:limit] = search.raw_answer['request_params']['per_page']
27
+ options[:page] = search.raw_answer['page']
28
+ options[:count] = search.raw_answer['found']
29
+
30
+ TypesenseRails.new(**options)
31
+ end
32
+ end
33
+ end
34
+ end
data/lib/pagy.rb CHANGED
@@ -1,106 +1,96 @@
1
- # See Pagy API documentation: https://ddnexus.github.io/pagy/docs/api/pagy
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require 'pathname'
5
- require_relative 'pagy/shared_methods'
6
4
 
7
- # Top superclass: it should define only what's common to all the subclasses
5
+ require_relative 'pagy/classes/exceptions'
6
+ require_relative 'pagy/modules/abilities/linkable'
7
+ require_relative 'pagy/modules/abilities/configurable'
8
+ require_relative 'pagy/toolbox/helpers/loaders'
9
+
10
+ # Top superclass
8
11
  class Pagy
9
- VERSION = '9.4.0'
10
-
11
- # Core default: constant for easy access, but mutable for customizable defaults
12
- DEFAULT = { count_args: [:all], # rubocop:disable Style/MutableConstant
13
- ends: true,
14
- limit: 20,
15
- outset: 0,
16
- page: 1,
17
- page_param: :page,
18
- size: 7 } # AR friendly
19
-
20
- # Gem root pathname to get the path of Pagy files stylesheets, javascripts, apps, locales, etc.
21
- def self.root
22
- @root ||= Pathname.new(__dir__).parent.freeze
12
+ VERSION = '43.5.5'
13
+ ROOT = Pathname.new(__dir__).parent.freeze
14
+ DEFAULT = { limit: 20, limit_key: 'limit', page_key: 'page' }.freeze
15
+ PAGE_TOKEN = EscapedValue.new('P ')
16
+ LIMIT_TOKEN = EscapedValue.new('L ')
17
+ LABEL_TOKEN = 'L'
18
+ A_TAG = '<a style="display: none;">#</a>'
19
+
20
+ path = Pathname.new(__FILE__).sub_ext('')
21
+ autoload :Method, path.join('toolbox/paginators/method')
22
+ autoload :I18n, path.join('modules/i18n/i18n')
23
+ autoload :Console, path.join('modules/console')
24
+ autoload :Calendar, path.join('classes/calendar/calendar')
25
+ autoload :Offset, path.join('classes/offset/offset')
26
+ autoload :Search, path.join('classes/offset/search')
27
+ autoload :ElasticsearchRails, path.join('classes/offset/search')
28
+ autoload :Meilisearch, path.join('classes/offset/search')
29
+ autoload :Searchkick, path.join('classes/offset/search')
30
+ autoload :TypesenseRails, path.join('classes/offset/search')
31
+ autoload :Keyset, path.join('classes/keyset/keyset')
32
+ autoload :SyncTask, path.join('tasks/sync')
33
+
34
+ OPTIONS = {} # rubocop:disable Style/MutableConstant
35
+
36
+ extend Configurable
37
+ include Linkable
38
+ include HelperLoader
39
+
40
+ attr_reader :page, :next, :in, :limit, :options
41
+
42
+ protected
43
+
44
+ # Instance identity methods, overridden by the respective classes
45
+ def offset? = false
46
+ def countless? = false
47
+ def calendar? = false
48
+ def search? = false
49
+ def keyset? = false
50
+ def keynav? = false
51
+
52
+ # Validate presence and min value of options
53
+ def assign_and_check(name_min)
54
+ name_min.each do |name, min|
55
+ value = @options[name]
56
+
57
+ if value.respond_to?(:to_i) && (integer = value.to_i) >= min
58
+ instance_variable_set(:"@#{name}", integer)
59
+ else
60
+ raise OptionError.new(self, name, ">= #{min}", value)
61
+ end
62
+ end
23
63
  end
24
64
 
25
- include SharedMethods
26
-
27
- attr_reader :count, :from, :in, :last, :next, :offset, :prev, :to
28
- alias pages last
29
-
30
- # Merge and validate the options, do some simple arithmetic and set the instance variables
31
- def initialize(**vars)
32
- assign_vars(DEFAULT, vars)
33
- assign_and_check(count: 0, page: 1, outset: 0)
34
- assign_limit
35
- assign_offset
36
- assign_last
37
- check_overflow
38
- @from = [@offset - @outset + 1, @count].min
39
- @to = [@offset - @outset + @limit, @count].min
40
- @in = [@to - @from + 1, @count].min
41
- assign_prev_and_next
65
+ def validate_string_values(options)
66
+ (options.keys & %i[page_key limit_key]).each do |key|
67
+ raise OptionError.new(self, key, 'to be String', options[key]) \
68
+ unless options[key].is_a?(String)
69
+ end
42
70
  end
43
71
 
44
- # Setup @last (overridden by the gearbox extra)
45
- def assign_last
46
- @last = [(@count.to_f / @limit).ceil, 1].max
47
- @last = @vars[:max_pages] if @vars[:max_pages] && @last > vars[:max_pages]
48
- end
72
+ # Merge all the DEFAULT constants of the class hierarchy with the options
73
+ def assign_options(**options)
74
+ @request = options.delete(:request) # internal object
75
+ validate_string_values(options)
49
76
 
50
- # Assign @offset (overridden by the gearbox extra)
51
- def assign_offset
52
- @offset = (@limit * (@page - 1)) + @outset # may be already set from gear_box
53
- end
77
+ default = {}
78
+ current = self.class
54
79
 
55
- # Assign @prev and @next
56
- def assign_prev_and_next
57
- @prev = (@page - 1 unless @page == 1)
58
- @next = @page == @last ? (1 if @vars[:cycle]) : @page + 1
59
- end
80
+ loop do
81
+ default = current::DEFAULT.merge(default)
82
+ current = current.superclass
83
+ break if current == Object
84
+ end
60
85
 
61
- # Checks the @page <= @last
62
- def check_overflow
63
- raise OverflowError.new(self, :page, "in 1..#{@last}", @page) if @page > @last
86
+ clean_options = options.delete_if { |k, v| default.key?(k) && (v.nil? || v == '') }
87
+ @options = default.merge!(clean_options).freeze
64
88
  end
65
89
 
66
- # Label for the current page. Allow the customization of the output (overridden by the calendar extra)
67
- def label = @page.to_s
68
-
69
- # Label for any page. Allow the customization of the output (overridden by the calendar extra)
70
- def label_for(page) = page.to_s
71
-
72
- # Return the array of page numbers and :gap e.g. [1, :gap, 8, "9", 10, :gap, 36]
73
- def series(size: @vars[:size], **_)
74
- raise VariableError.new(self, :size, 'to be an Integer >= 0', size) \
75
- unless size.is_a?(Integer) && size >= 0
76
- return [] if size.zero?
77
-
78
- [].tap do |series|
79
- if size >= @last
80
- series.push(*1..@last)
81
- else
82
- left = ((size - 1) / 2.0).floor # left half might be 1 page shorter for even size
83
- start = if @page <= left # beginning pages
84
- 1
85
- elsif @page > (@last - size + left) # end pages
86
- @last - size + 1
87
- else # intermediate pages
88
- @page - left
89
- end
90
- series.push(*start...(start + size))
91
- # Set first and last pages plus gaps when needed, respecting the size
92
- if vars[:ends] && size >= 7
93
- series[0] = 1
94
- series[1] = :gap unless series[1] == 2
95
- series[-2] = :gap unless series[-2] == @last - 1
96
- series[-1] = @last
97
- end
98
- end
99
- series[series.index(@page)] = @page.to_s
100
- end
90
+ # Hook module for numeric UI helpers
91
+ module NumericHelpers
92
+ include NumericHelperLoader
101
93
  end
102
94
  end
103
95
 
104
- require_relative 'pagy/backend'
105
- require_relative 'pagy/frontend'
106
- require_relative 'pagy/exceptions'
96
+ require_relative ENV['PAGY_NEXT'] == 'true' ? 'pagy/next' : 'pagy/deprecated'
data/locales/ar.yml CHANGED
@@ -1,6 +1,8 @@
1
- # :arabic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb)
1
+ # See https://ddnexus.github.io/pagy/resources/i18n
2
+
2
3
  ar:
3
4
  pagy:
5
+ p11n: 'Arabic'
4
6
  aria_label:
5
7
  nav:
6
8
  zero: "لا يوجد صفحات"
@@ -9,9 +11,9 @@ ar:
9
11
  few: "صفحات"
10
12
  many: "صفحات"
11
13
  other: "صفحات"
12
- prev: "السابق"
14
+ previous: "السابق"
13
15
  next: "التالي"
14
- prev: "&lt;"
16
+ previous: "&lt;"
15
17
  next: "&gt;"
16
18
  gap: "&hellip;"
17
19
  item_name:
@@ -21,9 +23,10 @@ ar:
21
23
  few: "قليل"
22
24
  many: "كثير"
23
25
  other: "عناصر"
24
- info:
26
+ info_tag:
27
+ no_count: "الصفحة %{page} من %{pages}"
25
28
  no_items: "لا يوجد %{item_name}"
26
29
  single_page: "عرض %{count} %{item_name}"
27
30
  multiple_pages: "عرض %{item_name} %{from}-%{to} من اجمالي %{count}"
28
- combo_nav_js: "الصفحة %{page_input} من %{pages}"
29
- limit_selector_js: "عرض %{limit_input} %{item_name} لكل صفحة"
31
+ input_nav_js: "الصفحة %{page_input} من %{pages}"
32
+ limit_tag_js: "عرض %{limit_input} %{item_name} لكل صفحة"
data/locales/be.yml CHANGED
@@ -1,15 +1,17 @@
1
- # :east_slavic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb)
1
+ # See https://ddnexus.github.io/pagy/resources/i18n
2
+
2
3
  be:
3
4
  pagy:
5
+ p11n: 'EastSlavic'
4
6
  aria_label:
5
7
  nav:
6
8
  one: "Старонка"
7
9
  few: "Старонкi"
8
10
  many: "Старонкi"
9
11
  other: "Старонкi"
10
- prev: "Назад"
12
+ previous: "Назад"
11
13
  next: "Наперад"
12
- prev: "&lt;"
14
+ previous: "&lt;"
13
15
  next: "&gt;"
14
16
  gap: "&hellip;"
15
17
  item_name:
@@ -17,9 +19,10 @@ be:
17
19
  few: "запісы"
18
20
  many: "запісаў"
19
21
  other: "запісаў"
20
- info:
22
+ info_tag:
23
+ no_count: "Старонка %{page} з %{pages}"
21
24
  no_items: "Пакуль %{item_name} няма"
22
25
  single_page: "%{count} %{item_name}"
23
26
  multiple_pages: "Усяго %{count} %{item_name}, паказаны з %{from} па %{to}"
24
- combo_nav_js: "Старонка %{page_input} з %{pages}"
25
- limit_selector_js: "Паказаць %{limit_input} %{item_name} на старонцы"
27
+ input_nav_js: "Старонка %{page_input} з %{pages}"
28
+ limit_tag_js: "Паказаць %{limit_input} %{item_name} на старонцы"
data/locales/bg.yml CHANGED
@@ -1,21 +1,24 @@
1
- # :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb)
1
+ # See https://ddnexus.github.io/pagy/resources/i18n
2
+
2
3
  bg:
3
4
  pagy:
5
+ p11n: 'OneOther'
4
6
  aria_label:
5
7
  nav:
6
8
  one: "Страница"
7
9
  other: "Страници"
8
- prev: "Предишна"
10
+ previous: "Предишна"
9
11
  next: "Следваща"
10
- prev: "&lt;"
12
+ previous: "&lt;"
11
13
  next: "&gt;"
12
14
  gap: "&hellip;"
13
15
  item_name:
14
16
  one: "резултат"
15
17
  other: "резултати"
16
- info:
18
+ info_tag:
19
+ no_count: "Страница %{page} от %{pages}"
17
20
  no_items: "Няма намерени %{item_name}"
18
21
  single_page: "Показани са %{count} %{item_name}"
19
22
  multiple_pages: "Показани са %{item_name} %{from}-%{to} от %{count} общо"
20
- combo_nav_js: "Страница %{page_input} от %{pages}"
21
- limit_selector_js: "Покажи %{limit_input} %{item_name} на страница"
23
+ input_nav_js: "Страница %{page_input} от %{pages}"
24
+ limit_tag_js: "Покажи %{limit_input} %{item_name} на страница"
data/locales/bs.yml CHANGED
@@ -1,15 +1,17 @@
1
- # :east_slavic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb)
1
+ # See https://ddnexus.github.io/pagy/resources/i18n
2
+
2
3
  bs:
3
4
  pagy:
5
+ p11n: 'EastSlavic'
4
6
  aria_label:
5
7
  nav:
6
8
  one: "Stranica"
7
9
  few: "Stranice"
8
10
  many: "Stranica"
9
11
  other: "Stranice"
10
- prev: "Prethodna"
12
+ previous: "Prethodna"
11
13
  next: "Sljedeća"
12
- prev: "&lt;"
14
+ previous: "&lt;"
13
15
  next: "&gt;"
14
16
  gap: "&hellip;"
15
17
  item_name:
@@ -17,9 +19,10 @@ bs:
17
19
  few: "stavke"
18
20
  many: "stavki"
19
21
  other: "stavki"
20
- info:
22
+ info_tag:
23
+ no_count: "Stranica %{page} od %{pages}"
21
24
  no_items: "Nije pronađena %{item_name}"
22
25
  single_page: "Prikazuje se %{count} %{item_name}"
23
26
  multiple_pages: "Prikaz %{item_name} %{from}-%{to} od %{count} ukupno"
24
- combo_nav_js: "Stranica %{page_input} od %{pages}"
25
- limit_selector_js: "Prikaži %{limit_input} %{item_name} po stranici"
27
+ input_nav_js: "Stranica %{page_input} od %{pages}"
28
+ limit_tag_js: "Prikaži %{limit_input} %{item_name} po stranici"
data/locales/ca.yml CHANGED
@@ -1,21 +1,24 @@
1
- # :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb)
1
+ # See https://ddnexus.github.io/pagy/resources/i18n
2
+
2
3
  ca:
3
4
  pagy:
5
+ p11n: 'OneOther'
4
6
  aria_label:
5
7
  nav:
6
8
  one: "Pàgina"
7
9
  other: "Pàgines"
8
- prev: "Anterior"
10
+ previous: "Anterior"
9
11
  next: "Següent"
10
- prev: "&lt;"
12
+ previous: "&lt;"
11
13
  next: "&gt;"
12
14
  gap: "&hellip;"
13
15
  item_name:
14
16
  one: "element"
15
17
  other: "elements"
16
- info:
18
+ info_tag:
19
+ no_count: "Pàgina %{page} de %{pages}"
17
20
  no_items: "No s'ha trobat cap resultat"
18
21
  single_page: "Mostrant %{count} %{item_name}"
19
22
  multiple_pages: "Mostrant %{item_name} %{from}-%{to} de %{count} en total"
20
- combo_nav_js: "Pàgina %{page_input} de %{pages}"
21
- limit_selector_js: "Mostra %{limit_input} %{item_name} per pàgina"
23
+ input_nav_js: "Pàgina %{page_input} de %{pages}"
24
+ limit_tag_js: "Mostra %{limit_input} %{item_name} per pàgina"
data/locales/ckb.yml CHANGED
@@ -1,18 +1,20 @@
1
- # :other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb)
1
+ # See https://ddnexus.github.io/pagy/resources/i18n
2
2
 
3
3
  ckb:
4
4
  pagy:
5
+ p11n: 'Other'
5
6
  item_name: "بابەت"
6
7
  aria_label:
7
8
  nav: "پەڕەکان"
8
- prev: "پاش"
9
+ previous: "پاش"
9
10
  next: "پێش"
10
- prev: "&lt;"
11
+ previous: "&lt;"
11
12
  next: "&gt;"
12
13
  gap: "&hellip;"
13
- info:
14
+ info_tag:
15
+ no_count: "پەڕی %{page} لە %{pages}"
14
16
  no_items: "هیچ %{item_name}ێک نەدۆزرایەوە"
15
17
  single_page: "پیشاندانی %{count} %{item_name}"
16
18
  multiple_pages: "پشاندانی %{item_name}ی %{from}-%{to} لە کۆی %{count} بە گشتی"
17
- combo_nav_js: "پەڕی %{page_input} لە %{pages}"
18
- limit_selector_js: "نیشاندانی %{limit_input} %{item_name} لە هەر پەڕێک"
19
+ input_nav_js: "پەڕی %{page_input} لە %{pages}"
20
+ limit_tag_js: "نیشاندانی %{limit_input} %{item_name} لە هەر پەڕێک"