pagy 43.0.0 → 43.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/apps/calendar.ru +11 -12
- data/apps/demo.ru +5 -5
- data/apps/enable_rails_page_segment.rb +54 -0
- data/apps/index.rb +1 -1
- data/apps/keynav+root_key.ru +316 -0
- data/apps/keynav.ru +10 -13
- data/apps/keyset.ru +5 -11
- data/apps/keyset_sequel.ru +10 -12
- data/apps/rails.ru +8 -12
- data/apps/repro.ru +11 -11
- data/bin/pagy +2 -94
- data/config/pagy.rb +8 -7
- data/javascripts/ai_widget.js +65 -51
- data/javascripts/pagy.js +20 -17
- data/javascripts/pagy.js.map +3 -3
- data/javascripts/pagy.min.js +2 -1
- data/javascripts/pagy.mjs +19 -16
- data/javascripts/wand.js +15 -9
- data/lib/pagy/classes/calendar/calendar.rb +36 -31
- data/lib/pagy/classes/calendar/day.rb +1 -1
- data/lib/pagy/classes/calendar/month.rb +1 -1
- data/lib/pagy/classes/calendar/quarter.rb +1 -1
- data/lib/pagy/classes/calendar/unit.rb +12 -13
- data/lib/pagy/classes/calendar/year.rb +1 -1
- data/lib/pagy/classes/exceptions.rb +1 -8
- data/lib/pagy/classes/keyset/adapters/active_record.rb +3 -1
- data/lib/pagy/classes/keyset/adapters/sequel.rb +3 -1
- data/lib/pagy/classes/keyset/keynav.rb +9 -4
- data/lib/pagy/classes/keyset/keyset.rb +57 -32
- data/lib/pagy/classes/offset/countish.rb +17 -0
- data/lib/pagy/classes/offset/countless.rb +26 -14
- data/lib/pagy/classes/offset/offset.rb +8 -2
- data/lib/pagy/classes/offset/search.rb +6 -10
- data/lib/pagy/classes/request.rb +29 -20
- data/lib/pagy/cli.rb +135 -0
- data/lib/pagy/console.rb +6 -0
- data/lib/pagy/modules/abilities/configurable.rb +2 -2
- data/lib/pagy/modules/abilities/countable.rb +24 -0
- data/lib/pagy/modules/abilities/linkable.rb +35 -24
- data/lib/pagy/modules/abilities/rangeable.rb +3 -3
- data/lib/pagy/modules/b64.rb +9 -3
- data/lib/pagy/modules/console.rb +15 -20
- data/lib/pagy/modules/i18n/i18n.rb +38 -14
- data/lib/pagy/modules/i18n/p11n/arabic.rb +1 -0
- data/lib/pagy/modules/i18n/p11n/east_slavic.rb +1 -0
- data/lib/pagy/modules/i18n/p11n/polish.rb +1 -0
- data/lib/pagy/modules/searcher.rb +9 -8
- data/lib/pagy/toolbox/helpers/anchor_tags.rb +11 -15
- data/lib/pagy/toolbox/helpers/bootstrap/input_nav_js.rb +3 -0
- data/lib/pagy/toolbox/helpers/bootstrap/series_nav.rb +3 -1
- data/lib/pagy/toolbox/helpers/bootstrap/series_nav_js.rb +2 -0
- data/lib/pagy/toolbox/helpers/bulma/input_nav_js.rb +3 -0
- data/lib/pagy/toolbox/helpers/bulma/previous_next_html.rb +1 -1
- data/lib/pagy/toolbox/helpers/bulma/series_nav.rb +3 -1
- data/lib/pagy/toolbox/helpers/bulma/series_nav_js.rb +2 -0
- data/lib/pagy/toolbox/helpers/data_hash.rb +19 -17
- data/lib/pagy/toolbox/helpers/headers_hash.rb +15 -9
- data/lib/pagy/toolbox/helpers/info_tag.rb +2 -0
- data/lib/pagy/toolbox/helpers/input_nav_js.rb +9 -6
- data/lib/pagy/toolbox/helpers/limit_tag_js.rb +4 -3
- data/lib/pagy/toolbox/helpers/loader.rb +3 -0
- data/lib/pagy/toolbox/helpers/page_url.rb +10 -16
- data/lib/pagy/toolbox/helpers/series_nav.rb +5 -4
- data/lib/pagy/toolbox/helpers/series_nav_js.rb +2 -1
- data/lib/pagy/toolbox/helpers/support/a_lambda.rb +8 -6
- data/lib/pagy/toolbox/helpers/support/data_pagy_attribute.rb +6 -1
- data/lib/pagy/toolbox/helpers/support/series.rb +1 -2
- data/lib/pagy/toolbox/helpers/support/wrap_input_nav_js.rb +1 -1
- data/lib/pagy/toolbox/helpers/support/wrap_series_nav.rb +2 -1
- data/lib/pagy/toolbox/helpers/support/wrap_series_nav_js.rb +10 -4
- data/lib/pagy/toolbox/helpers/urls_hash.rb +7 -7
- data/lib/pagy/toolbox/paginators/calendar.rb +13 -9
- data/lib/pagy/toolbox/paginators/countish.rb +39 -0
- data/lib/pagy/toolbox/paginators/countless.rb +13 -15
- data/lib/pagy/toolbox/paginators/elasticsearch_rails.rb +43 -18
- data/lib/pagy/toolbox/paginators/keynav_js.rb +14 -15
- data/lib/pagy/toolbox/paginators/keyset.rb +7 -9
- data/lib/pagy/toolbox/paginators/meilisearch.rb +21 -18
- data/lib/pagy/toolbox/paginators/method.rb +15 -3
- data/lib/pagy/toolbox/paginators/offset.rb +14 -22
- data/lib/pagy/toolbox/paginators/searchkick.rb +21 -18
- data/lib/pagy/toolbox/paginators/typesense_rails.rb +35 -0
- data/lib/pagy.rb +23 -10
- data/locales/id.yml +1 -3
- data/locales/ja.yml +1 -3
- data/locales/km.yml +1 -3
- data/locales/sw.yml +2 -2
- data/locales/tr.yml +10 -8
- data/stylesheets/pagy-tailwind.css +1 -1
- data/stylesheets/pagy.css +1 -6
- metadata +25 -8
- data/lib/optimist.rb +0 -1022
- data/lib/pagy/classes/keyset/active_record.rb +0 -11
- data/lib/pagy/classes/keyset/keynav/active_record.rb +0 -13
- data/lib/pagy/classes/keyset/keynav/sequel.rb +0 -13
- data/lib/pagy/classes/keyset/sequel.rb +0 -11
data/apps/keyset_sequel.ru
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
# URL
|
|
17
17
|
# http://127.0.0.1:8000
|
|
18
18
|
|
|
19
|
-
VERSION = '43.
|
|
19
|
+
VERSION = '43.3.0'
|
|
20
20
|
|
|
21
21
|
if VERSION != Pagy::VERSION
|
|
22
22
|
Warning.warn("\n>>> WARNING! '#{File.basename(__FILE__)}-#{VERSION}' running with 'pagy-#{Pagy::VERSION}'! <<< \n\n")
|
|
@@ -41,7 +41,7 @@ class PagyKeysetSequel < Sinatra::Base
|
|
|
41
41
|
|
|
42
42
|
# Root route/action
|
|
43
43
|
get '/' do
|
|
44
|
-
@order = { animal: :asc, name: :asc, birthdate: :desc, id: :asc }
|
|
44
|
+
@order = { animal: :asc, name: :asc, birthdate: :desc, id: :asc }.freeze
|
|
45
45
|
@pagy, @pets = pagy(:keyset, Pet.order(:animal, :name, Sequel.desc(:birthdate), :id),
|
|
46
46
|
limit: 10, client_max_limit: 100)
|
|
47
47
|
erb :main
|
|
@@ -58,14 +58,13 @@ class PagyKeysetSequel < Sinatra::Base
|
|
|
58
58
|
<<~ERB
|
|
59
59
|
<!DOCTYPE html>
|
|
60
60
|
<html lang="en">
|
|
61
|
-
<html>
|
|
62
61
|
<head>
|
|
63
|
-
|
|
62
|
+
<title>Pagy Keyset App</title>
|
|
64
63
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
65
64
|
<style type="text/css">
|
|
66
65
|
@media screen { html, body {
|
|
67
66
|
font-size: 1rem;
|
|
68
|
-
line-height: 1.
|
|
67
|
+
line-height: 1.2;
|
|
69
68
|
padding: 0;
|
|
70
69
|
margin: 0;
|
|
71
70
|
} }
|
|
@@ -121,7 +120,6 @@ class PagyKeysetSequel < Sinatra::Base
|
|
|
121
120
|
<% end %>
|
|
122
121
|
</table>
|
|
123
122
|
</div>
|
|
124
|
-
<p>
|
|
125
123
|
<nav class="pagy" id="next" aria-label="Pagy next">
|
|
126
124
|
<%= @pagy.next_tag(text: 'Next page >') %>
|
|
127
125
|
</nav>
|
|
@@ -133,14 +131,14 @@ end
|
|
|
133
131
|
# Sequel setup
|
|
134
132
|
require 'sequel'
|
|
135
133
|
Sequel.default_timezone = :utc
|
|
136
|
-
# SQLite DB files
|
|
137
|
-
dir = ENV['APP_ENV'].equal?('development') ? '.' : Dir.pwd # app dir in dev or pwd otherwise
|
|
138
|
-
abort "ERROR: Cannot create DB files: the directory #{dir.inspect} is not writable." \
|
|
139
|
-
unless File.writable?(dir)
|
|
140
134
|
# Connection
|
|
141
135
|
output = ENV['APP_ENV'].equal?('showcase') ? IO::NULL : $stdout
|
|
142
|
-
|
|
143
|
-
|
|
136
|
+
# Use 'sqlite' adapter (Sequel uses 'sqlite', AR uses 'sqlite3')
|
|
137
|
+
# Use the same shared memory URI string for the database
|
|
138
|
+
DB = Sequel.connect(adapter: 'sqlite',
|
|
139
|
+
database: 'file:memdb1?mode=memory&cache=shared',
|
|
140
|
+
max_connections: 10,
|
|
141
|
+
loggers: [Logger.new(output)])
|
|
144
142
|
# Schema
|
|
145
143
|
DB.create_table! :pets do
|
|
146
144
|
primary_key :id
|
data/apps/rails.ru
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
# URL
|
|
17
17
|
# http://127.0.0.1:8000
|
|
18
18
|
|
|
19
|
-
VERSION = '43.
|
|
19
|
+
VERSION = '43.3.0'
|
|
20
20
|
|
|
21
21
|
if VERSION != Pagy::VERSION
|
|
22
22
|
Warning.warn("\n>>> WARNING! '#{File.basename(__FILE__)}-#{VERSION}' running with 'pagy-#{Pagy::VERSION}'! <<< \n\n")
|
|
@@ -47,22 +47,19 @@ class PagyRails < Rails::Application # :nodoc:
|
|
|
47
47
|
config.logger = Logger.new(OUTPUT)
|
|
48
48
|
Rails.logger = config.logger
|
|
49
49
|
|
|
50
|
+
# Pagy initializer
|
|
51
|
+
# require Pagy::ROOT.join('apps/enable_rails_page_segment.rb') # Uncomment to test the enable_rails_page_segment.rb override
|
|
52
|
+
|
|
50
53
|
routes.draw do
|
|
51
54
|
root to: 'comments#index'
|
|
55
|
+
# get '/comments(/:page)', to: 'comments#index' # Uncomment to test the enable_rails_page_segment.rb override
|
|
52
56
|
get '/javascripts/:file', to: 'pagy#javascripts', file: /.*/
|
|
53
57
|
end
|
|
54
58
|
end
|
|
55
59
|
|
|
56
|
-
# AR config
|
|
57
|
-
dir = Rails.env.development? ? '.' : Dir.pwd # app dir in dev or pwd otherwise
|
|
58
|
-
unless File.writable?(dir)
|
|
59
|
-
warn "ERROR: directory #{dir.inspect} is not writable (the pagy-rails-app needs to create DB files)"
|
|
60
|
-
exit 1
|
|
61
|
-
end
|
|
62
|
-
|
|
63
60
|
# Activerecord initializer
|
|
64
61
|
ActiveRecord::Base.logger = Logger.new(OUTPUT)
|
|
65
|
-
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database:
|
|
62
|
+
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'file:memdb1?mode=memory&cache=shared')
|
|
66
63
|
ActiveRecord::Schema.define do
|
|
67
64
|
create_table :posts, force: true do |t|
|
|
68
65
|
t.string :title
|
|
@@ -129,9 +126,8 @@ run PagyRails
|
|
|
129
126
|
TEMPLATE = <<~ERB
|
|
130
127
|
<!DOCTYPE html>
|
|
131
128
|
<html lang="en">
|
|
132
|
-
<html>
|
|
133
129
|
<head>
|
|
134
|
-
|
|
130
|
+
<title>Pagy Rails App</title>
|
|
135
131
|
<script src="/javascripts/pagy.js"></script>
|
|
136
132
|
<script>
|
|
137
133
|
window.addEventListener("load", Pagy.init);
|
|
@@ -140,7 +136,7 @@ TEMPLATE = <<~ERB
|
|
|
140
136
|
<style type="text/css">
|
|
141
137
|
@media screen { html, body {
|
|
142
138
|
font-size: 1rem;
|
|
143
|
-
line-height: 1.
|
|
139
|
+
line-height: 1.2;
|
|
144
140
|
padding: 0;
|
|
145
141
|
margin: 0;
|
|
146
142
|
} }
|
data/apps/repro.ru
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
# URL
|
|
17
17
|
# http://127.0.0.1:8000
|
|
18
18
|
|
|
19
|
-
VERSION = '43.
|
|
19
|
+
VERSION = '43.3.0'
|
|
20
20
|
|
|
21
21
|
if VERSION != Pagy::VERSION
|
|
22
22
|
Warning.warn("\n>>> WARNING! '#{File.basename(__FILE__)}-#{VERSION}' running with 'pagy-#{Pagy::VERSION}'! <<< \n\n")
|
|
@@ -34,7 +34,7 @@ end
|
|
|
34
34
|
|
|
35
35
|
# Edit this section adding the legacy as needed
|
|
36
36
|
# Pagy initializer
|
|
37
|
-
Pagy
|
|
37
|
+
Pagy::OPTIONS[:client_max_limit] = 100
|
|
38
38
|
|
|
39
39
|
# Sinatra setup
|
|
40
40
|
require 'sinatra/base'
|
|
@@ -55,8 +55,9 @@ class PagyRepro < Sinatra::Base
|
|
|
55
55
|
# Edit this action as needed
|
|
56
56
|
get '/' do
|
|
57
57
|
collection = MockCollection.new
|
|
58
|
-
@pagy, @records = pagy(collection)
|
|
58
|
+
@pagy, @records = pagy(collection) # simplest form
|
|
59
59
|
# @pagy, @records = pagy(:offset, collection, limit: 7, client_max_limit: 30)
|
|
60
|
+
# @pagy, @records = pagy(:countish, collection, ttl: 20)
|
|
60
61
|
# @pagy, @records = pagy(:countless, collection)
|
|
61
62
|
# @pagy, @records = pagy(Array(1..1000))
|
|
62
63
|
# response.headers.merge!(@pagy.headers_hash)
|
|
@@ -68,9 +69,8 @@ class PagyRepro < Sinatra::Base
|
|
|
68
69
|
<<~ERB
|
|
69
70
|
<!DOCTYPE html>
|
|
70
71
|
<html lang="en">
|
|
71
|
-
<html>
|
|
72
72
|
<head>
|
|
73
|
-
|
|
73
|
+
<title>Pagy Repro App</title>
|
|
74
74
|
<script src="javascripts/pagy.js"></script>
|
|
75
75
|
<script>
|
|
76
76
|
window.addEventListener("load", Pagy.init);
|
|
@@ -79,7 +79,7 @@ class PagyRepro < Sinatra::Base
|
|
|
79
79
|
<style type="text/css">
|
|
80
80
|
@media screen { html, body {
|
|
81
81
|
font-size: 1rem;
|
|
82
|
-
line-height: 1.
|
|
82
|
+
line-height: 1.2;
|
|
83
83
|
padding: 0;
|
|
84
84
|
margin: 0;
|
|
85
85
|
} }
|
|
@@ -123,7 +123,7 @@ class PagyRepro < Sinatra::Base
|
|
|
123
123
|
<h1>Pagy Repro App</h1>
|
|
124
124
|
<p> Self-contained, standalone app usable to easily reproduce any pagy issue.</p>
|
|
125
125
|
|
|
126
|
-
<h2>Versions</
|
|
126
|
+
<h2>Versions</h2>
|
|
127
127
|
<ul>
|
|
128
128
|
<li>Ruby: <%= RUBY_VERSION %></li>
|
|
129
129
|
<li>Rack: <%= Rack::RELEASE %></li>
|
|
@@ -142,7 +142,7 @@ class PagyRepro < Sinatra::Base
|
|
|
142
142
|
|
|
143
143
|
<h4>@pagy.series_nav_js (responsive)</h4>
|
|
144
144
|
<%= @pagy.series_nav_js(id: 'series-nav-js-responsive',
|
|
145
|
-
aria_label: 'Pages
|
|
145
|
+
aria_label: 'Pages nav_js_responsive',
|
|
146
146
|
steps: { 0 => 5, 500 => 7, 600 => 9, 700 => 11 }) %>
|
|
147
147
|
|
|
148
148
|
<h4>@pagy.input_nav_js</h4>
|
|
@@ -160,7 +160,7 @@ class PagyRepro < Sinatra::Base
|
|
|
160
160
|
end
|
|
161
161
|
|
|
162
162
|
# Simple array-based collection that acts as a standard DB collection.
|
|
163
|
-
# Use it as a simple way to get a collection that acts as
|
|
163
|
+
# Use it as a simple way to get a collection that acts as an AR scope, but without any DB
|
|
164
164
|
# or create an ActiveRecord class or anything else that you need instead
|
|
165
165
|
class MockCollection < Array
|
|
166
166
|
def initialize(arr = Array(1..1000))
|
|
@@ -169,12 +169,12 @@ class MockCollection < Array
|
|
|
169
169
|
end
|
|
170
170
|
|
|
171
171
|
def offset(value)
|
|
172
|
-
@collection = self[value..]
|
|
172
|
+
@collection = self[value..] || []
|
|
173
173
|
self
|
|
174
174
|
end
|
|
175
175
|
|
|
176
176
|
def limit(value)
|
|
177
|
-
@collection[0, value]
|
|
177
|
+
@collection.empty? ? [] : @collection[0, value]
|
|
178
178
|
end
|
|
179
179
|
|
|
180
180
|
def count(*)
|
data/bin/pagy
CHANGED
|
@@ -1,97 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
HOST = 'localhost'
|
|
7
|
-
PORT = '8000'
|
|
8
|
-
|
|
9
|
-
require_relative '../lib/optimist'
|
|
10
|
-
require_relative '../lib/pagy'
|
|
11
|
-
require_relative '../apps/index'
|
|
12
|
-
|
|
13
|
-
apps = PagyApps::INDEX
|
|
14
|
-
opts = Optimist.options do
|
|
15
|
-
text <<~HEAD
|
|
16
|
-
Pagy #{VERSION} (https://ddnexus.github.io/pagy/playground)
|
|
17
|
-
Playground to showcase, clone and develop pagy APPs
|
|
18
|
-
APPs
|
|
19
|
-
#{ apps.map do |name, path|
|
|
20
|
-
" #{name}#{' ' * (18 - name.length)}#{File.readlines(path)[3].sub('# ', '').strip}"
|
|
21
|
-
end.join("\n") }
|
|
22
|
-
USAGE
|
|
23
|
-
pagy APP [opts] Showcase APP from the installed gem
|
|
24
|
-
pagy clone APP Clone APP to the current dir
|
|
25
|
-
pagy FILE [opts] Develop app FILE from local path
|
|
26
|
-
EXAMPLES
|
|
27
|
-
pagy demo Showcase demo at http://#{HOST}:#{PORT}
|
|
28
|
-
pagy clone repro Clone repro to ./repro.ru (rename it)
|
|
29
|
-
pagy ~/myapp.ru Develop ~/myapp.ru at #{HOST}:#{PORT}
|
|
30
|
-
HEAD
|
|
31
|
-
text 'Rackup options'
|
|
32
|
-
opt :env, 'Environment', default: 'development'
|
|
33
|
-
opt :host, 'Host', default: HOST, short: :o
|
|
34
|
-
opt :port, 'Port', default: PORT
|
|
35
|
-
if LINUX
|
|
36
|
-
text 'Rerun options'
|
|
37
|
-
opt :rerun, 'Enable rerun for development'
|
|
38
|
-
opt :clear, 'Clear screen before each rerun'
|
|
39
|
-
end
|
|
40
|
-
text 'Other options'
|
|
41
|
-
opt :quiet, 'Quiet mode for development'
|
|
42
|
-
version VERSION
|
|
43
|
-
end
|
|
44
|
-
Optimist.educate if ARGV.empty?
|
|
45
|
-
|
|
46
|
-
run_from_repo = Pagy::ROOT.join('pagy.gemspec').exist?
|
|
47
|
-
|
|
48
|
-
# Bundle
|
|
49
|
-
require 'bundler/inline'
|
|
50
|
-
gemfile(!run_from_repo) do
|
|
51
|
-
source 'https://rubygems.org'
|
|
52
|
-
gem 'logger'
|
|
53
|
-
gem 'rackup'
|
|
54
|
-
gem 'rerun' if LINUX
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
arg = ARGV.shift
|
|
58
|
-
if arg.eql?('clone')
|
|
59
|
-
name = ARGV.shift
|
|
60
|
-
Optimist.die("Expected APP to be in [#{apps.keys.join(', ')}]; got #{name.inspect}") unless apps.key?(name)
|
|
61
|
-
if File.exist?(name)
|
|
62
|
-
print "Do you want to overwrite the #{name.inspect} file? (y/n)> "
|
|
63
|
-
answer = gets.chomp
|
|
64
|
-
Optimist.die("#{name.inspect} file already present") unless answer.start_with?(/y/i)
|
|
65
|
-
end
|
|
66
|
-
require 'fileutils'
|
|
67
|
-
FileUtils.cp(apps[name], '.', verbose: true)
|
|
68
|
-
else
|
|
69
|
-
if apps.key?(arg) # showcase env
|
|
70
|
-
opts[:env] = 'showcase'
|
|
71
|
-
opts[:rerun] = false
|
|
72
|
-
opts[:quiet] = true
|
|
73
|
-
# Avoid the creation of './tmp/local_secret.txt' for showcase env
|
|
74
|
-
ENV['SECRET_KEY_BASE'] = 'absolute secret!' if arg.eql?('rails')
|
|
75
|
-
file = apps[arg]
|
|
76
|
-
else # development env
|
|
77
|
-
file = arg
|
|
78
|
-
end
|
|
79
|
-
Optimist.die("#{file.inspect} app not found") unless File.exist?(file)
|
|
80
|
-
# Run command
|
|
81
|
-
gem_dir = File.expand_path('..', __dir__)
|
|
82
|
-
rackup = "rackup -I #{gem_dir}/lib -r pagy -o #{opts[:host]} -p #{opts[:port]} -E #{opts[:env]} #{file}"
|
|
83
|
-
rackup << ' -q' if opts[:quiet]
|
|
84
|
-
if opts[:rerun]
|
|
85
|
-
name = File.basename(file)
|
|
86
|
-
dir = File.dirname(file)
|
|
87
|
-
rerun = if run_from_repo # rerun app also when gem dir files change (for pagy devs)
|
|
88
|
-
"rerun --name #{name} -d #{dir},#{gem_dir} -p **/*.{rb,js,css,scss,ru,yml}"
|
|
89
|
-
else
|
|
90
|
-
"rerun --name #{name} -d #{dir} -p #{name}" # rerun only when app.ru changes
|
|
91
|
-
end
|
|
92
|
-
rerun << ' -q' if opts[:quiet]
|
|
93
|
-
rerun << ' -c' if opts[:clear]
|
|
94
|
-
rerun << " -- #{rackup}"
|
|
95
|
-
end
|
|
96
|
-
exec(rerun || rackup)
|
|
97
|
-
end
|
|
4
|
+
require_relative '../lib/pagy/cli'
|
|
5
|
+
Pagy::CLI.new.start
|
data/config/pagy.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# Pagy initializer file (43.
|
|
3
|
+
# Pagy initializer file (43.3.0)
|
|
4
4
|
# See https://ddnexus.github.io/pagy/resources/initializer/
|
|
5
5
|
|
|
6
6
|
############ Global Options ################################################################
|
|
@@ -8,11 +8,12 @@
|
|
|
8
8
|
# Add your global options below. They will be applied globally.
|
|
9
9
|
# For example:
|
|
10
10
|
#
|
|
11
|
-
# Pagy
|
|
12
|
-
# Pagy
|
|
13
|
-
# Pagy
|
|
14
|
-
# Pagy
|
|
11
|
+
# Pagy::OPTIONS[:limit] = 10 # Limit the items per page
|
|
12
|
+
# Pagy::OPTIONS[:client_max_limit] = 100 # The client can request a limit up to 100
|
|
13
|
+
# Pagy::OPTIONS[:max_pages] = 200 # Allow only 200 pages
|
|
14
|
+
# Pagy::OPTIONS[:jsonapi] = true # Use JSON:API compliant URLs
|
|
15
15
|
|
|
16
|
+
Pagy::OPTIONS.freeze
|
|
16
17
|
|
|
17
18
|
############ JavaScript ####################################################################
|
|
18
19
|
# See https://ddnexus.github.io/pagy/resources/javascript/ for details.
|
|
@@ -27,10 +28,10 @@
|
|
|
27
28
|
|
|
28
29
|
############# Overriding Pagy::I18n Lookup #################################################
|
|
29
30
|
# Refer to https://ddnexus.github.io/pagy/resources/i18n/ for details.
|
|
30
|
-
# Override the
|
|
31
|
+
# Override the I18n lookup by dropping your custom dictionary in some pagy dir.
|
|
31
32
|
# Example for Rails:
|
|
32
33
|
#
|
|
33
|
-
# Pagy::I18n.pathnames << Rails.root.join('config/locales')
|
|
34
|
+
# Pagy::I18n.pathnames << Rails.root.join('config/locales/pagy')
|
|
34
35
|
|
|
35
36
|
|
|
36
37
|
############# I18n Gem Translation #########################################################
|
data/javascripts/ai_widget.js
CHANGED
|
@@ -1,23 +1,63 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
const PagyAIWidget = {
|
|
2
|
+
HOST_ID: 'gurubase-chat-widget-container',
|
|
3
|
+
IMG_SELECTOR: '#chatWindow > div.anteon-header > div > img',
|
|
4
|
+
NAME_SELECTOR: '#chatWindow > div.anteon-header > div > span',
|
|
5
|
+
DESCRIPTION_SELECTOR: '#chatWindow > div.chat-messages > div > p',
|
|
6
|
+
NEW_IMG_SIZE: '40px',
|
|
7
|
+
NEW_NAME: 'Ask Pagy AI',
|
|
8
|
+
NEW_DESCRIPTION: 'Pagy AI uses the latest data in the documentation to answer your questions.',
|
|
9
|
+
ICON_URL: 'https://github.com/ddnexus/pagy/blob/master/assets/images/pagy-the-frog.png?raw=true',
|
|
10
|
+
skipTurbo: true,
|
|
11
|
+
|
|
12
|
+
checkAndEdit: function() {
|
|
13
|
+
const hostElement = document.getElementById(this.HOST_ID);
|
|
14
|
+
if (hostElement && hostElement.shadowRoot) {
|
|
15
|
+
const shadowRoot = hostElement.shadowRoot;
|
|
16
|
+
const img = shadowRoot.querySelector(this.IMG_SELECTOR);
|
|
17
|
+
const name = shadowRoot.querySelector(this.NAME_SELECTOR);
|
|
18
|
+
const description = shadowRoot.querySelector(this.DESCRIPTION_SELECTOR);
|
|
19
|
+
|
|
20
|
+
if (img) {
|
|
21
|
+
img.style.maxWidth = this.NEW_IMG_SIZE;
|
|
22
|
+
img.style.maxHeight = this.NEW_IMG_SIZE;
|
|
23
|
+
}
|
|
24
|
+
if (name) {
|
|
25
|
+
name.textContent = this.NEW_NAME;
|
|
26
|
+
}
|
|
27
|
+
if (description) {
|
|
28
|
+
description.textContent = this.NEW_DESCRIPTION;
|
|
29
|
+
}
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
attemptEditing: function() {
|
|
36
|
+
if (this.checkAndEdit()) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
setTimeout(() => this.attemptEditing(), 200);
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
editChatWidget: function() {
|
|
43
|
+
this.attemptEditing();
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
appendWidgetScript: function() {
|
|
3
47
|
const script = document.createElement('script');
|
|
4
48
|
const hostname = window.location.hostname;
|
|
5
|
-
|
|
6
|
-
const iconURL = 'https://github.com/ddnexus/pagy/blob/master-pre/assets/images/pagy-the-frog.png?raw=true'
|
|
49
|
+
|
|
7
50
|
switch (hostname) {
|
|
8
51
|
case 'ddnexus.github.io': // remote docs
|
|
9
|
-
|
|
10
|
-
script.dataset.widgetId = 'mH2nvQJ1iOq_Ei6ZE9ep4g-YNTHjrwZS7Cif-8uYjx4'; // pre
|
|
52
|
+
script.dataset.widgetId = 'HKtFSPZLGiAXOdBWS4rSAxEkqv8czIbJoQdMEwCqgEc';
|
|
11
53
|
script.dataset.margins = '{"bottom": "1.48rem", "right": "6rem"}';
|
|
12
54
|
break;
|
|
13
55
|
case 'localhost': // local docs
|
|
14
|
-
|
|
15
|
-
script.dataset.widgetId = 's6flQNakiWudQCus-Z2q_8iiUSIbRm60lm2d4pc93jM'; // pre
|
|
56
|
+
script.dataset.widgetId = 'djgBhRlpdH8b07oj0Gsaerz69Xfs0FXMuUluyOo2iR4';
|
|
16
57
|
script.dataset.margins = '{"bottom": "1.48rem", "right": "6rem"}';
|
|
17
58
|
break;
|
|
18
59
|
case '127.0.0.1': // apps
|
|
19
|
-
|
|
20
|
-
script.dataset.widgetId = 'PRTyyLAaXm1rsVnGNA964gO-iI3bRaNx7-rrcvb2ECk'; // pre
|
|
60
|
+
script.dataset.widgetId = '_rXLissYyqe-dJ9vGGGXzmJwavoW0GvuzQPEq5BZjP8';
|
|
21
61
|
break;
|
|
22
62
|
default:
|
|
23
63
|
console.error('Pagy AI - Unknown hostname: ', hostname);
|
|
@@ -25,52 +65,26 @@
|
|
|
25
65
|
script.async = true;
|
|
26
66
|
script.src = 'https://widget.gurubase.io/widget.latest.min.js';
|
|
27
67
|
script.id = 'guru-widget-id';
|
|
28
|
-
script.dataset.iconUrl =
|
|
68
|
+
script.dataset.iconUrl = this.ICON_URL;
|
|
29
69
|
script.dataset.text = 'Pagy AI';
|
|
30
70
|
script.dataset.bgColor = '#1f7a1f';
|
|
31
|
-
script.dataset.lightMode = '
|
|
71
|
+
script.dataset.lightMode = 'auto';
|
|
32
72
|
script.dataset.tooltipSide = 'bottom';
|
|
33
73
|
document.head.appendChild(script);
|
|
34
74
|
}
|
|
35
|
-
|
|
75
|
+
};
|
|
36
76
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
descriptionSelector = '#chatWindow > div.chat-messages > div > p',
|
|
42
|
-
newImgSize = '40px',
|
|
43
|
-
newName = 'Ask Pagy AI',
|
|
44
|
-
newDescription = 'Pagy AI uses the latest data in the documentation to answer your questions.';
|
|
77
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
78
|
+
PagyAIWidget.appendWidgetScript();
|
|
79
|
+
PagyAIWidget.editChatWidget();
|
|
80
|
+
});
|
|
45
81
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (img) {
|
|
54
|
-
img.style.maxWidth = newImgSize;
|
|
55
|
-
img.style.maxHeight = newImgSize;
|
|
56
|
-
}
|
|
57
|
-
if (name) {
|
|
58
|
-
name.textContent = newName;
|
|
59
|
-
}
|
|
60
|
-
if (description) {
|
|
61
|
-
description.textContent = newDescription;
|
|
62
|
-
}
|
|
63
|
-
return true;
|
|
64
|
-
}
|
|
65
|
-
return false;
|
|
66
|
-
};
|
|
67
|
-
const attemptEditing = () => {
|
|
68
|
-
if (checkAndEdit()) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
setTimeout(attemptEditing, 200);
|
|
72
|
-
};
|
|
73
|
-
attemptEditing();
|
|
82
|
+
document.addEventListener("turbo:load", () => {
|
|
83
|
+
// skip only the first time (already done by DOMContentLoaded)
|
|
84
|
+
if (PagyAIWidget.skipTurbo) {
|
|
85
|
+
PagyAIWidget.skipTurbo = false;
|
|
86
|
+
} else {
|
|
87
|
+
window.chatWidget = new ChatWidget();
|
|
88
|
+
PagyAIWidget.editChatWidget();
|
|
74
89
|
}
|
|
75
|
-
|
|
76
|
-
}
|
|
90
|
+
});
|
data/javascripts/pagy.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// pagy.ts
|
|
2
2
|
window.Pagy = (() => {
|
|
3
|
-
const storageSupport = "sessionStorage" in window && "BroadcastChannel" in window
|
|
3
|
+
const storageSupport = "sessionStorage" in window && "BroadcastChannel" in window;
|
|
4
4
|
let pagy = "pagy", storage, sync, tabId;
|
|
5
5
|
if (storageSupport) {
|
|
6
6
|
storage = sessionStorage;
|
|
@@ -24,18 +24,18 @@ window.Pagy = (() => {
|
|
|
24
24
|
}));
|
|
25
25
|
const B64SafeEncode = (unicode) => btoa(String.fromCharCode(...new TextEncoder().encode(unicode))).replace(/[+/=]/g, (m) => m == "+" ? "-" : m == "/" ? "_" : ""), B64Decode = (base64) => new TextDecoder().decode(Uint8Array.from(atob(base64), (c) => c.charCodeAt(0)));
|
|
26
26
|
const randKey = () => Math.floor(Math.random() * 36 ** 3).toString(36);
|
|
27
|
-
const augmentKeynav = async (nav, [storageKey, pageKey, last, spliceArgs]) => {
|
|
28
|
-
let
|
|
27
|
+
const augmentKeynav = async (nav, [storageKey, rootKey, pageKey, last, spliceArgs]) => {
|
|
28
|
+
let augmentPage;
|
|
29
29
|
const browserKey = document.cookie.split(/;\s+/).find((row) => row.startsWith(pagy + "="))?.split("=")[1] ?? randKey();
|
|
30
30
|
document.cookie = pagy + "=" + browserKey;
|
|
31
31
|
if (storageKey && !(storageKey in storage)) {
|
|
32
32
|
sync.postMessage({ from: tabId, key: storageKey });
|
|
33
33
|
await new Promise((resolve) => setTimeout(() => resolve(""), 100));
|
|
34
34
|
if (!(storageKey in storage)) {
|
|
35
|
-
|
|
35
|
+
augmentPage = (page) => page + "+" + last;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
-
if (!
|
|
38
|
+
if (!augmentPage) {
|
|
39
39
|
if (!storageKey) {
|
|
40
40
|
do {
|
|
41
41
|
storageKey = randKey();
|
|
@@ -46,7 +46,7 @@ window.Pagy = (() => {
|
|
|
46
46
|
cutoffs.splice(...spliceArgs);
|
|
47
47
|
storage.setItem(storageKey, JSON.stringify(cutoffs));
|
|
48
48
|
}
|
|
49
|
-
|
|
49
|
+
augmentPage = (page) => {
|
|
50
50
|
const pageNum = parseInt(page);
|
|
51
51
|
return B64SafeEncode(JSON.stringify([
|
|
52
52
|
browserKey,
|
|
@@ -58,14 +58,16 @@ window.Pagy = (() => {
|
|
|
58
58
|
]));
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
|
+
const search = rootKey ? `${rootKey}%5B${pageKey}%5D` : pageKey;
|
|
62
|
+
const re = new RegExp(`(?<=\\?.*)(\\b${search}=)(\\d+)`);
|
|
61
63
|
for (const a of nav.querySelectorAll("a[href]")) {
|
|
62
|
-
|
|
63
|
-
a.href = url.replace(re, pageKey + "=" + augment(url.match(re)[1]));
|
|
64
|
+
a.href = a.href.replace(re, (_match, prefix, digit) => `${prefix}${augmentPage(digit)}`);
|
|
64
65
|
}
|
|
65
|
-
return
|
|
66
|
+
return augmentPage;
|
|
66
67
|
};
|
|
67
68
|
const buildNavJs = (nav, [
|
|
68
69
|
[before, anchor, current, gap, after],
|
|
70
|
+
pageToken,
|
|
69
71
|
[widths, series, labels],
|
|
70
72
|
keynavArgs
|
|
71
73
|
]) => {
|
|
@@ -78,7 +80,7 @@ window.Pagy = (() => {
|
|
|
78
80
|
}
|
|
79
81
|
let html = before;
|
|
80
82
|
series[index].forEach((item, i) => {
|
|
81
|
-
html += item == "gap" ? gap : (typeof item == "number" ? anchor.replace(
|
|
83
|
+
html += item == "gap" ? gap : (typeof item == "number" ? anchor.replace(pageToken, item) : current).replace("L<", labels?.[index][i] ?? item + "<");
|
|
82
84
|
});
|
|
83
85
|
html += after;
|
|
84
86
|
nav.innerHTML = "";
|
|
@@ -92,13 +94,13 @@ window.Pagy = (() => {
|
|
|
92
94
|
rjsObserver.observe(parent);
|
|
93
95
|
}
|
|
94
96
|
};
|
|
95
|
-
const initInputNavJs = async (nav, [url_token, keynavArgs]) => {
|
|
97
|
+
const initInputNavJs = async (nav, [url_token, pageToken, keynavArgs]) => {
|
|
96
98
|
const augment = keynavArgs && storageSupport ? await augmentKeynav(nav, keynavArgs) : (page) => page;
|
|
97
|
-
initInput(nav, (inputValue) => url_token.replace(
|
|
99
|
+
initInput(nav, (inputValue) => url_token.replace(pageToken, augment(inputValue)));
|
|
98
100
|
};
|
|
99
|
-
const initLimitTagJs = (span, [from, url_token]) => {
|
|
101
|
+
const initLimitTagJs = (span, [from, url_token, page_token, limitToken]) => {
|
|
100
102
|
initInput(span, (inputValue) => {
|
|
101
|
-
return url_token.replace(
|
|
103
|
+
return url_token.replace(page_token, Math.max(Math.ceil(from / parseInt(inputValue)), 1)).replace(limitToken, inputValue);
|
|
102
104
|
});
|
|
103
105
|
};
|
|
104
106
|
const initInput = (element, getUrl) => {
|
|
@@ -124,7 +126,7 @@ window.Pagy = (() => {
|
|
|
124
126
|
});
|
|
125
127
|
};
|
|
126
128
|
return {
|
|
127
|
-
version: "43.
|
|
129
|
+
version: "43.3.0",
|
|
128
130
|
init(arg) {
|
|
129
131
|
const target = arg instanceof HTMLElement ? arg : document, elements = target.querySelectorAll("[data-pagy]");
|
|
130
132
|
for (const element of elements) {
|
|
@@ -140,12 +142,13 @@ window.Pagy = (() => {
|
|
|
140
142
|
initLimitTagJs(element, args);
|
|
141
143
|
}
|
|
142
144
|
} catch (err) {
|
|
143
|
-
console.warn(
|
|
145
|
+
console.warn(`Pagy.init: %o
|
|
146
|
+
%s`, element, err);
|
|
144
147
|
}
|
|
145
148
|
}
|
|
146
149
|
}
|
|
147
150
|
};
|
|
148
151
|
})();
|
|
149
152
|
|
|
150
|
-
//# debugId=
|
|
153
|
+
//# debugId=975696F2DDC5F9D164756E2164756E21
|
|
151
154
|
//# sourceMappingURL=pagy.js.map
|