pagy 43.2.3 → 43.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/apps/calendar.ru +5 -6
  3. data/apps/demo.ru +1 -1
  4. data/apps/enable_rails_page_segment.rb +6 -2
  5. data/apps/keynav+root_key.ru +4 -5
  6. data/apps/keynav.ru +6 -7
  7. data/apps/keyset.ru +3 -5
  8. data/apps/keyset_sequel.ru +3 -5
  9. data/apps/rails.ru +3 -4
  10. data/apps/repro.ru +5 -6
  11. data/config/pagy.rb +1 -1
  12. data/javascripts/pagy.js +2 -2
  13. data/javascripts/pagy.js.map +2 -2
  14. data/javascripts/pagy.min.js +1 -1
  15. data/javascripts/pagy.mjs +1 -1
  16. data/lib/pagy/classes/calendar/calendar.rb +31 -25
  17. data/lib/pagy/classes/calendar/unit.rb +7 -4
  18. data/lib/pagy/classes/exceptions.rb +1 -0
  19. data/lib/pagy/classes/keyset/adapters/active_record.rb +3 -1
  20. data/lib/pagy/classes/keyset/adapters/sequel.rb +3 -1
  21. data/lib/pagy/classes/keyset/keynav.rb +3 -0
  22. data/lib/pagy/classes/keyset/keyset.rb +13 -17
  23. data/lib/pagy/classes/offset/countless.rb +10 -3
  24. data/lib/pagy/classes/offset/offset.rb +6 -1
  25. data/lib/pagy/classes/request.rb +10 -7
  26. data/lib/pagy/modules/abilities/configurable.rb +1 -1
  27. data/lib/pagy/modules/abilities/countable.rb +1 -0
  28. data/lib/pagy/modules/abilities/linkable.rb +19 -12
  29. data/lib/pagy/modules/abilities/rangeable.rb +0 -1
  30. data/lib/pagy/modules/b64.rb +8 -2
  31. data/lib/pagy/modules/console.rb +15 -6
  32. data/lib/pagy/modules/i18n/i18n.rb +11 -4
  33. data/lib/pagy/modules/searcher.rb +8 -4
  34. data/lib/pagy/toolbox/helpers/data_hash.rb +1 -0
  35. data/lib/pagy/toolbox/helpers/headers_hash.rb +2 -1
  36. data/lib/pagy/toolbox/helpers/info_tag.rb +2 -0
  37. data/lib/pagy/toolbox/helpers/input_nav_js.rb +1 -0
  38. data/lib/pagy/toolbox/helpers/page_url.rb +1 -0
  39. data/lib/pagy/toolbox/helpers/series_nav.rb +1 -0
  40. data/lib/pagy/toolbox/helpers/series_nav_js.rb +1 -0
  41. data/lib/pagy/toolbox/helpers/support/a_lambda.rb +1 -1
  42. data/lib/pagy/toolbox/paginators/calendar.rb +9 -6
  43. data/lib/pagy/toolbox/paginators/countish.rb +6 -3
  44. data/lib/pagy/toolbox/paginators/countless.rb +5 -2
  45. data/lib/pagy/toolbox/paginators/elasticsearch_rails.rb +12 -6
  46. data/lib/pagy/toolbox/paginators/keynav_js.rb +5 -3
  47. data/lib/pagy/toolbox/paginators/keyset.rb +2 -1
  48. data/lib/pagy/toolbox/paginators/meilisearch.rb +10 -7
  49. data/lib/pagy/toolbox/paginators/method.rb +7 -5
  50. data/lib/pagy/toolbox/paginators/offset.rb +9 -2
  51. data/lib/pagy/toolbox/paginators/searchkick.rb +12 -9
  52. data/lib/pagy.rb +1 -1
  53. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 02730cf68f13d1c235310c23d80f5ec7b6a50aae70cafc92cefad56b2f38d3ea
4
- data.tar.gz: 62ffd2d52460961fea32f50fd62e10c38e59c71f4ca78a522620c823a9af4c71
3
+ metadata.gz: 0e875b9703ce63e0ea0fb713757bebbb752f17a80b7414e8b88ef1abbc9d3446
4
+ data.tar.gz: e6ea0a3dfcae811e97dd851c00ecb5089c4700d70763c6ef37112486bf129d97
5
5
  SHA512:
6
- metadata.gz: cf75f45a79964854e8130b22a6a8c57c35c01726947f2b985c69e303134be5969619ee330027e2a3f0d759ad9d9e60e6e2c7e2b5678ab45ec9a1b0e77c04125e
7
- data.tar.gz: 4132abcd02fec9570731f837711fd33e92b511cc0746218a17fe3314bcdc70ab8982ed8af5ac02609fb66fdcf34848adbffb27305456900075fccb349f26b9ed
6
+ metadata.gz: 5da60ae142b168c6f0d465a88fa7938fd23c9bb832fb4da5afcb2bd87d113238796bb1a01f37a304db4a0d77e90b59ad10847ac33403dd596f8c02a8d6a38f60
7
+ data.tar.gz: 0a914f93b8d74895ce872812f50e7d5f9a883f0fc848bb077f452a389817078ace734cdbb1592d0aaab43f4fb4dff948732a16b4b11dd1a9bbdebf7a163f417b
data/apps/calendar.ru CHANGED
@@ -16,7 +16,7 @@
16
16
  # URL
17
17
  # http://127.0.0.1:8000
18
18
 
19
- VERSION = '43.2.3'
19
+ VERSION = '43.2.5'
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")
@@ -95,9 +95,8 @@ class PagyCalendar < Sinatra::Base
95
95
  <<~ERB
96
96
  <!DOCTYPE html>
97
97
  <html lang="en">
98
- <html>
99
98
  <head>
100
- <title>Pagy Calendar App</title>
99
+ <title>Pagy Calendar App</title>
101
100
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
102
101
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
103
102
  integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
@@ -105,13 +104,13 @@ class PagyCalendar < Sinatra::Base
105
104
  <style type="text/css">
106
105
  @media screen { html, body {
107
106
  font-size: .8rem;
108
- line-height: 1.1s;
107
+ line-height: 1.1;
109
108
  padding: 0;
110
109
  margin: 0;
111
110
  } }
112
111
  body {
113
112
  background-color: #f7f7f7;
114
- color: #51585F;"
113
+ color: #51585F;
115
114
  font-family: sans-serif;
116
115
  }
117
116
  .content {
@@ -182,7 +181,7 @@ class PagyCalendar < Sinatra::Base
182
181
  </div>
183
182
 
184
183
  <!-- standard pagination of the last unit (month) -->
185
- <p><%= @pagy.series_nav(:bootstrap, id: 'pages-nav', aria_label: 'Pages') if @pagy.last > 1 %><p/>
184
+ <p><%= @pagy.series_nav(:bootstrap, id: 'pages-nav', aria_label: 'Pages') if @pagy.last > 1 %></p>
186
185
  </div>
187
186
  ERB
188
187
  end
data/apps/demo.ru CHANGED
@@ -19,7 +19,7 @@
19
19
  # URL
20
20
  # http://127.0.0.1:8000
21
21
 
22
- VERSION = '43.2.3'
22
+ VERSION = '43.2.5'
23
23
 
24
24
  if VERSION != Pagy::VERSION
25
25
  Warning.warn("\n>>> WARNING! '#{File.basename(__FILE__)}-#{VERSION}' running with 'pagy-#{Pagy::VERSION}'! <<< \n\n")
@@ -28,13 +28,17 @@ require_relative '../lib/pagy/modules/abilities/linkable'
28
28
  class Pagy
29
29
  # Switch to the `request.params` to get access to rails-added path parameters
30
30
  module RequestOverride
31
- def get_params(request) = request.params
31
+ def get_params(request)
32
+ request.params
33
+ end
32
34
  end
33
35
  Request.prepend RequestOverride
34
36
 
35
37
  # Inject the caller context into the Pagy instance
36
38
  module MethodOverride
37
- def pagy(...) = super.tap { |result| result[0].instance_variable_set(:@context, self) }
39
+ def pagy(...)
40
+ super.tap { _1[0].instance_variable_set(:@context, self) }
41
+ end
38
42
  end
39
43
  Method.prepend MethodOverride
40
44
 
@@ -16,7 +16,7 @@
16
16
  # URL
17
17
  # http://127.0.0.1:8000
18
18
 
19
- VERSION = '43.2.3'
19
+ VERSION = '43.2.5'
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")
@@ -71,7 +71,6 @@ class PagyKeynav < Sinatra::Base
71
71
  <<~ERB
72
72
  <!DOCTYPE html>
73
73
  <html lang="en">
74
- <html>
75
74
  <head>
76
75
  <title>Pagy Keynav (root_key) App</title>
77
76
  <script src="javascripts/pagy.js"></script>
@@ -82,7 +81,7 @@ class PagyKeynav < Sinatra::Base
82
81
  <style type="text/css">
83
82
  @media screen { html, body {
84
83
  font-size: 1rem;
85
- line-height: 1.2s;
84
+ line-height: 1.2;
86
85
  padding: 0;
87
86
  margin: 0;
88
87
  } }
@@ -113,8 +112,8 @@ class PagyKeynav < Sinatra::Base
113
112
  border-radius: 6px;
114
113
  box-shadow: 0 2px 5px rgba(0,0,0,0.1);
115
114
  border: 1px solid #ddd;
116
- }
117
- .pagy {
115
+ }
116
+ .pagy {
118
117
  padding: .5em;
119
118
  margin: .3em 0;
120
119
  width: fit-content;
data/apps/keynav.ru CHANGED
@@ -16,7 +16,7 @@
16
16
  # URL
17
17
  # http://127.0.0.1:8000
18
18
 
19
- VERSION = '43.2.3'
19
+ VERSION = '43.2.5'
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")
@@ -71,18 +71,17 @@ class PagyKeynav < Sinatra::Base
71
71
  <<~ERB
72
72
  <!DOCTYPE html>
73
73
  <html lang="en">
74
- <html>
75
74
  <head>
76
- <title>Pagy Keynav App</title>
75
+ <title>Pagy Keynav App</title>
77
76
  <script src="javascripts/pagy.js"></script>
78
- <script>
77
+ <script>
79
78
  window.addEventListener("load", Pagy.init);
80
79
  </script>
81
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
80
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
82
81
  <style type="text/css">
83
82
  @media screen { html, body {
84
83
  font-size: 1rem;
85
- line-height: 1.2s;
84
+ line-height: 1.2;
86
85
  padding: 0;
87
86
  margin: 0;
88
87
  } }
@@ -94,7 +93,7 @@ class PagyKeynav < Sinatra::Base
94
93
  .main-content {
95
94
  padding: 1rem 1.5rem 2rem !important;
96
95
  }
97
- .pagy {
96
+ .pagy {
98
97
  padding: .5em;
99
98
  margin: .3em 0;
100
99
  width: fit-content;
data/apps/keyset.ru CHANGED
@@ -16,7 +16,7 @@
16
16
  # URL
17
17
  # http://127.0.0.1:8000
18
18
 
19
- VERSION = '43.2.3'
19
+ VERSION = '43.2.5'
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")
@@ -59,14 +59,13 @@ class PagyKeyset < Sinatra::Base
59
59
  <<~ERB
60
60
  <!DOCTYPE html>
61
61
  <html lang="en">
62
- <html>
63
62
  <head>
64
- <title>Pagy Keyset App</title>
63
+ <title>Pagy Keyset App</title>
65
64
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
66
65
  <style type="text/css">
67
66
  @media screen { html, body {
68
67
  font-size: 1rem;
69
- line-height: 1.2s;
68
+ line-height: 1.2;
70
69
  padding: 0;
71
70
  margin: 0;
72
71
  } }
@@ -122,7 +121,6 @@ class PagyKeyset < Sinatra::Base
122
121
  <% end %>
123
122
  </table>
124
123
  </div>
125
- <p>
126
124
  <nav class="pagy" id="next" aria-label="Pagy next">
127
125
  <%= @pagy.next_tag(text: 'Next page &gt;') %>
128
126
  </nav>
@@ -16,7 +16,7 @@
16
16
  # URL
17
17
  # http://127.0.0.1:8000
18
18
 
19
- VERSION = '43.2.3'
19
+ VERSION = '43.2.5'
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")
@@ -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>
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.2.3'
19
+ VERSION = '43.2.5'
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")
@@ -126,9 +126,8 @@ run PagyRails
126
126
  TEMPLATE = <<~ERB
127
127
  <!DOCTYPE html>
128
128
  <html lang="en">
129
- <html>
130
129
  <head>
131
- <title>Pagy Rails App</title>
130
+ <title>Pagy Rails App</title>
132
131
  <script src="/javascripts/pagy.js"></script>
133
132
  <script>
134
133
  window.addEventListener("load", Pagy.init);
@@ -137,7 +136,7 @@ TEMPLATE = <<~ERB
137
136
  <style type="text/css">
138
137
  @media screen { html, body {
139
138
  font-size: 1rem;
140
- line-height: 1.2s;
139
+ line-height: 1.2;
141
140
  padding: 0;
142
141
  margin: 0;
143
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.2.3'
19
+ VERSION = '43.2.5'
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")
@@ -69,9 +69,8 @@ class PagyRepro < Sinatra::Base
69
69
  <<~ERB
70
70
  <!DOCTYPE html>
71
71
  <html lang="en">
72
- <html>
73
72
  <head>
74
- <title>Pagy Repro App</title>
73
+ <title>Pagy Repro App</title>
75
74
  <script src="javascripts/pagy.js"></script>
76
75
  <script>
77
76
  window.addEventListener("load", Pagy.init);
@@ -80,7 +79,7 @@ class PagyRepro < Sinatra::Base
80
79
  <style type="text/css">
81
80
  @media screen { html, body {
82
81
  font-size: 1rem;
83
- line-height: 1.2s;
82
+ line-height: 1.2;
84
83
  padding: 0;
85
84
  margin: 0;
86
85
  } }
@@ -124,7 +123,7 @@ class PagyRepro < Sinatra::Base
124
123
  <h1>Pagy Repro App</h1>
125
124
  <p> Self-contained, standalone app usable to easily reproduce any pagy issue.</p>
126
125
 
127
- <h2>Versions</h4>
126
+ <h2>Versions</h2>
128
127
  <ul>
129
128
  <li>Ruby: <%= RUBY_VERSION %></li>
130
129
  <li>Rack: <%= Rack::RELEASE %></li>
@@ -143,7 +142,7 @@ class PagyRepro < Sinatra::Base
143
142
 
144
143
  <h4>@pagy.series_nav_js (responsive)</h4>
145
144
  <%= @pagy.series_nav_js(id: 'series-nav-js-responsive',
146
- aria_label: 'Pages nav_js_responsove',
145
+ aria_label: 'Pages nav_js_responsive',
147
146
  steps: { 0 => 5, 500 => 7, 600 => 9, 700 => 11 }) %>
148
147
 
149
148
  <h4>@pagy.input_nav_js</h4>
data/config/pagy.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Pagy initializer file (43.2.3)
3
+ # Pagy initializer file (43.2.5)
4
4
  # See https://ddnexus.github.io/pagy/resources/initializer/
5
5
 
6
6
  ############ Global Options ################################################################
data/javascripts/pagy.js CHANGED
@@ -126,7 +126,7 @@ window.Pagy = (() => {
126
126
  });
127
127
  };
128
128
  return {
129
- version: "43.2.3",
129
+ version: "43.2.5",
130
130
  init(arg) {
131
131
  const target = arg instanceof HTMLElement ? arg : document, elements = target.querySelectorAll("[data-pagy]");
132
132
  for (const element of elements) {
@@ -150,5 +150,5 @@ window.Pagy = (() => {
150
150
  };
151
151
  })();
152
152
 
153
- //# debugId=F5943E60CF7813AC64756E2164756E21
153
+ //# debugId=9616AB509F644C8D64756E2164756E21
154
154
  //# sourceMappingURL=pagy.js.map
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/pagy.ts"],
4
4
  "sourcesContent": [
5
- "interface SyncData {\n from?: number\n to?: number\n key: string\n str?: string\n}\ntype InitArgs = [\"k\", KeynavArgs] | // series_nav[_js] with keynav instance\n [\"snj\", SeriesNavJsArgs] | // series_nav_js\n [\"inj\", InputNavJsArgs] | // input_nav_js\n [\"ltj\", LimitTagJsArgs] // limit_tag_js\ntype AugmentKeynav = (nav:HTMLElement, keynavArgs:KeynavArgs) => Promise<((page: string) => string)>\ntype KeynavArgs = readonly [storageKey: string | null,\n rootKey: string | null,\n pageKey: string,\n last: number,\n spliceArgs?: SpliceArgs]\ntype SpliceArgs = readonly [start: number,\n deleteCount: number, // it would be optional, but ts complains\n ...items: Cutoff[]]\ntype Cutoff = readonly (string | number | boolean)[]\ntype AugmentedPage = [browserId: string,\n storageKey: string,\n pageNumber: number,\n pages: number,\n priorCutoff: Cutoff | null,\n pageCutoff: Cutoff | null]\ntype SeriesNavJsArgs = readonly [NavJsTokens, pageToken: string, NavJsSeries, KeynavArgs?]\ntype NavJsSeries = readonly [widths: number[],\n series: (string | number)[][],\n labels: string[][] | null]\ntype InputNavJsArgs = readonly [urlToken: string,\n pageToken: string,\n KeynavArgs?]\ntype LimitTagJsArgs = readonly [from: number,\n urlToken: string,\n pageToken: string,\n limitToken: string]\ntype NavJsTokens = readonly [before: string,\n anchor: string,\n current: string,\n gap: string,\n after: string]\ninterface NavJsElement extends HTMLElement {\n render(): void\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nconst Pagy = (() => {\n const storageSupport = 'sessionStorage' in window && 'BroadcastChannel' in window;\n // eslint-disable-next-line prefer-const\n let pagy = \"pagy\", storage: Storage, sync: BroadcastChannel, tabId: number;\n if (storageSupport) {\n storage = sessionStorage; // shorten the compiled size\n sync = new BroadcastChannel(pagy);\n tabId = Date.now();\n // Sync the sessionStorage keys for the cutoffs opened in a new tab/window\n sync.addEventListener(\"message\", (e:MessageEvent<SyncData>) => {\n if (e.data.from) { // request cutoffs\n const cutoffs = storage.getItem(e.data.key);\n if (cutoffs) {\n sync.postMessage(<SyncData>{to: e.data.from, key: e.data.key, str: cutoffs});\n } // send response\n } else if (e.data.to) { // receive cutoffs\n if (e.data.to == tabId) {\n storage.setItem(e.data.key, <string>e.data.str);\n }\n }\n });\n }\n // The observer instance for responsive navs\n const rjsObserver = new ResizeObserver(\n entries => entries.forEach(e => {\n e.target.querySelectorAll<NavJsElement>(\".pagy-rjs\").forEach(el => el.render());\n }));\n\n /* Full set of B64 functions\n const B64Encode = (unicode:string) => btoa(String.fromCharCode(...(new TextEncoder).encode(unicode))),\n B64Safe = (unsafe:string) => unsafe.replace(/[+/=]/g, (m) => m == \"+\" ? \"-\" : m == \"/\" ? \"_\" : \"\"),\n B64SafeEncode = (unicode:string) => B64Safe(B64Encode(unicode)),\n B64Decode = (base64:string) => (new TextDecoder()).decode(Uint8Array.from(atob(base64), c => c.charCodeAt(0))),\n B64Unsafe = (safe:string) => safe.replace(/[-_]/g, (match) => match == \"-\" ? \"+\" : \"/\"),\n B64SafeDecode = (base64:string) => B64Decode(B64Unsafe(base64))\n */\n const B64SafeEncode = (unicode:string) => btoa(String.fromCharCode(...(new TextEncoder).encode(unicode)))\n .replace(/[+/=]/g, (m) => m == \"+\" ? \"-\" : m == \"/\" ? \"_\" : \"\"),\n B64Decode = (base64:string) => (new TextDecoder()).decode(Uint8Array.from(atob(base64), c => c.charCodeAt(0)));\n\n // Return a random key: 3 chars max, base-36 number < 36**3\n const randKey = () => Math.floor(Math.random() * 36 ** 3).toString(36);\n\n // Manage the page augmentation for Keynav, called only if storageSupport\n const augmentKeynav: AugmentKeynav = async (nav, [storageKey, rootKey, pageKey, last, spliceArgs]) => {\n let augmentPage:(page: string) => string;\n const browserKey = document.cookie.split(/;\\s+/) // it works even if malformed\n .find((row) => row.startsWith(pagy + \"=\"))\n ?.split(\"=\")[1] ?? randKey();\n document.cookie = pagy + \"=\" + browserKey; // Smaller .min size: set the cookie without checking\n if (storageKey && !(storageKey in storage)) {\n // Sync the sessiongStorage from other tabs/windows (e.g., open page in the new tab/window)\n sync.postMessage(<SyncData>{ from: tabId, key: storageKey });\n // Wait for the listener to copy the cutoffs in the current sessionStorage\n await new Promise<string|null>((resolve) => setTimeout(() => resolve(\"\"), 100));\n if (!(storageKey in storage)) { // the storageKey didn't get copied: fallback to countless pagination\n augmentPage = (page: string) => page + '+' + last;\n }\n }\n // @ts-expect-error If it is not assigned it means it supports keynav\n if (!augmentPage) { // regular keynav pagination\n if (!storageKey) { do { storageKey = randKey() } while (storageKey in storage) } // no dup keys\n const data = storage.getItem(storageKey),\n cutoffs = <Cutoff[]>(data ? JSON.parse(data) : [undefined]);\n if (spliceArgs) {\n cutoffs.splice(...spliceArgs);\n storage.setItem(storageKey, JSON.stringify(cutoffs));\n }\n // Augment function\n augmentPage = (page:string) => {\n const pageNum = parseInt(page);\n return B64SafeEncode(JSON.stringify(\n <AugmentedPage>[browserKey,\n storageKey,\n pageNum,\n cutoffs.length, // pages/last\n cutoffs[pageNum - 1], // priorCutoff\n cutoffs[pageNum]])); // pageCutoff\n };\n }\n const search = (rootKey) ? `${rootKey}%5B${pageKey}%5D` : pageKey;\n const re = new RegExp(`(?<=\\\\?.*)(\\\\b${search}=)(\\\\d+)`);\n // Augment the page param of each href\n for (const a of <NodeListOf<HTMLAnchorElement>><unknown>nav.querySelectorAll('a[href]')) {\n a.href = a.href.replace(re, (_match, prefix, digit): string => `${prefix}${augmentPage(<string>digit)}`);\n }\n // Return the augment function for further augmentation (i.e., url token in input_nav_js)\n return augmentPage;\n };\n\n // Build the series_nav_js helper\n const buildNavJs = (nav:NavJsElement, [[before, anchor, current, gap, after], pageToken,\n [widths, series, labels], keynavArgs]:SeriesNavJsArgs) => {\n const parent = <HTMLElement>nav.parentElement;\n let lastWidth = -1;\n (nav.render = () => {\n const index = widths.findIndex(w => w < parent.clientWidth);\n if (widths[index] === lastWidth) { return } // no change: abort\n\n let html = before;\n series[index].forEach((item, i) => {\n // Avoid the if blocks and chain the results (shorter pagy.min.js and easier reading)\n html += item == \"gap\" ? gap :\n // @ts-expect-error the item may be a number, but the 'replace' converts it to string (shorter pagy.min.js)\n (typeof item == \"number\" ? anchor.replace(pageToken, item) : current)\n .replace(\"L<\", labels?.[index][i] ?? item + \"<\");\n });\n html += after;\n nav.innerHTML = \"\";\n nav.insertAdjacentHTML(\"afterbegin\", html);\n lastWidth = widths[index];\n if (keynavArgs && storageSupport) { void augmentKeynav(nav, keynavArgs) }\n })();\n if (nav.classList.contains(pagy + \"-rjs\")) { rjsObserver.observe(parent) }\n };\n\n // Init the input_nav_js helpers\n const initInputNavJs = async (nav:HTMLElement, [url_token, pageToken, keynavArgs]:InputNavJsArgs) => {\n const augment = keynavArgs && storageSupport\n ? await augmentKeynav(nav, keynavArgs)\n : (page: string) => page;\n initInput(nav, inputValue => url_token.replace(pageToken, augment(inputValue)));\n };\n\n // Init the limit_tag_js helper\n const initLimitTagJs = (span:HTMLSpanElement, [from, url_token, page_token, limitToken]:LimitTagJsArgs) => {\n initInput(span, inputValue => {\n // @ts-expect-error the page is a number, but the 'replace' converts it to string (shorter pagy.min.js)\n return url_token.replace(page_token, Math.max(Math.ceil(from / parseInt(inputValue)), 1))\n .replace(limitToken, inputValue);\n });\n };\n\n // Init the input element\n const initInput = (element:HTMLElement, getUrl:(v:string) => string) => {\n const input = <HTMLInputElement>element.querySelector(\"input\"),\n link = <HTMLAnchorElement>element.querySelector(\"a\"),\n initial = input.value,\n action = () => {\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 link.href = getUrl(input.value);\n link.click();\n };\n input.addEventListener(\"focus\", () => input.select());\n input.addEventListener(\"focusout\", action);\n input.addEventListener(\"keypress\", e => { if (e.key == \"Enter\") { action() } });\n };\n\n // Public interface\n return {\n version: \"43.2.3\",\n\n // Scan for elements with a \"data-pagy\" attribute and call their init functions with the decoded args\n init(arg?:HTMLElement) {\n const target = arg instanceof HTMLElement ? arg : document,\n elements = target.querySelectorAll(\"[data-pagy]\");\n for (const element of <NodeListOf<HTMLElement>>elements) {\n try {\n const [helperId, ...args] = <InitArgs>JSON.parse(B64Decode(<string>element.getAttribute(\"data-pagy\")));\n if (helperId == \"k\") {\n // @ts-expect-error spread 2 arguments, not 3 as it complains about\n void augmentKeynav(element, ...<KeynavArgs><unknown>args);\n } else if (helperId == \"snj\") {\n buildNavJs(<NavJsElement>element, <SeriesNavJsArgs><unknown>args);\n } else if (helperId == \"inj\") {\n void initInputNavJs(element, <InputNavJsArgs><unknown>args);\n } else if (helperId == \"ltj\") {\n initLimitTagJs(element, <LimitTagJsArgs><unknown>args);\n }\n // else { console.warn(\"Pagy.init: %o\\nUnknown helperId '%s'\", element, helperId) }\n } catch (err) { console.warn(\"Pagy.init: %o\\n%s\", element, err) }\n }\n }\n };\n})();\n"
5
+ "interface SyncData {\n from?: number\n to?: number\n key: string\n str?: string\n}\ntype InitArgs = [\"k\", KeynavArgs] | // series_nav[_js] with keynav instance\n [\"snj\", SeriesNavJsArgs] | // series_nav_js\n [\"inj\", InputNavJsArgs] | // input_nav_js\n [\"ltj\", LimitTagJsArgs] // limit_tag_js\ntype AugmentKeynav = (nav:HTMLElement, keynavArgs:KeynavArgs) => Promise<((page: string) => string)>\ntype KeynavArgs = readonly [storageKey: string | null,\n rootKey: string | null,\n pageKey: string,\n last: number,\n spliceArgs?: SpliceArgs]\ntype SpliceArgs = readonly [start: number,\n deleteCount: number, // it would be optional, but ts complains\n ...items: Cutoff[]]\ntype Cutoff = readonly (string | number | boolean)[]\ntype AugmentedPage = [browserId: string,\n storageKey: string,\n pageNumber: number,\n pages: number,\n priorCutoff: Cutoff | null,\n pageCutoff: Cutoff | null]\ntype SeriesNavJsArgs = readonly [NavJsTokens, pageToken: string, NavJsSeries, KeynavArgs?]\ntype NavJsSeries = readonly [widths: number[],\n series: (string | number)[][],\n labels: string[][] | null]\ntype InputNavJsArgs = readonly [urlToken: string,\n pageToken: string,\n KeynavArgs?]\ntype LimitTagJsArgs = readonly [from: number,\n urlToken: string,\n pageToken: string,\n limitToken: string]\ntype NavJsTokens = readonly [before: string,\n anchor: string,\n current: string,\n gap: string,\n after: string]\ninterface NavJsElement extends HTMLElement {\n render(): void\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nconst Pagy = (() => {\n const storageSupport = 'sessionStorage' in window && 'BroadcastChannel' in window;\n // eslint-disable-next-line prefer-const\n let pagy = \"pagy\", storage: Storage, sync: BroadcastChannel, tabId: number;\n if (storageSupport) {\n storage = sessionStorage; // shorten the compiled size\n sync = new BroadcastChannel(pagy);\n tabId = Date.now();\n // Sync the sessionStorage keys for the cutoffs opened in a new tab/window\n sync.addEventListener(\"message\", (e:MessageEvent<SyncData>) => {\n if (e.data.from) { // request cutoffs\n const cutoffs = storage.getItem(e.data.key);\n if (cutoffs) {\n sync.postMessage(<SyncData>{to: e.data.from, key: e.data.key, str: cutoffs});\n } // send response\n } else if (e.data.to) { // receive cutoffs\n if (e.data.to == tabId) {\n storage.setItem(e.data.key, <string>e.data.str);\n }\n }\n });\n }\n // The observer instance for responsive navs\n const rjsObserver = new ResizeObserver(\n entries => entries.forEach(e => {\n e.target.querySelectorAll<NavJsElement>(\".pagy-rjs\").forEach(el => el.render());\n }));\n\n /* Full set of B64 functions\n const B64Encode = (unicode:string) => btoa(String.fromCharCode(...(new TextEncoder).encode(unicode))),\n B64Safe = (unsafe:string) => unsafe.replace(/[+/=]/g, (m) => m == \"+\" ? \"-\" : m == \"/\" ? \"_\" : \"\"),\n B64SafeEncode = (unicode:string) => B64Safe(B64Encode(unicode)),\n B64Decode = (base64:string) => (new TextDecoder()).decode(Uint8Array.from(atob(base64), c => c.charCodeAt(0))),\n B64Unsafe = (safe:string) => safe.replace(/[-_]/g, (match) => match == \"-\" ? \"+\" : \"/\"),\n B64SafeDecode = (base64:string) => B64Decode(B64Unsafe(base64))\n */\n const B64SafeEncode = (unicode:string) => btoa(String.fromCharCode(...(new TextEncoder).encode(unicode)))\n .replace(/[+/=]/g, (m) => m == \"+\" ? \"-\" : m == \"/\" ? \"_\" : \"\"),\n B64Decode = (base64:string) => (new TextDecoder()).decode(Uint8Array.from(atob(base64), c => c.charCodeAt(0)));\n\n // Return a random key: 3 chars max, base-36 number < 36**3\n const randKey = () => Math.floor(Math.random() * 36 ** 3).toString(36);\n\n // Manage the page augmentation for Keynav, called only if storageSupport\n const augmentKeynav: AugmentKeynav = async (nav, [storageKey, rootKey, pageKey, last, spliceArgs]) => {\n let augmentPage:(page: string) => string;\n const browserKey = document.cookie.split(/;\\s+/) // it works even if malformed\n .find((row) => row.startsWith(pagy + \"=\"))\n ?.split(\"=\")[1] ?? randKey();\n document.cookie = pagy + \"=\" + browserKey; // Smaller .min size: set the cookie without checking\n if (storageKey && !(storageKey in storage)) {\n // Sync the sessiongStorage from other tabs/windows (e.g., open page in the new tab/window)\n sync.postMessage(<SyncData>{ from: tabId, key: storageKey });\n // Wait for the listener to copy the cutoffs in the current sessionStorage\n await new Promise<string|null>((resolve) => setTimeout(() => resolve(\"\"), 100));\n if (!(storageKey in storage)) { // the storageKey didn't get copied: fallback to countless pagination\n augmentPage = (page: string) => page + '+' + last;\n }\n }\n // @ts-expect-error If it is not assigned it means it supports keynav\n if (!augmentPage) { // regular keynav pagination\n if (!storageKey) { do { storageKey = randKey() } while (storageKey in storage) } // no dup keys\n const data = storage.getItem(storageKey),\n cutoffs = <Cutoff[]>(data ? JSON.parse(data) : [undefined]);\n if (spliceArgs) {\n cutoffs.splice(...spliceArgs);\n storage.setItem(storageKey, JSON.stringify(cutoffs));\n }\n // Augment function\n augmentPage = (page:string) => {\n const pageNum = parseInt(page);\n return B64SafeEncode(JSON.stringify(\n <AugmentedPage>[browserKey,\n storageKey,\n pageNum,\n cutoffs.length, // pages/last\n cutoffs[pageNum - 1], // priorCutoff\n cutoffs[pageNum]])); // pageCutoff\n };\n }\n const search = (rootKey) ? `${rootKey}%5B${pageKey}%5D` : pageKey;\n const re = new RegExp(`(?<=\\\\?.*)(\\\\b${search}=)(\\\\d+)`);\n // Augment the page param of each href\n for (const a of <NodeListOf<HTMLAnchorElement>><unknown>nav.querySelectorAll('a[href]')) {\n a.href = a.href.replace(re, (_match, prefix, digit): string => `${prefix}${augmentPage(<string>digit)}`);\n }\n // Return the augment function for further augmentation (i.e., url token in input_nav_js)\n return augmentPage;\n };\n\n // Build the series_nav_js helper\n const buildNavJs = (nav:NavJsElement, [[before, anchor, current, gap, after], pageToken,\n [widths, series, labels], keynavArgs]:SeriesNavJsArgs) => {\n const parent = <HTMLElement>nav.parentElement;\n let lastWidth = -1;\n (nav.render = () => {\n const index = widths.findIndex(w => w < parent.clientWidth);\n if (widths[index] === lastWidth) { return } // no change: abort\n\n let html = before;\n series[index].forEach((item, i) => {\n // Avoid the if blocks and chain the results (shorter pagy.min.js and easier reading)\n html += item == \"gap\" ? gap :\n // @ts-expect-error the item may be a number, but the 'replace' converts it to string (shorter pagy.min.js)\n (typeof item == \"number\" ? anchor.replace(pageToken, item) : current)\n .replace(\"L<\", labels?.[index][i] ?? item + \"<\");\n });\n html += after;\n nav.innerHTML = \"\";\n nav.insertAdjacentHTML(\"afterbegin\", html);\n lastWidth = widths[index];\n if (keynavArgs && storageSupport) { void augmentKeynav(nav, keynavArgs) }\n })();\n if (nav.classList.contains(pagy + \"-rjs\")) { rjsObserver.observe(parent) }\n };\n\n // Init the input_nav_js helpers\n const initInputNavJs = async (nav:HTMLElement, [url_token, pageToken, keynavArgs]:InputNavJsArgs) => {\n const augment = keynavArgs && storageSupport\n ? await augmentKeynav(nav, keynavArgs)\n : (page: string) => page;\n initInput(nav, inputValue => url_token.replace(pageToken, augment(inputValue)));\n };\n\n // Init the limit_tag_js helper\n const initLimitTagJs = (span:HTMLSpanElement, [from, url_token, page_token, limitToken]:LimitTagJsArgs) => {\n initInput(span, inputValue => {\n // @ts-expect-error the page is a number, but the 'replace' converts it to string (shorter pagy.min.js)\n return url_token.replace(page_token, Math.max(Math.ceil(from / parseInt(inputValue)), 1))\n .replace(limitToken, inputValue);\n });\n };\n\n // Init the input element\n const initInput = (element:HTMLElement, getUrl:(v:string) => string) => {\n const input = <HTMLInputElement>element.querySelector(\"input\"),\n link = <HTMLAnchorElement>element.querySelector(\"a\"),\n initial = input.value,\n action = () => {\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 link.href = getUrl(input.value);\n link.click();\n };\n input.addEventListener(\"focus\", () => input.select());\n input.addEventListener(\"focusout\", action);\n input.addEventListener(\"keypress\", e => { if (e.key == \"Enter\") { action() } });\n };\n\n // Public interface\n return {\n version: \"43.2.5\",\n\n // Scan for elements with a \"data-pagy\" attribute and call their init functions with the decoded args\n init(arg?:HTMLElement) {\n const target = arg instanceof HTMLElement ? arg : document,\n elements = target.querySelectorAll(\"[data-pagy]\");\n for (const element of <NodeListOf<HTMLElement>>elements) {\n try {\n const [helperId, ...args] = <InitArgs>JSON.parse(B64Decode(<string>element.getAttribute(\"data-pagy\")));\n if (helperId == \"k\") {\n // @ts-expect-error spread 2 arguments, not 3 as it complains about\n void augmentKeynav(element, ...<KeynavArgs><unknown>args);\n } else if (helperId == \"snj\") {\n buildNavJs(<NavJsElement>element, <SeriesNavJsArgs><unknown>args);\n } else if (helperId == \"inj\") {\n void initInputNavJs(element, <InputNavJsArgs><unknown>args);\n } else if (helperId == \"ltj\") {\n initLimitTagJs(element, <LimitTagJsArgs><unknown>args);\n }\n // else { console.warn(\"Pagy.init: %o\\nUnknown helperId '%s'\", element, helperId) }\n } catch (err) { console.warn(\"Pagy.init: %o\\n%s\", element, err) }\n }\n }\n };\n})();\n"
6
6
  ],
7
7
  "mappings": "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",
8
- "debugId": "F5943E60CF7813AC64756E2164756E21",
8
+ "debugId": "9616AB509F644C8D64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,2 +1,2 @@
1
- window.Pagy=(()=>{let B="sessionStorage"in window&&"BroadcastChannel"in window,L="pagy",Z,O,W;if(B)Z=sessionStorage,O=new BroadcastChannel(L),W=Date.now(),O.addEventListener("message",(q)=>{if(q.data.from){let z=Z.getItem(q.data.key);if(z)O.postMessage({to:q.data.from,key:q.data.key,str:z})}else if(q.data.to){if(q.data.to==W)Z.setItem(q.data.key,q.data.str)}});let P=new ResizeObserver((q)=>q.forEach((z)=>{z.target.querySelectorAll(".pagy-rjs").forEach((C)=>C.render())})),V=(q)=>btoa(String.fromCharCode(...new TextEncoder().encode(q))).replace(/[+/=]/g,(z)=>z=="+"?"-":z=="/"?"_":""),_=(q)=>new TextDecoder().decode(Uint8Array.from(atob(q),(z)=>z.charCodeAt(0))),S=()=>Math.floor(Math.random()*46656).toString(36),J=async(q,[z,C,F,H,G])=>{let Q,X=document.cookie.split(/;\s+/).find((M)=>M.startsWith(L+"="))?.split("=")[1]??S();if(document.cookie=L+"="+X,z&&!(z in Z)){if(O.postMessage({from:W,key:z}),await new Promise((M)=>setTimeout(()=>M(""),100)),!(z in Z))Q=(M)=>M+"+"+H}if(!Q){if(!z)do z=S();while(z in Z);let M=Z.getItem(z),Y=M?JSON.parse(M):[void 0];if(G)Y.splice(...G),Z.setItem(z,JSON.stringify(Y));Q=($)=>{let R=parseInt($);return V(JSON.stringify([X,z,R,Y.length,Y[R-1],Y[R]]))}}let D=C?`${C}%5B${F}%5D`:F,E=new RegExp(`(?<=\\?.*)(\\b${D}=)(\\d+)`);for(let M of q.querySelectorAll("a[href]"))M.href=M.href.replace(E,(Y,$,R)=>`${$}${Q(R)}`);return Q},x=(q,[[z,C,F,H,G],Q,[X,D,E],M])=>{let Y=q.parentElement,$=-1;if((q.render=()=>{let R=X.findIndex((j)=>j<Y.clientWidth);if(X[R]===$)return;let U=z;if(D[R].forEach((j,I)=>{U+=j=="gap"?H:(typeof j=="number"?C.replace(Q,j):F).replace("L<",E?.[R][I]??j+"<")}),U+=G,q.innerHTML="",q.insertAdjacentHTML("afterbegin",U),$=X[R],M&&B)J(q,M)})(),q.classList.contains(L+"-rjs"))P.observe(Y)},T=async(q,[z,C,F])=>{let H=F&&B?await J(q,F):(G)=>G;N(q,(G)=>z.replace(C,H(G)))},A=(q,[z,C,F,H])=>{N(q,(G)=>{return C.replace(F,Math.max(Math.ceil(z/parseInt(G)),1)).replace(H,G)})},N=(q,z)=>{let C=q.querySelector("input"),F=q.querySelector("a"),H=C.value,G=()=>{if(C.value===H)return;let[Q,X,D]=[C.min,C.value,C.max].map((E)=>parseInt(E)||0);if(X<Q||X>D){C.value=H,C.select();return}F.href=z(C.value),F.click()};C.addEventListener("focus",()=>C.select()),C.addEventListener("focusout",G),C.addEventListener("keypress",(Q)=>{if(Q.key=="Enter")G()})};return{version:"43.2.3",init(q){let z=q instanceof HTMLElement?q:document,C=z.querySelectorAll("[data-pagy]");for(let F of C)try{let[H,...G]=JSON.parse(_(F.getAttribute("data-pagy")));if(H=="k")J(F,...G);else if(H=="snj")x(F,G);else if(H=="inj")T(F,G);else if(H=="ltj")A(F,G)}catch(H){console.warn(`Pagy.init: %o
1
+ window.Pagy=(()=>{let B="sessionStorage"in window&&"BroadcastChannel"in window,L="pagy",Z,O,W;if(B)Z=sessionStorage,O=new BroadcastChannel(L),W=Date.now(),O.addEventListener("message",(q)=>{if(q.data.from){let z=Z.getItem(q.data.key);if(z)O.postMessage({to:q.data.from,key:q.data.key,str:z})}else if(q.data.to){if(q.data.to==W)Z.setItem(q.data.key,q.data.str)}});let P=new ResizeObserver((q)=>q.forEach((z)=>{z.target.querySelectorAll(".pagy-rjs").forEach((C)=>C.render())})),V=(q)=>btoa(String.fromCharCode(...new TextEncoder().encode(q))).replace(/[+/=]/g,(z)=>z=="+"?"-":z=="/"?"_":""),_=(q)=>new TextDecoder().decode(Uint8Array.from(atob(q),(z)=>z.charCodeAt(0))),S=()=>Math.floor(Math.random()*46656).toString(36),J=async(q,[z,C,F,H,G])=>{let Q,X=document.cookie.split(/;\s+/).find((M)=>M.startsWith(L+"="))?.split("=")[1]??S();if(document.cookie=L+"="+X,z&&!(z in Z)){if(O.postMessage({from:W,key:z}),await new Promise((M)=>setTimeout(()=>M(""),100)),!(z in Z))Q=(M)=>M+"+"+H}if(!Q){if(!z)do z=S();while(z in Z);let M=Z.getItem(z),Y=M?JSON.parse(M):[void 0];if(G)Y.splice(...G),Z.setItem(z,JSON.stringify(Y));Q=($)=>{let R=parseInt($);return V(JSON.stringify([X,z,R,Y.length,Y[R-1],Y[R]]))}}let D=C?`${C}%5B${F}%5D`:F,E=new RegExp(`(?<=\\?.*)(\\b${D}=)(\\d+)`);for(let M of q.querySelectorAll("a[href]"))M.href=M.href.replace(E,(Y,$,R)=>`${$}${Q(R)}`);return Q},x=(q,[[z,C,F,H,G],Q,[X,D,E],M])=>{let Y=q.parentElement,$=-1;if((q.render=()=>{let R=X.findIndex((j)=>j<Y.clientWidth);if(X[R]===$)return;let U=z;if(D[R].forEach((j,I)=>{U+=j=="gap"?H:(typeof j=="number"?C.replace(Q,j):F).replace("L<",E?.[R][I]??j+"<")}),U+=G,q.innerHTML="",q.insertAdjacentHTML("afterbegin",U),$=X[R],M&&B)J(q,M)})(),q.classList.contains(L+"-rjs"))P.observe(Y)},T=async(q,[z,C,F])=>{let H=F&&B?await J(q,F):(G)=>G;N(q,(G)=>z.replace(C,H(G)))},A=(q,[z,C,F,H])=>{N(q,(G)=>{return C.replace(F,Math.max(Math.ceil(z/parseInt(G)),1)).replace(H,G)})},N=(q,z)=>{let C=q.querySelector("input"),F=q.querySelector("a"),H=C.value,G=()=>{if(C.value===H)return;let[Q,X,D]=[C.min,C.value,C.max].map((E)=>parseInt(E)||0);if(X<Q||X>D){C.value=H,C.select();return}F.href=z(C.value),F.click()};C.addEventListener("focus",()=>C.select()),C.addEventListener("focusout",G),C.addEventListener("keypress",(Q)=>{if(Q.key=="Enter")G()})};return{version:"43.2.5",init(q){let z=q instanceof HTMLElement?q:document,C=z.querySelectorAll("[data-pagy]");for(let F of C)try{let[H,...G]=JSON.parse(_(F.getAttribute("data-pagy")));if(H=="k")J(F,...G);else if(H=="snj")x(F,G);else if(H=="inj")T(F,G);else if(H=="ltj")A(F,G)}catch(H){console.warn(`Pagy.init: %o
2
2
  %s`,F,H)}}}})();
data/javascripts/pagy.mjs CHANGED
@@ -125,7 +125,7 @@ const Pagy = (() => {
125
125
  });
126
126
  };
127
127
  return {
128
- version: "43.2.3",
128
+ version: "43.2.5",
129
129
  init(arg) {
130
130
  const target = arg instanceof HTMLElement ? arg : document, elements = target.querySelectorAll("[data-pagy]");
131
131
  for (const element of elements) {
@@ -36,26 +36,25 @@ class Pagy
36
36
  private
37
37
 
38
38
  # Return calendar, from, to
39
- def init(...)
40
- new.send(:init, ...)
41
- end
39
+ def init(...) = new.send(:init, ...)
42
40
  end
43
41
 
44
42
  # Return the current time of the smallest time unit shown
45
- def showtime
46
- self[@units.last].from
47
- end
43
+ def showtime = self[@units.last].from
48
44
 
49
45
  # Return the url for the calendar (shortest unit) page at time
50
46
  def url_at(time, **)
51
- conf = Marshal.load(Marshal.dump(@conf))
52
47
  page_keys = {}
53
- @units.inject(nil) do |object, unit|
54
- conf[unit][:period] = object&.send(:active_period) || @period
55
- conf[unit][:page] = page_keys["#{unit}_#{@page_key}"] \
56
- = create(unit, **conf[unit]).send(:page_at, time, **)
57
- conf[unit][:querify] = ->(params) { params.merge!(page_keys) }
58
- create(unit, **conf[unit])
48
+
49
+ @units.inject(nil) do |parent, unit|
50
+ unit_conf = @conf[unit]
51
+ unit_conf[:period] = parent&.send(:active_period) || @period
52
+ unit_conf[:page] = page = create(unit, **unit_conf).send(:page_at, time, **)
53
+
54
+ page_keys["#{unit}_#{@page_key}"] = page
55
+ unit_conf[:querify] = ->(params) { params.merge!(page_keys) }
56
+
57
+ create(unit, **unit_conf)
59
58
  end.send(:compose_page_url, 1, **)
60
59
  end
61
60
 
@@ -63,34 +62,41 @@ class Pagy
63
62
 
64
63
  # Create the calendar
65
64
  def init(conf, period, params)
66
- @conf = Marshal.load(Marshal.dump(conf)) # store a copy
67
- @units = Calendar::UNITS & @conf.keys # get the units in time length desc order
65
+ @conf = conf
66
+ @units = Calendar::UNITS & conf.keys # get the units in time length desc order
68
67
  @period = period
69
68
  @params = params
70
69
  @page_key = conf[:offset][:page_key] || DEFAULT[:page_key]
70
+
71
71
  # set all the :page_key options for later deletion
72
72
  @units.each { |unit| conf[unit][:page_key] = "#{unit}_#{@page_key}" }
73
- calendar = {}
74
- object = nil
73
+
74
+ calendar = {}
75
+ unit_object = nil
76
+
75
77
  @units.each_with_index do |unit, index|
76
- params_to_delete = @units[(index + 1), @units.length].map { |sub| conf[sub][:page_key] } + [@page_key]
77
- conf[unit][:querify] = ->(up) { up.except!(*params_to_delete.map(&:to_s)) }
78
- conf[unit][:period] = object&.send(:active_period) || @period
79
- conf[unit][:page] = @params["#{unit}_#{@page_key}"] # requested page
78
+ params_to_delete = @units[(index + 1)..].map { conf[_1][:page_key] } + [@page_key]
79
+ unit_conf = conf[unit]
80
+ unit_conf[:querify] = ->(up) { up.except!(*params_to_delete.map(&:to_s)) }
81
+ unit_conf[:period] = unit_object&.send(:active_period) || @period
82
+ unit_conf[:page] = @params[unit_conf[:page_key]] # requested page
80
83
  # :nocov:
81
84
  # simplecov doesn't need to fail block_given?
82
- conf[unit][:counts] = yield(unit, conf[unit][:period]) if block_given?
85
+ unit_conf[:counts] = yield(unit, unit_conf[:period]) if block_given?
83
86
  # :nocov:
84
- calendar[unit] = object = create(unit, **conf[unit])
87
+ calendar[unit] = unit_object = create(unit, **unit_conf)
85
88
  end
86
- [replace(calendar), object.from, object.to]
89
+
90
+ [replace(calendar), unit_object.from, unit_object.to]
87
91
  end
88
92
 
89
93
  # Create a unit subclass instance by using the unit name (internal use)
90
94
  def create(unit, **)
91
95
  raise InternalError, "unit must be in #{UNITS.inspect}; got #{unit}" unless UNITS.include?(unit)
92
96
 
93
- Pagy::Calendar.const_get(unit.to_s.capitalize).new(**, request: @conf[:request])
97
+ unit_class = Pagy::Calendar.const_get(unit.to_s.capitalize)
98
+
99
+ unit_class.new(**, request: @conf[:request])
94
100
  end
95
101
  end
96
102
  end
@@ -10,7 +10,7 @@ class Pagy
10
10
  # To define a "bimester" unit you should:
11
11
  # - Define a `Pagy::Calendar::Bimester` class
12
12
  # - Add the `:bimester` unit symbol in the `Pagy::Calendar::UNITS`
13
- # - Ensure the desc durtion order of the UNITS (i.e. insert it between `:quarter` and `:month`)
13
+ # - Ensure the desc duration order of the UNITS (i.e. insert it between `:quarter` and `:month`)
14
14
  class Unit < Pagy
15
15
  DEFAULT = { page: 1 }.freeze
16
16
 
@@ -21,7 +21,10 @@ class Pagy
21
21
  assign_options(**)
22
22
  assign_and_check(page: 1)
23
23
  assign_unit_variables
24
- return unless in_range? { @page <= @last }
24
+ unless in_range? { @page <= @last }
25
+ assign_empty_page_variables
26
+ return
27
+ end
25
28
 
26
29
  assign_previous_and_next
27
30
  end
@@ -60,13 +63,13 @@ class Pagy
60
63
  def assign_unit_variables
61
64
  @order = @options[:order]
62
65
  @starting, @ending = @options[:period]
63
- raise OptionError.new(self, :period, 'to be a an Array of min and max TimeWithZone instances', @options[:period]) \
66
+ raise OptionError.new(self, :period, 'to be an Array of min and max TimeWithZone instances', @options[:period]) \
64
67
  unless @starting.is_a?(ActiveSupport::TimeWithZone) \
65
68
  && @ending.is_a?(ActiveSupport::TimeWithZone) && @starting <= @ending
66
69
  end
67
70
 
68
71
  # Apply the strftime format to the time.
69
- # Localization other than :en, require the rails-I18n gem.
72
+ # Localization other than :en, requires the rails-I18n gem.
70
73
  def localize(time, **options)
71
74
  # Impossible to "unprepend" the rails-i18n after it runs localize_with_rails_i18n_gem in test
72
75
  # :nocov:
@@ -10,6 +10,7 @@ class Pagy
10
10
  @pagy = pagy
11
11
  @option = option
12
12
  @value = value
13
+
13
14
  super("expected :#{@option} #{description}; got #{@value.inspect}")
14
15
  end
15
16
  end
@@ -13,7 +13,9 @@ class Pagy
13
13
  end
14
14
 
15
15
  # Get the keyset attributes from a record
16
- def keyset_attributes_from(record) = record.slice(*@keyset.keys)
16
+ def keyset_attributes_from(record)
17
+ record.slice(*@keyset.keys)
18
+ end
17
19
 
18
20
  # Get the hash of quoted keyset identifiers
19
21
  def quoted_identifiers(table)
@@ -22,7 +22,9 @@ class Pagy
22
22
  end
23
23
 
24
24
  # Get the keyset attributes from a record
25
- def keyset_attributes_from(record) = record.to_hash.slice(*@keyset.keys)
25
+ def keyset_attributes_from(record)
26
+ record.to_hash.slice(*@keyset.keys)
27
+ end
26
28
 
27
29
  # Get the hash of quoted keyset identifiers
28
30
  def quoted_identifiers(table)
@@ -52,6 +52,7 @@ class Pagy
52
52
  else
53
53
  @page = @last = 1
54
54
  end
55
+
55
56
  @update = [storage_key, @options[:root_key], @options[:page_key]]
56
57
  end
57
58
 
@@ -62,11 +63,13 @@ class Pagy
62
63
  # Compound predicate for visited pages
63
64
  predicate = +''
64
65
  arguments = {}
66
+
65
67
  if @prior_cutoff # not the first page
66
68
  # Include the records after @prior_cutoff
67
69
  predicate << "(#{compose_predicate(PRIOR_PREFIX)}) AND "
68
70
  arguments.merge!(arguments_from(@prior_cutoff, PRIOR_PREFIX))
69
71
  end
72
+
70
73
  # Exclude the records after @page_cutoff
71
74
  predicate << "NOT (#{compose_predicate(PAGE_PREFIX)})"
72
75
  arguments.merge!(arguments_from(@page_cutoff, PAGE_PREFIX))