pagy 43.2.2 → 43.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a8e46eb6e0538fa7b8f8bf5eeffd17dbe5699a878a11fbb56c0d87e2d4cdf231
4
- data.tar.gz: 5e7ff81fdefb19102cfd91e3b6863a98ef2b82a28b393e8a6ae9c9c6523a3637
3
+ metadata.gz: ccb42c6368e3fa431f97d6be3b7f89122ae7b3e4cf2bff5748fb7ea978c2382b
4
+ data.tar.gz: 465601dc8f911ef033ca3aa18dc714515c840a2cf8fdcd005fc2e82be99b9d96
5
5
  SHA512:
6
- metadata.gz: 64d39bdf7be486eab1372e065dbed034f601b05d5293145f45c6b53e8098619ca5896332370566dd8a540d62781e055564005c61ee4f572bf613fea542effd75
7
- data.tar.gz: 5c9a71e48ca7d133e7240ac587cd429a28875d0c8b857b426fa331c266fc66483884ba4e16cec7a03734ef2b3547a0ccce29f61dddd07436b715431c2b1a7796
6
+ metadata.gz: 59459274129f2b25073ccdaf5bc1bd0323f5cfa95fefb69121e51e08e6ad84254524e4c708cea293920bc693187fff0806244d82d497d44513d97463aa2e2647
7
+ data.tar.gz: 1c2b1356ec82ce9a582f2ea75bcb9e7340ec9d3ff6f190858b2af039d3f361c350d779db5e170003318624af3c53c974c00cf5865eb0915318dca8da576da59a
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2017-2025 Domizio Demichelis
3
+ Copyright (c) 2017-2026 Domizio Demichelis
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
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.2'
19
+ VERSION = '43.2.4'
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.2'
22
+ VERSION = '43.2.4'
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")
@@ -16,7 +16,7 @@
16
16
  # URL
17
17
  # http://127.0.0.1:8000
18
18
 
19
- VERSION = '43.2.2'
19
+ VERSION = '43.2.4'
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.2'
19
+ VERSION = '43.2.4'
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.2'
19
+ VERSION = '43.2.4'
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.2'
19
+ VERSION = '43.2.4'
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.2'
19
+ VERSION = '43.2.4'
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.2'
19
+ VERSION = '43.2.4'
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.2)
3
+ # Pagy initializer file (43.2.4)
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.2",
129
+ version: "43.2.4",
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=98E0CC9BFBB1A85D64756E2164756E21
153
+ //# debugId=5554FC8F70F87D9964756E2164756E21
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.2\",\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.4\",\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": ";AA+CA,IAAM,QAAQ,MAAM;AAAA,EAClB,MAAM,iBAAiB,oBAAoB,UAAU,sBAAsB;AAAA,EAE3E,IAAI,OAAO,QAAQ,SAAkB,MAAwB;AAAA,EAC7D,IAAI,gBAAgB;AAAA,IAClB,UAAU;AAAA,IACV,OAAU,IAAI,iBAAiB,IAAI;AAAA,IACnC,QAAU,KAAK,IAAI;AAAA,IAEnB,KAAK,iBAAiB,WAAW,CAAC,MAA6B;AAAA,MAC7D,IAAI,EAAE,KAAK,MAAM;AAAA,QACf,MAAM,UAAU,QAAQ,QAAQ,EAAE,KAAK,GAAG;AAAA,QAC1C,IAAI,SAAS;AAAA,UACX,KAAK,YAAsB,EAAC,IAAI,EAAE,KAAK,MAAM,KAAK,EAAE,KAAK,KAAK,KAAK,QAAO,CAAC;AAAA,QAC7E;AAAA,MACF,EAAO,SAAI,EAAE,KAAK,IAAI;AAAA,QACpB,IAAI,EAAE,KAAK,MAAM,OAAO;AAAA,UACtB,QAAQ,QAAQ,EAAE,KAAK,KAAa,EAAE,KAAK,GAAG;AAAA,QAChD;AAAA,MACF;AAAA,KACD;AAAA,EACH;AAAA,EAEA,MAAM,cAAc,IAAI,eACpB,aAAW,QAAQ,QAAQ,OAAK;AAAA,IAC9B,EAAE,OAAO,iBAA+B,WAAW,EAAE,QAAQ,QAAM,GAAG,OAAO,CAAC;AAAA,GAC/E,CAAC;AAAA,EAUN,MAAM,gBAAgB,CAAC,YAAmB,KAAK,OAAO,aAAa,GAAI,IAAI,cAAa,OAAO,OAAO,CAAC,CAAC,EAC7D,QAAQ,UAAU,CAAC,MAAM,KAAK,MAAM,MAAM,KAAK,MAAM,MAAM,EAAE,GAClG,YAAgB,CAAC,WAAoB,IAAI,YAAY,EAAG,OAAO,WAAW,KAAK,KAAK,MAAM,GAAG,OAAK,EAAE,WAAW,CAAC,CAAC,CAAC;AAAA,EAGxH,MAAM,UAAU,MAAM,KAAK,MAAM,KAAK,OAAO,IAAI,MAAM,CAAC,EAAE,SAAS,EAAE;AAAA,EAGrE,MAAM,gBAA+B,OAAO,MAAM,YAAY,SAAS,SAAS,MAAM,gBAAgB;AAAA,IACpG,IAAI;AAAA,IACJ,MAAM,aAAa,SAAS,OAAO,MAAM,MAAM,EACnB,KAAK,CAAC,QAAQ,IAAI,WAAW,OAAO,GAAG,CAAC,GACvC,MAAM,GAAG,EAAE,MAAM,QAAQ;AAAA,IACtD,SAAS,SAAS,OAAO,MAAM;AAAA,IAC/B,IAAI,cAAc,EAAE,cAAc,UAAU;AAAA,MAE1C,KAAK,YAAsB,EAAE,MAAM,OAAO,KAAK,WAAW,CAAC;AAAA,MAE3D,MAAM,IAAI,QAAqB,CAAC,YAAY,WAAW,MAAM,QAAQ,EAAE,GAAG,GAAG,CAAC;AAAA,MAC9E,IAAI,EAAE,cAAc,UAAU;AAAA,QAC5B,cAAc,CAAC,SAAiB,OAAO,MAAM;AAAA,MAC/C;AAAA,IACF;AAAA,IAEA,IAAI,CAAC,aAAa;AAAA,MAChB,IAAI,CAAC,YAAY;AAAA,QAAE,GAAG;AAAA,UAAE,aAAa,QAAQ;AAAA,QAAE,SAAS,cAAc;AAAA,MAAS;AAAA,MAC/E,MAAM,OAAO,QAAQ,QAAQ,UAAU,GACnC,UAAqB,OAAO,KAAK,MAAM,IAAI,IAAI,CAAC,SAAS;AAAA,MAC7D,IAAI,YAAY;AAAA,QACd,QAAQ,OAAO,GAAG,UAAU;AAAA,QAC5B,QAAQ,QAAQ,YAAY,KAAK,UAAU,OAAO,CAAC;AAAA,MACrD;AAAA,MAEA,cAAc,CAAC,SAAgB;AAAA,QAC7B,MAAM,UAAU,SAAS,IAAI;AAAA,QAC7B,OAAO,cAAc,KAAK,UACP;AAAA,UAAC;AAAA,UACA;AAAA,UACA;AAAA,UACA,QAAQ;AAAA,UACR,QAAQ,UAAU;AAAA,UAClB,QAAQ;AAAA,QAAQ,CAAC,CAAC;AAAA;AAAA,IAE1C;AAAA,IACA,MAAM,SAAU,UAAW,GAAG,aAAa,eAAe;AAAA,IAC1D,MAAM,KAAS,IAAI,OAAO,iBAAiB,gBAAgB;AAAA,IAE3D,WAAW,KAA6C,IAAI,iBAAiB,SAAS,GAAG;AAAA,MACvF,EAAE,OAAO,EAAE,KAAK,QAAQ,IAAI,CAAC,QAAQ,QAAQ,UAAkB,GAAG,SAAS,YAAoB,KAAK,GAAG;AAAA,IACzG;AAAA,IAEA,OAAO;AAAA;AAAA,EAIT,MAAM,aAAa,CAAC;AAAA,KAAoB,QAAQ,QAAQ,SAAS,KAAK;AAAA,IAAQ;AAAA,KACvC,QAAQ,QAAQ;AAAA,IAAS;AAAA,QAAgC;AAAA,IAC9F,MAAO,SAAsB,IAAI;AAAA,IACjC,IAAI,YAAY;AAAA,KACf,IAAI,SAAS,MAAM;AAAA,MAClB,MAAM,QAAQ,OAAO,UAAU,OAAK,IAAI,OAAO,WAAW;AAAA,MAC1D,IAAI,OAAO,WAAW,WAAW;AAAA,QAAE;AAAA,MAAO;AAAA,MAE1C,IAAI,OAAO;AAAA,MACX,OAAO,OAAO,QAAQ,CAAC,MAAM,MAAM;AAAA,QAEjC,QAAQ,QAAQ,QAAQ,OAEf,OAAO,QAAQ,WAAW,OAAO,QAAQ,WAAW,IAAI,IAAI,SACxD,QAAQ,MAAM,SAAS,OAAO,MAAM,OAAO,GAAG;AAAA,OAC5D;AAAA,MACD,QAAgB;AAAA,MAChB,IAAI,YAAY;AAAA,MAChB,IAAI,mBAAmB,cAAc,IAAI;AAAA,MACzC,YAAY,OAAO;AAAA,MACnB,IAAI,cAAc,gBAAgB;AAAA,QAAO,cAAc,KAAK,UAAU;AAAA,MAAE;AAAA,OACvE;AAAA,IACH,IAAI,IAAI,UAAU,SAAS,OAAO,MAAM,GAAG;AAAA,MAAE,YAAY,QAAQ,MAAM;AAAA,IAAE;AAAA;AAAA,EAI3E,MAAM,iBAAiB,OAAO,MAAkB,WAAW,WAAW,gBAA+B;AAAA,IACnG,MAAM,UAAU,cAAc,iBACZ,MAAM,cAAc,KAAK,UAAU,IACnC,CAAC,SAAiB;AAAA,IACpC,UAAU,KAAK,gBAAc,UAAU,QAAQ,WAAW,QAAQ,UAAU,CAAC,CAAC;AAAA;AAAA,EAIhF,MAAM,iBAAiB,CAAC,OAAuB,MAAM,WAAW,YAAY,gBAA+B;AAAA,IACzG,UAAU,MAAM,gBAAc;AAAA,MAE5B,OAAO,UAAU,QAAQ,YAAY,KAAK,IAAI,KAAK,KAAK,OAAO,SAAS,UAAU,CAAC,GAAG,CAAC,CAAC,EACvE,QAAQ,YAAY,UAAU;AAAA,KAChD;AAAA;AAAA,EAIH,MAAM,YAAY,CAAC,SAAqB,WAAgC;AAAA,IACtE,MAAM,QAA4B,QAAQ,cAAc,OAAO,GACzD,OAA6B,QAAQ,cAAc,GAAG,GACtD,UAAU,MAAM,OAChB,SAAU,MAAM;AAAA,MACJ,IAAI,MAAM,UAAU,SAAS;AAAA,QAAE;AAAA,MAAO;AAAA,MACtC,OAAO,KAAK,KAAK,OAAO,CAAC,MAAM,KAAK,MAAM,OAAO,MAAM,GAAG,EAAE,IAAI,OAAK,SAAS,CAAC,KAAK,CAAC;AAAA,MACrF,IAAI,MAAM,OAAO,MAAM,KAAK;AAAA,QAC1B,MAAM,QAAQ;AAAA,QACd,MAAM,OAAO;AAAA,QACb;AAAA,MACF;AAAA,MACA,KAAK,OAAO,OAAO,MAAM,KAAK;AAAA,MAC9B,KAAK,MAAM;AAAA;AAAA,IAE7B,MAAM,iBAAiB,SAAS,MAAM,MAAM,OAAO,CAAC;AAAA,IACpD,MAAM,iBAAiB,YAAY,MAAM;AAAA,IACzC,MAAM,iBAAiB,YAAY,OAAK;AAAA,MAAE,IAAI,EAAE,OAAO,SAAS;AAAA,QAAE,OAAO;AAAA,MAAE;AAAA,KAAG;AAAA;AAAA,EAIhF,OAAO;AAAA,IACL,SAAS;AAAA,IAGT,IAAI,CAAC,KAAkB;AAAA,MACrB,MAAM,SAAW,eAAe,cAAc,MAAM,UAC9C,WAAW,OAAO,iBAAiB,aAAa;AAAA,MACtD,WAAW,WAAoC,UAAU;AAAA,QACvD,IAAI;AAAA,UACF,OAAO,aAAa,QAAkB,KAAK,MAAM,UAAkB,QAAQ,aAAa,WAAW,CAAC,CAAC;AAAA,UACrG,IAAI,YAAY,KAAK;AAAA,YAEd,cAAc,SAAS,GAAwB,IAAI;AAAA,UAC1D,EAAO,SAAI,YAAY,OAAO;AAAA,YAC5B,WAAyB,SAAmC,IAAI;AAAA,UAClE,EAAO,SAAI,YAAY,OAAO;AAAA,YACvB,eAAe,SAAkC,IAAI;AAAA,UAC5D,EAAO,SAAI,YAAY,OAAO;AAAA,YAC5B,eAAe,SAAkC,IAAI;AAAA,UACvD;AAAA,UAEA,OAAO,KAAK;AAAA,UAAE,QAAQ,KAAK;AAAA,KAAqB,SAAS,GAAG;AAAA;AAAA,MAChE;AAAA;AAAA,EAEJ;AAAA,GACC;",
8
- "debugId": "98E0CC9BFBB1A85D64756E2164756E21",
8
+ "debugId": "5554FC8F70F87D9964756E2164756E21",
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.2",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.4",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.2",
128
+ version: "43.2.4",
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) {
@@ -3,7 +3,7 @@
3
3
  class Pagy
4
4
  class Calendar
5
5
  class Day < Unit
6
- DEFAULT = { slots: 31,
6
+ DEFAULT = { slots: 31,
7
7
  compact: true,
8
8
  order: :asc,
9
9
  format: '%d' }.freeze
@@ -3,7 +3,7 @@
3
3
  class Pagy # :nodoc:
4
4
  class Calendar # :nodoc:
5
5
  class Month < Unit
6
- DEFAULT = { slots: 12,
6
+ DEFAULT = { slots: 12,
7
7
  compact: true,
8
8
  order: :asc,
9
9
  format: '%b' }.freeze
@@ -3,7 +3,7 @@
3
3
  class Pagy # :nodoc:
4
4
  class Calendar # :nodoc:
5
5
  class Quarter < Unit
6
- DEFAULT = { slots: 4,
6
+ DEFAULT = { slots: 4,
7
7
  compact: true,
8
8
  order: :asc,
9
9
  format: 'Q%q' }.freeze # '%q' token
@@ -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
 
@@ -60,13 +60,13 @@ class Pagy
60
60
  def assign_unit_variables
61
61
  @order = @options[:order]
62
62
  @starting, @ending = @options[:period]
63
- raise OptionError.new(self, :period, 'to be a an Array of min and max TimeWithZone instances', @options[:period]) \
63
+ raise OptionError.new(self, :period, 'to be an Array of min and max TimeWithZone instances', @options[:period]) \
64
64
  unless @starting.is_a?(ActiveSupport::TimeWithZone) \
65
65
  && @ending.is_a?(ActiveSupport::TimeWithZone) && @starting <= @ending
66
66
  end
67
67
 
68
68
  # Apply the strftime format to the time.
69
- # Localization other than :en, require the rails-I18n gem.
69
+ # Localization other than :en, requires the rails-I18n gem.
70
70
  def localize(time, **options)
71
71
  # Impossible to "unprepend" the rails-i18n after it runs localize_with_rails_i18n_gem in test
72
72
  # :nocov:
@@ -4,7 +4,7 @@ class Pagy # :nodoc:
4
4
  class Calendar # :nodoc:
5
5
  # Year unit subclass
6
6
  class Year < Unit
7
- DEFAULT = { slots: 10,
7
+ DEFAULT = { slots: 10,
8
8
  compact: true,
9
9
  order: :asc,
10
10
  format: '%Y' }.freeze
@@ -36,7 +36,7 @@ class Pagy
36
36
  @count = 0 if fetched_size.zero? && @page == 1
37
37
  return self unless in_range? { fetched_size.positive? || @page == 1 }
38
38
 
39
- past = @last && @page < @last # this page has been past
39
+ past = @last && @page < @last # current page is before the known last page
40
40
  more = fetched_size > @limit # more pages after this one
41
41
  @last = upto_max_pages(more ? @page + 1 : @page) unless past && more
42
42
  @in = [fetched_size, @limit].min
@@ -20,8 +20,7 @@ class Pagy
20
20
  def resolve_page(force_integer: true)
21
21
  page_key = @options[:page_key] || DEFAULT[:page_key]
22
22
  page = @params.dig(@options[:root_key], page_key) || @params[page_key]
23
- page = nil if page == '' # fix for app-generated queries like ?page=
24
- force_integer ? (page || 1).to_i : page
23
+ force_integer ? [page.to_i, 1].max : page
25
24
  end
26
25
 
27
26
  def resolve_limit
data/lib/pagy/cli.rb CHANGED
@@ -8,7 +8,6 @@ require_relative '../../apps/index'
8
8
 
9
9
  class Pagy
10
10
  class CLI
11
- LINUX = RbConfig::CONFIG['host_os'].include?('linux')
12
11
  HOST = 'localhost'
13
12
  PORT = '8000'
14
13
 
@@ -20,8 +19,7 @@ class Pagy
20
19
  private
21
20
 
22
21
  def parse_options(args)
23
- options = { env: 'development', host: HOST, port: PORT,
24
- rerun: false, clear: false, quiet: false }
22
+ options = { env: 'development', host: HOST, port: PORT, quiet: false }
25
23
 
26
24
  parser = OptionParser.new do |opts|
27
25
  opts.banner = <<~BANNER
@@ -48,12 +46,6 @@ class Pagy
48
46
  opts.on('-o', '--host HOST', 'Host') { |v| options[:host] = v }
49
47
  opts.on('-p', '--port PORT', 'Port') { |v| options[:port] = v }
50
48
 
51
- if LINUX
52
- opts.separator "\nRerun options"
53
- opts.on('--rerun', 'Enable rerun for development') { options[:rerun] = true }
54
- opts.on('--clear', 'Clear screen before each rerun') { options[:clear] = true }
55
- end
56
-
57
49
  opts.separator "\nOther options"
58
50
  opts.on('-q', '--quiet', 'Quiet mode for development') { options[:quiet] = true }
59
51
  opts.on('-v', '--version', 'Show version') do
@@ -94,7 +86,7 @@ class Pagy
94
86
  if arg.eql?('clone')
95
87
  clone_app(args.shift)
96
88
  else
97
- serve_app(arg, options, run_from_repo)
89
+ serve_app(arg, options)
98
90
  end
99
91
  end
100
92
 
@@ -109,10 +101,9 @@ class Pagy
109
101
  FileUtils.cp(PagyApps::INDEX[name], '.', verbose: true)
110
102
  end
111
103
 
112
- def serve_app(arg, options, run_from_repo)
104
+ def serve_app(arg, options)
113
105
  if PagyApps::INDEX.key?(arg)
114
106
  options[:env] = 'showcase'
115
- options[:rerun] = false
116
107
  options[:quiet] = true
117
108
  # Avoid the creation of './tmp/local_secret.txt' for showcase env
118
109
  ENV['SECRET_KEY_BASE'] = 'absolute secret!' if arg.eql?('rails')
@@ -126,20 +117,7 @@ class Pagy
126
117
  rackup = "rackup -I #{gem_dir}/lib -r pagy -o #{options[:host]} -p #{options[:port]} -E #{options[:env]} #{file}"
127
118
  rackup << ' -q' if options[:quiet]
128
119
 
129
- if options[:rerun]
130
- name = File.basename(file)
131
- dir = File.dirname(file)
132
- rerun = if run_from_repo
133
- "rerun --name #{name} -d #{dir},#{gem_dir} -p **/*.{rb,js,css,scss,ru,yml}"
134
- else
135
- "rerun --name #{name} -d #{dir} -p #{name}"
136
- end
137
- rerun << ' -q' if options[:quiet]
138
- rerun << ' -c' if options[:clear]
139
- rerun << " -- #{rackup}"
140
- end
141
-
142
- exec(rerun || rackup)
120
+ exec(rackup)
143
121
  end
144
122
 
145
123
  # Kept as a separate method because mocking 'gemfile' (dsl) is complex otherwise
@@ -149,7 +127,6 @@ class Pagy
149
127
  source 'https://rubygems.org'
150
128
  gem 'logger'
151
129
  gem 'rackup'
152
- gem 'rerun' if LINUX
153
130
  end
154
131
  end
155
132
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Pagy
4
- # Add configurstion methods
4
+ # Add configuration methods
5
5
  module Configurable
6
6
  # Sync the pagy javascript targets
7
7
  def sync_javascript(destination, *targets)
@@ -38,7 +38,7 @@ class Pagy
38
38
 
39
39
  protected
40
40
 
41
- # Overriddable by classes with composite page param
41
+ # Overridable by classes with composite page param
42
42
  def compose_page_param(page) = page
43
43
 
44
44
  # Return the URL for the page, relying on the Pagy::Request
@@ -13,7 +13,7 @@ class Pagy
13
13
 
14
14
  # Return a performance optimized lambda to generate the anchor tag
15
15
  # Benchmarked on a 20 link nav: it is ~22x faster and uses ~18x less memory than rails' link_to
16
- def a_lambda(anchor_string: nil, **)
16
+ def a_lambda(anchor_string: @options[:anchor_string], **)
17
17
  left, right = %(<a href="#{compose_page_url(PAGE_TOKEN, **)}"#{
18
18
  %( #{anchor_string}) if anchor_string}).split(PAGE_TOKEN, 2)
19
19
 
data/lib/pagy.rb CHANGED
@@ -8,7 +8,7 @@ require_relative 'pagy/toolbox/helpers/loader'
8
8
 
9
9
  # Top superclass: it defines only what's common to all the subclasses
10
10
  class Pagy
11
- VERSION = '43.2.2'
11
+ VERSION = '43.2.4'
12
12
  ROOT = Pathname.new(__dir__).parent.freeze
13
13
  DEFAULT = { limit: 20, limit_key: 'limit', page_key: 'page' }.freeze
14
14
  PAGE_TOKEN = EscapedValue.new('P ')
@@ -25,7 +25,7 @@
25
25
  --background-input: hsl(var(--H) var(--S) calc(var(--L) + (45 * var(--B))));
26
26
  --opacity: 1;
27
27
 
28
- @apply flex space-x-[var(--spacing)] font-[var(--font-weight)]
28
+ @apply flex gap-x-[var(--spacing)] font-[var(--font-weight)]
29
29
  text-[length:var(--font-size)] text-[var(--text)]
30
30
  leading-[var(--line-height)];
31
31
 
data/stylesheets/pagy.css CHANGED
@@ -28,12 +28,7 @@
28
28
  }
29
29
 
30
30
  .pagy > :not([hidden]) ~ :not([hidden]) {
31
- margin-left: calc(var(--spacing) * (1 - var(--space-reverse, 0)));
32
- margin-right: calc(var(--spacing) * var(--space-reverse, 0));
33
- }
34
-
35
- .rtl .pagy > :not([hidden]) ~ :not([hidden]) {
36
- --space-reverse: 1;
31
+ margin-inline-start: var(--spacing);
37
32
  }
38
33
 
39
34
  .pagy a:not([role="separator"]) { /* all but gaps */
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pagy
3
3
  version: !ruby/object:Gem::Version
4
- version: 43.2.2
4
+ version: 43.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Domizio Demichelis
@@ -202,7 +202,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
202
202
  - !ruby/object:Gem::Version
203
203
  version: '0'
204
204
  requirements: []
205
- rubygems_version: 3.6.9
205
+ rubygems_version: 4.0.3
206
206
  specification_version: 4
207
207
  summary: "Pagy \U0001F438 The Leaping Gem!"
208
208
  test_files: []