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.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/apps/calendar.ru +11 -12
  4. data/apps/demo.ru +5 -5
  5. data/apps/enable_rails_page_segment.rb +54 -0
  6. data/apps/index.rb +1 -1
  7. data/apps/keynav+root_key.ru +316 -0
  8. data/apps/keynav.ru +10 -13
  9. data/apps/keyset.ru +5 -11
  10. data/apps/keyset_sequel.ru +10 -12
  11. data/apps/rails.ru +8 -12
  12. data/apps/repro.ru +11 -11
  13. data/bin/pagy +2 -94
  14. data/config/pagy.rb +8 -7
  15. data/javascripts/ai_widget.js +65 -51
  16. data/javascripts/pagy.js +20 -17
  17. data/javascripts/pagy.js.map +3 -3
  18. data/javascripts/pagy.min.js +2 -1
  19. data/javascripts/pagy.mjs +19 -16
  20. data/javascripts/wand.js +15 -9
  21. data/lib/pagy/classes/calendar/calendar.rb +36 -31
  22. data/lib/pagy/classes/calendar/day.rb +1 -1
  23. data/lib/pagy/classes/calendar/month.rb +1 -1
  24. data/lib/pagy/classes/calendar/quarter.rb +1 -1
  25. data/lib/pagy/classes/calendar/unit.rb +12 -13
  26. data/lib/pagy/classes/calendar/year.rb +1 -1
  27. data/lib/pagy/classes/exceptions.rb +1 -8
  28. data/lib/pagy/classes/keyset/adapters/active_record.rb +3 -1
  29. data/lib/pagy/classes/keyset/adapters/sequel.rb +3 -1
  30. data/lib/pagy/classes/keyset/keynav.rb +9 -4
  31. data/lib/pagy/classes/keyset/keyset.rb +57 -32
  32. data/lib/pagy/classes/offset/countish.rb +17 -0
  33. data/lib/pagy/classes/offset/countless.rb +26 -14
  34. data/lib/pagy/classes/offset/offset.rb +8 -2
  35. data/lib/pagy/classes/offset/search.rb +6 -10
  36. data/lib/pagy/classes/request.rb +29 -20
  37. data/lib/pagy/cli.rb +135 -0
  38. data/lib/pagy/console.rb +6 -0
  39. data/lib/pagy/modules/abilities/configurable.rb +2 -2
  40. data/lib/pagy/modules/abilities/countable.rb +24 -0
  41. data/lib/pagy/modules/abilities/linkable.rb +35 -24
  42. data/lib/pagy/modules/abilities/rangeable.rb +3 -3
  43. data/lib/pagy/modules/b64.rb +9 -3
  44. data/lib/pagy/modules/console.rb +15 -20
  45. data/lib/pagy/modules/i18n/i18n.rb +38 -14
  46. data/lib/pagy/modules/i18n/p11n/arabic.rb +1 -0
  47. data/lib/pagy/modules/i18n/p11n/east_slavic.rb +1 -0
  48. data/lib/pagy/modules/i18n/p11n/polish.rb +1 -0
  49. data/lib/pagy/modules/searcher.rb +9 -8
  50. data/lib/pagy/toolbox/helpers/anchor_tags.rb +11 -15
  51. data/lib/pagy/toolbox/helpers/bootstrap/input_nav_js.rb +3 -0
  52. data/lib/pagy/toolbox/helpers/bootstrap/series_nav.rb +3 -1
  53. data/lib/pagy/toolbox/helpers/bootstrap/series_nav_js.rb +2 -0
  54. data/lib/pagy/toolbox/helpers/bulma/input_nav_js.rb +3 -0
  55. data/lib/pagy/toolbox/helpers/bulma/previous_next_html.rb +1 -1
  56. data/lib/pagy/toolbox/helpers/bulma/series_nav.rb +3 -1
  57. data/lib/pagy/toolbox/helpers/bulma/series_nav_js.rb +2 -0
  58. data/lib/pagy/toolbox/helpers/data_hash.rb +19 -17
  59. data/lib/pagy/toolbox/helpers/headers_hash.rb +15 -9
  60. data/lib/pagy/toolbox/helpers/info_tag.rb +2 -0
  61. data/lib/pagy/toolbox/helpers/input_nav_js.rb +9 -6
  62. data/lib/pagy/toolbox/helpers/limit_tag_js.rb +4 -3
  63. data/lib/pagy/toolbox/helpers/loader.rb +3 -0
  64. data/lib/pagy/toolbox/helpers/page_url.rb +10 -16
  65. data/lib/pagy/toolbox/helpers/series_nav.rb +5 -4
  66. data/lib/pagy/toolbox/helpers/series_nav_js.rb +2 -1
  67. data/lib/pagy/toolbox/helpers/support/a_lambda.rb +8 -6
  68. data/lib/pagy/toolbox/helpers/support/data_pagy_attribute.rb +6 -1
  69. data/lib/pagy/toolbox/helpers/support/series.rb +1 -2
  70. data/lib/pagy/toolbox/helpers/support/wrap_input_nav_js.rb +1 -1
  71. data/lib/pagy/toolbox/helpers/support/wrap_series_nav.rb +2 -1
  72. data/lib/pagy/toolbox/helpers/support/wrap_series_nav_js.rb +10 -4
  73. data/lib/pagy/toolbox/helpers/urls_hash.rb +7 -7
  74. data/lib/pagy/toolbox/paginators/calendar.rb +13 -9
  75. data/lib/pagy/toolbox/paginators/countish.rb +39 -0
  76. data/lib/pagy/toolbox/paginators/countless.rb +13 -15
  77. data/lib/pagy/toolbox/paginators/elasticsearch_rails.rb +43 -18
  78. data/lib/pagy/toolbox/paginators/keynav_js.rb +14 -15
  79. data/lib/pagy/toolbox/paginators/keyset.rb +7 -9
  80. data/lib/pagy/toolbox/paginators/meilisearch.rb +21 -18
  81. data/lib/pagy/toolbox/paginators/method.rb +15 -3
  82. data/lib/pagy/toolbox/paginators/offset.rb +14 -22
  83. data/lib/pagy/toolbox/paginators/searchkick.rb +21 -18
  84. data/lib/pagy/toolbox/paginators/typesense_rails.rb +35 -0
  85. data/lib/pagy.rb +23 -10
  86. data/locales/id.yml +1 -3
  87. data/locales/ja.yml +1 -3
  88. data/locales/km.yml +1 -3
  89. data/locales/sw.yml +2 -2
  90. data/locales/tr.yml +10 -8
  91. data/stylesheets/pagy-tailwind.css +1 -1
  92. data/stylesheets/pagy.css +1 -6
  93. metadata +25 -8
  94. data/lib/optimist.rb +0 -1022
  95. data/lib/pagy/classes/keyset/active_record.rb +0 -11
  96. data/lib/pagy/classes/keyset/keynav/active_record.rb +0 -13
  97. data/lib/pagy/classes/keyset/keynav/sequel.rb +0 -13
  98. data/lib/pagy/classes/keyset/sequel.rb +0 -11
@@ -16,7 +16,7 @@
16
16
  # URL
17
17
  # http://127.0.0.1:8000
18
18
 
19
- VERSION = '43.0.0'
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
- <title>Pagy Keyset App</title>
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.2s;
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 &gt;') %>
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
- DB = Sequel.connect(adapter: 'sqlite', user: 'root', password: 'password', host: 'localhost', port: '3306',
143
- database: "#{dir}/tmp/pagy-keyset-s.sqlite3", max_connections: 10, loggers: [Logger.new(output)])
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.0.0'
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: "#{dir}/tmp/pagy-rails.sqlite3")
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
- <title>Pagy Rails App</title>
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.2s;
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.0.0'
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.options[:client_max_limit] = 100
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
- <title>Pagy Repro App</title>
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.2s;
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</h4>
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 nav_js_responsove',
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 a AR scope, but without any DB
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
- VERSION = '43.0.0'
5
- LINUX = RbConfig::CONFIG['host_os'].include?('linux')
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.0.0)
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.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
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 dictionary lookup for customization by dropping your customized
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 #########################################################
@@ -1,23 +1,63 @@
1
- () => {
2
- function loadWidget() {
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
- //const iconURL = 'https://github.com/ddnexus/pagy/blob/master/assets/images/pagy-the-frog.png?raw=true'
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
- //script.dataset.widgetId = 'HKtFSPZLGiAXOdBWS4rSAxEkqv8czIbJoQdMEwCqgEc';
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
- // script.dataset.widgetId = 'djgBhRlpdH8b07oj0Gsaerz69Xfs0FXMuUluyOo2iR4';
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
- // script.dataset.widgetId = '_rXLissYyqe-dJ9vGGGXzmJwavoW0GvuzQPEq5BZjP8';
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 = iconURL; // pre
68
+ script.dataset.iconUrl = this.ICON_URL;
29
69
  script.dataset.text = 'Pagy AI';
30
70
  script.dataset.bgColor = '#1f7a1f';
31
- script.dataset.lightMode = 'false';
71
+ script.dataset.lightMode = 'auto';
32
72
  script.dataset.tooltipSide = 'bottom';
33
73
  document.head.appendChild(script);
34
74
  }
35
- loadWidget();
75
+ };
36
76
 
37
- function editChatWidget() {
38
- const hostId = 'gurubase-chat-widget-container',
39
- imgSelector = '#chatWindow > div.anteon-header > div > img',
40
- nameSelector = '#chatWindow > div.anteon-header > div > span',
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
- const checkAndEdit = () => {
47
- const hostElement = document.getElementById(hostId);
48
- if (hostElement && hostElement.shadowRoot) {
49
- const shadowRoot = hostElement.shadowRoot,
50
- img = shadowRoot.querySelector(imgSelector),
51
- name = shadowRoot.querySelector(nameSelector),
52
- description = shadowRoot.querySelector(descriptionSelector);
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
- editChatWidget();
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, pageRe = "P ";
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 augment;
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
- augment = (page) => page + "+" + last;
35
+ augmentPage = (page) => page + "+" + last;
36
36
  }
37
37
  }
38
- if (!augment) {
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
- augment = (page) => {
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
- const url = a.href, re = new RegExp(`(?<=\\?.*)\\b${pageKey}=(\\d+)`);
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 augment;
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(pageRe, item) : current).replace("L<", labels?.[index][i] ?? item + "<");
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(pageRe, augment(inputValue)));
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(pageRe, Math.max(Math.ceil(from / parseInt(inputValue)), 1)).replace("L ", inputValue);
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.0.0",
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("Pagy.init: %o\n%s", element, err);
145
+ console.warn(`Pagy.init: %o
146
+ %s`, element, err);
144
147
  }
145
148
  }
146
149
  }
147
150
  };
148
151
  })();
149
152
 
150
- //# debugId=46963D274F782A9664756E2164756E21
153
+ //# debugId=975696F2DDC5F9D164756E2164756E21
151
154
  //# sourceMappingURL=pagy.js.map