From daad628ef1eef06f65a1760d3661cac4a526329c Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Sat, 6 Apr 2024 16:39:33 +0700
Subject: [PATCH 01/11] Improve release automation
---
.github/latest_release_body.md | 2 +-
scripts/version-bump.sh | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/latest_release_body.md b/.github/latest_release_body.md
index a7de6819e..b1689d802 100644
--- a/.github/latest_release_body.md
+++ b/.github/latest_release_body.md
@@ -11,7 +11,7 @@ If you wish to keep your favorites alive, please, [vote here](https://github.com
your side (try the [pagy demo](https://ddnexus.github.io/pagy/playground.md#3-demo-app))
- See the [CHANGELOG](https://ddnexus.github.io/pagy/changelog) for possible breaking changes
-### Changes
+### Changes in 8.0.2
- Minor change in rails app and RM run config
diff --git a/scripts/version-bump.sh b/scripts/version-bump.sh
index 92d231588..5de3a4109 100755
--- a/scripts/version-bump.sh
+++ b/scripts/version-bump.sh
@@ -29,6 +29,7 @@ function bump(){
bump "$ROOT/retype.yml"
bump "$ROOT/.github/ISSUE_TEMPLATE/Code.yml"
+bump "$ROOT/.github/latest_release_body.md"
bump "$ROOT/gem/apps/calendar.ru"
bump "$ROOT/gem/apps/demo.ru"
bump "$ROOT/gem/apps/rails.ru"
From a9cd810d799497f98d6984c0c9e984a88a8f19cd Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Sat, 6 Apr 2024 18:59:09 +0700
Subject: [PATCH 02/11] Removed redundant @pages, aliased with @last
---
CHANGELOG.md | 3 ++-
docs/api/pagy.md | 7 +++----
gem/lib/pagy.rb | 18 ++++++++++--------
gem/lib/pagy/calendar.rb | 4 ++--
gem/lib/pagy/calendar/day.rb | 2 +-
gem/lib/pagy/calendar/month.rb | 2 +-
gem/lib/pagy/calendar/quarter.rb | 2 +-
gem/lib/pagy/calendar/week.rb | 2 +-
gem/lib/pagy/calendar/year.rb | 2 +-
gem/lib/pagy/countless.rb | 12 ++++++------
gem/lib/pagy/extras/gearbox.rb | 26 +++++++++++++-------------
test/pagy/extras/gearbox_test.rb | 2 +-
12 files changed, 42 insertions(+), 40 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ec023372d..29b7ef3c0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,7 +25,8 @@ If you upgrade from version `< 8.0.0` see the following:
## Deprecations
-None
+- Protected method `Pagy#setup_pages_var`. Use `Pagy#setup_last_var` instead
+
## Version 8.0.2
diff --git a/docs/api/pagy.md b/docs/api/pagy.md
index 5cea8a693..1a891973c 100644
--- a/docs/api/pagy.md
+++ b/docs/api/pagy.md
@@ -166,9 +166,9 @@ or `nil`), except the `vars` hash:
| `count` | The collection `:count` |
| `page` | The current page number |
| `items` | The requested number of items for the page |
-| `pages` | The number of total pages in the collection (same as `last` but with cardinal meaning) |
| `in` | The number of the items in the page |
-| `last` | The number of the last page in the collection (same as `pages` but with ordinal meaning) |
+| `last` | The number of the last page in the collection (ordinal meaning) |
+| `pages` | Alias for `last` (cardinal meaning) |
| `offset` | The number of items skipped from the collection in order to get the start of the current page (`:outset` included) |
| `from` | The collection-position of the first item in the page (`:outset` excluded) |
| `to` | The collection-position of the last item in the page (`:outset` excluded) |
@@ -187,7 +187,6 @@ the following peculiar attributes:
|:----------|:--------|
| `count` | `0` |
| `page` | `1` |
-| `pages` | `1` |
| `last` | `1` |
| `in` | `0` |
| `from` | `0` |
@@ -199,7 +198,7 @@ the following peculiar attributes:
Which means:
- there is always a `page` #`1` in the pagination, even if it's empty
-- `pages` and `last` are always at least both `1`
+- `last` is always at least `1`
- the `series` array contains always at least the page #`1`, which for a single page is also the current page, thus a string.
With `size: []` the `series` method returns `[]`
- `in`, `from` and `to` of an empty page are all `0`
diff --git a/gem/lib/pagy.rb b/gem/lib/pagy.rb
index 9155a94a2..84f2a496a 100644
--- a/gem/lib/pagy.rb
+++ b/gem/lib/pagy.rb
@@ -28,14 +28,15 @@ def self.root
# frontend/helpers
anchor_string: nil }
- attr_reader :count, :page, :items, :vars, :pages, :last, :offset, :in, :from, :to, :prev, :next, :params, :request_path
+ attr_reader :count, :page, :items, :vars, :last, :offset, :in, :from, :to, :prev, :next, :params, :request_path
+ alias pages last
# Merge and validate the options, do some simple arithmetic and set the instance variables
def initialize(vars)
normalize_vars(vars)
setup_vars(count: 0, page: 1, outset: 0)
setup_items_var
- setup_pages_var
+ setup_last_var
setup_offset_var
setup_params_var
setup_request_path_var
@@ -71,12 +72,12 @@ def series(size: @vars[:size], **_)
series.push(*start..@last)
elsif size.is_a?(Integer) && size.positive? # only central series
# The simplest and fastest algorithm
- size = @pages if size > @pages # reduce the max size to @pages
+ size = @last if size > @last # reduce the max size to @last
left = ((size - 1) / 2.0).floor # left half might be 1 page shorter for even size
start = if @page <= left # beginning pages
1
- elsif @page > @pages - (size - left) # end pages
- @pages - size + 1
+ elsif @page > @last - (size - left) # end pages
+ @last - size + 1
else # intermediate pages
@page - left
end
@@ -120,10 +121,11 @@ def setup_items_var
setup_vars(items: 1)
end
- # Setup @pages and @last (overridden by the gearbox extra)
- def setup_pages_var
- @pages = @last = [(@count.to_f / @items).ceil, 1].max
+ # Setup @last and @last (overridden by the gearbox extra)
+ def setup_last_var
+ @last = [(@count.to_f / @items).ceil, 1].max
end
+ alias setup_pages_var setup_last_var
# Setup @offset based on the :gearbox_items variable
def setup_offset_var
diff --git a/gem/lib/pagy/calendar.rb b/gem/lib/pagy/calendar.rb
index af73c71e8..53a618c74 100644
--- a/gem/lib/pagy/calendar.rb
+++ b/gem/lib/pagy/calendar.rb
@@ -67,7 +67,7 @@ def page_at(time, **opts)
Warning.warn "Pagy::Calendar#page_at: Rescued #{time} out of range by returning the #{ordinal} page."
end
offset = page_offset_at(fit_time) # offset starts from 0
- @order == :asc ? offset + 1 : @pages - offset
+ @order == :asc ? offset + 1 : @last - offset
end
# Base class method for the setup of the unit variables (subclasses must implement it and call super)
@@ -90,7 +90,7 @@ def localize(time, opts)
# Number of time units to offset from the @initial time, in order to get the ordered starting time for the page.
# Used in starting_time_for(page) where page starts from 1 (e.g. page to starting_time means subtracting 1)
def time_offset_for(page)
- @order == :asc ? page - 1 : @pages - page
+ @order == :asc ? page - 1 : @last - page
end
# Period of the active page (used internally for nested units)
diff --git a/gem/lib/pagy/calendar/day.rb b/gem/lib/pagy/calendar/day.rb
index 5815583f9..34575e705 100644
--- a/gem/lib/pagy/calendar/day.rb
+++ b/gem/lib/pagy/calendar/day.rb
@@ -16,7 +16,7 @@ def setup_unit_vars
super
@initial = @starting.beginning_of_day
@final = @ending.tomorrow.beginning_of_day
- @pages = @last = page_offset(@initial, @final)
+ @last = page_offset(@initial, @final)
@from = starting_time_for(@page)
@to = @from.tomorrow
end
diff --git a/gem/lib/pagy/calendar/month.rb b/gem/lib/pagy/calendar/month.rb
index 9f256877a..7761b88be 100644
--- a/gem/lib/pagy/calendar/month.rb
+++ b/gem/lib/pagy/calendar/month.rb
@@ -16,7 +16,7 @@ def setup_unit_vars
super
@initial = @starting.beginning_of_month
@final = @ending.next_month.beginning_of_month
- @pages = @last = (months_in(@final) - months_in(@initial))
+ @last = (months_in(@final) - months_in(@initial))
@from = starting_time_for(@page)
@to = @from.next_month
end
diff --git a/gem/lib/pagy/calendar/quarter.rb b/gem/lib/pagy/calendar/quarter.rb
index 811111abf..135fbcb87 100644
--- a/gem/lib/pagy/calendar/quarter.rb
+++ b/gem/lib/pagy/calendar/quarter.rb
@@ -23,7 +23,7 @@ def setup_unit_vars
super
@initial = @starting.beginning_of_quarter
@final = @ending.next_quarter.beginning_of_quarter
- @pages = @last = (months_in(@final) - months_in(@initial)) / 3
+ @last = (months_in(@final) - months_in(@initial)) / 3
@from = starting_time_for(@page)
@to = @from.next_quarter
end
diff --git a/gem/lib/pagy/calendar/week.rb b/gem/lib/pagy/calendar/week.rb
index 8fb165a74..00d0eada5 100644
--- a/gem/lib/pagy/calendar/week.rb
+++ b/gem/lib/pagy/calendar/week.rb
@@ -15,7 +15,7 @@ def setup_unit_vars
super
@initial = @starting.beginning_of_week
@final = @ending.next_week.beginning_of_week
- @pages = @last = page_offset(@initial, @final)
+ @last = page_offset(@initial, @final)
@from = starting_time_for(@page)
@to = @from.next_week
end
diff --git a/gem/lib/pagy/calendar/year.rb b/gem/lib/pagy/calendar/year.rb
index e48f2b117..42eabbece 100644
--- a/gem/lib/pagy/calendar/year.rb
+++ b/gem/lib/pagy/calendar/year.rb
@@ -16,7 +16,7 @@ def setup_unit_vars
super
@initial = @starting.beginning_of_year
@final = @ending.next_year.beginning_of_year
- @pages = @last = @final.year - @initial.year
+ @last = @final.year - @initial.year
@from = starting_time_for(@page)
@to = @from.next_year
end
diff --git a/gem/lib/pagy/countless.rb b/gem/lib/pagy/countless.rb
index ca6e8b247..3fb99f2d3 100644
--- a/gem/lib/pagy/countless.rb
+++ b/gem/lib/pagy/countless.rb
@@ -19,12 +19,12 @@ def initialize(vars = {}) # rubocop:disable Lint/MissingSuper
def finalize(fetched_size)
raise OverflowError.new(self, :page, "to be < #{@page}", @page) if fetched_size.zero? && @page > 1
- @pages = @last = (fetched_size > @items ? @page + 1 : @page)
- @in = [fetched_size, @items].min
- @from = @in.zero? ? 0 : @offset - @outset + 1
- @to = @offset - @outset + @in
- @prev = (@page - 1 unless @page == 1)
- @next = @page == @last ? (1 if @vars[:cycle]) : @page + 1
+ @last = (fetched_size > @items ? @page + 1 : @page)
+ @in = [fetched_size, @items].min
+ @from = @in.zero? ? 0 : @offset - @outset + 1
+ @to = @offset - @outset + @in
+ @prev = (@page - 1 unless @page == 1)
+ @next = @page == @last ? (1 if @vars[:cycle]) : @page + 1
self
end
diff --git a/gem/lib/pagy/extras/gearbox.rb b/gem/lib/pagy/extras/gearbox.rb
index 19822cc90..374f70e4b 100644
--- a/gem/lib/pagy/extras/gearbox.rb
+++ b/gem/lib/pagy/extras/gearbox.rb
@@ -19,23 +19,23 @@ def setup_items_var
@items = gearbox_items[@page - 1] || gearbox_items.last
end
- # Setup @pages and @last based on the :gearbox_items variable (not used by Pagy::Countless)
- def setup_pages_var
+ # Setup @last based on the :gearbox_items variable (not used by Pagy::Countless)
+ def setup_last_var
return super if !@vars[:gearbox_extra] || @vars[:items_extra]
gearbox_items = @vars[:gearbox_items]
# This algorithm is thousands of times faster than the one in the geared_pagination gem
- @pages = @last = (if @count > (sum = gearbox_items.sum)
- [((@count - sum).to_f / gearbox_items.last).ceil, 1].max + gearbox_items.count
- else
- pages = 0
- remainder = @count
- while remainder.positive?
- pages += 1
- remainder -= gearbox_items[pages - 1]
- end
- [pages, 1].max
- end)
+ @last = (if @count > (sum = gearbox_items.sum)
+ [((@count - sum).to_f / gearbox_items.last).ceil, 1].max + gearbox_items.count
+ else
+ pages = 0
+ remainder = @count
+ while remainder.positive?
+ pages += 1
+ remainder -= gearbox_items[pages - 1]
+ end
+ [pages, 1].max
+ end)
end
# Setup @offset based on the :gearbox_items variable
diff --git a/test/pagy/extras/gearbox_test.rb b/test/pagy/extras/gearbox_test.rb
index 4d4108de0..b7b271341 100644
--- a/test/pagy/extras/gearbox_test.rb
+++ b/test/pagy/extras/gearbox_test.rb
@@ -51,7 +51,7 @@
end
end
- describe '#setup_pages_var' do
+ describe '#setup_last_var' do
it 'can skip gearbox for pages' do
_(Pagy.new(count: 90, page: 1, items_extra: true).pages).must_equal 5
_(Pagy.new(count: 103, page: 1, gearbox_extra: false).pages).must_equal 6
From 575ae82131e533f7ccee4ff7b8fe52517e3dd5a2 Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Sat, 6 Apr 2024 19:35:20 +0700
Subject: [PATCH 03/11] Fix old link_extra arg in tests
---
gem/config/pagy.rb | 16 +++++------
test/pagy/backend_test.rb | 16 +++++------
test/pagy/extras/arel_test.rb | 16 +++++------
test/pagy/extras/array_test.rb | 10 +++----
test/pagy/extras/elasticsearch_rails_test.rb | 30 ++++++++++----------
test/pagy/extras/meilisearch_test.rb | 18 ++++++------
test/pagy/extras/searchkick_test.rb | 18 ++++++------
7 files changed, 62 insertions(+), 62 deletions(-)
diff --git a/gem/config/pagy.rb b/gem/config/pagy.rb
index 0ad70d0dc..79b754385 100644
--- a/gem/config/pagy.rb
+++ b/gem/config/pagy.rb
@@ -18,14 +18,14 @@
# Other Variables
# See https://ddnexus.github.io/pagy/docs/api/pagy#other-variables
-# Pagy::DEFAULT[:size] = [1,4,4,1] # default in pagy < 7.0
-# Pagy::DEFAULT[:page_param] = :page # default
-# Pagy::DEFAULT[:fragment] = '#fragment' # example
-# Pagy::DEFAULT[:link_extra] = 'data-remote="true"' # example
-# Pagy::DEFAULT[:cycle] = true # example
-# Pagy::DEFAULT[:request_path] = '/foo' # example
-# Pagy::DEFAULT[:count_args] = [] # example for non AR ORMs
-# Pagy::DEFAULT[:params] = {} # default
+# Pagy::DEFAULT[:size] = [1,4,4,1] # default in pagy < 7.0
+# Pagy::DEFAULT[:page_param] = :page # default
+# Pagy::DEFAULT[:fragment] = '#fragment' # example
+# Pagy::DEFAULT[:anchor_string] = 'data-remote="true"' # example
+# Pagy::DEFAULT[:cycle] = true # example
+# Pagy::DEFAULT[:request_path] = '/foo' # example
+# Pagy::DEFAULT[:count_args] = [] # example for non AR ORMs
+# Pagy::DEFAULT[:params] = {} # default
# NOTICE: The :params can be also set as a lambda e.g:
# ->(params){ params.exclude('useless').merge!('custom' => 'useful') }
diff --git a/test/pagy/backend_test.rb b/test/pagy/backend_test.rb
index 5536ab1b8..64d50e104 100644
--- a/test/pagy/backend_test.rb
+++ b/test/pagy/backend_test.rb
@@ -22,12 +22,12 @@
_(records).must_equal [41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]
end
it 'paginates with vars' do
- pagy, records = app.send(:pagy, @collection, page: 2, items: 10, link_extra: 'X')
+ pagy, records = app.send(:pagy, @collection, page: 2, items: 10, anchor_string: 'X')
_(pagy).must_be_instance_of Pagy
_(pagy.count).must_equal 1000
_(pagy.items).must_equal 10
_(pagy.page).must_equal 2
- _(pagy.vars[:link_extra]).must_equal 'X'
+ _(pagy.vars[:anchor_string]).must_equal 'X'
_(records.count).must_equal 10
_(records).must_equal [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
end
@@ -46,30 +46,30 @@
_(merged[:page]).must_equal 3
end
it 'gets vars' do
- vars = { page: 2, items: 10, link_extra: 'X' }
+ vars = { page: 2, items: 10, anchor_string: 'X' }
merged = app.send :pagy_get_vars, @collection, vars
_(merged.keys).must_include :count
_(merged.keys).must_include :page
_(merged.keys).must_include :items
- _(merged.keys).must_include :link_extra
+ _(merged.keys).must_include :anchor_string
_(merged[:count]).must_equal 1000
_(merged[:page]).must_equal 2
_(merged[:items]).must_equal 10
- _(merged[:link_extra]).must_equal 'X'
+ _(merged[:anchor_string]).must_equal 'X'
end
it 'works with grouped collections' do
collection = MockCollection::Grouped.new((1..1000).to_a)
- vars = { page: 2, items: 10, link_extra: 'X' }
+ vars = { page: 2, items: 10, anchor_string: 'X' }
merged = app.send :pagy_get_vars, collection, vars
_(collection.count.size).must_equal 1000
_(merged.keys).must_include :count
_(merged.keys).must_include :page
_(merged.keys).must_include :items
- _(merged.keys).must_include :link_extra
+ _(merged.keys).must_include :anchor_string
_(merged[:count]).must_equal 1000
_(merged[:page]).must_equal 2
_(merged[:items]).must_equal 10
- _(merged[:link_extra]).must_equal 'X'
+ _(merged[:anchor_string]).must_equal 'X'
end
it 'overrides count and page' do
vars = { count: 10, page: 32 }
diff --git a/test/pagy/extras/arel_test.rb b/test/pagy/extras/arel_test.rb
index 7247a0d52..b08be2545 100644
--- a/test/pagy/extras/arel_test.rb
+++ b/test/pagy/extras/arel_test.rb
@@ -24,12 +24,12 @@
_(items).must_equal [41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]
end
it 'paginates with vars' do
- pagy, items = app.send(:pagy_arel, @collection, page: 2, items: 10, link_extra: 'X')
+ pagy, items = app.send(:pagy_arel, @collection, page: 2, items: 10, anchor_string: 'X')
_(pagy).must_be_instance_of Pagy
_(pagy.count).must_equal 1000
_(pagy.items).must_equal 10
_(pagy.page).must_equal 2
- _(pagy.vars[:link_extra]).must_equal 'X'
+ _(pagy.vars[:anchor_string]).must_equal 'X'
_(items.size).must_equal 10
_(items).must_equal [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
end
@@ -48,29 +48,29 @@
_(merged[:page]).must_equal 3
end
it 'gets vars' do
- vars = { page: 2, items: 10, link_extra: 'X' }
+ vars = { page: 2, items: 10, anchor_string: 'X' }
merged = app.send :pagy_arel_get_vars, @collection, vars
_(merged.keys).must_include :count
_(merged.keys).must_include :page
_(merged.keys).must_include :items
- _(merged.keys).must_include :link_extra
+ _(merged.keys).must_include :anchor_string
_(merged[:count]).must_equal 1000
_(merged[:page]).must_equal 2
_(merged[:items]).must_equal 10
- _(merged[:link_extra]).must_equal 'X'
+ _(merged[:anchor_string]).must_equal 'X'
end
it 'works with grouped collections' do
collection = MockCollection::Grouped.new((1..1000).to_a)
- vars = { page: 2, items: 10, link_extra: 'X' }
+ vars = { page: 2, items: 10, anchor_string: 'X' }
merged = app.send :pagy_arel_get_vars, collection, vars
_(merged.keys).must_include :count
_(merged.keys).must_include :page
_(merged.keys).must_include :items
- _(merged.keys).must_include :link_extra
+ _(merged.keys).must_include :anchor_string
_(merged[:count]).must_equal 1000
_(merged[:page]).must_equal 2
_(merged[:items]).must_equal 10
- _(merged[:link_extra]).must_equal 'X'
+ _(merged[:anchor_string]).must_equal 'X'
end
it 'overrides count and page' do
vars = { count: 10, page: 32 }
diff --git a/test/pagy/extras/array_test.rb b/test/pagy/extras/array_test.rb
index a96c3538c..de8ab5327 100644
--- a/test/pagy/extras/array_test.rb
+++ b/test/pagy/extras/array_test.rb
@@ -22,12 +22,12 @@
_(items).must_equal [41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]
end
it 'paginates with vars' do
- pagy, items = app.send(:pagy_array, @collection, page: 2, items: 10, link_extra: 'X')
+ pagy, items = app.send(:pagy_array, @collection, page: 2, items: 10, anchor_string: 'X')
_(pagy).must_be_instance_of Pagy
_(pagy.count).must_equal 1000
_(pagy.items).must_equal 10
_(pagy.page).must_equal 2
- _(pagy.vars[:link_extra]).must_equal 'X'
+ _(pagy.vars[:anchor_string]).must_equal 'X'
_(items.count).must_equal 10
_(items).must_equal [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
end
@@ -46,16 +46,16 @@
_(merged[:page]).must_equal 3
end
it 'gets vars' do
- vars = { page: 2, items: 10, link_extra: 'X' }
+ vars = { page: 2, items: 10, anchor_string: 'X' }
merged = app.send :pagy_array_get_vars, @collection, vars
_(merged.keys).must_include :count
_(merged.keys).must_include :page
_(merged.keys).must_include :items
- _(merged.keys).must_include :link_extra
+ _(merged.keys).must_include :anchor_string
_(merged[:count]).must_equal 1000
_(merged[:page]).must_equal 2
_(merged[:items]).must_equal 10
- _(merged[:link_extra]).must_equal 'X'
+ _(merged[:anchor_string]).must_equal 'X'
end
end
end
diff --git a/test/pagy/extras/elasticsearch_rails_test.rb b/test/pagy/extras/elasticsearch_rails_test.rb
index a53276caa..42a997866 100644
--- a/test/pagy/extras/elasticsearch_rails_test.rb
+++ b/test/pagy/extras/elasticsearch_rails_test.rb
@@ -53,24 +53,24 @@
it 'paginates with vars' do
pagy, records = app.send(:pagy_elasticsearch_rails,
MockElasticsearchRails::Model.pagy_search('b').records,
- page: 2, items: 10, link_extra: 'X')
+ page: 2, items: 10, anchor_string: 'X')
_(pagy).must_be_instance_of Pagy
_(pagy.count).must_equal 1000
_(pagy.items).must_equal 10
_(pagy.page).must_equal 2
- _(pagy.vars[:link_extra]).must_equal 'X'
+ _(pagy.vars[:anchor_string]).must_equal 'X'
_(records.count).must_equal 10
_(records).must_rematch :records
end
it 'paginates with overflow' do
pagy, records = app.send(:pagy_elasticsearch_rails,
MockElasticsearchRails::Model.pagy_search('b').records,
- page: 200, items: 10, link_extra: 'X', overflow: :last_page)
+ page: 200, items: 10, anchor_string: 'X', overflow: :last_page)
_(pagy).must_be_instance_of Pagy
_(pagy.count).must_equal 1000
_(pagy.items).must_equal 10
_(pagy.page).must_equal 100
- _(pagy.vars[:link_extra]).must_equal 'X'
+ _(pagy.vars[:anchor_string]).must_equal 'X'
_(records.count).must_equal 10
_(records).must_rematch :records
end
@@ -103,24 +103,24 @@
it 'paginates with vars' do
pagy, records = app.send(:pagy_elasticsearch_rails,
MockElasticsearchRails::ModelES7.pagy_search('b').records,
- page: 2, items: 10, link_extra: 'X')
+ page: 2, items: 10, anchor_string: 'X')
_(pagy).must_be_instance_of Pagy
_(pagy.count).must_equal 1000
_(pagy.items).must_equal 10
_(pagy.page).must_equal 2
- _(pagy.vars[:link_extra]).must_equal 'X'
+ _(pagy.vars[:anchor_string]).must_equal 'X'
_(records.count).must_equal 10
_(records).must_rematch :records
end
it 'paginates with overflow' do
pagy, records = app.send(:pagy_elasticsearch_rails,
MockElasticsearchRails::Model.pagy_search('b').records,
- page: 200, items: 10, link_extra: 'X', overflow: :last_page)
+ page: 200, items: 10, anchor_string: 'X', overflow: :last_page)
_(pagy).must_be_instance_of Pagy
_(pagy.count).must_equal 1000
_(pagy.items).must_equal 10
_(pagy.page).must_equal 100
- _(pagy.vars[:link_extra]).must_equal 'X'
+ _(pagy.vars[:anchor_string]).must_equal 'X'
_(records.count).must_equal 10
_(records).must_rematch :records
end
@@ -136,14 +136,14 @@
_(merged[:items]).must_equal 20
end
it 'gets vars' do
- vars = { page: 2, items: 10, link_extra: 'X' }
+ vars = { page: 2, items: 10, anchor_string: 'X' }
merged = app.send :pagy_elasticsearch_rails_get_vars, nil, vars
_(merged.keys).must_include :page
_(merged.keys).must_include :items
- _(merged.keys).must_include :link_extra
+ _(merged.keys).must_include :anchor_string
_(merged[:page]).must_equal 2
_(merged[:items]).must_equal 10
- _(merged[:link_extra]).must_equal 'X'
+ _(merged[:anchor_string]).must_equal 'X'
end
end
@@ -158,12 +158,12 @@
end
it 'paginates response with vars' do
response = MockElasticsearchRails::Model.search('b', from: 15, size: 15)
- pagy = Pagy.new_from_elasticsearch_rails(response, link_extra: 'X')
+ pagy = Pagy.new_from_elasticsearch_rails(response, anchor_string: 'X')
_(pagy).must_be_instance_of Pagy
_(pagy.count).must_equal 1000
_(pagy.items).must_equal 15
_(pagy.page).must_equal 2
- _(pagy.vars[:link_extra]).must_equal 'X'
+ _(pagy.vars[:anchor_string]).must_equal 'X'
end
it 'paginates response with defaults on Elasticsearch 5' do
response = MockElasticsearchRails::ModelES5.search('a')
@@ -175,12 +175,12 @@
end
it 'paginates response with vars on Elasticsearch 5' do
response = MockElasticsearchRails::ModelES5.search('b', from: 15, size: 15)
- pagy = Pagy.new_from_elasticsearch_rails(response, link_extra: 'X')
+ pagy = Pagy.new_from_elasticsearch_rails(response, anchor_string: 'X')
_(pagy).must_be_instance_of Pagy
_(pagy.count).must_equal 1000
_(pagy.items).must_equal 15
_(pagy.page).must_equal 2
- _(pagy.vars[:link_extra]).must_equal 'X'
+ _(pagy.vars[:anchor_string]).must_equal 'X'
end
end
end
diff --git a/test/pagy/extras/meilisearch_test.rb b/test/pagy/extras/meilisearch_test.rb
index df307fcae..8bfa57742 100644
--- a/test/pagy/extras/meilisearch_test.rb
+++ b/test/pagy/extras/meilisearch_test.rb
@@ -38,23 +38,23 @@
end
it 'paginates with vars' do
pagy, results = app.send(:pagy_meilisearch, MockMeilisearch::Model.pagy_search('b'),
- page: 2, items: 10, link_extra: 'X')
+ page: 2, items: 10, anchor_string: 'X')
_(pagy).must_be_instance_of Pagy
_(pagy.count).must_equal 1000
_(pagy.items).must_equal 10
_(pagy.page).must_equal 2
- _(pagy.vars[:link_extra]).must_equal 'X'
+ _(pagy.vars[:anchor_string]).must_equal 'X'
_(results.length).must_equal 10
_(results.to_a).must_rematch :results
end
it 'paginates with overflow' do
pagy, results = app.send(:pagy_meilisearch, MockMeilisearch::Model.pagy_search('b'),
- page: 200, items: 10, link_extra: 'X', overflow: :last_page)
+ page: 200, items: 10, anchor_string: 'X', overflow: :last_page)
_(pagy).must_be_instance_of Pagy
_(pagy.count).must_equal 1000
_(pagy.items).must_equal 10
_(pagy.page).must_equal 100
- _(pagy.vars[:link_extra]).must_equal 'X'
+ _(pagy.vars[:anchor_string]).must_equal 'X'
_(results.length).must_equal 10
_(results.to_a).must_rematch :results
end
@@ -70,14 +70,14 @@
_(merged[:items]).must_equal 20
end
it 'gets vars' do
- vars = { page: 2, items: 10, link_extra: 'X' }
+ vars = { page: 2, items: 10, anchor_string: 'X' }
merged = app.send :pagy_meilisearch_get_vars, nil, vars
_(merged.keys).must_include :page
_(merged.keys).must_include :items
- _(merged.keys).must_include :link_extra
+ _(merged.keys).must_include :anchor_string
_(merged[:page]).must_equal 2
_(merged[:items]).must_equal 10
- _(merged[:link_extra]).must_equal 'X'
+ _(merged[:anchor_string]).must_equal 'X'
end
end
@@ -92,12 +92,12 @@
end
it 'paginates results with vars' do
results = MockMeilisearch::Model.ms_search('b', hits_per_page: 15, page: 3)
- pagy = Pagy.new_from_meilisearch(results, link_extra: 'X')
+ pagy = Pagy.new_from_meilisearch(results, anchor_string: 'X')
_(pagy).must_be_instance_of Pagy
_(pagy.count).must_equal 1000
_(pagy.items).must_equal 15
_(pagy.page).must_equal 3
- _(pagy.vars[:link_extra]).must_equal 'X'
+ _(pagy.vars[:anchor_string]).must_equal 'X'
end
end
end
diff --git a/test/pagy/extras/searchkick_test.rb b/test/pagy/extras/searchkick_test.rb
index d586f586e..722322f95 100644
--- a/test/pagy/extras/searchkick_test.rb
+++ b/test/pagy/extras/searchkick_test.rb
@@ -64,23 +64,23 @@
end
it 'paginates with vars' do
pagy, results = app.send(:pagy_searchkick, MockSearchkick::Model.pagy_search('b').results,
- page: 2, items: 10, link_extra: 'X')
+ page: 2, items: 10, anchor_string: 'X')
_(pagy).must_be_instance_of Pagy
_(pagy.count).must_equal 1000
_(pagy.items).must_equal 10
_(pagy.page).must_equal 2
- _(pagy.vars[:link_extra]).must_equal 'X'
+ _(pagy.vars[:anchor_string]).must_equal 'X'
_(results.count).must_equal 10
_(results).must_rematch :results
end
it 'paginates with overflow' do
pagy, results = app.send(:pagy_searchkick, MockSearchkick::Model.pagy_search('b').results,
- page: 200, items: 10, link_extra: 'X', overflow: :last_page)
+ page: 200, items: 10, anchor_string: 'X', overflow: :last_page)
_(pagy).must_be_instance_of Pagy
_(pagy.count).must_equal 1000
_(pagy.items).must_equal 10
_(pagy.page).must_equal 100
- _(pagy.vars[:link_extra]).must_equal 'X'
+ _(pagy.vars[:anchor_string]).must_equal 'X'
_(results.count).must_equal 10
_(results).must_rematch :results
end
@@ -96,14 +96,14 @@
_(merged[:items]).must_equal 20
end
it 'gets vars' do
- vars = { page: 2, items: 10, link_extra: 'X' }
+ vars = { page: 2, items: 10, anchor_string: 'X' }
merged = app.send :pagy_searchkick_get_vars, nil, vars
_(merged.keys).must_include :page
_(merged.keys).must_include :items
- _(merged.keys).must_include :link_extra
+ _(merged.keys).must_include :anchor_string
_(merged[:page]).must_equal 2
_(merged[:items]).must_equal 10
- _(merged[:link_extra]).must_equal 'X'
+ _(merged[:anchor_string]).must_equal 'X'
end
end
@@ -118,12 +118,12 @@
end
it 'paginates results with vars' do
results = MockSearchkick::Model.search('b', page: 2, per_page: 15)
- pagy = Pagy.new_from_searchkick(results, link_extra: 'X')
+ pagy = Pagy.new_from_searchkick(results, anchor_string: 'X')
_(pagy).must_be_instance_of Pagy
_(pagy.count).must_equal 1000
_(pagy.items).must_equal 15
_(pagy.page).must_equal 2
- _(pagy.vars[:link_extra]).must_equal 'X'
+ _(pagy.vars[:anchor_string]).must_equal 'X'
end
end
end
From 662ee68b6e0080a205c1a4135d9f37ad48dac4ed Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Sat, 6 Apr 2024 19:56:39 +0700
Subject: [PATCH 04/11] Fix minor string typos
---
src/main.js | 2 +-
test/README.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main.js b/src/main.js
index 98f36c167..1dea3abed 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,3 +1,3 @@
import Pagy from "./pagy-module";
-// Toplevel var (needed for generating the production file)
+// Toplevel var (needed to generate the production file)
window.Pagy = Pagy;
diff --git a/test/README.md b/test/README.md
index c631280e8..46170faf3 100644
--- a/test/README.md
+++ b/test/README.md
@@ -4,7 +4,7 @@ Ruby is tested with `minitest` through `rake` tasks.
## Run the Ruby tests
-Almost every test recreates a different environment and must run in a separate process in order to avoid to override other tests. That means that you can run a single test file (or a single spec in a test file) and it will be OK, but you cannot run a directory of test file, with a single minitest command because they will interfere with each other and will fail.
+Almost every test recreates a different environment and must run in a separate process in order to avoid to override other tests. That means that you can run a single test file (or a single spec in a test file) and it will be OK, but you cannot run a directory of test files, with a single minitest command because they will interfere with each other and will fail.
### Rake tasks
From e5aa702d05f1be2f49685fdcf34dd2efbdd40c00 Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Sat, 6 Apr 2024 20:08:41 +0700
Subject: [PATCH 05/11] Comment out the :performance gem group
---
Gemfile | 10 +++++-----
Gemfile.lock | 10 ----------
2 files changed, 5 insertions(+), 15 deletions(-)
diff --git a/Gemfile b/Gemfile
index 1f2b0a6df..12ee174ed 100644
--- a/Gemfile
+++ b/Gemfile
@@ -34,8 +34,8 @@ group :apps do
gem 'sinatra-contrib'
end
-group :performance do
- gem 'benchmark-ips'
- gem 'kalibera'
- gem 'memory_profiler'
-end
+# group :performance do
+# gem 'benchmark-ips'
+# gem 'kalibera'
+# gem 'memory_profiler'
+# end
diff --git a/Gemfile.lock b/Gemfile.lock
index 9f6f494e2..c088f753e 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -16,7 +16,6 @@ GEM
ansi (1.5.0)
ast (2.4.2)
base64 (0.2.0)
- benchmark-ips (2.13.0)
bigdecimal (3.1.7)
builder (3.2.4)
concurrent-ruby (1.2.3)
@@ -40,9 +39,6 @@ GEM
i18n (1.14.4)
concurrent-ruby (~> 1.0)
json (2.7.2)
- kalibera (0.1.2)
- memoist (~> 0.16)
- rbzip2 (~> 0.3)
language_server-protocol (3.17.0.3)
listen (3.9.0)
rb-fsevent (~> 0.10, >= 0.10.3)
@@ -50,8 +46,6 @@ GEM
llhttp-ffi (0.5.0)
ffi-compiler (~> 1.0)
rake (~> 13.0)
- memoist (0.16.2)
- memory_profiler (1.0.1)
minitest (5.22.3)
minitest-reporters (1.6.1)
ansi
@@ -87,7 +81,6 @@ GEM
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
- rbzip2 (0.3.0)
readline-ext (0.2.0)
regexp_parser (2.9.0)
rematch (2.1.0)
@@ -149,11 +142,8 @@ PLATFORMS
DEPENDENCIES
activesupport
- benchmark-ips
http
i18n
- kalibera
- memory_profiler
minitest
minitest-reporters
oj
From 70c75de7b81a8c1e6f69228744813c14b44ce054 Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Sun, 7 Apr 2024 11:36:52 +0700
Subject: [PATCH 06/11] Remove nil variables from DEFAULT
---
docs/api/pagy.md | 6 ++--
gem/lib/pagy.rb | 22 +++++-------
test/pagy/extras/metadata_test.rb.rematch | 43 +++++++++++------------
test/pagy_test.rb | 5 +--
4 files changed, 32 insertions(+), 44 deletions(-)
diff --git a/docs/api/pagy.md b/docs/api/pagy.md
index 1a891973c..f0c0edafe 100644
--- a/docs/api/pagy.md
+++ b/docs/api/pagy.md
@@ -147,7 +147,7 @@ They are all integers:
| `:size` | The size of the page links to show: can be an array of initial pages, before current page, after current page, final pages or the total page size. _(see also [How to control the page links](/docs/how-to.md#control-the-page-links))_ | `7` |
| `:page_param` | The name of the page param name used in the url. _(see [How to customize the page param](/docs/how-to.md#customize-the-page-param))_ | `:page` |
| `:params` | It can be a `Hash` of params to add to the URL, or a `Proc` that can edit/add/delete the request params _(see [How to customize the params](/docs/how-to.md#customize-the-params))_ | `{}` |
-| `:fragment` | The arbitrary fragment string (including the "#") to add to the url. _(see [How to customize the params](/docs/how-to.md#customize-the-params))_ | `''` |
+| `:fragment` | The arbitrary fragment string (including the "#") to add to the url. _(see [How to customize the params](/docs/how-to.md#customize-the-params))_ | `nil` |
| `:anchor_string` | The extra attributes string (formatted as a valid HTML attribute/value pairs) added to the page links _(see [How to customize the link attributes](/docs/how-to.md#customize-the-link-attributes))_ | `nil` |
| `:cycle` | Enable cycling/circular/infinite pagination: `true` sets `next` to `1` when the current page is the last page | `false` |
| `:request_path` | Allows overriding the request path for pagination links. Pass the path only (not the absolute url). _(see [Customize the request path](/docs/how-to.md#customize-the-request-path))_ | `nil` |
@@ -167,8 +167,8 @@ or `nil`), except the `vars` hash:
| `page` | The current page number |
| `items` | The requested number of items for the page |
| `in` | The number of the items in the page |
-| `last` | The number of the last page in the collection (ordinal meaning) |
-| `pages` | Alias for `last` (cardinal meaning) |
+| `last` | The number of the last page in the collection (ordinal meaning) |
+| `pages` | Alias for `last` (cardinal meaning) |
| `offset` | The number of items skipped from the collection in order to get the start of the current page (`:outset` included) |
| `from` | The collection-position of the first item in the page (`:outset` excluded) |
| `to` | The collection-position of the last item in the page (`:outset` excluded) |
diff --git a/gem/lib/pagy.rb b/gem/lib/pagy.rb
index 84f2a496a..79f0093f2 100644
--- a/gem/lib/pagy.rb
+++ b/gem/lib/pagy.rb
@@ -13,20 +13,14 @@ def self.root
end
# Core defult: constant for easy access, but mutable for customizable defaults
- DEFAULT = { page: 1, # rubocop:disable Style/MutableConstant
- items: 20,
- outset: 0,
- size: 7,
- cycle: false,
- # backend/collection
- count_args: [:all], # AR friendly
- # backend/url
- params: {},
- page_param: :page,
- fragment: '',
- request_path: nil,
- # frontend/helpers
- anchor_string: nil }
+ DEFAULT = { page: 1, # rubocop:disable Style/MutableConstant
+ items: 20,
+ outset: 0,
+ size: 7,
+ cycle: false,
+ count_args: [:all], # AR friendly
+ params: {},
+ page_param: :page }
attr_reader :count, :page, :items, :vars, :last, :offset, :in, :from, :to, :prev, :next, :params, :request_path
alias pages last
diff --git a/test/pagy/extras/metadata_test.rb.rematch b/test/pagy/extras/metadata_test.rb.rematch
index b43381efb..797a3890d 100644
--- a/test/pagy/extras/metadata_test.rb.rematch
+++ b/test/pagy/extras/metadata_test.rb.rematch
@@ -15,6 +15,26 @@ pagy/extras/metadata::#pagy_metadata for Pagy::Calendar#test_0002_returns only s
:prev: 2
:next: 4
:pages: 26
+pagy/extras/metadata::#pagy_metadata for Pagy#test_0001_defines all metadata:
+ :metadata:
+ - :scaffold_url
+ - :first_url
+ - :prev_url
+ - :page_url
+ - :next_url
+ - :last_url
+ - :count
+ - :page
+ - :items
+ - :vars
+ - :pages
+ - :last
+ - :in
+ - :from
+ - :to
+ - :prev
+ - :next
+ - :series
pagy/extras/metadata::#pagy_metadata for Pagy#test_0002_returns the full pagy metadata:
:metadata:
:scaffold_url: "/foo?page=__pagy_page__"
@@ -40,9 +60,6 @@ pagy/extras/metadata::#pagy_metadata for Pagy#test_0002_returns the full pagy me
- :all
:params: {}
:page_param: :page
- :fragment: ''
- :request_path:
- :anchor_string:
:countless_minimal: false
:steps: false
:metadata:
@@ -102,23 +119,3 @@ pagy/extras/metadata::#pagy_metadata for Pagy#test_0004_returns only specific me
:prev: 2
:next: 4
:pages: 50
-pagy/extras/metadata::#pagy_metadata for Pagy#test_0001_defines all metadata:
- :metadata:
- - :scaffold_url
- - :first_url
- - :prev_url
- - :page_url
- - :next_url
- - :last_url
- - :count
- - :page
- - :items
- - :vars
- - :pages
- - :last
- - :in
- - :from
- - :to
- - :prev
- - :next
- - :series
diff --git a/test/pagy_test.rb b/test/pagy_test.rb
index e436baeff..42ce5fa3c 100644
--- a/test/pagy_test.rb
+++ b/test/pagy_test.rb
@@ -304,7 +304,7 @@ def series_for(page, *expected)
end
it 'initializes the request_path' do
pagy = Pagy.new(count: 100, request_path: '/foo')
- _(pagy.request_path).must_equal('/foo')
+ _(pagy.vars[:request_path]).must_equal('/foo')
end
end
@@ -327,9 +327,6 @@ def series_for(page, *expected)
_(Pagy::DEFAULT[:size]).must_equal 7
_(Pagy::DEFAULT[:page_param]).must_equal :page
_(Pagy::DEFAULT[:params]).must_equal({})
- _(Pagy::DEFAULT[:fragment]).must_equal('')
- _(Pagy::DEFAULT[:request_path]).must_be_nil
- _(Pagy::DEFAULT[:anchor_string]).must_be_nil
end
end
From 8d0b15239b64016c92f3bdc93025390f78c43ef1 Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Sun, 7 Apr 2024 11:37:26 +0700
Subject: [PATCH 07/11] Improve efficiency of params in pagy_url_for
---
gem/lib/pagy/extras/standalone.rb | 4 ++--
gem/lib/pagy/url_helpers.rb | 16 ++++++++--------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/gem/lib/pagy/extras/standalone.rb b/gem/lib/pagy/extras/standalone.rb
index 25eb1018c..8f9524560 100644
--- a/gem/lib/pagy/extras/standalone.rb
+++ b/gem/lib/pagy/extras/standalone.rb
@@ -42,9 +42,9 @@ def pagy_url_for(pagy, page, absolute: false, **_)
return super unless pagy.vars[:url]
vars = pagy.vars
- params = pagy.params.is_a?(Hash) ? pagy.params.clone : {} # safe when it gets reused
+ params = vars[:params].is_a?(Hash) ? vars[:params].clone : {} # safe when it gets reused
pagy_set_query_params(page, vars, params)
- params = pagy.params.call(params) if pagy.params.is_a?(Proc)
+ params = vars[:params].(params) if vars[:params].is_a?(Proc)
query_string = "?#{QueryUtils.build_nested_query(params)}"
"#{vars[:url]}#{query_string}#{vars[:fragment]}"
end
diff --git a/gem/lib/pagy/url_helpers.rb b/gem/lib/pagy/url_helpers.rb
index c7ad4b200..34d64d78b 100644
--- a/gem/lib/pagy/url_helpers.rb
+++ b/gem/lib/pagy/url_helpers.rb
@@ -8,19 +8,19 @@ module UrlHelpers
# For non-rack environments you can use the standalone extra
def pagy_url_for(pagy, page, absolute: false, **_)
vars = pagy.vars
- pagy_params = pagy.params.is_a?(Hash) ? pagy.params.transform_keys(&:to_s) : {}
- params = request.GET.merge(pagy_params)
- pagy_set_query_params(page, vars, params)
- params = pagy.params.call(params) if pagy.params.is_a?(Proc)
- query_string = "?#{Rack::Utils.build_nested_query(params)}"
+ query_params = request.GET
+ query_params.merge!(vars[:params].transform_keys(&:to_s)) if vars[:params].is_a?(Hash)
+ pagy_set_query_params(page, vars, query_params)
+ query_params = vars[:params].(query_params) if vars[:params].is_a?(Proc)
+ query_string = "?#{Rack::Utils.build_nested_query(query_params)}"
"#{request.base_url if absolute}#{vars[:request_path] || request.path}#{query_string}#{vars[:fragment]}"
end
# Add the page and items params
# Overridable by the jsonapi extra
- def pagy_set_query_params(page, vars, params)
- params[vars[:page_param].to_s] = page
- params[vars[:items_param].to_s] = vars[:items] if vars[:items_extra]
+ def pagy_set_query_params(page, vars, query_params)
+ query_params[vars[:page_param].to_s] = page
+ query_params[vars[:items_param].to_s] = vars[:items] if vars[:items_extra]
end
end
end
From 1e4829fe6391a6c9dc48f00ba7bd9579bfea259b Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Tue, 9 Apr 2024 08:06:31 +0700
Subject: [PATCH 08/11] Improve code issue template
---
.github/ISSUE_TEMPLATE/Code.yml | 35 ++++++++++++++++++++++++++++++---
1 file changed, 32 insertions(+), 3 deletions(-)
diff --git a/.github/ISSUE_TEMPLATE/Code.yml b/.github/ISSUE_TEMPLATE/Code.yml
index bd5e7c0ff..d79bd6592 100644
--- a/.github/ISSUE_TEMPLATE/Code.yml
+++ b/.github/ISSUE_TEMPLATE/Code.yml
@@ -37,17 +37,46 @@ body:
OR it will be automatically closed!**
- #### Valid code files
+ #### VALID code files
- Edited copy of a single-file APP from the [Pagy Playground](https://ddnexus.github.io/pagy/playground)
- Link to a pagy fork containing an added test file
- - A plain ruby file that can run as a single command `ruby issue_123.rb`
+ - A plain ruby file that can run as a single command like `ruby my_issue.rb`
_(without any other setup step, installation or guessing, and with no or minimal interaction required)_
+ #### INVALID "code"
+
+
+ - EVERYTHING other than the above!
+
+ - Totally useless things like (but not limited to):
+
+ - Code snippets
+
+ - Multiple files
+
+ - Complex setup
+
+ - Complete applications
+
+ - Any description of errors generated by running your own code
+
+ - Rationalizations about "WHY" and "WHAT" you think it's a bug
+
+
+ Please, understand that we won't guess your environment/usage/configuration/conflicts out of some snippet
+ or description, nor clone/install/setup/debug your complete application.
+
+
+ Please, start from a [pagy APP](https://ddnexus.github.io/pagy/playground/#pagy-apps)
+ and add the minimum that makes it fail. It's a very simple process and, most of the times,
+ it will make your issue just "disappear". ;)
+
+
_If anything is unclear to you, please ask for [support](https://github.com/ddnexus/pagy/discussions/categories/q-a).
We will be happy to help._
@@ -66,7 +95,7 @@ body:
attributes:
label: Description
placeholder: >
- 1. Describe what actually happens
+ 1. Describe what actually happens WITH THE CODE FILE you provided
2. Describe what should happen instead
validations:
From 8929ab3aa0eade1cf672fc0577ab7acfd76fb898 Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Tue, 9 Apr 2024 08:07:03 +0700
Subject: [PATCH 09/11] Implement max_pages to limit the pagination regardless
the actual count
---
docs/api/pagy.md | 78 +++++++++++++++-----------------
docs/how-to.md | 47 +++++++++++++++----
gem/lib/pagy.rb | 4 +-
gem/lib/pagy/countless.rb | 5 +-
gem/lib/pagy/extras/gearbox.rb | 33 +++++++-------
test/pagy/extras/gearbox_test.rb | 35 +++++++++-----
test/pagy_test.rb | 8 +++-
7 files changed, 130 insertions(+), 80 deletions(-)
diff --git a/docs/api/pagy.md b/docs/api/pagy.md
index f0c0edafe..be88a980c 100644
--- a/docs/api/pagy.md
+++ b/docs/api/pagy.md
@@ -113,48 +113,44 @@ for `Pagy::Calendar` instances. It returns the page label that will get displaye
## Variables
-All the variables passed to the new method will be merged with the `Pagy::DEFAULT` hash and will be kept in the object, passed
+All the variables passed to the new method are merged with the `Pagy::DEFAULT` hash and are kept in the object, passed
around with it and accessible through the `pagy.vars` hash.
They can be set globally by using the `Pagy::DEFAULT` hash or passed to the `Pagy.new` method and are accessible through
the `vars` reader.
-**Notice**: Pagy replaces the blank values of the passed variables with their default values coming from the `Pagy::DEFAULT` hash.
-It also applies `to_i` on the values expected to be integers, so you can use values from request `params` without problems. For
-example: `pagy(some_scope, items: params[:items])` will work without any additional cleanup.
-
-### Instance Variables
+!!!success
+Pagy replaces the blank values of the passed variables with their default values coming from the `Pagy::DEFAULT` hash.
+It also applies `to_i` on the values expected to be integers, so you can use values from request `params` without any problem.
+For example: `pagy(some_scope, items: params[:items])` will work without any additional cleanup.
+!!!
-A few variables are particularly important for the calculation of the pagination, and therefore are validated and used to
-initialize a few instance variables.
+### Variables
The only mandatory instance variable to be passed is the `:count` of the collection to paginate: all the other variables are
optional and have sensible defaults. Of course you will also have to pass the `page` or you will always get the default page
number 1.
-They are all integers:
-
-| Variable | Description | Default |
-|:----------|:-----------------------------------------------------------------------------------------------|:--------|
-| `:count` | The total count of the collection to paginate (mandatory argument) | `nil` |
-| `:page` | The requested page number | `1` |
-| `:items` | The requested number of items for the page | `20` |
-| `:outset` | The initial offset of the collection to paginate: pass it only if the collection had an offset | `0` |
-
-### Other Variables
-
-| Variable | Description | Default |
-|:-----------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------|
-| `:size` | The size of the page links to show: can be an array of initial pages, before current page, after current page, final pages or the total page size. _(see also [How to control the page links](/docs/how-to.md#control-the-page-links))_ | `7` |
-| `:page_param` | The name of the page param name used in the url. _(see [How to customize the page param](/docs/how-to.md#customize-the-page-param))_ | `:page` |
-| `:params` | It can be a `Hash` of params to add to the URL, or a `Proc` that can edit/add/delete the request params _(see [How to customize the params](/docs/how-to.md#customize-the-params))_ | `{}` |
-| `:fragment` | The arbitrary fragment string (including the "#") to add to the url. _(see [How to customize the params](/docs/how-to.md#customize-the-params))_ | `nil` |
-| `:anchor_string` | The extra attributes string (formatted as a valid HTML attribute/value pairs) added to the page links _(see [How to customize the link attributes](/docs/how-to.md#customize-the-link-attributes))_ | `nil` |
-| `:cycle` | Enable cycling/circular/infinite pagination: `true` sets `next` to `1` when the current page is the last page | `false` |
-| `:request_path` | Allows overriding the request path for pagination links. Pass the path only (not the absolute url). _(see [Customize the request path](/docs/how-to.md#customize-the-request-path))_ | `nil` |
-| `jsonapi` | Enable `jsonapi` compliance of the pagy query params | `false` |
-| `count_args` | The arguments passed to the `collection.count`. You may want to set it to `[]` in ORMs different than ActiveRecord | [:all] |
-
-There is no specific validation for non-instance variables.
+
+| Variable | Description | Default |
+|:-----------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------|
+| `:anchor_string` | The extra attributes string (formatted as a valid HTML attribute/value pairs) added to the page links _(see [Customize the link attributes](/docs/how-to.md#customize-the-link-attributes))_ | `nil` |
+| `:count` | The total count of the collection to paginate (mandatory argument) | `nil` |
+| `:count_args` | The arguments passed to the `collection.count`. You may want to set it to `[]` in ORMs different than ActiveRecord | [:all] |
+| `:cycle` | Enable cycling/circular/infinite pagination: `true` sets `next` to `1` when the current page is the last page | `false` |
+| `:fragment` | The arbitrary fragment string (including the "#") to add to the url. _(see [Customize the params](/docs/how-to.md#customize-the-params))_ | `nil` |
+| `:items` | The requested number of items for the page | `20` |
+| `:jsonapi` | Enable `jsonapi` compliance of the pagy query params | `false` |
+| `:max_pages` | Paginate only `:max_pages`. _(see also [Paginate only max_pages](/docs/how-to.md#paginate-only-max_pages-regardless-the-count))_ | `nil` |
+| `:outset` | The initial offset of the collection to paginate: pass it only if the collection had an offset | `0` |
+| `:page` | The requested page number: extracted from the `request.params`, or forced by passeing a variable | `1` |
+| `:page_param` | The name of the page param name used in the url. _(see [Customize the page param](/docs/how-to.md#customize-the-page-param))_ | `:page` |
+| `:params` | It can be a `Hash` of params to add to the URL, or a `Proc` that can edit/add/delete the request params _(see [Customize the params](/docs/how-to.md#customize-the-params))_ | `{}` |
+| `:request_path` | Allows overriding the request path for pagination links. Pass the path only (not the absolute url). _(see [Customize the request path](/docs/how-to.md#customize-the-request-path))_ | `nil` |
+| `:size` | The size of the page links to show: can be an array of 4 items or the integer of the total page size. _(see also [Control the page links](/docs/how-to.md#control-the-page-links))_ | `7` |
+
+!!!
+Extras may add and document their own variables
+!!!
### Attribute Readers
@@ -164,19 +160,19 @@ or `nil`), except the `vars` hash:
| Reader | Description |
|:---------------|:-------------------------------------------------------------------------------------------------------------------|
| `count` | The collection `:count` |
-| `page` | The current page number |
-| `items` | The requested number of items for the page |
+| `from` | The collection-position of the first item in the page (`:outset` excluded) |
| `in` | The number of the items in the page |
+| `items` | The requested number of items for the page |
| `last` | The number of the last page in the collection (ordinal meaning) |
-| `pages` | Alias for `last` (cardinal meaning) |
-| `offset` | The number of items skipped from the collection in order to get the start of the current page (`:outset` included) |
-| `from` | The collection-position of the first item in the page (`:outset` excluded) |
-| `to` | The collection-position of the last item in the page (`:outset` excluded) |
-| `prev` | The previous page number or `nil` if there is no previous page |
| `next` | The next page number or `nil` if there is no next page |
-| `vars` | The variables hash |
+| `offset` | The number of items skipped from the collection in order to get the start of the current page (`:outset` included) |
+| `page` | The current page number |
+| `pages` | Alias for `last` (cardinal meaning) |
| `params` | The `:params` variable (`Hash` or `Proc`) |
+| `prev` | The previous page number or `nil` if there is no previous page |
| `request_path` | The request path used for pagination helpers. If nil, helpers will use `request.path` |
+| `to` | The collection-position of the last item in the page (`:outset` excluded) |
+| `vars` | The variables hash |
### Lowest limit analysis
@@ -203,7 +199,7 @@ Which means:
With `size: []` the `series` method returns `[]`
- `in`, `from` and `to` of an empty page are all `0`
- `prev` and `next` of a single page (not necessary an empty one) are both `nil` (i.e. there is no other page)
-
+
===
## Exceptions
diff --git a/docs/how-to.md b/docs/how-to.md
index 7bfe8832d..2061a8440 100644
--- a/docs/how-to.md
+++ b/docs/how-to.md
@@ -41,7 +41,7 @@ See also a couple of extras that handle the `:items` in some special way:
## Control the page links
-You can control the number and position of the page links in the navigation through the `:size` variable or override the
+You can control the number and position of the page links in the navigation through the `:size` variable or override the
`series` method.
==- Simple nav
@@ -196,7 +196,7 @@ Pagy::DEFAULT[:anchor_string] = 'data-remote="true"'
pagy = Pagy.new(count: 1000, anchor_string: 'data-remote="true"')
# or from a view: e.g.:
-<%== pagy_bootstrap_nav(@pagy, anchor_string: 'data-action="hello#world"') %>
+< %== pagy_bootstrap_nav(@pagy, anchor_string: 'data-action="hello#world"') % >
```
_See more advanced details about [The anchor_string variable](api/frontend.md#the-anchor_string-variable)_
@@ -221,7 +221,7 @@ You can also use the `:fragment` variable to add a fragment the URLs of the page
@pagy, @records = pagy(collection, fragment: '#your-fragment')
```
-!!!warning
+!!!warning
For performance reasons the `:fragment` string must include the `"#"`!
!!!
@@ -276,6 +276,7 @@ For a broader tutorial about this topic
see [Handling Pagination When POSTing Complex Search Forms](https://benkoshy.github.io/2019/10/09/paginating-search-results-with-a-post-request.html)
by Ben Koshy.
===
+
## Customize the item name
The `pagy_info` and the `pagy_items_selector_js` helpers use the "item"/"items" generic name in their output. You can change that
@@ -353,7 +354,7 @@ See the [array](extras/array.md) extra.
## Paginate ActiveRecord collections
-Pagy works out of the box with `ActiveRecord` collections, however here are a few specific cases that might be treated
+Pagy works out of the box with `ActiveRecord` collections, however here are a few specific cases that might be treated
differently:
==- Grouped collection
@@ -390,7 +391,7 @@ Ransack `result` returns an `ActiveRecord` collection, which can be paginated ou
q = Person.ransack(params[:q])
@pagy, @people = pagy(q.result)
```
-
+
==- PostgreSQL Collections
[Always order your colections!](troubleshooting.md#records-may-randomly-repeat-in-different-pages-or-be-missing)
@@ -440,7 +441,7 @@ day).
By default pagy tries to derive parameters and variables from the request and the collection, so you don't have to explicitly pass
it to the `pagy*` method. That is very handy, but assumes you are paginating a single collection per request.
-When you need to paginate multiple collections in a single request, you need to explicitly differentiate the pagination
+When you need to paginate multiple collections in a single request, you need to explicitly differentiate the pagination
objects. You have the following commong ways to do so:
==- Pass the request path
@@ -570,9 +571,35 @@ to different existing statements.
```
Then follow the [calendar extra documentation](extras/calendar.md) for more details.
-
+
===
+## Paginate only max_pages, regardless the count
+
+In order to limit the pagination to a maximum number of pages, you can pass the `:max_pages` variable.
+
+For example:
+
+```ruby
+@pagy, @records = pagy(scope, max_pages: 50, items: 20)
+@records.size #=> 20
+@pagy.count #=> 10_000
+@pagy.last #=> 50
+
+@pagy, @records = pagy(scope, max_pages: 50, items: 20, page: 51)
+#=> Pagy::OverflowError: expected :page in 1..50; got 51
+```
+
+If the `@pagy.count` in the example is `10_000`, the pages served without `:max_pages` would be `500`, but with
+`:max_pages: 50` pagy would serve only the first `50` pages of your collection.
+
+That works at the `Pagy`/`Pagy::Countless` level, so it works with any combination of collection/extra, including `items`,
+`gearbox` and search extras.
+
+!!! Notice
+The `items` and `gearbox` extras serve a variabe number of items per page. If your goal is limiting the pagination to a max number of records (instead of pages), you have to keep into account how you configure the `items` range.
+!!!
+
## Paginate pre-offset and pre-limited collections
With the other pagination gems you cannot paginate a subset of a collection that you got using `offset` and `limit`. With Pagy it
@@ -669,7 +696,7 @@ ready to use in your view. For example:
```
!!!primary Extras Provide Added Functionality
-The [frontend extras](/categories/frontend) add a few other helpers that you can use the same way, in order to get added features
+The [frontend extras](/categories/frontend) add a few other helpers that you can use the same way, in order to get added features
!!!
## Skip single page navs
@@ -842,7 +869,7 @@ standards. Using your own templates is possible, but it's likely just reinventin
!!!
If you really need to use your own templates, you absolutely can. Here is a static example that doesn't use any other helper nor
-dictionary file for the sake of simplicity, however feel free to add your dynamic variables and use any helper and dictionary
+dictionary file for the sake of simplicity, however feel free to add your dynamic variables and use any helper and dictionary
entries as you need:
:::code source="assets/nav.html.erb" :::
@@ -855,10 +882,12 @@ You can use it as usual: just remember to pass the `:pagy` local set to the `@pa
!!!
You may want to look at the actual output interactively by running:
+
```sh
pagy demo
# or: bundle exec pagy demo
```
+
...and point your browser at http://0.0.0.0:8000/template
!!!
diff --git a/gem/lib/pagy.rb b/gem/lib/pagy.rb
index 79f0093f2..bd4b008ef 100644
--- a/gem/lib/pagy.rb
+++ b/gem/lib/pagy.rb
@@ -31,10 +31,11 @@ def initialize(vars)
setup_vars(count: 0, page: 1, outset: 0)
setup_items_var
setup_last_var
+ raise OverflowError.new(self, :page, "in 1..#{@last}", @page) if @page > @last
+
setup_offset_var
setup_params_var
setup_request_path_var
- raise OverflowError.new(self, :page, "in 1..#{@last}", @page) if @page > @last
@from = [@offset - @outset + 1, @count].min
@to = [@offset - @outset + @items, @count].min
@@ -118,6 +119,7 @@ def setup_items_var
# Setup @last and @last (overridden by the gearbox extra)
def setup_last_var
@last = [(@count.to_f / @items).ceil, 1].max
+ @last = vars[:max_pages] if vars[:max_pages] && @last > vars[:max_pages]
end
alias setup_pages_var setup_last_var
diff --git a/gem/lib/pagy/countless.rb b/gem/lib/pagy/countless.rb
index 3fb99f2d3..cf2389bf3 100644
--- a/gem/lib/pagy/countless.rb
+++ b/gem/lib/pagy/countless.rb
@@ -19,7 +19,10 @@ def initialize(vars = {}) # rubocop:disable Lint/MissingSuper
def finalize(fetched_size)
raise OverflowError.new(self, :page, "to be < #{@page}", @page) if fetched_size.zero? && @page > 1
- @last = (fetched_size > @items ? @page + 1 : @page)
+ @last = fetched_size > @items ? @page + 1 : @page
+ @last = vars[:max_pages] if vars[:max_pages] && @last > vars[:max_pages]
+ raise OverflowError.new(self, :page, "in 1..#{@last}", @page) if @page > @last
+
@in = [fetched_size, @items].min
@from = @in.zero? ? 0 : @offset - @outset + 1
@to = @offset - @outset + @in
diff --git a/gem/lib/pagy/extras/gearbox.rb b/gem/lib/pagy/extras/gearbox.rb
index 374f70e4b..78f645144 100644
--- a/gem/lib/pagy/extras/gearbox.rb
+++ b/gem/lib/pagy/extras/gearbox.rb
@@ -12,42 +12,43 @@ module GearboxExtra
def setup_items_var
return super if !@vars[:gearbox_extra] || @vars[:items_extra]
- gearbox_items = @vars[:gearbox_items]
- raise VariableError.new(self, :gearbox_items, 'to be an Array of positives', gearbox_items) \
- unless gearbox_items.is_a?(Array) && gearbox_items.all? { |num| num.positive? rescue false } # rubocop:disable Style/RescueModifier
+ gears = @vars[:gearbox_items]
+ raise VariableError.new(self, :gearbox_items, 'to be an Array of positives', gears) \
+ unless gears.is_a?(Array) && gears.all? { |num| num.positive? rescue false } # rubocop:disable Style/RescueModifier
- @items = gearbox_items[@page - 1] || gearbox_items.last
+ @items = gears[@page - 1] || gears.last
end
- # Setup @last based on the :gearbox_items variable (not used by Pagy::Countless)
+ # Setup Pagy @last based on the :gearbox_items variable and @count
def setup_last_var
return super if !@vars[:gearbox_extra] || @vars[:items_extra]
- gearbox_items = @vars[:gearbox_items]
+ gears = @vars[:gearbox_items]
# This algorithm is thousands of times faster than the one in the geared_pagination gem
- @last = (if @count > (sum = gearbox_items.sum)
- [((@count - sum).to_f / gearbox_items.last).ceil, 1].max + gearbox_items.count
+ @last = (if count > (sum = gears.sum)
+ [((count - sum).to_f / gears.last).ceil, 1].max + gears.count
else
pages = 0
- remainder = @count
+ remainder = count
while remainder.positive?
pages += 1
- remainder -= gearbox_items[pages - 1]
+ remainder -= gears[pages - 1]
end
[pages, 1].max
end)
+ @last = vars[:max_pages] if vars[:max_pages] && @last > vars[:max_pages]
end
# Setup @offset based on the :gearbox_items variable
def setup_offset_var
return super if !@vars[:gearbox_extra] || @vars[:items_extra]
- gearbox_items = @vars[:gearbox_items]
- @offset = if @page <= gearbox_items.count
- gearbox_items[0, @page - 1].sum
- else
- gearbox_items.sum + (gearbox_items.last * (@page - gearbox_items.count - 1))
- end + @outset
+ gears = @vars[:gearbox_items]
+ @offset = if @page <= gears.count
+ gears[0, @page - 1].sum
+ else
+ gears.sum + (gears.last * (@page - gears.count - 1))
+ end + @outset
end
end
prepend GearboxExtra
diff --git a/test/pagy/extras/gearbox_test.rb b/test/pagy/extras/gearbox_test.rb
index b7b271341..0eb142231 100644
--- a/test/pagy/extras/gearbox_test.rb
+++ b/test/pagy/extras/gearbox_test.rb
@@ -52,18 +52,31 @@
end
describe '#setup_last_var' do
- it 'can skip gearbox for pages' do
- _(Pagy.new(count: 90, page: 1, items_extra: true).pages).must_equal 5
- _(Pagy.new(count: 103, page: 1, gearbox_extra: false).pages).must_equal 6
+ it 'can skip gearbox for last' do
+ _(Pagy.new(count: 90, page: 1, items_extra: true).last).must_equal 5
+ _(Pagy.new(count: 103, page: 1, gearbox_extra: false).last).must_equal 6
end
- it 'sets the pages' do
- _(Pagy.new(count: 0, page: 1, gearbox_items: [3, 10]).pages).must_equal 1
- _(Pagy.new(count: 3, page: 1, gearbox_items: [3, 10]).pages).must_equal 1
- _(Pagy.new(count: 13, page: 2, gearbox_items: [3, 10]).pages).must_equal 2
- _(Pagy.new(count: 103, page: 1, gearbox_items: [3, 10]).pages).must_equal 11
- _(Pagy.new(count: 103, page: 2, gearbox_items: [3, 10]).pages).must_equal 11
- _(Pagy.new(count: 103, page: 3, gearbox_items: [3, 10]).pages).must_equal 11
- _(Pagy.new(count: 103, page: 11, gearbox_items: [3, 10]).pages).must_equal 11
+ it 'sets the last' do
+ _(Pagy.new(count: 0, page: 1, gearbox_items: [3, 10]).last).must_equal 1
+ _(Pagy.new(count: 3, page: 1, gearbox_items: [3, 10]).last).must_equal 1
+ _(Pagy.new(count: 13, page: 2, gearbox_items: [3, 10]).last).must_equal 2
+ _(Pagy.new(count: 103, page: 1, gearbox_items: [3, 10]).last).must_equal 11
+ _(Pagy.new(count: 103, page: 2, gearbox_items: [3, 10]).last).must_equal 11
+ _(Pagy.new(count: 103, page: 3, gearbox_items: [3, 10]).last).must_equal 11
+ _(Pagy.new(count: 103, page: 11, gearbox_items: [3, 10]).last).must_equal 11
+ # max_pages
+ _(Pagy.new(count: 24, page: 2, gearbox_items: [3, 10], max_pages: 2).last).must_equal 2
+ _ { Pagy.new(count: 24, page: 3, gearbox_items: [3, 10], max_pages: 2) }.must_raise Pagy::OverflowError
+
+ end
+ it "checks the last in Pagy::Countless" do
+ _(Pagy::Countless.new(page: 1, gearbox_items: [3, 10]).finalize(2).last).must_equal 1
+ _(Pagy::Countless.new(page: 1, gearbox_items: [3, 10]).finalize(4).last).must_equal 2
+ _(Pagy::Countless.new(page: 3, gearbox_items: [3, 10]).finalize(7).last).must_equal 3
+ _(Pagy::Countless.new(page: 3, gearbox_items: [3, 10]).finalize(11).last).must_equal 4
+ # max_pages
+ _(Pagy::Countless.new(page: 2, gearbox_items: [3, 10], max_pages: 2).finalize(11).last).must_equal 2
+ _ { Pagy::Countless.new(page: 3, gearbox_items: [3, 10], max_pages: 2).finalize(11) }.must_raise Pagy::OverflowError
end
end
diff --git a/test/pagy_test.rb b/test/pagy_test.rb
index 42ce5fa3c..243441aa6 100644
--- a/test/pagy_test.rb
+++ b/test/pagy_test.rb
@@ -299,9 +299,15 @@ def series_for(page, *expected)
end
it 'handles the :cycle variable' do
pagy = Pagy.new(count: 100, page: 10, items: 10, cycle: true)
- _(pagy.prev).must_equal(9)
+ _(pagy.prev).must_equal 9
_(pagy.next).must_equal 1
end
+ it 'handles the :ma_pages variable' do
+ pagy = Pagy.new(count: 100, page: 3, items: 10, max_pages: 8)
+ _(pagy.count).must_equal 100
+ _(pagy.last).must_equal 8
+ _ { Pagy.new(count: 100, page: 9, items: 10, max_pages: 8) }.must_raise Pagy::OverflowError
+ end
it 'initializes the request_path' do
pagy = Pagy.new(count: 100, request_path: '/foo')
_(pagy.vars[:request_path]).must_equal('/foo')
From 8cd0e9650a7c51a582f3255d88fe31df0576aa70 Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Tue, 9 Apr 2024 08:24:12 +0700
Subject: [PATCH 10/11] Update rubocop
---
Gemfile.lock | 2 +-
gem/lib/pagy/calendar.rb | 2 +-
test/pagy/extras/gearbox_test.rb | 1 -
3 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/Gemfile.lock b/Gemfile.lock
index c088f753e..3df2786c5 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -88,7 +88,7 @@ GEM
listen (~> 3.0)
rexml (3.2.6)
rouge (4.2.1)
- rubocop (1.62.1)
+ rubocop (1.63.0)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
diff --git a/gem/lib/pagy/calendar.rb b/gem/lib/pagy/calendar.rb
index 53a618c74..d9827a871 100644
--- a/gem/lib/pagy/calendar.rb
+++ b/gem/lib/pagy/calendar.rb
@@ -74,7 +74,7 @@ def page_at(time, **opts)
def setup_unit_vars
raise VariableError.new(self, :format, 'to be a strftime format', @vars[:format]) unless @vars[:format].is_a?(String)
raise VariableError.new(self, :order, 'to be in [:asc, :desc]', @order) \
- unless %i[asc desc].include?(@order = @vars[:order])
+ unless %i[asc desc].include?((@order = @vars[:order]))
@starting, @ending = @vars[:period]
raise VariableError.new(self, :period, 'to be a an Array of min and max TimeWithZone instances', @vars[:period]) \
diff --git a/test/pagy/extras/gearbox_test.rb b/test/pagy/extras/gearbox_test.rb
index 0eb142231..e53b76d75 100644
--- a/test/pagy/extras/gearbox_test.rb
+++ b/test/pagy/extras/gearbox_test.rb
@@ -67,7 +67,6 @@
# max_pages
_(Pagy.new(count: 24, page: 2, gearbox_items: [3, 10], max_pages: 2).last).must_equal 2
_ { Pagy.new(count: 24, page: 3, gearbox_items: [3, 10], max_pages: 2) }.must_raise Pagy::OverflowError
-
end
it "checks the last in Pagy::Countless" do
_(Pagy::Countless.new(page: 1, gearbox_items: [3, 10]).finalize(2).last).must_equal 1
From 79dd031bc27ad57e553a6df8419b91d683f5214d Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Tue, 9 Apr 2024 08:30:17 +0700
Subject: [PATCH 11/11] Version 8.1.0
---
.github/ISSUE_TEMPLATE/Code.yml | 2 +-
.github/latest_release_body.md | 15 ++++++---------
CHANGELOG.md | 7 +++++++
README.md | 2 +-
gem/apps/calendar.ru | 2 +-
gem/apps/demo.ru | 2 +-
gem/apps/rails.ru | 2 +-
gem/apps/repro.ru | 2 +-
gem/bin/pagy | 2 +-
gem/config/pagy.rb | 2 +-
gem/javascripts/pagy-dev.js | 4 ++--
gem/javascripts/pagy-module.js | 2 +-
gem/javascripts/pagy.js | 2 +-
gem/lib/pagy.rb | 2 +-
quick-start.md | 2 +-
retype.yml | 2 +-
src/pagy.ts | 2 +-
17 files changed, 29 insertions(+), 25 deletions(-)
diff --git a/.github/ISSUE_TEMPLATE/Code.yml b/.github/ISSUE_TEMPLATE/Code.yml
index d79bd6592..8d3c68405 100644
--- a/.github/ISSUE_TEMPLATE/Code.yml
+++ b/.github/ISSUE_TEMPLATE/Code.yml
@@ -19,7 +19,7 @@ body:
attributes:
label: Before submitting...
options:
- - label: I upgraded to pagy version 8.0.2
+ - label: I upgraded to pagy version 8.1.0
required: true
- label: I searched through the [Documentation](https://ddnexus.github.io/pagy/)
required: true
diff --git a/.github/latest_release_body.md b/.github/latest_release_body.md
index b1689d802..55c622bdd 100644
--- a/.github/latest_release_body.md
+++ b/.github/latest_release_body.md
@@ -7,21 +7,18 @@ If you wish to keep your favorites alive, please, [vote here](https://github.com
### ✴ What's new in 8.+ ✴
- Better frontend helpers
+- New `:max_pages` variable to limit the pagination regardless the actual count
- New [Pagy Playground](https://ddnexus.github.io/pagy/playground/) to showcase, clone and develop pagy APPs without any setup on
your side (try the [pagy demo](https://ddnexus.github.io/pagy/playground.md#3-demo-app))
- See the [CHANGELOG](https://ddnexus.github.io/pagy/changelog) for possible breaking changes
-### Changes in 8.0.2
+### Changes in 8.1.0
-- Minor change in rails app and RM run config
-- Fix canonical gem root:
- - Correct script.build: "NODE_PATH=\"$(bundle show 'pagy')/javascripts\"
- - Move pagy.gemspec inside the gem root dir
-- Fix for Turbo not intercepting changes in window.location
-- Use require_relative for gem/lib files
-- Complete translation of aria.nav for "ru" locale (close #599)
-- Docs improvement and fixes
+- Implement max_pages to limit the pagination regardless the actual count
+- Improve efficiency of params in pagy_url_for
+- Remove nil variables from DEFAULT
+- Removed redundant @pages, aliased with @last
[CHANGELOG](https://ddnexus.github.io/pagy/changelog)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 29b7ef3c0..d3e04b944 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,6 +29,13 @@ If you upgrade from version `< 8.0.0` see the following:
+## Version 8.1.0
+
+- Implement max_pages to limit the pagination regardless the actual count
+- Improve efficiency of params in pagy_url_for
+- Remove nil variables from DEFAULT
+- Removed redundant @pages, aliased with @last
+
## Version 8.0.2
- Minor change in rails app and RM run config
diff --git a/README.md b/README.md
index 5a8e18863..bd56d93a5 100644
--- a/README.md
+++ b/README.md
@@ -371,7 +371,7 @@ See also the [How To Page](https://ddnexus.github.io/pagy/docs/how-to)
## Top 💯 Contributors
-[](https://github.com/ddnexus)[](https://github.com/benkoshy)[](https://github.com/dependabot[bot])[](https://github.com/grosser)[](https://github.com/Earlopain)[](https://github.com/workgena)[](https://github.com/bquorning)[](https://github.com/molfar)[](https://github.com/sunny)[](https://github.com/enzinia)[](https://github.com/espen)[](https://github.com/berniechiu)[](https://github.com/renshuki)[](https://github.com/wimdavies)[](https://github.com/tiagotex)[](https://github.com/gamafranco)[](https://github.com/thomasklemm)[](https://github.com/tersor)[](https://github.com/simonneutert)[](https://github.com/rainerborene)[](https://github.com/petergoldstein)[](https://github.com/sabljak)[](https://github.com/cseelus)[](https://github.com/ashmaroli)[](https://github.com/747)[](https://github.com/WilliamHorel)[](https://github.com/okuramasafumi)[](https://github.com/olleolleolle)[](https://github.com/pedrocarmona)[](https://github.com/rafaeelaudibert)[](https://github.com/rafaelmontas)[](https://github.com/yenshirak)[](https://github.com/Tolchi)[](https://github.com/serghost)[](https://github.com/sliminas)[](https://github.com/artplan1)[](https://github.com/woller)[](https://github.com/sk8higher)[](https://github.com/muhammadnawzad)[](https://github.com/ronald)[](https://github.com/achmiral)[](https://github.com/mauro-ni)[](https://github.com/borama)[](https://github.com/creativetags)[](https://github.com/mcary)[](https://github.com/marckohlbrugge)[](https://github.com/tr4b4nt)[](https://github.com/tiejianluo)[](https://github.com/szTheory)[](https://github.com/smoothdvd)[](https://github.com/rhodes-david)[](https://github.com/radinreth)[](https://github.com/okliv)[](https://github.com/nedimdz)[](https://github.com/msdundar)[](https://github.com/m-abdurrehman)[](https://github.com/dwieringa)[](https://github.com/jyuvaraj03)[](https://github.com/YutoYasunaga)[](https://github.com/iamyujinwon)[](https://github.com/yhk1038)[](https://github.com/ya-s-u)[](https://github.com/yshmarov)[](https://github.com/thattimc)[](https://github.com/thomaschauffour)[](https://github.com/snkashis)[](https://github.com/fluser)[](https://github.com/tulak)[](https://github.com/Federico-G)[](https://github.com/egimenos)[](https://github.com/elliotlarson)[](https://github.com/hungdiep97)[](https://github.com/djpremier)[](https://github.com/davidwessman)[](https://github.com/david-a-wheeler)[](https://github.com/MrMoins)[](https://github.com/excid3)[](https://github.com/cellvinchung)[](https://github.com/brunoocasali)[](https://github.com/BrandonKlotz)[](https://github.com/Atul9)[](https://github.com/amenon)[](https://github.com/artinboghosian)[](https://github.com/antonzaharia)[](https://github.com/andrew)[](https://github.com/AliOsm)[](https://github.com/AbelToy)[](https://github.com/maful)[](https://github.com/loed-idzinga)[](https://github.com/epeirce)[](https://github.com/kobusjoubert)[](https://github.com/KevinColemanInc)[](https://github.com/neontuna)[](https://github.com/xuanxu)[](https://github.com/jpgarritano)[](https://github.com/archonic)[](https://github.com/jonasMirendo)[](https://github.com/lostapathy)[](https://github.com/jivko-chobanov)[](https://github.com/whithajess)
+[](https://github.com/ddnexus)[](https://github.com/benkoshy)[](https://github.com/dependabot[bot])[](https://github.com/grosser)[](https://github.com/Earlopain)[](https://github.com/workgena)[](https://github.com/bquorning)[](https://github.com/molfar)[](https://github.com/sunny)[](https://github.com/enzinia)[](https://github.com/espen)[](https://github.com/berniechiu)[](https://github.com/renshuki)[](https://github.com/wimdavies)[](https://github.com/tiagotex)[](https://github.com/gamafranco)[](https://github.com/thomasklemm)[](https://github.com/tersor)[](https://github.com/simonneutert)[](https://github.com/rainerborene)[](https://github.com/petergoldstein)[](https://github.com/sabljak)[](https://github.com/cseelus)[](https://github.com/ashmaroli)[](https://github.com/747)[](https://github.com/WilliamHorel)[](https://github.com/okuramasafumi)[](https://github.com/olleolleolle)[](https://github.com/pedrocarmona)[](https://github.com/rafaeelaudibert)[](https://github.com/rafaelmontas)[](https://github.com/yenshirak)[](https://github.com/Tolchi)[](https://github.com/serghost)[](https://github.com/sliminas)[](https://github.com/artplan1)[](https://github.com/woller)[](https://github.com/sk8higher)[](https://github.com/muhammadnawzad)[](https://github.com/ronald)[](https://github.com/achmiral)[](https://github.com/mauro-ni)[](https://github.com/borama)[](https://github.com/creativetags)[](https://github.com/mcary)[](https://github.com/marckohlbrugge)[](https://github.com/tr4b4nt)[](https://github.com/tiejianluo)[](https://github.com/szTheory)[](https://github.com/smoothdvd)[](https://github.com/rhodes-david)[](https://github.com/radinreth)[](https://github.com/okliv)[](https://github.com/nedimdz)[](https://github.com/msdundar)[](https://github.com/m-abdurrehman)[](https://github.com/dwieringa)[](https://github.com/jyuvaraj03)[](https://github.com/YutoYasunaga)[](https://github.com/iamyujinwon)[](https://github.com/yhk1038)[](https://github.com/ya-s-u)[](https://github.com/yshmarov)[](https://github.com/thattimc)[](https://github.com/thomaschauffour)[](https://github.com/snkashis)[](https://github.com/fluser)[](https://github.com/tulak)[](https://github.com/Federico-G)[](https://github.com/egimenos)[](https://github.com/elliotlarson)[](https://github.com/hungdiep97)[](https://github.com/djpremier)[](https://github.com/davidwessman)[](https://github.com/david-a-wheeler)[](https://github.com/MrMoins)[](https://github.com/excid3)[](https://github.com/cellvinchung)[](https://github.com/brunoocasali)[](https://github.com/BrandonKlotz)[](https://github.com/Atul9)[](https://github.com/amenon)[](https://github.com/artinboghosian)[](https://github.com/antonzaharia)[](https://github.com/andrew)[](https://github.com/AliOsm)[](https://github.com/AbelToy)[](https://github.com/maful)[](https://github.com/loed-idzinga)[](https://github.com/epeirce)[](https://github.com/kobusjoubert)[](https://github.com/KevinColemanInc)[](https://github.com/neontuna)[](https://github.com/xuanxu)[](https://github.com/jpgarritano)[](https://github.com/archonic)[](https://github.com/jonasMirendo)[](https://github.com/lostapathy)[](https://github.com/jivko-chobanov)[](https://github.com/whithajess)
diff --git a/gem/apps/calendar.ru b/gem/apps/calendar.ru
index 909f7bbd7..8d5bc71fe 100644
--- a/gem/apps/calendar.ru
+++ b/gem/apps/calendar.ru
@@ -18,7 +18,7 @@
# DOC
# https://ddnexus.github.io/pagy/playground/#4-calendar-app
-VERSION = '8.0.2'
+VERSION = '8.1.0'
require 'bundler/inline'
gemfile(true) do
diff --git a/gem/apps/demo.ru b/gem/apps/demo.ru
index b8f636230..a1973474a 100644
--- a/gem/apps/demo.ru
+++ b/gem/apps/demo.ru
@@ -18,7 +18,7 @@
# DOC
# https://ddnexus.github.io/pagy/playground/#3-demo-app
-VERSION = '8.0.2'
+VERSION = '8.1.0'
require 'bundler/inline'
gemfile(true) do
diff --git a/gem/apps/rails.ru b/gem/apps/rails.ru
index 50debd6b6..b8d632c13 100644
--- a/gem/apps/rails.ru
+++ b/gem/apps/rails.ru
@@ -15,7 +15,7 @@
# DOC
# https://ddnexus.github.io/pagy/playground/#2-rails-app
-VERSION = '8.0.2'
+VERSION = '8.1.0'
# Gemfile
require 'bundler/inline'
diff --git a/gem/apps/repro.ru b/gem/apps/repro.ru
index d5ee91529..5a19e5bfa 100644
--- a/gem/apps/repro.ru
+++ b/gem/apps/repro.ru
@@ -15,7 +15,7 @@
# DOC
# https://ddnexus.github.io/pagy/playground/#1-repro-app
-VERSION = '8.0.2'
+VERSION = '8.1.0'
require 'bundler/inline'
gemfile(true) do
diff --git a/gem/bin/pagy b/gem/bin/pagy
index ce2216cce..6a106a6ad 100755
--- a/gem/bin/pagy
+++ b/gem/bin/pagy
@@ -1,7 +1,7 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
-VERSION = '8.0.2'
+VERSION = '8.1.0'
APPS = %w[repro rails demo calendar].freeze
require_relative '../lib/optimist'
diff --git a/gem/config/pagy.rb b/gem/config/pagy.rb
index 79b754385..34284c091 100644
--- a/gem/config/pagy.rb
+++ b/gem/config/pagy.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-# Pagy initializer file (8.0.2)
+# Pagy initializer file (8.1.0)
# Customize only what you really need and notice that the core Pagy works also without any of the following lines.
# Should you just cherry pick part of this file, please maintain the require-order of the extras
diff --git a/gem/javascripts/pagy-dev.js b/gem/javascripts/pagy-dev.js
index dadfd4398..5f12ca6d5 100644
--- a/gem/javascripts/pagy-dev.js
+++ b/gem/javascripts/pagy-dev.js
@@ -82,7 +82,7 @@ window.Pagy = (() => {
const trim = (a, param) => a.replace(new RegExp(`[?&]${param}=1\\b(?!&)|\\b${param}=1&`), "");
// Public interface
return {
- version: "8.0.2",
+ version: "8.1.0",
// Scan for elements with a "data-pagy" attribute and call their init functions with the decoded args
init(arg) {
const target = arg instanceof Element ? arg : document;
@@ -111,4 +111,4 @@ window.Pagy = (() => {
}
};
})();
-//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFneS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInBhZ3kudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQWtCQSxNQUFNLElBQUksR0FBRyxDQUFDLEdBQUcsRUFBRTtJQUNmLDRDQUE0QztJQUM1QyxNQUFNLFdBQVcsR0FBRyxJQUFJLGNBQWMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUNOLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFhLFdBQVcsQ0FBQyxDQUFDLE9BQU8sQ0FDM0UsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFeEUsNEJBQTRCO0lBQzVCLE1BQU0sT0FBTyxHQUFHLENBQUMsRUFBYSxFQUFFLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsU0FBUyxDQUFTLEVBQUUsRUFBRTtRQUNsRixNQUFNLFNBQVMsR0FBRyxFQUFFLENBQUMsYUFBYSxJQUFJLEVBQUUsQ0FBQztRQUN6QyxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNoRixJQUFJLFNBQVMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNuQixNQUFNLE1BQU0sR0FBRyxDQUFDLENBQVEsRUFBRSxJQUFXLEVBQUUsS0FBWSxFQUFTLEVBQUUsQ0FDMUQsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDeEUsQ0FBQyxFQUFFLENB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TyxHQUFHLEVBQUUsQ0FBQztvQkFBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGlDQUFpQyxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUMsQ0FBQTtnQkFBQyxDQUFDO1lBQzlFLENBQUM7UUFDTCxDQUFDO0tBQ0osQ0FBQztBQUNOLENBQUMsQ0FBQyxFQUFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJ0eXBlIE5hdkFyZ3MgPSByZWFkb25seSBbVG9rZW5zLCBTZXF1ZWxzLCBudWxsIHwgTGFiZWxTZXF1ZWxzLCBzdHJpbmc/XVxudHlwZSBDb21ib0FyZ3MgPSByZWFkb25seSBbc3RyaW5nLCBzdHJpbmc/XVxudHlwZSBTZWxlY3RvckFyZ3MgPSByZWFkb25seSBbbnVtYmVyLCBzdHJpbmcsIHN0cmluZz9dXG5cbmludGVyZmFjZSBUb2tlbnMge1xuICAgIHJlYWRvbmx5IGJlZm9yZTpzdHJpbmdcbiAgICByZWFkb25seSBhOnN0cmluZ1xuICAgIHJlYWRvbmx5IGN1cnJlbnQ6c3RyaW5nXG4gICAgcmVhZG9ubHkgZ2FwOnN0cmluZ1xuICAgIHJlYWRvbmx5IGFmdGVyOnN0cmluZ1xufVxuXG5pbnRlcmZhY2UgU2VxdWVscyB7cmVhZG9ubHkgW3dpZHRoOnN0cmluZ106KHN0cmluZyB8IG51bWJlcilbXX1cblxuaW50ZXJmYWNlIExhYmVsU2VxdWVscyB7cmVhZG9ubHkgW3dpZHRoOnN0cmluZ106c3RyaW5nW119XG5cbmludGVyZmFjZSBOYXZFbGVtZW50IGV4dGVuZHMgRWxlbWVudCB7cGFneVJlbmRlcigpOnZvaWR9XG5cbmNvbnN0IFBhZ3kgPSAoKCkgPT4ge1xuICAgIC8vIFRoZSBvYnNlcnZlciBpbnN0YW5jZSBmb3IgcmVzcG9uc2l2ZSBuYXZzXG4gICAgY29uc3QgcmpzT2JzZXJ2ZXIgPSBuZXcgUmVzaXplT2JzZXJ2ZXIoZW50cmllcyA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbnRyaWVzLmZvckVhY2goZSA9PiBlLnRhcmdldC5xdWVyeVNlbGVjdG9yQWxsPE5hdkVsZW1lbnQ+KFwiLnBhZ3ktcmpzXCIpLmZvckVhY2goXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbCA9PiBlbC5wYWd5UmVuZGVyKCkpKSk7XG5cbiAgICAvLyBJbml0IHRoZSAqX25hdl9qcyBoZWxwZXJzXG4gICAgY29uc3QgaW5pdE5hdiA9IChlbDpOYXZFbGVtZW50LCBbdG9rZW5zLCBzZXF1ZWxzLCBsYWJlbFNlcXVlbHMsIHRyaW1QYXJhbV06TmF2QXJncykgPT4ge1xuICAgICAgICBjb25zdCBjb250YWluZXIgPSBlbC5wYXJlbnRFbGVtZW50ID8/IGVsO1xuICAgICAgICBjb25zdCB3aWR0aHMgPSBPYmplY3Qua2V5cyhzZXF1ZWxzKS5tYXAodyA9PiBwYXJzZUludCh3KSkuc29ydCgoYSwgYikgPT4gYiAtIGEpO1xuICAgICAgICBsZXQgbGFzdFdpZHRoID0gLTE7XG4gICAgICAgIGNvbnN0IGZpbGxJbiA9IChhOnN0cmluZywgcGFnZTpzdHJpbmcsIGxhYmVsOnN0cmluZyk6c3RyaW5nID0+XG4gICAgICAgICAgICBhLnJlcGxhY2UoL19fcGFneV9wYWdlX18vZywgcGFnZSkucmVwbGFjZSgvX19wYWd5X2xhYmVsX18vZywgbGFiZWwpO1xuICAgICAgICAoZWwucGFneVJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gd2lkdGhzLmZpbmQodyA9PiB3IDwgY29udGFpbmVyLmNsaWVudFdpZHRoKSB8fCAwO1xuICAgICAgICAgICAgaWYgKHdpZHRoID09PSBsYXN0V2lkdGgpIHsgcmV0dXJuIH0gLy8gbm8gY2hhbmdlOiBhYm9ydFxuICAgICAgICAgICAgbGV0IGh0bWwgPSB0b2tlbnMuYmVmb3JlOyAgLy8gYWxyZWFkeSB0cmltbWVkIGluIGh0bWxcbiAgICAgICAgICAgIGNvbnN0IHNlcmllcyA9IHNlcXVlbHNbd2lkdGgudG9TdHJpbmcoKV07XG4gICAgICAgICAgICBjb25zdCBsYWJlbHMgPSBsYWJlbFNlcXVlbHM/Llt3aWR0aC50b1N0cmluZygpXSA/PyBzZXJpZXMubWFwKGwgPT4gbC50b1N0cmluZygpKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgaSBpbiBzZXJpZXMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBpdGVtID0gc2VyaWVzW2ldO1xuICAgICAgICAgICAgICAgIGNvbnN0IGxhYmVsID0gbGFiZWxzW2ldO1xuICAgICAgICAgICAgICAgIGxldCBmaWxsZWQ7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBpdGVtID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpbGxlZCA9IGZpbGxJbih0b2tlbnMuYSwgaXRlbS50b1N0cmluZygpLCBsYWJlbCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpdGVtID09PSBcImdhcFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpbGxlZCA9IHRva2Vucy5nYXA7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHsgLy8gYWN0aXZlIHBhZ2VcbiAgICAgICAgICAgICAgICAgICAgZmlsbGVkID0gZmlsbEluKHRva2Vucy5jdXJyZW50LCBpdGVtLCBsYWJlbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGh0bWwgKz0gKHR5cGVvZiB0cmltUGFyYW0gPT09IFwic3RyaW5nXCIgJiYgaXRlbSA9PSAxKSA/IHRyaW0oZmlsbGVkLCB0cmltUGFyYW0pIDogZmlsbGVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaHRtbCArPSB0b2tlbnMuYWZ0ZXI7ICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBhbGlnbi1hc3NpZ25tZW50cy9hbGlnbi1hc3NpZ25tZW50c1xuICAgICAgICAgICAgZWwuaW5uZXJIVE1MID0gXCJcIjtcbiAgICAgICAgICAgIGVsLmluc2VydEFkamFjZW50SFRNTChcImFmdGVyYmVnaW5cIiwgaHRtbCk7XG4gICAgICAgICAgICBsYXN0V2lkdGggPSB3aWR0aDtcbiAgICAgICAgfSkoKTtcbiAgICAgICAgaWYgKGVsLmNsYXNzTGlzdC5jb250YWlucyhcInBhZ3ktcmpzXCIpKSB7IHJqc09ic2VydmVyLm9ic2VydmUoY29udGFpbmVyKSB9XG4gICAgfTtcblxuICAgIC8vIEluaXQgdGhlICpfY29tYm9fbmF2X2pzIGhlbHBlcnNcbiAgICBjb25zdCBpbml0Q29tYm8gPSAoZWw6RWxlbWVudCwgW3VybF90b2tlbiwgdHJpbVBhcmFtXTpDb21ib0FyZ3MpID0+XG4gICAgICAgIGluaXRJbnB1dChlbCwgaW5wdXRWYWx1ZSA9PiBbaW5wdXRWYWx1ZSwgdXJsX3Rva2VuLnJlcGxhY2UoL19fcGFneV9wYWdlX18vLCBpbnB1dFZhbHVlKV0sIHRyaW1QYXJhbSk7XG5cbiAgICAvLyBJbml0IHRoZSBpdGVtc19zZWxlY3Rvcl9qcyBoZWxwZXJcbiAgICBjb25zdCBpbml0U2VsZWN0b3IgPSAoZWw6RWxlbWVudCwgW2Zyb20sIHVybF90b2tlbiwgdHJpbVBhcmFtXTpTZWxlY3RvckFyZ3MpID0+IHtcbiAgICAgICAgaW5pdElucHV0KGVsLCBpbnB1dFZhbHVlID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHBhZ2UgPSBNYXRoLm1heChNYXRoLmNlaWwoZnJvbSAvIHBhcnNlSW50KGlucHV0VmFsdWUpKSwgMSkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGNvbnN0IHVybCA9IHVybF90b2tlbi5yZXBsYWNlKC9fX3BhZ3lfcGFnZV9fLywgcGFnZSkucmVwbGFjZSgvX19wYWd5X2l0ZW1zX18vLCBpbnB1dFZhbHVlKTtcbiAgICAgICAgICAgIHJldHVybiBbcGFnZSwgdXJsXTtcbiAgICAgICAgfSwgdHJpbVBhcmFtKTtcbiAgICB9O1xuXG4gICAgLy8gSW5pdCB0aGUgaW5wdXQgZWxlbWVudFxuICAgIGNvbnN0IGluaXRJbnB1dCA9IChlbDpFbGVtZW50LCBnZXRWYXJzOih2OnN0cmluZykgPT4gW3N0cmluZywgc3RyaW5nXSwgdHJpbVBhcmFtPzpzdHJpbmcpID0+IHtcbiAgICAgICAgY29uc3QgaW5wdXQgPSBlbC5xdWVyeVNlbGVjdG9yKFwiaW5wdXRcIikgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICAgICAgY29uc3QgbGluayA9IGVsLnF1ZXJ5U2VsZWN0b3IoXCJhXCIpIGFzIEhUTUxBbmNob3JFbGVtZW50O1xuICAgICAgICBjb25zdCBpbml0aWFsID0gaW5wdXQudmFsdWU7XG4gICAgICAgIGNvbnN0IGFjdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChpbnB1dC52YWx1ZSA9PT0gaW5pdGlhbCkgeyByZXR1cm4gfSAgLy8gbm90IGNoYW5nZWRcbiAgICAgICAgICAgIGNvbnN0IFttaW4sIHZhbCwgbWF4XSA9IFtpbnB1dC5taW4sIGlucHV0LnZhbHVlLCBpbnB1dC5tYXhdLm1hcChuID0+IHBhcnNlSW50KG4pIHx8IDApO1xuICAgICAgICAgICAgaWYgKHZhbCA8IG1pbiB8fCB2YWwgPiBtYXgpIHsgIC8vIHJlc2V0IGludmFsaWQvb3V0LW9mLXJhbmdlXG4gICAgICAgICAgICAgICAgaW5wdXQudmFsdWUgPSBpbml0aWFsO1xuICAgICAgICAgICAgICAgIGlucHV0LnNlbGVjdCgpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBbcGFnZSwgdXJsXSA9IGdldFZhcnMoaW5wdXQudmFsdWUpOyAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgcHJlZmVyLWNvbnN0XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRyaW1QYXJhbSA9PT0gXCJzdHJpbmdcIiAmJiBwYWdlID09PSBcIjFcIikgeyB1cmwgPSB0cmltKHVybCwgdHJpbVBhcmFtKSB9XG4gICAgICAgICAgICBsaW5rLmhyZWYgPSB1cmw7XG4gICAgICAgICAgICBsaW5rLmNsaWNrKCk7XG4gICAgICAgIH07XG4gICAgICAgIFtcImNoYW5nZVwiLCBcImZvY3VzXCJdLmZvckVhY2goZSA9PiBpbnB1dC5hZGRFdmVudExpc3RlbmVyKGUsIGlucHV0LnNlbGVjdCkpOyAgICAgICAgLy8gYXV0by1zZWxlY3RcbiAgICAgICAgaW5wdXQuYWRkRXZlbnRMaXN0ZW5lcihcImZvY3Vzb3V0XCIsIGFjdGlvbik7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdHJpZ2dlciBhY3Rpb25cbiAgICAgICAgaW5wdXQuYWRkRXZlbnRMaXN0ZW5lcihcImtleXByZXNzXCIsIGUgPT4geyBpZiAoZS5rZXkgPT09IFwiRW50ZXJcIikgeyBhY3Rpb24oKSB9IH0pOyAvLyB0cmlnZ2VyIGFjdGlvblxuICAgIH07XG5cbiAgICAvLyBUcmltIHRoZSAke3BhZ2UtcGFyYW19PTEgcGFyYW1zIGluIGxpbmtzXG4gICAgY29uc3QgdHJpbSA9IChhOnN0cmluZywgcGFyYW06c3RyaW5nKSA9PlxuICAgICAgICBhLnJlcGxhY2UobmV3IFJlZ0V4cChgWz8mXSR7cGFyYW19PTFcXFxcYig/ISYpfFxcXFxiJHtwYXJhbX09MSZgKSwgXCJcIik7XG5cbiAgICAvLyBQdWJsaWMgaW50ZXJmYWNlXG4gICAgcmV0dXJuIHtcbiAgICAgICAgdmVyc2lvbjogXCI4LjAuMlwiLFxuXG4gICAgICAgIC8vIFNjYW4gZm9yIGVsZW1lbnRzIHdpdGggYSBcImRhdGEtcGFneVwiIGF0dHJpYnV0ZSBhbmQgY2FsbCB0aGVpciBpbml0IGZ1bmN0aW9ucyB3aXRoIHRoZSBkZWNvZGVkIGFyZ3NcbiAgICAgICAgaW5pdChhcmc/OkVsZW1lbnQgfCBuZXZlcikge1xuICAgICAgICAgICAgY29uc3QgdGFyZ2V0ID0gYXJnIGluc3RhbmNlb2YgRWxlbWVudCA/IGFyZyA6IGRvY3VtZW50O1xuICAgICAgICAgICAgY29uc3QgZWxlbWVudHMgPSB0YXJnZXQucXVlcnlTZWxlY3RvckFsbChcIltkYXRhLXBhZ3ldXCIpO1xuICAgICAgICAgICAgZm9yIChjb25zdCBlbCBvZiBlbGVtZW50cykge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHVpbnQ4YXJyYXkgPSBVaW50OEFycmF5LmZyb20oYXRvYihlbC5nZXRBdHRyaWJ1dGUoXCJkYXRhLXBhZ3lcIikgYXMgc3RyaW5nKSwgYyA9PiBjLmNoYXJDb2RlQXQoMCkpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBba2V5d29yZCwgLi4uYXJnc10gPSBKU09OLnBhcnNlKChuZXcgVGV4dERlY29kZXIoKSkuZGVjb2RlKHVpbnQ4YXJyYXkpKTsgLy8gYmFzZTY0LXV0ZjggLT4gSlNPTiAtPiBBcnJheVxuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5d29yZCA9PT0gXCJuYXZcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdE5hdihlbCBhcyBOYXZFbGVtZW50LCBhcmdzIGFzIE5hdkFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGtleXdvcmQgPT09IFwiY29tYm9cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdENvbWJvKGVsLCBhcmdzIGFzIENvbWJvQXJncyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoa2V5d29yZCA9PT0gXCJzZWxlY3RvclwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbml0U2VsZWN0b3IoZWwsIGFyZ3MgYXMgU2VsZWN0b3JBcmdzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlNraXBwZWQgUGFneS5pbml0KCkgZm9yOiAlb1xcblVua25vd24ga2V5d29yZCAnJXMnXCIsIGVsLCBrZXl3b3JkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikgeyBjb25zb2xlLndhcm4oXCJTa2lwcGVkIFBhZ3kuaW5pdCgpIGZvcjogJW9cXG4lc1wiLCBlbCwgZXJyKSB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xufSkoKTtcbiJdfQ==
\ No newline at end of file
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFneS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInBhZ3kudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQWtCQSxNQUFNLElBQUksR0FBRyxDQUFDLEdBQUcsRUFBRTtJQUNmLDRDQUE0QztJQUM1QyxNQUFNLFdBQVcsR0FBRyxJQUFJLGNBQWMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUNOLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFhLFdBQVcsQ0FBQyxDQUFDLE9BQU8sQ0FDM0UsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFeEUsNEJBQTRCO0lBQzVCLE1BQU0sT0FBTyxHQUFHLENBQUMsRUFBYSxFQUFFLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsU0FBUyxDQUFTLEVBQUUsRUFBRTtRQUNsRixNQUFNLFNBQVMsR0FBRyxFQUFFLENBQUMsYUFBYSxJQUFJLEVBQUUsQ0FBQztRQUN6QyxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNoRixJQUFJLFNBQVMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNuQixNQUFNLE1BQU0sR0FBRyxDQUFDLENBQVEsRUFBRSxJQUFXLEVBQUUsS0FBWSxFQUFTLEVBQUUsQ0FDMUQsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDeEUsQ0FBQyxFQUFFLENB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TyxHQUFHLEVBQUUsQ0FBQztvQkFBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGlDQUFpQyxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUMsQ0FBQTtnQkFBQyxDQUFDO1lBQzlFLENBQUM7UUFDTCxDQUFDO0tBQ0osQ0FBQztBQUNOLENBQUMsQ0FBQyxFQUFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJ0eXBlIE5hdkFyZ3MgPSByZWFkb25seSBbVG9rZW5zLCBTZXF1ZWxzLCBudWxsIHwgTGFiZWxTZXF1ZWxzLCBzdHJpbmc/XVxudHlwZSBDb21ib0FyZ3MgPSByZWFkb25seSBbc3RyaW5nLCBzdHJpbmc/XVxudHlwZSBTZWxlY3RvckFyZ3MgPSByZWFkb25seSBbbnVtYmVyLCBzdHJpbmcsIHN0cmluZz9dXG5cbmludGVyZmFjZSBUb2tlbnMge1xuICAgIHJlYWRvbmx5IGJlZm9yZTpzdHJpbmdcbiAgICByZWFkb25seSBhOnN0cmluZ1xuICAgIHJlYWRvbmx5IGN1cnJlbnQ6c3RyaW5nXG4gICAgcmVhZG9ubHkgZ2FwOnN0cmluZ1xuICAgIHJlYWRvbmx5IGFmdGVyOnN0cmluZ1xufVxuXG5pbnRlcmZhY2UgU2VxdWVscyB7cmVhZG9ubHkgW3dpZHRoOnN0cmluZ106KHN0cmluZyB8IG51bWJlcilbXX1cblxuaW50ZXJmYWNlIExhYmVsU2VxdWVscyB7cmVhZG9ubHkgW3dpZHRoOnN0cmluZ106c3RyaW5nW119XG5cbmludGVyZmFjZSBOYXZFbGVtZW50IGV4dGVuZHMgRWxlbWVudCB7cGFneVJlbmRlcigpOnZvaWR9XG5cbmNvbnN0IFBhZ3kgPSAoKCkgPT4ge1xuICAgIC8vIFRoZSBvYnNlcnZlciBpbnN0YW5jZSBmb3IgcmVzcG9uc2l2ZSBuYXZzXG4gICAgY29uc3QgcmpzT2JzZXJ2ZXIgPSBuZXcgUmVzaXplT2JzZXJ2ZXIoZW50cmllcyA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbnRyaWVzLmZvckVhY2goZSA9PiBlLnRhcmdldC5xdWVyeVNlbGVjdG9yQWxsPE5hdkVsZW1lbnQ+KFwiLnBhZ3ktcmpzXCIpLmZvckVhY2goXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbCA9PiBlbC5wYWd5UmVuZGVyKCkpKSk7XG5cbiAgICAvLyBJbml0IHRoZSAqX25hdl9qcyBoZWxwZXJzXG4gICAgY29uc3QgaW5pdE5hdiA9IChlbDpOYXZFbGVtZW50LCBbdG9rZW5zLCBzZXF1ZWxzLCBsYWJlbFNlcXVlbHMsIHRyaW1QYXJhbV06TmF2QXJncykgPT4ge1xuICAgICAgICBjb25zdCBjb250YWluZXIgPSBlbC5wYXJlbnRFbGVtZW50ID8/IGVsO1xuICAgICAgICBjb25zdCB3aWR0aHMgPSBPYmplY3Qua2V5cyhzZXF1ZWxzKS5tYXAodyA9PiBwYXJzZUludCh3KSkuc29ydCgoYSwgYikgPT4gYiAtIGEpO1xuICAgICAgICBsZXQgbGFzdFdpZHRoID0gLTE7XG4gICAgICAgIGNvbnN0IGZpbGxJbiA9IChhOnN0cmluZywgcGFnZTpzdHJpbmcsIGxhYmVsOnN0cmluZyk6c3RyaW5nID0+XG4gICAgICAgICAgICBhLnJlcGxhY2UoL19fcGFneV9wYWdlX18vZywgcGFnZSkucmVwbGFjZSgvX19wYWd5X2xhYmVsX18vZywgbGFiZWwpO1xuICAgICAgICAoZWwucGFneVJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gd2lkdGhzLmZpbmQodyA9PiB3IDwgY29udGFpbmVyLmNsaWVudFdpZHRoKSB8fCAwO1xuICAgICAgICAgICAgaWYgKHdpZHRoID09PSBsYXN0V2lkdGgpIHsgcmV0dXJuIH0gLy8gbm8gY2hhbmdlOiBhYm9ydFxuICAgICAgICAgICAgbGV0IGh0bWwgPSB0b2tlbnMuYmVmb3JlOyAgLy8gYWxyZWFkeSB0cmltbWVkIGluIGh0bWxcbiAgICAgICAgICAgIGNvbnN0IHNlcmllcyA9IHNlcXVlbHNbd2lkdGgudG9TdHJpbmcoKV07XG4gICAgICAgICAgICBjb25zdCBsYWJlbHMgPSBsYWJlbFNlcXVlbHM/Llt3aWR0aC50b1N0cmluZygpXSA/PyBzZXJpZXMubWFwKGwgPT4gbC50b1N0cmluZygpKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgaSBpbiBzZXJpZXMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBpdGVtID0gc2VyaWVzW2ldO1xuICAgICAgICAgICAgICAgIGNvbnN0IGxhYmVsID0gbGFiZWxzW2ldO1xuICAgICAgICAgICAgICAgIGxldCBmaWxsZWQ7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBpdGVtID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpbGxlZCA9IGZpbGxJbih0b2tlbnMuYSwgaXRlbS50b1N0cmluZygpLCBsYWJlbCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpdGVtID09PSBcImdhcFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpbGxlZCA9IHRva2Vucy5nYXA7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHsgLy8gYWN0aXZlIHBhZ2VcbiAgICAgICAgICAgICAgICAgICAgZmlsbGVkID0gZmlsbEluKHRva2Vucy5jdXJyZW50LCBpdGVtLCBsYWJlbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGh0bWwgKz0gKHR5cGVvZiB0cmltUGFyYW0gPT09IFwic3RyaW5nXCIgJiYgaXRlbSA9PSAxKSA/IHRyaW0oZmlsbGVkLCB0cmltUGFyYW0pIDogZmlsbGVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaHRtbCArPSB0b2tlbnMuYWZ0ZXI7ICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBhbGlnbi1hc3NpZ25tZW50cy9hbGlnbi1hc3NpZ25tZW50c1xuICAgICAgICAgICAgZWwuaW5uZXJIVE1MID0gXCJcIjtcbiAgICAgICAgICAgIGVsLmluc2VydEFkamFjZW50SFRNTChcImFmdGVyYmVnaW5cIiwgaHRtbCk7XG4gICAgICAgICAgICBsYXN0V2lkdGggPSB3aWR0aDtcbiAgICAgICAgfSkoKTtcbiAgICAgICAgaWYgKGVsLmNsYXNzTGlzdC5jb250YWlucyhcInBhZ3ktcmpzXCIpKSB7IHJqc09ic2VydmVyLm9ic2VydmUoY29udGFpbmVyKSB9XG4gICAgfTtcblxuICAgIC8vIEluaXQgdGhlICpfY29tYm9fbmF2X2pzIGhlbHBlcnNcbiAgICBjb25zdCBpbml0Q29tYm8gPSAoZWw6RWxlbWVudCwgW3VybF90b2tlbiwgdHJpbVBhcmFtXTpDb21ib0FyZ3MpID0+XG4gICAgICAgIGluaXRJbnB1dChlbCwgaW5wdXRWYWx1ZSA9PiBbaW5wdXRWYWx1ZSwgdXJsX3Rva2VuLnJlcGxhY2UoL19fcGFneV9wYWdlX18vLCBpbnB1dFZhbHVlKV0sIHRyaW1QYXJhbSk7XG5cbiAgICAvLyBJbml0IHRoZSBpdGVtc19zZWxlY3Rvcl9qcyBoZWxwZXJcbiAgICBjb25zdCBpbml0U2VsZWN0b3IgPSAoZWw6RWxlbWVudCwgW2Zyb20sIHVybF90b2tlbiwgdHJpbVBhcmFtXTpTZWxlY3RvckFyZ3MpID0+IHtcbiAgICAgICAgaW5pdElucHV0KGVsLCBpbnB1dFZhbHVlID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHBhZ2UgPSBNYXRoLm1heChNYXRoLmNlaWwoZnJvbSAvIHBhcnNlSW50KGlucHV0VmFsdWUpKSwgMSkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGNvbnN0IHVybCA9IHVybF90b2tlbi5yZXBsYWNlKC9fX3BhZ3lfcGFnZV9fLywgcGFnZSkucmVwbGFjZSgvX19wYWd5X2l0ZW1zX18vLCBpbnB1dFZhbHVlKTtcbiAgICAgICAgICAgIHJldHVybiBbcGFnZSwgdXJsXTtcbiAgICAgICAgfSwgdHJpbVBhcmFtKTtcbiAgICB9O1xuXG4gICAgLy8gSW5pdCB0aGUgaW5wdXQgZWxlbWVudFxuICAgIGNvbnN0IGluaXRJbnB1dCA9IChlbDpFbGVtZW50LCBnZXRWYXJzOih2OnN0cmluZykgPT4gW3N0cmluZywgc3RyaW5nXSwgdHJpbVBhcmFtPzpzdHJpbmcpID0+IHtcbiAgICAgICAgY29uc3QgaW5wdXQgPSBlbC5xdWVyeVNlbGVjdG9yKFwiaW5wdXRcIikgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICAgICAgY29uc3QgbGluayA9IGVsLnF1ZXJ5U2VsZWN0b3IoXCJhXCIpIGFzIEhUTUxBbmNob3JFbGVtZW50O1xuICAgICAgICBjb25zdCBpbml0aWFsID0gaW5wdXQudmFsdWU7XG4gICAgICAgIGNvbnN0IGFjdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChpbnB1dC52YWx1ZSA9PT0gaW5pdGlhbCkgeyByZXR1cm4gfSAgLy8gbm90IGNoYW5nZWRcbiAgICAgICAgICAgIGNvbnN0IFttaW4sIHZhbCwgbWF4XSA9IFtpbnB1dC5taW4sIGlucHV0LnZhbHVlLCBpbnB1dC5tYXhdLm1hcChuID0+IHBhcnNlSW50KG4pIHx8IDApO1xuICAgICAgICAgICAgaWYgKHZhbCA8IG1pbiB8fCB2YWwgPiBtYXgpIHsgIC8vIHJlc2V0IGludmFsaWQvb3V0LW9mLXJhbmdlXG4gICAgICAgICAgICAgICAgaW5wdXQudmFsdWUgPSBpbml0aWFsO1xuICAgICAgICAgICAgICAgIGlucHV0LnNlbGVjdCgpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBbcGFnZSwgdXJsXSA9IGdldFZhcnMoaW5wdXQudmFsdWUpOyAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgcHJlZmVyLWNvbnN0XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRyaW1QYXJhbSA9PT0gXCJzdHJpbmdcIiAmJiBwYWdlID09PSBcIjFcIikgeyB1cmwgPSB0cmltKHVybCwgdHJpbVBhcmFtKSB9XG4gICAgICAgICAgICBsaW5rLmhyZWYgPSB1cmw7XG4gICAgICAgICAgICBsaW5rLmNsaWNrKCk7XG4gICAgICAgIH07XG4gICAgICAgIFtcImNoYW5nZVwiLCBcImZvY3VzXCJdLmZvckVhY2goZSA9PiBpbnB1dC5hZGRFdmVudExpc3RlbmVyKGUsIGlucHV0LnNlbGVjdCkpOyAgICAgICAgLy8gYXV0by1zZWxlY3RcbiAgICAgICAgaW5wdXQuYWRkRXZlbnRMaXN0ZW5lcihcImZvY3Vzb3V0XCIsIGFjdGlvbik7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdHJpZ2dlciBhY3Rpb25cbiAgICAgICAgaW5wdXQuYWRkRXZlbnRMaXN0ZW5lcihcImtleXByZXNzXCIsIGUgPT4geyBpZiAoZS5rZXkgPT09IFwiRW50ZXJcIikgeyBhY3Rpb24oKSB9IH0pOyAvLyB0cmlnZ2VyIGFjdGlvblxuICAgIH07XG5cbiAgICAvLyBUcmltIHRoZSAke3BhZ2UtcGFyYW19PTEgcGFyYW1zIGluIGxpbmtzXG4gICAgY29uc3QgdHJpbSA9IChhOnN0cmluZywgcGFyYW06c3RyaW5nKSA9PlxuICAgICAgICBhLnJlcGxhY2UobmV3IFJlZ0V4cChgWz8mXSR7cGFyYW19PTFcXFxcYig/ISYpfFxcXFxiJHtwYXJhbX09MSZgKSwgXCJcIik7XG5cbiAgICAvLyBQdWJsaWMgaW50ZXJmYWNlXG4gICAgcmV0dXJuIHtcbiAgICAgICAgdmVyc2lvbjogXCI4LjEuMFwiLFxuXG4gICAgICAgIC8vIFNjYW4gZm9yIGVsZW1lbnRzIHdpdGggYSBcImRhdGEtcGFneVwiIGF0dHJpYnV0ZSBhbmQgY2FsbCB0aGVpciBpbml0IGZ1bmN0aW9ucyB3aXRoIHRoZSBkZWNvZGVkIGFyZ3NcbiAgICAgICAgaW5pdChhcmc/OkVsZW1lbnQgfCBuZXZlcikge1xuICAgICAgICAgICAgY29uc3QgdGFyZ2V0ID0gYXJnIGluc3RhbmNlb2YgRWxlbWVudCA/IGFyZyA6IGRvY3VtZW50O1xuICAgICAgICAgICAgY29uc3QgZWxlbWVudHMgPSB0YXJnZXQucXVlcnlTZWxlY3RvckFsbChcIltkYXRhLXBhZ3ldXCIpO1xuICAgICAgICAgICAgZm9yIChjb25zdCBlbCBvZiBlbGVtZW50cykge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHVpbnQ4YXJyYXkgPSBVaW50OEFycmF5LmZyb20oYXRvYihlbC5nZXRBdHRyaWJ1dGUoXCJkYXRhLXBhZ3lcIikgYXMgc3RyaW5nKSwgYyA9PiBjLmNoYXJDb2RlQXQoMCkpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBba2V5d29yZCwgLi4uYXJnc10gPSBKU09OLnBhcnNlKChuZXcgVGV4dERlY29kZXIoKSkuZGVjb2RlKHVpbnQ4YXJyYXkpKTsgLy8gYmFzZTY0LXV0ZjggLT4gSlNPTiAtPiBBcnJheVxuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5d29yZCA9PT0gXCJuYXZcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdE5hdihlbCBhcyBOYXZFbGVtZW50LCBhcmdzIGFzIE5hdkFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGtleXdvcmQgPT09IFwiY29tYm9cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdENvbWJvKGVsLCBhcmdzIGFzIENvbWJvQXJncyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoa2V5d29yZCA9PT0gXCJzZWxlY3RvclwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbml0U2VsZWN0b3IoZWwsIGFyZ3MgYXMgU2VsZWN0b3JBcmdzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlNraXBwZWQgUGFneS5pbml0KCkgZm9yOiAlb1xcblVua25vd24ga2V5d29yZCAnJXMnXCIsIGVsLCBrZXl3b3JkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikgeyBjb25zb2xlLndhcm4oXCJTa2lwcGVkIFBhZ3kuaW5pdCgpIGZvcjogJW9cXG4lc1wiLCBlbCwgZXJyKSB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xufSkoKTtcbiJdfQ==
\ No newline at end of file
diff --git a/gem/javascripts/pagy-module.js b/gem/javascripts/pagy-module.js
index 8e6e3b939..3b70e96e8 100644
--- a/gem/javascripts/pagy-module.js
+++ b/gem/javascripts/pagy-module.js
@@ -81,7 +81,7 @@ const Pagy = (() => {
const trim = (a, param) => a.replace(new RegExp(`[?&]${param}=1\\b(?!&)|\\b${param}=1&`), "");
// Public interface
return {
- version: "8.0.2",
+ version: "8.1.0",
// Scan for elements with a "data-pagy" attribute and call their init functions with the decoded args
init(arg) {
const target = arg instanceof Element ? arg : document;
diff --git a/gem/javascripts/pagy.js b/gem/javascripts/pagy.js
index 082a02238..059c1ccb1 100644
--- a/gem/javascripts/pagy.js
+++ b/gem/javascripts/pagy.js
@@ -1 +1 @@
-!function(){let e=(()=>{let e=new ResizeObserver(e=>e.forEach(e=>e.target.querySelectorAll(".pagy-rjs").forEach(e=>e.pagyRender()))),t=(t,[r,a,n,l])=>{let i=t.parentElement??t,c=Object.keys(a).map(e=>parseInt(e)).sort((e,t)=>t-e),p=-1,s=(e,t,r)=>e.replace(/__pagy_page__/g,t).replace(/__pagy_label__/g,r);(t.pagyRender=function(){let e=c.find(e=>ee.toString());for(let e in y){let t;let a=y[e],n=f[e];t="number"==typeof a?s(r.a,a.toString(),n):"gap"===a?r.gap:s(r.current,a,n),g+="string"==typeof l&&1==a?o(t,l):t}g+=r.after,t.innerHTML="",t.insertAdjacentHTML("afterbegin",g),p=e})(),t.classList.contains("pagy-rjs")&&e.observe(i)},r=(e,[t,r])=>n(e,e=>[e,t.replace(/__pagy_page__/,e)],r),a=(e,[t,r,a])=>{n(e,e=>{let a=Math.max(Math.ceil(t/parseInt(e)),1).toString(),n=r.replace(/__pagy_page__/,a).replace(/__pagy_items__/,e);return[a,n]},a)},n=(e,t,r)=>{let a=e.querySelector("input"),n=e.querySelector("a"),l=a.value,i=function(){if(a.value===l)return;let[e,i,c]=[a.min,a.value,a.max].map(e=>parseInt(e)||0);if(ic){a.value=l,a.select();return}let[p,s]=t(a.value);"string"==typeof r&&"1"===p&&(s=o(s,r)),n.href=s,n.click()};["change","focus"].forEach(e=>a.addEventListener(e,a.select)),a.addEventListener("focusout",i),a.addEventListener("keypress",e=>{"Enter"===e.key&&i()})},o=(e,t)=>e.replace(RegExp(`[?&]${t}=1\\b(?!&)|\\b${t}=1&`),"");return{version:"8.0.2",init(e){for(let n of(e instanceof Element?e:document).querySelectorAll("[data-pagy]"))try{let e=Uint8Array.from(atob(n.getAttribute("data-pagy")),e=>e.charCodeAt(0)),[o,...l]=JSON.parse(new TextDecoder().decode(e));"nav"===o?t(n,l):"combo"===o?r(n,l):"selector"===o?a(n,l):console.warn("Skipped Pagy.init() for: %o\nUnknown keyword '%s'",n,o)}catch(e){console.warn("Skipped Pagy.init() for: %o\n%s",n,e)}}}})();window.Pagy=e}();
\ No newline at end of file
+!function(){let e=(()=>{let e=new ResizeObserver(e=>e.forEach(e=>e.target.querySelectorAll(".pagy-rjs").forEach(e=>e.pagyRender()))),t=(t,[r,a,n,l])=>{let i=t.parentElement??t,c=Object.keys(a).map(e=>parseInt(e)).sort((e,t)=>t-e),p=-1,s=(e,t,r)=>e.replace(/__pagy_page__/g,t).replace(/__pagy_label__/g,r);(t.pagyRender=function(){let e=c.find(e=>ee.toString());for(let e in y){let t;let a=y[e],n=f[e];t="number"==typeof a?s(r.a,a.toString(),n):"gap"===a?r.gap:s(r.current,a,n),g+="string"==typeof l&&1==a?o(t,l):t}g+=r.after,t.innerHTML="",t.insertAdjacentHTML("afterbegin",g),p=e})(),t.classList.contains("pagy-rjs")&&e.observe(i)},r=(e,[t,r])=>n(e,e=>[e,t.replace(/__pagy_page__/,e)],r),a=(e,[t,r,a])=>{n(e,e=>{let a=Math.max(Math.ceil(t/parseInt(e)),1).toString(),n=r.replace(/__pagy_page__/,a).replace(/__pagy_items__/,e);return[a,n]},a)},n=(e,t,r)=>{let a=e.querySelector("input"),n=e.querySelector("a"),l=a.value,i=function(){if(a.value===l)return;let[e,i,c]=[a.min,a.value,a.max].map(e=>parseInt(e)||0);if(ic){a.value=l,a.select();return}let[p,s]=t(a.value);"string"==typeof r&&"1"===p&&(s=o(s,r)),n.href=s,n.click()};["change","focus"].forEach(e=>a.addEventListener(e,a.select)),a.addEventListener("focusout",i),a.addEventListener("keypress",e=>{"Enter"===e.key&&i()})},o=(e,t)=>e.replace(RegExp(`[?&]${t}=1\\b(?!&)|\\b${t}=1&`),"");return{version:"8.1.0",init(e){for(let n of(e instanceof Element?e:document).querySelectorAll("[data-pagy]"))try{let e=Uint8Array.from(atob(n.getAttribute("data-pagy")),e=>e.charCodeAt(0)),[o,...l]=JSON.parse(new TextDecoder().decode(e));"nav"===o?t(n,l):"combo"===o?r(n,l):"selector"===o?a(n,l):console.warn("Skipped Pagy.init() for: %o\nUnknown keyword '%s'",n,o)}catch(e){console.warn("Skipped Pagy.init() for: %o\n%s",n,e)}}}})();window.Pagy=e}();
\ No newline at end of file
diff --git a/gem/lib/pagy.rb b/gem/lib/pagy.rb
index bd4b008ef..b31f731e1 100644
--- a/gem/lib/pagy.rb
+++ b/gem/lib/pagy.rb
@@ -5,7 +5,7 @@
# Core class
class Pagy
- VERSION = '8.0.2'
+ VERSION = '8.1.0'
# Gem root pathname to get the path of Pagy files stylesheets, javascripts, apps, locales, etc.
def self.root
diff --git a/quick-start.md b/quick-start.md
index 84ebda5a6..ef2d4add9 100644
--- a/quick-start.md
+++ b/quick-start.md
@@ -40,7 +40,7 @@ If you use Bundler, add the gem in the Gemfile, optionally avoiding the next maj
see [RubyGem Specifiers](http://guides.rubygems.org/patterns/#pessimistic-version-constraint)):
```ruby Gemfile
-gem 'pagy', '~> 8.0' # omit patch digit
+gem 'pagy', '~> 8.1' # omit patch digit
```
+++ Without Bundler
diff --git a/retype.yml b/retype.yml
index a48ed2fd0..e03b937b7 100644
--- a/retype.yml
+++ b/retype.yml
@@ -8,7 +8,7 @@ url: https://ddnexus.github.io/pagy
branding:
title: Pagy
- label: 8.0.2
+ label: 8.1.0
colors:
label:
text: "#FFFFFF"
diff --git a/src/pagy.ts b/src/pagy.ts
index 5db65732d..a4d6dcd7b 100644
--- a/src/pagy.ts
+++ b/src/pagy.ts
@@ -98,7 +98,7 @@ const Pagy = (() => {
// Public interface
return {
- version: "8.0.2",
+ version: "8.1.0",
// Scan for elements with a "data-pagy" attribute and call their init functions with the decoded args
init(arg?:Element | never) {