pagy 8.6.3 → 9.3.4

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 (106) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/apps/calendar.ru +119 -127
  4. data/apps/demo.ru +274 -260
  5. data/apps/index.rb +7 -0
  6. data/apps/keyset_ar.ru +227 -0
  7. data/apps/keyset_s.ru +219 -0
  8. data/apps/rails.ru +25 -20
  9. data/apps/repro.ru +108 -103
  10. data/bin/pagy +18 -20
  11. data/config/pagy.rb +19 -15
  12. data/javascripts/pagy.min.js +2 -2
  13. data/javascripts/pagy.min.js.map +3 -3
  14. data/javascripts/pagy.mjs +2 -2
  15. data/lib/pagy/b64.rb +33 -0
  16. data/lib/pagy/backend.rb +20 -20
  17. data/lib/pagy/calendar/day.rb +2 -2
  18. data/lib/pagy/calendar/month.rb +2 -2
  19. data/lib/pagy/calendar/quarter.rb +2 -2
  20. data/lib/pagy/calendar/unit.rb +7 -10
  21. data/lib/pagy/calendar/week.rb +2 -2
  22. data/lib/pagy/calendar/year.rb +2 -2
  23. data/lib/pagy/calendar.rb +15 -13
  24. data/lib/pagy/countless.rb +10 -14
  25. data/lib/pagy/extras/arel.rb +3 -11
  26. data/lib/pagy/extras/array.rb +5 -10
  27. data/lib/pagy/extras/bootstrap.rb +5 -5
  28. data/lib/pagy/extras/bulma.rb +10 -7
  29. data/lib/pagy/extras/calendar.rb +13 -17
  30. data/lib/pagy/extras/countless.rb +8 -13
  31. data/lib/pagy/extras/elasticsearch_rails.rb +16 -25
  32. data/lib/pagy/extras/gearbox.rb +18 -18
  33. data/lib/pagy/extras/headers.rb +25 -24
  34. data/lib/pagy/extras/i18n.rb +1 -1
  35. data/lib/pagy/extras/js_tools.rb +6 -6
  36. data/lib/pagy/extras/jsonapi.rb +30 -21
  37. data/lib/pagy/extras/keyset.rb +30 -0
  38. data/lib/pagy/extras/limit.rb +63 -0
  39. data/lib/pagy/extras/meilisearch.rb +9 -17
  40. data/lib/pagy/extras/metadata.rb +3 -3
  41. data/lib/pagy/extras/overflow.rb +9 -9
  42. data/lib/pagy/extras/pagy.rb +16 -16
  43. data/lib/pagy/extras/searchkick.rb +9 -17
  44. data/lib/pagy/extras/size.rb +1 -1
  45. data/lib/pagy/extras/standalone.rb +6 -6
  46. data/lib/pagy/extras/trim.rb +3 -3
  47. data/lib/pagy/frontend.rb +32 -33
  48. data/lib/pagy/i18n.rb +3 -2
  49. data/lib/pagy/keyset/active_record.rb +38 -0
  50. data/lib/pagy/keyset/sequel.rb +51 -0
  51. data/lib/pagy/keyset.rb +118 -0
  52. data/lib/pagy/shared_methods.rb +26 -0
  53. data/lib/pagy/url_helpers.rb +5 -5
  54. data/lib/pagy.rb +53 -67
  55. data/locales/ar.yml +1 -1
  56. data/locales/be.yml +1 -1
  57. data/locales/bg.yml +1 -1
  58. data/locales/bs.yml +1 -1
  59. data/locales/ca.yml +1 -1
  60. data/locales/ckb.yml +1 -1
  61. data/locales/cs.yml +1 -1
  62. data/locales/da.yml +1 -1
  63. data/locales/de.yml +1 -1
  64. data/locales/dz.yml +17 -0
  65. data/locales/en.yml +1 -1
  66. data/locales/es.yml +1 -1
  67. data/locales/fr.yml +1 -1
  68. data/locales/hr.yml +1 -1
  69. data/locales/id.yml +1 -1
  70. data/locales/it.yml +1 -1
  71. data/locales/ja.yml +1 -1
  72. data/locales/km.yml +1 -1
  73. data/locales/ko.yml +1 -1
  74. data/locales/nb.yml +1 -1
  75. data/locales/nl.yml +1 -1
  76. data/locales/nn.yml +1 -1
  77. data/locales/pl.yml +1 -1
  78. data/locales/pt-BR.yml +1 -1
  79. data/locales/pt.yml +1 -1
  80. data/locales/ru.yml +1 -1
  81. data/locales/sr.yml +1 -1
  82. data/locales/sv-SE.yml +1 -1
  83. data/locales/sv.yml +1 -1
  84. data/locales/sw.yml +3 -1
  85. data/locales/ta.yml +3 -1
  86. data/locales/tr.yml +1 -1
  87. data/locales/uk.yml +1 -1
  88. data/locales/vi.yml +1 -1
  89. data/locales/zh-CN.yml +7 -9
  90. data/locales/zh-HK.yml +7 -9
  91. data/locales/zh-TW.yml +7 -9
  92. metadata +14 -27
  93. data/apps/tmp/calendar.sqlite3 +0 -0
  94. data/apps/tmp/calendar.sqlite3-shm +0 -0
  95. data/apps/tmp/calendar.sqlite3-wal +0 -0
  96. data/apps/tmp/local_secret.txt +0 -1
  97. data/apps/tmp/pagy-keyset.sqlite3 +0 -0
  98. data/apps/tmp/pagy-keyset.sqlite3-shm +0 -0
  99. data/apps/tmp/pagy-keyset.sqlite3-wal +0 -0
  100. data/javascripts/pagy-module.js +0 -100
  101. data/javascripts/pagy.js +0 -4
  102. data/lib/pagy/extras/foundation.rb +0 -95
  103. data/lib/pagy/extras/items.rb +0 -64
  104. data/lib/pagy/extras/materialize.rb +0 -100
  105. data/lib/pagy/extras/semantic.rb +0 -94
  106. data/lib/pagy/extras/uikit.rb +0 -98
data/apps/repro.ru CHANGED
@@ -1,22 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Starting point app to try pagy or reproduce issues
4
-
3
+ # DESCRIPTION
4
+ # Reproduce generic/simple issues
5
+ #
6
+ # DOC
7
+ # https://ddnexus.github.io/pagy/playground/#1-repro-app
8
+ #
9
+ # BIN HELP
10
+ # bundle exec pagy -h
11
+ #
5
12
  # DEV USAGE
6
- # pagy clone repro
7
- # pagy ./repro.ru
8
-
13
+ # bundle exec pagy clone repro
14
+ # bundle exec pagy ./repro.ru
15
+ #
9
16
  # URL
10
17
  # http://0.0.0.0:8000
11
18
 
12
- # HELP
13
- # pagy -h
14
-
15
- # DOC
16
- # https://ddnexus.github.io/pagy/playground/#1-repro-app
17
-
18
- VERSION = '8.6.3'
19
+ VERSION = '9.3.4'
19
20
 
21
+ # Bundle
20
22
  require 'bundler/inline'
21
23
  require 'bundler'
22
24
  Bundler.configure
@@ -25,23 +27,20 @@ gemfile(ENV['PAGY_INSTALL_BUNDLE'] == 'true') do
25
27
  gem 'oj'
26
28
  gem 'puma'
27
29
  gem 'sinatra'
28
- gem 'sinatra-contrib'
29
30
  end
30
31
 
31
32
  # Edit this section adding/removing the extras and Pagy::DEFAULT as needed
32
33
  # pagy initializer
33
34
  require 'pagy/extras/pagy'
34
- require 'pagy/extras/items'
35
+ require 'pagy/extras/limit'
35
36
  require 'pagy/extras/overflow'
36
37
  Pagy::DEFAULT[:overflow] = :empty_page
37
38
  Pagy::DEFAULT.freeze
38
39
 
40
+ # Sinatra setup
39
41
  require 'sinatra/base'
40
42
  # Sinatra application
41
43
  class PagyRepro < Sinatra::Base
42
- configure do
43
- enable :inline_templates
44
- end
45
44
  include Pagy::Backend
46
45
 
47
46
  get('/javascripts/:file') do
@@ -58,12 +57,103 @@ class PagyRepro < Sinatra::Base
58
57
  get '/' do
59
58
  collection = MockCollection.new
60
59
  @pagy, @records = pagy(collection)
61
- erb :main # template available in the __END__ section as @@ main
60
+ erb :main
62
61
  end
62
+
63
63
  # Edit this section adding your own helpers as needed
64
64
  helpers do
65
65
  include Pagy::Frontend
66
66
  end
67
+
68
+ # Views
69
+ template :layout do
70
+ <<~ERB
71
+ <!DOCTYPE html>
72
+ <html lang="en">
73
+ <html>
74
+ <head>
75
+ <title>Pagy Repro App</title>
76
+ <script src="javascripts/pagy.min.js"></script>
77
+ <script>
78
+ window.addEventListener("load", Pagy.init);
79
+ </script>
80
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
81
+ <style type="text/css">
82
+ @media screen { html, body {
83
+ font-size: 1rem;
84
+ line-height: 1.2s;
85
+ padding: 0;
86
+ margin: 0;
87
+ } }
88
+ body {
89
+ background: white !important;
90
+ margin: 0 !important;
91
+ font-family: sans-serif !important;
92
+ }
93
+ .content {
94
+ padding: 1rem 1.5rem 2rem !important;
95
+ }
96
+
97
+ /* Quick demo for overriding the element style attribute of certain pagy helpers
98
+ .pagy input[style] {
99
+ width: 5rem !important;
100
+ }
101
+ */
102
+
103
+ /*
104
+ If you want to customize the style,
105
+ please replace the line below with the actual file content
106
+ */
107
+ <%= Pagy.root.join('stylesheets', 'pagy.css').read %>
108
+ </style>
109
+ </head>
110
+ <body>
111
+ <%= yield %>
112
+ </body>
113
+ </html>
114
+ ERB
115
+ end
116
+
117
+ template :main do
118
+ <<~ERB
119
+ <div class="content">
120
+ <h1>Pagy Repro App</h1>
121
+ <p> Self-contained, standalone app usable to easily reproduce any pagy issue.</p>
122
+ <p>Please, report the following versions in any new issue.</p>
123
+ <h2>Versions</h4>
124
+ <ul>
125
+ <li>Ruby: <%= RUBY_VERSION %></li>
126
+ <li>Rack: <%= Rack::RELEASE %></li>
127
+ <li>Sinatra: <%= Sinatra::VERSION %></li>
128
+ <li>Pagy: <%= Pagy::VERSION %></li>
129
+ </ul>
130
+
131
+ <h3>Collection</h3>
132
+ <p id="records">@records: <%= @records.join(',') %></p>
133
+
134
+ <hr>
135
+
136
+ <h4>pagy_nav</h4>
137
+ <%= pagy_nav(@pagy, id: 'nav', aria_label: 'Pages nav') %>
138
+
139
+ <h4>pagy_nav_js</h4>
140
+ <%= pagy_nav_js(@pagy, id: 'nav-js', aria_label: 'Pages nav_js') %>
141
+
142
+ <h4>pagy_nav_js</h4>
143
+ <%= pagy_nav_js(@pagy, id: 'nav-js-responsive', aria_label: 'Pages nav_js_responsove',
144
+ steps: { 0 => 5, 500 => 7, 750 => 9, 1000 => 11 }) %>
145
+
146
+ <h4>pagy_combo_nav_js</h4>
147
+ <%= pagy_combo_nav_js(@pagy, id: 'combo-nav-js', aria_label: 'Pages combo_nav_js') %>
148
+
149
+ <h4>pagy_limit_selector_js</h4>
150
+ <%= pagy_limit_selector_js(@pagy, id: 'limit-selector-js') %>
151
+
152
+ <h4>pagy_info</h4>
153
+ <%= pagy_info(@pagy, id: 'pagy-info') %>
154
+ </div>
155
+ ERB
156
+ end
67
157
  end
68
158
 
69
159
  # Simple array-based collection that acts as a standard DB collection.
@@ -90,88 +180,3 @@ class MockCollection < Array
90
180
  end
91
181
 
92
182
  run PagyRepro
93
-
94
- __END__
95
-
96
- @@ layout
97
- <!DOCTYPE html>
98
- <html lang="en">
99
- <html>
100
- <head>
101
- <title>Pagy Repro App</title>
102
- <script src="javascripts/pagy.min.js"></script>
103
- <script>
104
- window.addEventListener("load", Pagy.init);
105
- </script>
106
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
107
- <style type="text/css">
108
- @media screen { html, body {
109
- font-size: 1rem;
110
- line-height: 1.2s;
111
- padding: 0;
112
- margin: 0;
113
- } }
114
- body {
115
- background: white !important;
116
- margin: 0 !important;
117
- font-family: sans-serif !important;
118
- }
119
- .content {
120
- padding: 1rem 1.5rem 2rem !important;
121
- }
122
-
123
- /* Quick demo for overriding the element style attribute of certain pagy helpers
124
- .pagy input[style] {
125
- width: 5rem !important;
126
- }
127
- */
128
-
129
- /*
130
- If you want to customize the style,
131
- please replace the line below with the actual file content
132
- */
133
- <%= Pagy.root.join('stylesheets', 'pagy.css').read %>
134
- </style>
135
- </head>
136
- <body>
137
- <%= yield %>
138
- </body>
139
- </html>
140
-
141
- @@ main
142
- <div class="content">
143
- <h1>Pagy Repro App</h1>
144
- <p> Self-contained, standalone Sinatra app usable to easily reproduce any pagy issue.</p>
145
- <p>Please, report the following versions in any new issue.</p>
146
- <h2>Versions</h4>
147
- <ul>
148
- <li>Ruby: <%= RUBY_VERSION %></li>
149
- <li>Rack: <%= Rack::RELEASE %></li>
150
- <li>Sinatra: <%= Sinatra::VERSION %></li>
151
- <li>Pagy: <%= Pagy::VERSION %></li>
152
- </ul>
153
-
154
- <h3>Collection</h3>
155
- <p id="records">@records: <%= @records.join(',') %></p>
156
-
157
- <hr>
158
-
159
- <h4>pagy_nav</h4>
160
- <%= pagy_nav(@pagy, id: 'nav', aria_label: 'Pages nav') %>
161
-
162
- <h4>pagy_nav_js</h4>
163
- <%= pagy_nav_js(@pagy, id: 'nav-js', aria_label: 'Pages nav_js') %>
164
-
165
- <h4>pagy_nav_js</h4>
166
- <%= pagy_nav_js(@pagy, id: 'nav-js-responsive', aria_label: 'Pages nav_js_responsove',
167
- steps: { 0 => 5, 500 => 7, 750 => 9, 1000 => 11 }) %>
168
-
169
- <h4>pagy_combo_nav_js</h4>
170
- <%= pagy_combo_nav_js(@pagy, id: 'combo-nav-js', aria_label: 'Pages combo_nav_js') %>
171
-
172
- <h4>pagy_items_selector_js</h4>
173
- <%= pagy_items_selector_js(@pagy, id: 'items-selector-js') %>
174
-
175
- <h4>pagy_info</h4>
176
- <%= pagy_info(@pagy, id: 'pagy-info') %>
177
- </div>
data/bin/pagy CHANGED
@@ -1,22 +1,23 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- VERSION = '8.6.3'
5
- APPS = %w[repro rails demo calendar].freeze
4
+ VERSION = '9.3.4'
6
5
  LINUX = RbConfig::CONFIG['host_os'].include?('linux')
7
6
  HOST = '0.0.0.0'
8
7
  PORT = '8000'
9
8
 
10
9
  require_relative '../lib/optimist'
10
+ require_relative '../apps/index'
11
+ apps = PagyApps::INDEX
11
12
  opts = Optimist.options do
12
13
  text <<~HEAD
13
14
  Pagy #{VERSION} (https://ddnexus.github.io/pagy/playground)
14
15
  Playground to showcase, clone and develop pagy APPs
15
16
  APPs
16
- repro Reproduce generic/simple issues
17
- rails Reproduce rails related issues
18
- demo Showcase all the helpers and styles
19
- calendar Showcase the calendar; reproduce related issues
17
+ #{ apps.map do |name, path|
18
+ " #{name}#{' ' * (27 - name.length)}#{File.readlines(path)[3].sub('# ', '').strip}"
19
+ end.join("\n")
20
+ }
20
21
  USAGE
21
22
  pagy APP [options] Showcase APP from the installed gem
22
23
  pagy clone APP Clone APP to the current dir
@@ -27,10 +28,10 @@ opts = Optimist.options do
27
28
  pagy ~/my-repro.ru Develop ~/my-repro.ru at#{HOST}:#{PORT}
28
29
  HEAD
29
30
  text 'Rackup options'
30
- opt :env, 'Environment', default: 'development'
31
- opt :host, 'Host', default: HOST, short: :o
32
- opt :port, 'Port', default: PORT
33
- opt :install, 'Install bundle for users', default: true
31
+ opt :env, 'Environment', default: 'development'
32
+ opt :host, 'Host', default: HOST, short: :o
33
+ opt :port, 'Port', default: PORT
34
+ opt :install, 'Install bundle for users', default: true
34
35
  if LINUX
35
36
  text 'Rerun options'
36
37
  opt :rerun, 'Enable rerun for development', default: true
@@ -44,7 +45,7 @@ Optimist.educate if ARGV.empty?
44
45
 
45
46
  run_from_repo = File.exist?(File.expand_path('../pagy.gemspec', __dir__))
46
47
 
47
- # Handles gems
48
+ # Bundle
48
49
  require 'bundler/inline'
49
50
  require 'bundler'
50
51
  Bundler.configure
@@ -54,28 +55,25 @@ gemfile(opts[:install]) do
54
55
  gem 'rerun' if LINUX
55
56
  end
56
57
 
57
- path = ->(app) { File.expand_path("../apps/#{app}.ru", __dir__) }
58
- arg = ARGV.shift
58
+ arg = ARGV.shift
59
59
  if arg.eql?('clone')
60
- arg = ARGV.shift
61
- Optimist.die("Expected APP to be in [#{APPS.join(', ')}]; got #{arg.inspect}") unless APPS.include?(arg)
62
- file = path.(arg)
63
- name = File.basename(file)
60
+ name = ARGV.shift
61
+ Optimist.die("Expected APP to be in [#{apps.keys.join(', ')}]; got #{arg.inspect}") unless apps.key?(arg)
64
62
  if File.exist?(name)
65
63
  print "Do you want to overwrite the #{name.inspect} file? (y/n)> "
66
64
  answer = gets.chomp
67
65
  Optimist.die("#{name.inspect} file already present") unless answer.start_with?(/y/i)
68
66
  end
69
67
  require 'fileutils'
70
- FileUtils.cp(file, '.', verbose: true)
68
+ FileUtils.cp(apps[arg], '.', verbose: true)
71
69
  else
72
- if APPS.include?(arg) # showcase env
70
+ if apps.key?(arg) # showcase env
73
71
  opts[:env] = 'showcase'
74
72
  opts[:rerun] = false
75
73
  opts[:quiet] = true
76
74
  # Avoid the creation of './tmp/local_secret.txt' for showcase env
77
75
  ENV['SECRET_KEY_BASE'] = 'absolute secret!' if arg.eql?('rails')
78
- file = path.(arg)
76
+ file = apps[arg]
79
77
  else # development env
80
78
  file = arg
81
79
  end
data/config/pagy.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Pagy initializer file (8.6.3)
3
+ # Pagy initializer file (9.3.4)
4
4
  # Customize only what you really need and notice that the core Pagy works also without any of the following lines.
5
5
  # Should you just cherry pick part of this file, please maintain the require-order of the extras
6
6
 
@@ -10,7 +10,7 @@
10
10
  # You can set any pagy variable as a Pagy::DEFAULT. They can also be overridden per instance by just passing them to
11
11
  # Pagy.new|Pagy::Countless.new|Pagy::Calendar::*.new or any of the #pagy* controller methods
12
12
  # Here are the few that make more sense as DEFAULTs:
13
- # Pagy::DEFAULT[:items] = 20 # default
13
+ # Pagy::DEFAULT[:limit] = 20 # default
14
14
  # Pagy::DEFAULT[:size] = 7 # default
15
15
  # Pagy::DEFAULT[:ends] = true # default
16
16
  # Pagy::DEFAULT[:page_param] = :page # default
@@ -72,13 +72,17 @@
72
72
  # require 'pagy/extras/elasticsearch_rails'
73
73
 
74
74
  # Headers extra: http response headers (and other helpers) useful for API pagination
75
- # See http://ddnexus.github.io/pagy/extras/headers
75
+ # See https://ddnexus.github.io/pagy/docs/extras/headers
76
76
  # require 'pagy/extras/headers'
77
77
  # Pagy::DEFAULT[:headers] = { page: 'Current-Page',
78
- # items: 'Page-Items',
78
+ # limit: 'Page-Items',
79
79
  # count: 'Total-Count',
80
80
  # pages: 'Total-Pages' } # default
81
81
 
82
+ # Keyset extra: Paginate with the Pagy keyset pagination technique
83
+ # See https://ddnexus.github.io/pagy/docs/extras/keyset
84
+ # require 'pagy/extras/keyset'
85
+
82
86
  # Meilisearch extra: Paginate `Meilisearch` result objects
83
87
  # See https://ddnexus.github.io/pagy/docs/extras/meilisearch
84
88
  # Default :pagy_search method: change only if you use also
@@ -100,7 +104,7 @@
100
104
  # See https://ddnexus.github.io/pagy/docs/extras/searchkick
101
105
  # Default :pagy_search method: change only if you use also
102
106
  # the elasticsearch_rails or meilisearch extra that defines the same
103
- # DEFAULT[:searchkick_pagy_search] = :pagy_search
107
+ # Pagy::DEFAULT[:searchkick_pagy_search] = :pagy_search
104
108
  # Default original :search method called internally to do the actual search
105
109
  # Pagy::DEFAULT[:searchkick_search] = :search
106
110
  # require 'pagy/extras/searchkick'
@@ -130,20 +134,20 @@
130
134
 
131
135
  # Feature Extras
132
136
 
133
- # Gearbox extra: Automatically change the number of items per page depending on the page number
137
+ # Gearbox extra: Automatically change the limit per page depending on the page number
134
138
  # See https://ddnexus.github.io/pagy/docs/extras/gearbox
135
139
  # require 'pagy/extras/gearbox'
136
140
  # set to false only if you want to make :gearbox_extra an opt-in variable
137
141
  # Pagy::DEFAULT[:gearbox_extra] = false # default true
138
- # Pagy::DEFAULT[:gearbox_items] = [15, 30, 60, 100] # default
142
+ # Pagy::DEFAULT[:gearbox_limit] = [15, 30, 60, 100] # default
139
143
 
140
- # Items extra: Allow the client to request a custom number of items per page with an optional selector UI
141
- # See https://ddnexus.github.io/pagy/docs/extras/items
142
- # require 'pagy/extras/items'
143
- # set to false only if you want to make :items_extra an opt-in variable
144
- # Pagy::DEFAULT[:items_extra] = false # default true
145
- # Pagy::DEFAULT[:items_param] = :items # default
146
- # Pagy::DEFAULT[:max_items] = 100 # default
144
+ # Limit extra: Allow the client to request a custom limit per page with an optional selector UI
145
+ # See https://ddnexus.github.io/pagy/docs/extras/limit
146
+ # require 'pagy/extras/limit'
147
+ # set to false only if you want to make :limit_extra an opt-in variable
148
+ # Pagy::DEFAULT[:limit_extra] = false # default true
149
+ # Pagy::DEFAULT[:limit_param] = :limit # default
150
+ # Pagy::DEFAULT[:limit_max] = 100 # default
147
151
 
148
152
  # Overflow extra: Allow for easy handling of overflowing pages
149
153
  # See https://ddnexus.github.io/pagy/docs/extras/overflow
@@ -169,7 +173,7 @@
169
173
 
170
174
  # Rails
171
175
  # Enable the .js file required by the helpers that use javascript
172
- # (pagy*_nav_js, pagy*_combo_nav_js, and pagy_items_selector_js)
176
+ # (pagy*_nav_js, pagy*_combo_nav_js, and pagy_limit_selector_js)
173
177
  # See https://ddnexus.github.io/pagy/docs/api/javascript
174
178
 
175
179
  # With the asset pipeline
@@ -1,4 +1,4 @@
1
- window.Pagy=(()=>{const j=new ResizeObserver((B)=>B.forEach((D)=>D.target.querySelectorAll(".pagy-rjs").forEach((E)=>E.pagyRender()))),x=(B,[D,E,z,G])=>{const F=B.parentElement??B,K=Object.keys(E).map((H)=>parseInt(H)).sort((H,M)=>M-H);let L=-1;const T=(H,M,R)=>H.replace(/__pagy_page__/g,M).replace(/__pagy_label__/g,R);if((B.pagyRender=function(){const H=K.find((Q)=>Q<F.clientWidth)||0;if(H===L)return;let M=D.before;const R=E[H.toString()],X=z?.[H.toString()]??R.map((Q)=>Q.toString());R.forEach((Q,J)=>{const $=X[J];let U;if(typeof Q==="number")U=T(D.a,Q.toString(),$);else if(Q==="gap")U=D.gap;else U=T(D.current,Q,$);M+=typeof G==="string"&&Q==1?Z(U,G):U}),M+=D.after,B.innerHTML="",B.insertAdjacentHTML("afterbegin",M),L=H})(),B.classList.contains("pagy-rjs"))j.observe(F)},A=(B,[D,E])=>Y(B,(z)=>[z,D.replace(/__pagy_page__/,z)],E),C=(B,[D,E,z])=>{Y(B,(G)=>{const F=Math.max(Math.ceil(D/parseInt(G)),1).toString(),K=E.replace(/__pagy_page__/,F).replace(/__pagy_items__/,G);return[F,K]},z)},Y=(B,D,E)=>{const z=B.querySelector("input"),G=B.querySelector("a"),F=z.value,K=function(){if(z.value===F)return;const[L,T,H]=[z.min,z.value,z.max].map((X)=>parseInt(X)||0);if(T<L||T>H){z.value=F,z.select();return}let[M,R]=D(z.value);if(typeof E==="string"&&M==="1")R=Z(R,E);G.href=R,G.click()};["change","focus"].forEach((L)=>z.addEventListener(L,()=>z.select())),z.addEventListener("focusout",K),z.addEventListener("keypress",(L)=>{if(L.key==="Enter")K()})},Z=(B,D)=>B.replace(new RegExp(`[?&]${D}=1\\b(?!&)|\\b${D}=1&`),"");return{version:"8.6.3",init(B){const E=(B instanceof Element?B:document).querySelectorAll("[data-pagy]");for(let z of E)try{const G=Uint8Array.from(atob(z.getAttribute("data-pagy")),(L)=>L.charCodeAt(0)),[F,...K]=JSON.parse((new TextDecoder()).decode(G));if(F==="nav")x(z,K);else if(F==="combo")A(z,K);else if(F==="selector")C(z,K);else console.warn("Skipped Pagy.init() for: %o\nUnknown keyword '%s'",z,F)}catch(G){console.warn("Skipped Pagy.init() for: %o\n%s",z,G)}}}})();
1
+ window.Pagy=(()=>{const j=new ResizeObserver((B)=>B.forEach((D)=>D.target.querySelectorAll(".pagy-rjs").forEach((E)=>E.pagyRender()))),x=(B,[D,E,z,G])=>{const F=B.parentElement??B,K=Object.keys(E).map((H)=>parseInt(H)).sort((H,M)=>M-H);let L=-1;const T=(H,M,R)=>H.replace(/__pagy_page__/g,M).replace(/__pagy_label__/g,R);if((B.pagyRender=function(){const H=K.find((Q)=>Q<F.clientWidth)||0;if(H===L)return;let M=D.before;const R=E[H.toString()],X=z?.[H.toString()]??R.map((Q)=>Q.toString());R.forEach((Q,J)=>{const $=X[J];let U;if(typeof Q==="number")U=T(D.a,Q.toString(),$);else if(Q==="gap")U=D.gap;else U=T(D.current,Q,$);M+=typeof G==="string"&&Q==1?Z(U,G):U}),M+=D.after,B.innerHTML="",B.insertAdjacentHTML("afterbegin",M),L=H})(),B.classList.contains("pagy-rjs"))j.observe(F)},A=(B,[D,E])=>Y(B,(z)=>[z,D.replace(/__pagy_page__/,z)],E),C=(B,[D,E,z])=>{Y(B,(G)=>{const F=Math.max(Math.ceil(D/parseInt(G)),1).toString(),K=E.replace(/__pagy_page__/,F).replace(/__pagy_limit__/,G);return[F,K]},z)},Y=(B,D,E)=>{const z=B.querySelector("input"),G=B.querySelector("a"),F=z.value,K=function(){if(z.value===F)return;const[L,T,H]=[z.min,z.value,z.max].map((X)=>parseInt(X)||0);if(T<L||T>H){z.value=F,z.select();return}let[M,R]=D(z.value);if(typeof E==="string"&&M==="1")R=Z(R,E);G.href=R,G.click()};["change","focus"].forEach((L)=>z.addEventListener(L,()=>z.select())),z.addEventListener("focusout",K),z.addEventListener("keypress",(L)=>{if(L.key==="Enter")K()})},Z=(B,D)=>B.replace(new RegExp(`[?&]${D}=1\\b(?!&)|\\b${D}=1&`),"");return{version:"9.3.4",init(B){const E=(B instanceof Element?B:document).querySelectorAll("[data-pagy]");for(let z of E)try{const G=Uint8Array.from(atob(z.getAttribute("data-pagy")),(L)=>L.charCodeAt(0)),[F,...K]=JSON.parse(new TextDecoder().decode(G));if(F==="nav")x(z,K);else if(F==="combo")A(z,K);else if(F==="selector")C(z,K);else console.warn("Skipped Pagy.init() for: %o\nUnknown keyword '%s'",z,F)}catch(G){console.warn("Skipped Pagy.init() for: %o\n%s",z,G)}}}})();
2
2
 
3
- //# debugId=B9DC02765C7A5B6764756E2164756E21
3
+ //# debugId=645A69572EDFDB9764756E2164756E21
4
4
  //# sourceMappingURL=pagy.min.js.map
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/pagy.ts"],
4
4
  "sourcesContent": [
5
- "type NavArgs = readonly [Tokens, Sequels, null | LabelSequels, string?]\ntype ComboArgs = readonly [string, string?]\ntype SelectorArgs = readonly [number, string, string?]\ntype JsonArgs = ['nav', NavArgs] | ['combo', ComboArgs] | ['selector', SelectorArgs]\n\ninterface Tokens {\n readonly before:string\n readonly a:string\n readonly current:string\n readonly gap:string\n readonly after:string\n}\ninterface Sequels {readonly [width:string]:(string | number)[]}\ninterface LabelSequels {readonly [width:string]:string[]}\ninterface NavElement extends Element {pagyRender():void}\n\nconst Pagy = (() => {\n // The observer instance for responsive navs\n const rjsObserver = new ResizeObserver(\n entries => entries.forEach(e => e.target.querySelectorAll<NavElement>(\".pagy-rjs\")\n .forEach(el => el.pagyRender())));\n // Init the *_nav_js helpers\n const initNav = (el:NavElement, [tokens, sequels, labelSequels, trimParam]:NavArgs) => {\n const container = el.parentElement ?? el;\n const widths = Object.keys(sequels).map(w => parseInt(w)).sort((a, b) => b - a);\n let lastWidth = -1;\n const fillIn = (a:string, page:string, label:string):string =>\n a.replace(/__pagy_page__/g, page).replace(/__pagy_label__/g, label);\n (el.pagyRender = function () {\n const width = widths.find(w => w < container.clientWidth) || 0;\n if (width === lastWidth) { return } // no change: abort\n let html = tokens.before; // already trimmed in html\n const series = sequels[width.toString()];\n const labels = labelSequels?.[width.toString()] ?? series.map(l => l.toString());\n series.forEach((item, i) => {\n const label = labels[i];\n let filled;\n if (typeof item === \"number\") {\n filled = fillIn(tokens.a, item.toString(), label);\n } else if (item === \"gap\") {\n filled = tokens.gap;\n } else { // active page\n filled = fillIn(tokens.current, item, label);\n }\n html += (typeof trimParam === \"string\" && item == 1) ? trim(filled, trimParam) : filled;\n });\n html += tokens.after;\n el.innerHTML = \"\";\n el.insertAdjacentHTML(\"afterbegin\", html);\n lastWidth = width;\n })();\n if (el.classList.contains(\"pagy-rjs\")) { rjsObserver.observe(container) }\n };\n\n // Init the *_combo_nav_js helpers\n const initCombo = (el:Element, [url_token, trimParam]:ComboArgs) =>\n initInput(el, inputValue => [inputValue, url_token.replace(/__pagy_page__/, inputValue)], trimParam);\n\n // Init the items_selector_js helper\n const initSelector = (el:Element, [from, url_token, trimParam]:SelectorArgs) => {\n initInput(el, inputValue => {\n const page = Math.max(Math.ceil(from / parseInt(inputValue)), 1).toString();\n const url = url_token.replace(/__pagy_page__/, page).replace(/__pagy_items__/, inputValue);\n return [page, url];\n }, trimParam);\n };\n\n // Init the input element\n const initInput = (el:Element, getVars:(v:string) => [string, string], trimParam?:string) => {\n const input = el.querySelector(\"input\") as HTMLInputElement;\n const link = el.querySelector(\"a\") as HTMLAnchorElement;\n const initial = input.value;\n const action = function () {\n if (input.value === initial) { return } // not changed\n const [min, val, max] = [input.min, input.value, input.max].map(n => parseInt(n) || 0);\n if (val < min || val > max) { // reset invalid/out-of-range\n input.value = initial;\n input.select();\n return;\n }\n let [page, url] = getVars(input.value); // eslint-disable-line prefer-const\n if (typeof trimParam === \"string\" && page === \"1\") { url = trim(url, trimParam) }\n link.href = url;\n link.click();\n };\n [\"change\", \"focus\"].forEach(e => input.addEventListener(e, () => input.select())); // auto-select\n input.addEventListener(\"focusout\", action); // trigger action\n input.addEventListener(\"keypress\", e => { if (e.key === \"Enter\") { action() } }); // trigger action\n };\n\n // Trim the ${page-param}=1 params in links\n const trim = (a:string, param:string) =>\n a.replace(new RegExp(`[?&]${param}=1\\\\b(?!&)|\\\\b${param}=1&`), \"\");\n\n // Public interface\n return {\n version: \"8.6.3\",\n\n // Scan for elements with a \"data-pagy\" attribute and call their init functions with the decoded args\n init(arg?:Element) {\n const target = arg instanceof Element ? arg : document;\n const elements = target.querySelectorAll(\"[data-pagy]\");\n for (const el of elements) {\n try {\n const uint8array = Uint8Array.from(atob(el.getAttribute(\"data-pagy\") as string), c => c.charCodeAt(0));\n const [keyword, ...args] = JSON.parse((new TextDecoder()).decode(uint8array)) as JsonArgs; // base64-utf8 -> JSON -> Array\n if (keyword === \"nav\") {\n initNav(el as NavElement, args as unknown as NavArgs);\n } else if (keyword === \"combo\") {\n initCombo(el, args as unknown as ComboArgs);\n } else if (keyword === \"selector\") {\n initSelector(el, args as unknown as SelectorArgs);\n } else {\n console.warn(\"Skipped Pagy.init() for: %o\\nUnknown keyword '%s'\", el, keyword);\n }\n } catch (err) { console.warn(\"Skipped Pagy.init() for: %o\\n%s\", el, err) }\n }\n }\n };\n})();\n\nexport default Pagy;\n"
5
+ "type NavArgs = readonly [Tokens, Sequels, null | LabelSequels, string?]\ntype ComboArgs = readonly [string, string?]\ntype SelectorArgs = readonly [number, string, string?]\ntype JsonArgs = ['nav', NavArgs] | ['combo', ComboArgs] | ['selector', SelectorArgs]\n\ninterface Tokens {\n readonly before:string\n readonly a:string\n readonly current:string\n readonly gap:string\n readonly after:string\n}\ninterface Sequels {readonly [width:string]:(string | number)[]}\ninterface LabelSequels {readonly [width:string]:string[]}\ninterface NavElement extends Element {pagyRender():void}\n\nconst Pagy = (() => {\n // The observer instance for responsive navs\n const rjsObserver = new ResizeObserver(\n entries => entries.forEach(e => e.target.querySelectorAll<NavElement>(\".pagy-rjs\")\n .forEach(el => el.pagyRender())));\n // Init the *_nav_js helpers\n const initNav = (el:NavElement, [tokens, sequels, labelSequels, trimParam]:NavArgs) => {\n const container = el.parentElement ?? el;\n const widths = Object.keys(sequels).map(w => parseInt(w)).sort((a, b) => b - a);\n let lastWidth = -1;\n const fillIn = (a:string, page:string, label:string):string =>\n a.replace(/__pagy_page__/g, page).replace(/__pagy_label__/g, label);\n (el.pagyRender = function () {\n const width = widths.find(w => w < container.clientWidth) || 0;\n if (width === lastWidth) { return } // no change: abort\n let html = tokens.before; // already trimmed in html\n const series = sequels[width.toString()];\n const labels = labelSequels?.[width.toString()] ?? series.map(l => l.toString());\n series.forEach((item, i) => {\n const label = labels[i];\n let filled;\n if (typeof item === \"number\") {\n filled = fillIn(tokens.a, item.toString(), label);\n } else if (item === \"gap\") {\n filled = tokens.gap;\n } else { // active page\n filled = fillIn(tokens.current, item, label);\n }\n html += (typeof trimParam === \"string\" && item == 1) ? trim(filled, trimParam) : filled;\n });\n html += tokens.after;\n el.innerHTML = \"\";\n el.insertAdjacentHTML(\"afterbegin\", html);\n lastWidth = width;\n })();\n if (el.classList.contains(\"pagy-rjs\")) { rjsObserver.observe(container) }\n };\n\n // Init the *_combo_nav_js helpers\n const initCombo = (el:Element, [url_token, trimParam]:ComboArgs) =>\n initInput(el, inputValue => [inputValue, url_token.replace(/__pagy_page__/, inputValue)], trimParam);\n\n // Init the limit_selector_js helper\n const initSelector = (el:Element, [from, url_token, trimParam]:SelectorArgs) => {\n initInput(el, inputValue => {\n const page = Math.max(Math.ceil(from / parseInt(inputValue)), 1).toString();\n const url = url_token.replace(/__pagy_page__/, page).replace(/__pagy_limit__/, inputValue);\n return [page, url];\n }, trimParam);\n };\n\n // Init the input element\n const initInput = (el:Element, getVars:(v:string) => [string, string], trimParam?:string) => {\n const input = el.querySelector(\"input\") as HTMLInputElement;\n const link = el.querySelector(\"a\") as HTMLAnchorElement;\n const initial = input.value;\n const action = function () {\n if (input.value === initial) { return } // not changed\n const [min, val, max] = [input.min, input.value, input.max].map(n => parseInt(n) || 0);\n if (val < min || val > max) { // reset invalid/out-of-range\n input.value = initial;\n input.select();\n return;\n }\n let [page, url] = getVars(input.value); // eslint-disable-line prefer-const\n if (typeof trimParam === \"string\" && page === \"1\") { url = trim(url, trimParam) }\n link.href = url;\n link.click();\n };\n [\"change\", \"focus\"].forEach(e => input.addEventListener(e, () => input.select())); // auto-select\n input.addEventListener(\"focusout\", action); // trigger action\n input.addEventListener(\"keypress\", e => { if (e.key === \"Enter\") { action() } }); // trigger action\n };\n\n // Trim the ${page-param}=1 params in links\n const trim = (a:string, param:string) =>\n a.replace(new RegExp(`[?&]${param}=1\\\\b(?!&)|\\\\b${param}=1&`), \"\");\n\n // Public interface\n return {\n version: \"9.3.4\",\n\n // Scan for elements with a \"data-pagy\" attribute and call their init functions with the decoded args\n init(arg?:Element) {\n const target = arg instanceof Element ? arg : document;\n const elements = target.querySelectorAll(\"[data-pagy]\");\n for (const el of elements) {\n try {\n const uint8array = Uint8Array.from(atob(el.getAttribute(\"data-pagy\") as string), c => c.charCodeAt(0));\n const [keyword, ...args] = JSON.parse((new TextDecoder()).decode(uint8array)) as JsonArgs; // base64-utf8 -> JSON -> Array\n if (keyword === \"nav\") {\n initNav(el as NavElement, args as unknown as NavArgs);\n } else if (keyword === \"combo\") {\n initCombo(el, args as unknown as ComboArgs);\n } else if (keyword === \"selector\") {\n initSelector(el, args as unknown as SelectorArgs);\n } else {\n console.warn(\"Skipped Pagy.init() for: %o\\nUnknown keyword '%s'\", el, keyword);\n }\n } catch (err) { console.warn(\"Skipped Pagy.init() for: %o\\n%s\", el, err) }\n }\n }\n };\n})();\n\nexport default Pagy;\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "B9DC02765C7A5B6764756E2164756E21",
7
+ "mappings": "AAgBA,IAAM,GAAQ,IAAM,CAElB,MAAM,EAAc,IAAI,eACpB,KAAW,EAAQ,QAAQ,KAAK,EAAE,OAAO,iBAA6B,WAAW,EAC/C,QAAQ,KAAM,EAAG,WAAW,CAAC,CAAC,CAAC,EAE/D,EAAU,CAAC,GAAgB,EAAQ,EAAS,EAAc,KAAuB,CACrF,MAAM,EAAY,EAAG,eAAiB,EAChC,EAAY,OAAO,KAAK,CAAO,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,EAAG,IAAM,EAAI,CAAC,EACjF,IAAI,EAAc,GAClB,MAAM,EAAY,CAAC,EAAU,EAAa,IACtC,EAAE,QAAQ,iBAAkB,CAAI,EAAE,QAAQ,kBAAmB,CAAK,EAwBtE,IAvBC,EAAG,mBAAsB,EAAG,CAC3B,MAAM,EAAQ,EAAO,KAAK,KAAK,EAAI,EAAU,WAAW,GAAK,EAC7D,GAAI,IAAU,EAAa,OAC3B,IAAI,EAAW,EAAO,OACtB,MAAM,EAAS,EAAQ,EAAM,SAAS,GAChC,EAAS,IAAe,EAAM,SAAS,IAAM,EAAO,IAAI,KAAK,EAAE,SAAS,CAAC,EAC/E,EAAO,QAAQ,CAAC,EAAM,IAAM,CAC1B,MAAM,EAAQ,EAAO,GACrB,IAAI,EACJ,UAAW,IAAS,SAClB,EAAS,EAAO,EAAO,EAAG,EAAK,SAAS,EAAG,CAAK,UACvC,IAAS,MAClB,EAAS,EAAO,QAEhB,GAAS,EAAO,EAAO,QAAS,EAAM,CAAK,EAE7C,UAAgB,IAAc,UAAY,GAAQ,EAAK,EAAK,EAAQ,CAAS,EAAI,EAClF,EACD,GAAe,EAAO,MACtB,EAAG,UAAY,GACf,EAAG,mBAAmB,aAAc,CAAI,EACxC,EAAY,IACX,EACC,EAAG,UAAU,SAAS,UAAU,EAAK,EAAY,QAAQ,CAAS,GAIlE,EAAY,CAAC,GAAa,EAAW,KACvC,EAAU,EAAI,KAAc,CAAC,EAAY,EAAU,QAAQ,gBAAiB,CAAU,CAAC,EAAG,CAAS,EAGjG,EAAe,CAAC,GAAa,EAAM,EAAW,KAA4B,CAC9E,EAAU,EAAI,KAAc,CAC1B,MAAM,EAAO,KAAK,IAAI,KAAK,KAAK,EAAO,SAAS,CAAU,CAAC,EAAG,CAAC,EAAE,SAAS,EACpE,EAAO,EAAU,QAAQ,gBAAiB,CAAI,EAAE,QAAQ,iBAAkB,CAAU,EAC1F,MAAO,CAAC,EAAM,CAAG,GAChB,CAAS,GAIR,EAAY,CAAC,EAAY,EAAwC,IAAsB,CAC3F,MAAM,EAAU,EAAG,cAAc,OAAO,EAClC,EAAU,EAAG,cAAc,GAAG,EAC9B,EAAU,EAAM,MAChB,UAAmB,EAAG,CAC1B,GAAI,EAAM,QAAU,EAAW,OAC/B,MAAO,EAAK,EAAK,GAAO,CAAC,EAAM,IAAK,EAAM,MAAO,EAAM,GAAG,EAAE,IAAI,KAAK,SAAS,CAAC,GAAK,CAAC,EACrF,GAAI,EAAM,GAAO,EAAM,EAAK,CAC1B,EAAM,MAAQ,EACd,EAAM,OAAO,EACb,OAEF,IAAK,EAAM,GAAO,EAAQ,EAAM,KAAK,EACrC,UAAW,IAAc,UAAY,IAAS,IAAO,EAAM,EAAK,EAAK,CAAS,EAC9E,EAAK,KAAO,EACZ,EAAK,MAAM,GAEb,CAAC,SAAU,OAAO,EAAE,QAAQ,KAAK,EAAM,iBAAiB,EAAG,IAAM,EAAM,OAAO,CAAC,CAAC,EAChF,EAAM,iBAAiB,WAAY,CAAM,EACzC,EAAM,iBAAiB,WAAY,KAAK,CAAE,GAAI,EAAE,MAAQ,QAAW,EAAO,EAAK,GAI3E,EAAO,CAAC,EAAU,IACpB,EAAE,QAAQ,IAAI,OAAO,OAAO,kBAAsB,MAAU,EAAG,EAAE,EAGrE,MAAO,CACL,QAAS,QAGT,IAAI,CAAC,EAAc,CAEjB,MAAM,GADW,aAAe,QAAU,EAAM,UACxB,iBAAiB,aAAa,EACtD,QAAW,KAAM,EACf,GAAI,CACF,MAAM,EAAqB,WAAW,KAAK,KAAK,EAAG,aAAa,WAAW,CAAW,EAAG,KAAK,EAAE,WAAW,CAAC,CAAC,GACtG,KAAY,GAAQ,KAAK,MAAO,IAAI,YAAY,EAAG,OAAO,CAAU,CAAC,EAC5E,GAAI,IAAY,MACd,EAAQ,EAAkB,CAA0B,UAC3C,IAAY,QACrB,EAAU,EAAI,CAA4B,UACjC,IAAY,WACrB,EAAa,EAAI,CAA+B,MAEhD,SAAQ,KAAK,oDAAqD,EAAI,CAAO,QAExE,EAAP,CAAc,QAAQ,KAAK,kCAAmC,EAAI,CAAG,GAG7E,IACC",
8
+ "debugId": "645A69572EDFDB9764756E2164756E21",
9
9
  "names": []
10
10
  }
data/javascripts/pagy.mjs CHANGED
@@ -38,7 +38,7 @@ const Pagy = (() => {
38
38
  const initSelector = (el, [from, url_token, trimParam]) => {
39
39
  initInput(el, (inputValue) => {
40
40
  const page = Math.max(Math.ceil(from / parseInt(inputValue)), 1).toString();
41
- const url = url_token.replace(/__pagy_page__/, page).replace(/__pagy_items__/, inputValue);
41
+ const url = url_token.replace(/__pagy_page__/, page).replace(/__pagy_limit__/, inputValue);
42
42
  return [page, url];
43
43
  }, trimParam);
44
44
  };
@@ -73,7 +73,7 @@ const Pagy = (() => {
73
73
  };
74
74
  const trim = (a, param) => a.replace(new RegExp(`[?&]${param}=1\\b(?!&)|\\b${param}=1&`), "");
75
75
  return {
76
- version: "8.6.3",
76
+ version: "9.3.4",
77
77
  init(arg) {
78
78
  const target = arg instanceof Element ? arg : document;
79
79
  const elements = target.querySelectorAll("[data-pagy]");
data/lib/pagy/b64.rb ADDED
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pagy # :nodoc:
4
+ # Cheap Base64 specialized methods to avoid dependencies
5
+ module B64
6
+ module_function
7
+
8
+ def encode(bin)
9
+ [bin].pack('m0')
10
+ end
11
+
12
+ def decode(str)
13
+ str.unpack1('m0')
14
+ end
15
+
16
+ def urlsafe_encode(bin)
17
+ str = encode(bin)
18
+ str.chomp!('==') or str.chomp!('=')
19
+ str.tr!('+/', '-_')
20
+ str
21
+ end
22
+
23
+ def urlsafe_decode(str)
24
+ if !str.end_with?('=') && str.length % 4 != 0
25
+ str = str.ljust((str.length + 3) & ~3, '=')
26
+ str.tr!('-_', '+/')
27
+ else
28
+ str = str.tr('-_', '+/')
29
+ end
30
+ decode(str)
31
+ end
32
+ end
33
+ end
data/lib/pagy/backend.rb CHANGED
@@ -3,24 +3,18 @@
3
3
 
4
4
  class Pagy
5
5
  # Define a few generic methods to paginate a collection out of the box,
6
- # or any collection by overriding pagy_get_items and/or pagy_get_vars in your controller
6
+ # or any collection by overriding any of the `pagy_*` methods in your controller.
7
7
  # See also the extras if you need specialized methods to paginate Arrays or other collections
8
8
  module Backend
9
9
  private
10
10
 
11
- # Return Pagy object and paginated items/results
12
- def pagy(collection, vars = {})
13
- pagy = Pagy.new(pagy_get_vars(collection, vars))
14
- [pagy, pagy_get_items(collection, pagy)]
15
- end
16
-
17
- # Sub-method called only by #pagy: here for easy customization of variables by overriding
18
- # You may need to override the count call for non AR collections
19
- def pagy_get_vars(collection, vars)
20
- pagy_set_items_from_params(vars) if defined?(ItemsExtra)
11
+ # Return Pagy object and paginated results
12
+ def pagy(collection, **vars)
21
13
  vars[:count] ||= pagy_get_count(collection, vars)
14
+ vars[:limit] ||= pagy_get_limit(vars)
22
15
  vars[:page] ||= pagy_get_page(vars)
23
- vars
16
+ pagy = Pagy.new(**vars)
17
+ [pagy, pagy_get_items(collection, pagy)]
24
18
  end
25
19
 
26
20
  # Get the count from the collection
@@ -29,16 +23,22 @@ class Pagy
29
23
  (count = collection.count(*count_args)).is_a?(Hash) ? count.size : count
30
24
  end
31
25
 
32
- # Get the page integer from the params
33
- # Overridable by the jsonapi extra
34
- def pagy_get_page(vars)
35
- [params[vars[:page_param] || DEFAULT[:page_param]].to_i, 1].max
36
- end
37
-
38
- # Sub-method called only by #pagy: here for easy customization of record-extraction by overriding
26
+ # Sub-method called only by #pagy: here for easy customization of fetching by overriding
39
27
  # You may need to override this method for collections without offset|limit
40
28
  def pagy_get_items(collection, pagy)
41
- collection.offset(pagy.offset).limit(pagy.items)
29
+ collection.offset(pagy.offset).limit(pagy.limit)
30
+ end
31
+
32
+ # Override for limit extra
33
+ def pagy_get_limit(_vars)
34
+ DEFAULT[:limit]
35
+ end
36
+
37
+ # Get the page integer from the params
38
+ # Overridable by the jsonapi extra
39
+ def pagy_get_page(vars, force_integer: true)
40
+ page = params[vars[:page_param] || DEFAULT[:page_param]]
41
+ force_integer ? (page || 1).to_i : page
42
42
  end
43
43
  end
44
44
  end
@@ -12,8 +12,8 @@ class Pagy # :nodoc:
12
12
 
13
13
  protected
14
14
 
15
- # Setup the calendar variables
16
- def setup_unit_vars
15
+ # Set up the calendar variables
16
+ def assign_unit_vars
17
17
  super
18
18
  @initial = @starting.beginning_of_day
19
19
  @final = @ending.tomorrow.beginning_of_day
@@ -12,8 +12,8 @@ class Pagy # :nodoc:
12
12
 
13
13
  protected
14
14
 
15
- # Setup the calendar variables
16
- def setup_unit_vars
15
+ # Set up the calendar variables
16
+ def assign_unit_vars
17
17
  super
18
18
  @initial = @starting.beginning_of_month
19
19
  @final = @ending.next_month.beginning_of_month
@@ -19,8 +19,8 @@ class Pagy # :nodoc:
19
19
 
20
20
  protected
21
21
 
22
- # Setup the calendar variables
23
- def setup_unit_vars
22
+ # Set up the calendar variables
23
+ def assign_unit_vars
24
24
  super
25
25
  @initial = @starting.beginning_of_quarter
26
26
  @final = @ending.next_quarter.beginning_of_quarter