pagy 9.4.0 → 43.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/apps/calendar.ru +566 -562
- data/apps/demo.ru +246 -182
- data/apps/enable_rails_page_segment.rb +56 -0
- data/apps/index.rb +4 -2
- data/apps/keynav+root_key.ru +316 -0
- data/apps/keynav.ru +255 -0
- data/apps/{keyset_ar.ru → keyset.ru} +33 -42
- data/apps/{keyset_s.ru → keyset_sequel.ru} +32 -40
- data/apps/rails.ru +57 -58
- data/apps/repro.ru +54 -51
- data/bin/pagy +2 -95
- data/config/pagy.rb +33 -207
- data/javascripts/ai_widget.js +90 -0
- data/javascripts/pagy.js +166 -0
- data/javascripts/pagy.min.js +2 -4
- data/javascripts/pagy.mjs +126 -67
- data/javascripts/wand.js +1172 -0
- data/lib/pagy/classes/calendar/calendar.rb +101 -0
- data/lib/pagy/{calendar → classes/calendar}/day.rb +7 -11
- data/lib/pagy/{calendar → classes/calendar}/month.rb +5 -10
- data/lib/pagy/{calendar → classes/calendar}/quarter.rb +10 -15
- data/lib/pagy/classes/calendar/unit.rb +93 -0
- data/lib/pagy/{calendar → classes/calendar}/week.rb +5 -9
- data/lib/pagy/{calendar → classes/calendar}/year.rb +5 -6
- data/lib/pagy/classes/exceptions.rb +26 -0
- data/lib/pagy/classes/keyset/adapters/active_record.rb +50 -0
- data/lib/pagy/classes/keyset/adapters/sequel.rb +62 -0
- data/lib/pagy/classes/keyset/keynav.rb +85 -0
- data/lib/pagy/classes/keyset/keyset.rb +155 -0
- data/lib/pagy/classes/offset/countish.rb +17 -0
- data/lib/pagy/classes/offset/countless.rb +63 -0
- data/lib/pagy/classes/offset/offset.rb +63 -0
- data/lib/pagy/classes/offset/search.rb +34 -0
- data/lib/pagy/classes/request.rb +48 -0
- data/lib/pagy/cli.rb +122 -0
- data/lib/pagy/console.rb +5 -20
- data/lib/pagy/deprecated.rb +84 -0
- data/lib/pagy/modules/abilities/configurable.rb +37 -0
- data/lib/pagy/modules/abilities/countable.rb +23 -0
- data/lib/pagy/modules/abilities/linkable.rb +72 -0
- data/lib/pagy/modules/abilities/rangeable.rb +14 -0
- data/lib/pagy/modules/abilities/shiftable.rb +12 -0
- data/lib/pagy/{b64.rb → modules/b64.rb} +4 -2
- data/lib/pagy/modules/console.rb +33 -0
- data/lib/pagy/modules/i18n/i18n.rb +72 -0
- data/lib/pagy/modules/i18n/p11n/arabic.rb +30 -0
- data/lib/pagy/modules/i18n/p11n/east_slavic.rb +27 -0
- data/lib/pagy/modules/i18n/p11n/one_other.rb +15 -0
- data/lib/pagy/modules/i18n/p11n/one_upto_two_other.rb +15 -0
- data/lib/pagy/modules/i18n/p11n/other.rb +13 -0
- data/lib/pagy/modules/i18n/p11n/polish.rb +27 -0
- data/lib/pagy/modules/i18n/p11n/west_slavic.rb +22 -0
- data/lib/pagy/modules/i18n/p11n.rb +16 -0
- data/lib/pagy/modules/searcher.rb +20 -0
- data/lib/pagy/next.rb +25 -0
- data/lib/pagy/tasks/sync.rb +20 -0
- data/lib/pagy/toolbox/helpers/anchor_tags.rb +19 -0
- data/lib/pagy/toolbox/helpers/bootstrap/input_nav_js.rb +28 -0
- data/lib/pagy/toolbox/helpers/bootstrap/previous_next_html.rb +19 -0
- data/lib/pagy/toolbox/helpers/bootstrap/series_nav.rb +32 -0
- data/lib/pagy/toolbox/helpers/bootstrap/series_nav_js.rb +24 -0
- data/lib/pagy/toolbox/helpers/bulma/input_nav_js.rb +25 -0
- data/lib/pagy/toolbox/helpers/bulma/previous_next_html.rb +20 -0
- data/lib/pagy/toolbox/helpers/bulma/series_nav.rb +31 -0
- data/lib/pagy/toolbox/helpers/bulma/series_nav_js.rb +23 -0
- data/lib/pagy/toolbox/helpers/data_hash.rb +29 -0
- data/lib/pagy/toolbox/helpers/headers_hash.rb +30 -0
- data/lib/pagy/toolbox/helpers/info_tag.rb +30 -0
- data/lib/pagy/toolbox/helpers/input_nav_js.rb +22 -0
- data/lib/pagy/toolbox/helpers/limit_tag_js.rb +25 -0
- data/lib/pagy/toolbox/helpers/loaders.rb +58 -0
- data/lib/pagy/toolbox/helpers/page_url.rb +16 -0
- data/lib/pagy/toolbox/helpers/series_nav.rb +30 -0
- data/lib/pagy/toolbox/helpers/series_nav_js.rb +20 -0
- data/lib/pagy/toolbox/helpers/support/a_lambda.rb +36 -0
- data/lib/pagy/toolbox/helpers/support/data_pagy_attribute.rb +19 -0
- data/lib/pagy/toolbox/helpers/support/nav_aria_label_attribute.rb +10 -0
- data/lib/pagy/toolbox/helpers/support/series.rb +37 -0
- data/lib/pagy/toolbox/helpers/support/wrap_input_nav_js.rb +18 -0
- data/lib/pagy/toolbox/helpers/support/wrap_series_nav.rb +15 -0
- data/lib/pagy/toolbox/helpers/support/wrap_series_nav_js.rb +38 -0
- data/lib/pagy/toolbox/helpers/urls_hash.rb +12 -0
- data/lib/pagy/toolbox/paginators/calendar.rb +34 -0
- data/lib/pagy/toolbox/paginators/countish.rb +38 -0
- data/lib/pagy/toolbox/paginators/countless.rb +22 -0
- data/lib/pagy/toolbox/paginators/elasticsearch_rails.rb +56 -0
- data/lib/pagy/toolbox/paginators/keynav_js.rb +26 -0
- data/lib/pagy/toolbox/paginators/keyset.rb +15 -0
- data/lib/pagy/toolbox/paginators/meilisearch.rb +34 -0
- data/lib/pagy/toolbox/paginators/method.rb +38 -0
- data/lib/pagy/toolbox/paginators/offset.rb +24 -0
- data/lib/pagy/toolbox/paginators/searchkick.rb +34 -0
- data/lib/pagy/toolbox/paginators/typesense_rails.rb +34 -0
- data/lib/pagy.rb +79 -89
- data/locales/ar.yml +9 -6
- data/locales/be.yml +9 -6
- data/locales/bg.yml +9 -6
- data/locales/bs.yml +9 -6
- data/locales/ca.yml +9 -6
- data/locales/ckb.yml +8 -6
- data/locales/cs.yml +9 -6
- data/locales/da.yml +9 -6
- data/locales/de.yml +9 -6
- data/locales/dz.yml +9 -6
- data/locales/en.yml +9 -6
- data/locales/es.yml +9 -6
- data/locales/fr.yml +9 -6
- data/locales/hr.yml +9 -6
- data/locales/hu.yml +24 -0
- data/locales/id.yml +10 -9
- data/locales/it.yml +9 -6
- data/locales/ja.yml +10 -9
- data/locales/km.yml +10 -9
- data/locales/ko.yml +9 -6
- data/locales/nb.yml +9 -6
- data/locales/nl.yml +9 -6
- data/locales/nn.yml +9 -6
- data/locales/pl.yml +9 -6
- data/locales/pt-BR.yml +10 -7
- data/locales/pt.yml +10 -7
- data/locales/ru.yml +9 -6
- data/locales/sk.yml +9 -6
- data/locales/sr.yml +9 -6
- data/locales/sv-SE.yml +9 -6
- data/locales/sv.yml +9 -6
- data/locales/sw.yml +12 -9
- data/locales/ta.yml +9 -6
- data/locales/tr.yml +17 -12
- data/locales/uk.yml +9 -6
- data/locales/vi.yml +9 -6
- data/locales/zh-CN.yml +9 -6
- data/locales/zh-HK.yml +9 -6
- data/locales/zh-TW.yml +9 -6
- data/stylesheets/pagy-tailwind.css +68 -0
- data/stylesheets/pagy.css +64 -27
- metadata +134 -53
- data/javascripts/pagy.min.js.map +0 -10
- data/lib/optimist.rb +0 -1022
- data/lib/pagy/backend.rb +0 -44
- data/lib/pagy/calendar/unit.rb +0 -103
- data/lib/pagy/calendar.rb +0 -84
- data/lib/pagy/countless.rb +0 -38
- data/lib/pagy/exceptions.rb +0 -25
- data/lib/pagy/extras/arel.rb +0 -28
- data/lib/pagy/extras/array.rb +0 -19
- data/lib/pagy/extras/bootstrap.rb +0 -97
- data/lib/pagy/extras/bulma.rb +0 -93
- data/lib/pagy/extras/calendar.rb +0 -79
- data/lib/pagy/extras/countless.rb +0 -32
- data/lib/pagy/extras/elasticsearch_rails.rb +0 -71
- data/lib/pagy/extras/gearbox.rb +0 -55
- data/lib/pagy/extras/headers.rb +0 -54
- data/lib/pagy/extras/i18n.rb +0 -26
- data/lib/pagy/extras/js_tools.rb +0 -70
- data/lib/pagy/extras/jsonapi.rb +0 -88
- data/lib/pagy/extras/keyset.rb +0 -30
- data/lib/pagy/extras/limit.rb +0 -63
- data/lib/pagy/extras/meilisearch.rb +0 -57
- data/lib/pagy/extras/metadata.rb +0 -42
- data/lib/pagy/extras/overflow.rb +0 -81
- data/lib/pagy/extras/pagy.rb +0 -82
- data/lib/pagy/extras/searchkick.rb +0 -59
- data/lib/pagy/extras/size.rb +0 -40
- data/lib/pagy/extras/standalone.rb +0 -60
- data/lib/pagy/extras/trim.rb +0 -29
- data/lib/pagy/frontend.rb +0 -99
- data/lib/pagy/i18n.rb +0 -167
- data/lib/pagy/keyset/active_record.rb +0 -44
- data/lib/pagy/keyset/sequel.rb +0 -57
- data/lib/pagy/keyset.rb +0 -118
- data/lib/pagy/shared_methods.rb +0 -26
- data/lib/pagy/url_helpers.rb +0 -26
- data/stylesheets/pagy.scss +0 -48
- data/stylesheets/pagy.tailwind.css +0 -21
data/lib/pagy/extras/pagy.rb
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
# See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/pagy
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
require_relative 'js_tools'
|
|
5
|
-
|
|
6
|
-
class Pagy # :nodoc:
|
|
7
|
-
# Frontend modules are specially optimized for performance.
|
|
8
|
-
# The resulting code may not look very elegant, but produces the best benchmarks
|
|
9
|
-
module PagyExtra
|
|
10
|
-
# pagy_nav is defined in the Frontend itself
|
|
11
|
-
# Javascript pagination: it returns a nav with a data-pagy attribute used by the pagy.js file
|
|
12
|
-
def pagy_nav_js(pagy, id: nil, aria_label: nil, **vars)
|
|
13
|
-
sequels = pagy.sequels(**vars)
|
|
14
|
-
id = %( id="#{id}") if id
|
|
15
|
-
a = pagy_anchor(pagy, **vars)
|
|
16
|
-
tokens = { 'before' => prev_a(pagy, a),
|
|
17
|
-
'a' => a.(PAGE_TOKEN, LABEL_TOKEN),
|
|
18
|
-
'current' => %(<a class="current" role="link" aria-current="page" aria-disabled="true">#{
|
|
19
|
-
LABEL_TOKEN}</a>),
|
|
20
|
-
'gap' => %(<a class="gap" role="link" aria-disabled="true">#{pagy_t('pagy.gap')}</a>),
|
|
21
|
-
'after' => next_a(pagy, a) }
|
|
22
|
-
|
|
23
|
-
%(<nav#{id} class="#{'pagy-rjs ' if sequels.size > 1}pagy nav-js" #{
|
|
24
|
-
nav_aria_label(pagy, aria_label:)} #{
|
|
25
|
-
pagy_data(pagy, :nav, tokens, sequels, pagy.label_sequels(sequels))
|
|
26
|
-
}></nav>)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# Javascript combo pagination: it returns a nav with a data-pagy attribute used by the pagy.js file
|
|
30
|
-
def pagy_combo_nav_js(pagy, id: nil, aria_label: nil, **vars)
|
|
31
|
-
id = %( id="#{id}") if id
|
|
32
|
-
a = pagy_anchor(pagy, **vars)
|
|
33
|
-
pages = pagy.pages
|
|
34
|
-
|
|
35
|
-
page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page" ) <<
|
|
36
|
-
%(style="text-align: center; width: #{pages.to_s.length + 1}rem; padding: 0;">#{JSTools::A_TAG})
|
|
37
|
-
|
|
38
|
-
%(<nav#{id} class="pagy combo-nav-js" #{
|
|
39
|
-
nav_aria_label(pagy, aria_label:)} #{
|
|
40
|
-
pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN, **vars))}>#{
|
|
41
|
-
prev_a(pagy, a)
|
|
42
|
-
}<label>#{
|
|
43
|
-
pagy_t('pagy.combo_nav_js', page_input:, pages:)
|
|
44
|
-
}</label>#{
|
|
45
|
-
next_a(pagy, a)
|
|
46
|
-
}</nav>)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# Return the previous page URL string or nil
|
|
50
|
-
def pagy_prev_url(pagy, **vars)
|
|
51
|
-
pagy_url_for(pagy, pagy.prev, **vars) if pagy.prev
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# Return the next page URL string or nil
|
|
55
|
-
def pagy_next_url(pagy, **vars)
|
|
56
|
-
pagy_url_for(pagy, pagy.next, **vars) if pagy.next
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# Return the enabled/disabled previous page anchor tag
|
|
60
|
-
def pagy_prev_a(pagy, text: pagy_t('pagy.prev'), aria_label: pagy_t('pagy.aria_label.prev'), **vars)
|
|
61
|
-
a = pagy_anchor(pagy, **vars)
|
|
62
|
-
prev_a(pagy, a, text:, aria_label:)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# Return the enabled/disabled next page anchor tag
|
|
66
|
-
def pagy_next_a(pagy, text: pagy_t('pagy.next'), aria_label: pagy_t('pagy.aria_label.next'), **vars)
|
|
67
|
-
a = pagy_anchor(pagy, **vars)
|
|
68
|
-
next_a(pagy, a, text:, aria_label:)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
# Conditionally return the previous page link tag
|
|
72
|
-
def pagy_prev_link(pagy, **vars)
|
|
73
|
-
%(<link href="#{pagy_url_for(pagy, pagy.prev, **vars)}"/>) if pagy.prev
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Conditionally return the next page link tag
|
|
77
|
-
def pagy_next_link(pagy, **vars)
|
|
78
|
-
%(<link href="#{pagy_url_for(pagy, pagy.next, **vars)}"/>) if pagy.next
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
Frontend.prepend PagyExtra
|
|
82
|
-
end
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
# See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/searchkick
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
class Pagy # :nodoc:
|
|
5
|
-
DEFAULT[:searchkick_search] ||= :search
|
|
6
|
-
DEFAULT[:searchkick_pagy_search] ||= :pagy_search
|
|
7
|
-
|
|
8
|
-
# Paginate Searchkick::Results objects
|
|
9
|
-
module SearchkickExtra
|
|
10
|
-
module ModelExtension # :nodoc:
|
|
11
|
-
# Return an array used to delay the call of #search
|
|
12
|
-
# after the pagination variables are merged to the options.
|
|
13
|
-
# It also pushes to the same array an optional method call.
|
|
14
|
-
def pagy_searchkick(term = '*', **options, &block)
|
|
15
|
-
[self, term, options, block].tap do |args|
|
|
16
|
-
args.define_singleton_method(:method_missing) { |*a| args += a }
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
alias_method Pagy::DEFAULT[:searchkick_pagy_search], :pagy_searchkick
|
|
20
|
-
end
|
|
21
|
-
Pagy::Searchkick = ModelExtension
|
|
22
|
-
|
|
23
|
-
# Additions for the Pagy class
|
|
24
|
-
module PagyExtension
|
|
25
|
-
# Create a Pagy object from a Searchkick::Results object
|
|
26
|
-
def new_from_searchkick(results, **vars)
|
|
27
|
-
vars[:limit] = results.options[:per_page]
|
|
28
|
-
vars[:page] = results.options[:page]
|
|
29
|
-
vars[:count] = results.total_count
|
|
30
|
-
new(**vars)
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
Pagy.extend PagyExtension
|
|
34
|
-
|
|
35
|
-
# Add specialized backend methods to paginate Searchkick::Results
|
|
36
|
-
module BackendAddOn
|
|
37
|
-
private
|
|
38
|
-
|
|
39
|
-
# Return Pagy object and results
|
|
40
|
-
def pagy_searchkick(pagy_search_args, **vars)
|
|
41
|
-
vars[:page] ||= pagy_get_page(vars)
|
|
42
|
-
vars[:limit] ||= pagy_get_limit(vars)
|
|
43
|
-
model, term, options, block, *called = pagy_search_args
|
|
44
|
-
options[:per_page] = vars[:limit]
|
|
45
|
-
options[:page] = vars[:page]
|
|
46
|
-
results = model.send(DEFAULT[:searchkick_search], term, **options, &block)
|
|
47
|
-
vars[:count] = results.total_count
|
|
48
|
-
|
|
49
|
-
pagy = ::Pagy.new(**vars)
|
|
50
|
-
# with :last_page overflow we need to re-run the method in order to get the hits
|
|
51
|
-
return pagy_searchkick(pagy_search_args, **vars, page: pagy.page) \
|
|
52
|
-
if defined?(::Pagy::OverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page
|
|
53
|
-
|
|
54
|
-
[pagy, called.empty? ? results : results.send(*called)]
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
Backend.prepend BackendAddOn
|
|
58
|
-
end
|
|
59
|
-
end
|
data/lib/pagy/extras/size.rb
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
# See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/size
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
class Pagy # :nodoc:
|
|
5
|
-
# Implement the legacy bar using the array size.
|
|
6
|
-
# Unless you have very specific requirements, use the faster and better looking default bar.
|
|
7
|
-
module SizeExtra
|
|
8
|
-
# Implements the old series algorithm
|
|
9
|
-
def series(size: @vars[:size], **_)
|
|
10
|
-
return super unless size.is_a?(Array)
|
|
11
|
-
return [] if size == []
|
|
12
|
-
raise VariableError.new(self, :size, 'to be an Array of 4 Integers or []', size) \
|
|
13
|
-
unless size.is_a?(Array) && size.size == 4 && size.all? { |num| !num.negative? rescue false } # rubocop:disable Style/RescueModifier
|
|
14
|
-
|
|
15
|
-
[].tap do |series|
|
|
16
|
-
# This algorithm is up to ~5x faster and ~2.3x lighter than the previous one (pagy < 4.3)
|
|
17
|
-
# However the behavior of the legacy nav bar was taken straight from WillPaginate and Kaminari:
|
|
18
|
-
# it's ill-concieved and complicates the experience of devs and users.
|
|
19
|
-
left_gap_start = 1 + size[0]
|
|
20
|
-
left_gap_end = @page - size[1] - 1
|
|
21
|
-
right_gap_start = @page + size[2] + 1
|
|
22
|
-
right_gap_end = @last - size[3]
|
|
23
|
-
left_gap_end = right_gap_end if left_gap_end > right_gap_end
|
|
24
|
-
right_gap_start = left_gap_start if left_gap_start > right_gap_start
|
|
25
|
-
start = 1
|
|
26
|
-
if (left_gap_end - left_gap_start).positive?
|
|
27
|
-
series.push(*start...left_gap_start, :gap)
|
|
28
|
-
start = left_gap_end + 1
|
|
29
|
-
end
|
|
30
|
-
if (right_gap_end - right_gap_start).positive?
|
|
31
|
-
series.push(*start...right_gap_start, :gap)
|
|
32
|
-
start = right_gap_end + 1
|
|
33
|
-
end
|
|
34
|
-
series.push(*start..@last)
|
|
35
|
-
series[series.index(@page)] = @page.to_s
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
prepend SizeExtra
|
|
40
|
-
end
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
# See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/standalone
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
require 'uri'
|
|
5
|
-
|
|
6
|
-
class Pagy # :nodoc:
|
|
7
|
-
# Use pagy without any request object, nor Rack environment/gem, nor any defined params method,
|
|
8
|
-
# even in the irb/rails console without any app or config.
|
|
9
|
-
module StandaloneExtra
|
|
10
|
-
# Extracted from Rack::Utils and reformatted for rubocop
|
|
11
|
-
# :nocov:
|
|
12
|
-
module QueryUtils
|
|
13
|
-
module_function
|
|
14
|
-
|
|
15
|
-
def build_nested_query(value, prefix = nil)
|
|
16
|
-
case value
|
|
17
|
-
when Array
|
|
18
|
-
value.map { |v| build_nested_query(v, "#{prefix}[]") }.join('&')
|
|
19
|
-
when Hash
|
|
20
|
-
value.map do |k, v|
|
|
21
|
-
build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
|
|
22
|
-
end.delete_if(&:empty?).join('&')
|
|
23
|
-
when nil
|
|
24
|
-
escape(prefix)
|
|
25
|
-
else
|
|
26
|
-
raise ArgumentError, 'value must be a Hash' if prefix.nil?
|
|
27
|
-
|
|
28
|
-
"#{escape(prefix)}=#{escape(value)}"
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def escape(str)
|
|
33
|
-
URI.encode_www_form_component(str)
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
# :nocov:
|
|
37
|
-
|
|
38
|
-
# Return the URL for the page. If there is no pagy.vars[:url]
|
|
39
|
-
# it works exactly as the regular #pagy_url_for, relying on the params method and Rack.
|
|
40
|
-
# If there is a defined pagy.vars[:url] variable it does not need the params method nor Rack.
|
|
41
|
-
def pagy_url_for(pagy, page, fragment: nil, **_)
|
|
42
|
-
return super unless pagy.vars[:url]
|
|
43
|
-
|
|
44
|
-
vars = pagy.vars
|
|
45
|
-
params = vars[:params].is_a?(Hash) ? vars[:params].clone : {} # safe when it gets reused
|
|
46
|
-
pagy_set_query_params(page, vars, params)
|
|
47
|
-
params = vars[:params].(params) if vars[:params].is_a?(Proc)
|
|
48
|
-
query_string = "?#{QueryUtils.build_nested_query(params)}"
|
|
49
|
-
"#{vars[:url]}#{query_string}#{fragment}"
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
UrlHelpers.prepend StandaloneExtra
|
|
53
|
-
|
|
54
|
-
# Define a dummy params method if it's not already defined in the including module
|
|
55
|
-
module Backend
|
|
56
|
-
def self.included(controller)
|
|
57
|
-
controller.define_method(:params) { {} } unless controller.method_defined?(:params)
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
data/lib/pagy/extras/trim.rb
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/trim
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
class Pagy # :nodoc:
|
|
5
|
-
DEFAULT[:trim_extra] = true # extra enabled by default
|
|
6
|
-
|
|
7
|
-
# Remove the page=1 param from the first page link
|
|
8
|
-
module TrimExtra
|
|
9
|
-
# Override the original pagy_anchor.
|
|
10
|
-
# Call the pagy_trim method for page 1 if the trim_extra is enabled
|
|
11
|
-
def pagy_anchor(pagy, **_)
|
|
12
|
-
a_proc = super
|
|
13
|
-
return a_proc unless pagy.vars[:trim_extra]
|
|
14
|
-
|
|
15
|
-
lambda do |page, text = pagy.label_for(page), **opts|
|
|
16
|
-
a = +a_proc.(page, text, **opts)
|
|
17
|
-
return a unless page.to_s == '1'
|
|
18
|
-
|
|
19
|
-
pagy_trim(pagy, a) # in method for isolated testing
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
# Remove the :page_param param from the first page anchor
|
|
24
|
-
def pagy_trim(pagy, a)
|
|
25
|
-
a.sub!(/[?&]#{pagy.vars[:page_param]}=1\b(?!&)|\b#{pagy.vars[:page_param]}=1&/, '')
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
Frontend.prepend TrimExtra
|
|
29
|
-
end
|
data/lib/pagy/frontend.rb
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
# See Pagy::Frontend API documentation: https://ddnexus.github.io/pagy/docs/api/frontend
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
require_relative 'i18n'
|
|
5
|
-
require_relative 'url_helpers'
|
|
6
|
-
|
|
7
|
-
class Pagy
|
|
8
|
-
# Used for search and replace, hardcoded also in the pagy.js file
|
|
9
|
-
PAGE_TOKEN = '__pagy_page__'
|
|
10
|
-
LABEL_TOKEN = '__pagy_label__'
|
|
11
|
-
|
|
12
|
-
# Frontend modules are specially optimized for performance.
|
|
13
|
-
# The resulting code may not look very elegant, but produces the best benchmarks
|
|
14
|
-
module Frontend
|
|
15
|
-
include UrlHelpers
|
|
16
|
-
|
|
17
|
-
# Return a performance optimized lambda to generate the HTML anchor element (a tag)
|
|
18
|
-
# Benchmarked on a 20 link nav: it is ~22x faster and uses ~18x less memory than rails' link_to
|
|
19
|
-
def pagy_anchor(pagy, anchor_string: nil, **vars)
|
|
20
|
-
anchor_string &&= %( #{anchor_string})
|
|
21
|
-
left, right = %(<a#{anchor_string} href="#{pagy_url_for(pagy, PAGE_TOKEN, **vars)}").split(PAGE_TOKEN, 2)
|
|
22
|
-
# lambda used by all the helpers
|
|
23
|
-
lambda do |page, text = pagy.label_for(page), classes: nil, aria_label: nil|
|
|
24
|
-
classes = %( class="#{classes}") if classes
|
|
25
|
-
aria_label = %( aria-label="#{aria_label}") if aria_label
|
|
26
|
-
%(#{left}#{page}#{right}#{classes}#{aria_label}>#{text}</a>)
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# Return examples: "Displaying items 41-60 of 324 in total" or "Displaying Products 41-60 of 324 in total"
|
|
31
|
-
def pagy_info(pagy, id: nil, item_name: nil)
|
|
32
|
-
id = %( id="#{id}") if id
|
|
33
|
-
p_count = pagy.count
|
|
34
|
-
key = if p_count.zero?
|
|
35
|
-
'pagy.info.no_items'
|
|
36
|
-
elsif pagy.pages == 1
|
|
37
|
-
'pagy.info.single_page'
|
|
38
|
-
else
|
|
39
|
-
'pagy.info.multiple_pages'
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
%(<span#{id} class="pagy info">#{
|
|
43
|
-
pagy_t key, item_name: item_name || pagy_t('pagy.item_name', count: p_count),
|
|
44
|
-
count: p_count, from: pagy.from, to: pagy.to
|
|
45
|
-
}</span>)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
# Generic pagination: it returns the html with the series of links to the pages
|
|
49
|
-
def pagy_nav(pagy, id: nil, aria_label: nil, **vars)
|
|
50
|
-
id = %( id="#{id}") if id
|
|
51
|
-
a = pagy_anchor(pagy, **vars)
|
|
52
|
-
|
|
53
|
-
html = %(<nav#{id} class="pagy nav" #{nav_aria_label(pagy, aria_label:)}>#{
|
|
54
|
-
prev_a(pagy, a)})
|
|
55
|
-
pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
|
|
56
|
-
html << case item
|
|
57
|
-
when Integer
|
|
58
|
-
a.(item)
|
|
59
|
-
when String
|
|
60
|
-
%(<a role="link" aria-disabled="true" aria-current="page" class="current">#{pagy.label_for(item)}</a>)
|
|
61
|
-
when :gap
|
|
62
|
-
%(<a role="link" aria-disabled="true" class="gap">#{pagy_t('pagy.gap')}</a>)
|
|
63
|
-
else
|
|
64
|
-
raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
html << %(#{next_a(pagy, a)}</nav>)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
# Similar to I18n.t: just ~18x faster using ~10x less memory
|
|
71
|
-
# (@pagy_locale explicitly initialized in order to avoid warning)
|
|
72
|
-
def pagy_t(key, **opts)
|
|
73
|
-
Pagy::I18n.translate(@pagy_locale ||= nil, key, **opts)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
private
|
|
77
|
-
|
|
78
|
-
def nav_aria_label(pagy, aria_label: nil)
|
|
79
|
-
aria_label ||= pagy_t('pagy.aria_label.nav', count: pagy.pages)
|
|
80
|
-
%(aria-label="#{aria_label}")
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def prev_a(pagy, a, text: pagy_t('pagy.prev'), aria_label: pagy_t('pagy.aria_label.prev'))
|
|
84
|
-
if (p_prev = pagy.prev)
|
|
85
|
-
a.(p_prev, text, aria_label:)
|
|
86
|
-
else
|
|
87
|
-
%(<a role="link" aria-disabled="true" aria-label="#{aria_label}">#{text}</a>)
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def next_a(pagy, a, text: pagy_t('pagy.next'), aria_label: pagy_t('pagy.aria_label.next'))
|
|
92
|
-
if (p_next = pagy.next)
|
|
93
|
-
a.(p_next, text, aria_label:)
|
|
94
|
-
else
|
|
95
|
-
%(<a role="link" aria-disabled="true" aria-label="#{aria_label}">#{text}</a>)
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
end
|
data/lib/pagy/i18n.rb
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
# See Pagy::I18n API documentation https://ddnexus.github.io/pagy/docs/api/i18n
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
require 'yaml'
|
|
5
|
-
|
|
6
|
-
class Pagy
|
|
7
|
-
# Pagy i18n implementation, compatible with the I18n gem, just a lot faster and lighter
|
|
8
|
-
module I18n
|
|
9
|
-
extend self
|
|
10
|
-
|
|
11
|
-
# Pluralization rules
|
|
12
|
-
module P11n
|
|
13
|
-
# Pluralization variables
|
|
14
|
-
from0to1 = (0..1).to_a.freeze
|
|
15
|
-
from2to4 = (2..4).to_a.freeze
|
|
16
|
-
from3to10 = (3..10).to_a.freeze
|
|
17
|
-
from5to9 = (5..9).to_a.freeze
|
|
18
|
-
from11to14 = (11..14).to_a.freeze
|
|
19
|
-
from11to99 = (11..99).to_a.freeze
|
|
20
|
-
from12to14 = (12..14).to_a.freeze
|
|
21
|
-
|
|
22
|
-
from0to1_from5to9 = from0to1 + from5to9
|
|
23
|
-
|
|
24
|
-
# Store the proc defining each pluralization RULE
|
|
25
|
-
# Logic adapted from https://github.com/svenfuchs/rails-i18n
|
|
26
|
-
RULE = {
|
|
27
|
-
arabic:
|
|
28
|
-
lambda do |n = 0|
|
|
29
|
-
mod100 = n % 100
|
|
30
|
-
case
|
|
31
|
-
when n == 0 then 'zero' # rubocop:disable Style/NumericPredicate
|
|
32
|
-
when n == 1 then 'one'
|
|
33
|
-
when n == 2 then 'two'
|
|
34
|
-
when from3to10.include?(mod100) then 'few'
|
|
35
|
-
when from11to99.include?(mod100) then 'many'
|
|
36
|
-
else 'other'
|
|
37
|
-
end
|
|
38
|
-
end,
|
|
39
|
-
|
|
40
|
-
east_slavic:
|
|
41
|
-
lambda do |n = 0|
|
|
42
|
-
mod10 = n % 10
|
|
43
|
-
mod100 = n % 100
|
|
44
|
-
case
|
|
45
|
-
when mod10 == 1 && mod100 != 11 then 'one'
|
|
46
|
-
when from2to4.include?(mod10) && !from12to14.include?(mod100) then 'few'
|
|
47
|
-
when mod10 == 0 || from5to9.include?(mod10) || from11to14.include?(mod100) then 'many' # rubocop:disable Style/NumericPredicate
|
|
48
|
-
else 'other'
|
|
49
|
-
end
|
|
50
|
-
end,
|
|
51
|
-
|
|
52
|
-
one_other:
|
|
53
|
-
->(n) { n == 1 ? 'one' : 'other' }, # default RULE
|
|
54
|
-
|
|
55
|
-
one_two_other:
|
|
56
|
-
lambda do |n|
|
|
57
|
-
case n
|
|
58
|
-
when 1 then 'one'
|
|
59
|
-
when 2 then 'two'
|
|
60
|
-
else 'other'
|
|
61
|
-
end
|
|
62
|
-
end,
|
|
63
|
-
|
|
64
|
-
one_upto_two_other:
|
|
65
|
-
->(n) { n && n >= 0 && n < 2 ? 'one' : 'other' },
|
|
66
|
-
|
|
67
|
-
other:
|
|
68
|
-
->(*) { 'other' },
|
|
69
|
-
|
|
70
|
-
polish:
|
|
71
|
-
lambda do |n = 0|
|
|
72
|
-
mod10 = n % 10
|
|
73
|
-
mod100 = n % 100
|
|
74
|
-
case
|
|
75
|
-
when n == 1 then 'one'
|
|
76
|
-
when from2to4.include?(mod10) && !from12to14.include?(mod100) then 'few'
|
|
77
|
-
when from0to1_from5to9.include?(mod10) || from12to14.include?(mod100) then 'many'
|
|
78
|
-
else 'other'
|
|
79
|
-
end
|
|
80
|
-
end,
|
|
81
|
-
|
|
82
|
-
west_slavic:
|
|
83
|
-
lambda do |n|
|
|
84
|
-
case n
|
|
85
|
-
when 1 then 'one'
|
|
86
|
-
when *from2to4 then 'few'
|
|
87
|
-
else 'other'
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
}.freeze
|
|
92
|
-
|
|
93
|
-
# Store the RULE to apply to each LOCALE
|
|
94
|
-
# the :one_other RULE is the default for locales missing from this list
|
|
95
|
-
LOCALE = Hash.new(RULE[:one_other]).tap do |hash|
|
|
96
|
-
hash['ar'] = RULE[:arabic]
|
|
97
|
-
hash['be'] = RULE[:east_slavic]
|
|
98
|
-
hash['bs'] = RULE[:east_slavic]
|
|
99
|
-
hash['ckb'] = RULE[:other]
|
|
100
|
-
hash['cs'] = RULE[:west_slavic]
|
|
101
|
-
hash['id'] = RULE[:other]
|
|
102
|
-
hash['fr'] = RULE[:one_upto_two_other]
|
|
103
|
-
hash['hr'] = RULE[:east_slavic]
|
|
104
|
-
hash['ja'] = RULE[:other]
|
|
105
|
-
hash['km'] = RULE[:other]
|
|
106
|
-
hash['ko'] = RULE[:other]
|
|
107
|
-
hash['pl'] = RULE[:polish]
|
|
108
|
-
hash['ru'] = RULE[:east_slavic]
|
|
109
|
-
hash['sk'] = RULE[:west_slavic]
|
|
110
|
-
hash['sr'] = RULE[:east_slavic]
|
|
111
|
-
hash['tr'] = RULE[:other]
|
|
112
|
-
hash['uk'] = RULE[:east_slavic]
|
|
113
|
-
hash['vi'] = RULE[:other]
|
|
114
|
-
hash['zh-CN'] = RULE[:other]
|
|
115
|
-
hash['zh-HK'] = RULE[:other]
|
|
116
|
-
hash['zh-TW'] = RULE[:other]
|
|
117
|
-
hash['dz'] = RULE[:other]
|
|
118
|
-
end.freeze
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
# Stores the i18n DATA structure for each loaded locale
|
|
122
|
-
# default on the first locale DATA
|
|
123
|
-
DATA = Hash.new { |hash,| hash.first[1] }
|
|
124
|
-
|
|
125
|
-
private
|
|
126
|
-
|
|
127
|
-
# Create a flat hash with dotted notation keys
|
|
128
|
-
def flatten(initial, prefix = '')
|
|
129
|
-
initial.each.reduce({}) do |hash, (key, value)|
|
|
130
|
-
hash.merge!(value.is_a?(Hash) ? flatten(value, "#{prefix}#{key}.") : { "#{prefix}#{key}" => value })
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
# Build the DATA hash out of the passed locales
|
|
135
|
-
def build(*locales)
|
|
136
|
-
locales.each do |locale|
|
|
137
|
-
locale[:filepath] ||= Pagy.root.join('locales', "#{locale[:locale]}.yml")
|
|
138
|
-
locale[:pluralize] ||= P11n::LOCALE[locale[:locale]]
|
|
139
|
-
dictionary = YAML.safe_load(File.read(locale[:filepath], encoding: 'UTF-8'))
|
|
140
|
-
raise I18nError, %(expected :locale "#{locale[:locale]}" not found in :filepath "#{locale[:filepath].inspect}") \
|
|
141
|
-
unless dictionary.key?(locale[:locale])
|
|
142
|
-
|
|
143
|
-
DATA[locale[:locale]] = [flatten(dictionary[locale[:locale]]), locale[:pluralize]]
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
# Build the default at require time
|
|
147
|
-
build(locale: 'en')
|
|
148
|
-
|
|
149
|
-
public
|
|
150
|
-
|
|
151
|
-
# Public method to configure the locales: overrides the default, build the DATA and freezes it
|
|
152
|
-
def load(*locales)
|
|
153
|
-
DATA.clear
|
|
154
|
-
build(*locales)
|
|
155
|
-
DATA.freeze
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
# Translate and pluralize the key with the locale DATA
|
|
159
|
-
def translate(locale, key, **opts)
|
|
160
|
-
data, pluralize = DATA[locale]
|
|
161
|
-
translation = data[key] || (opts[:count] && data[key += ".#{pluralize.call(opts[:count])}"]) \
|
|
162
|
-
or return %([translation missing: "#{key}"])
|
|
163
|
-
translation.gsub(/%{[^}]+?}/) { |match| opts[:"#{match[2..-2]}"] || match }
|
|
164
|
-
end
|
|
165
|
-
alias t translate
|
|
166
|
-
end
|
|
167
|
-
end
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# See Pagy API documentation: https://ddnexus.github.io/pagy/docs/api/keyset
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
class Pagy
|
|
5
|
-
class Keyset
|
|
6
|
-
# Keyset adapter for ActiveRecord
|
|
7
|
-
class ActiveRecord < Keyset
|
|
8
|
-
protected
|
|
9
|
-
|
|
10
|
-
# Get the keyset attributes from the record
|
|
11
|
-
def keyset_attributes_from(record) = record.slice(*@keyset.keys)
|
|
12
|
-
|
|
13
|
-
# Get the hash of quoted keyset identifiers
|
|
14
|
-
def quoted_identifiers(table)
|
|
15
|
-
connection = @set.connection
|
|
16
|
-
@keyset.to_h { |column| [column, "#{connection.quote_table_name(table)}.#{connection.quote_column_name(column)}"] }
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# Extract the keyset from the set
|
|
20
|
-
def extract_keyset
|
|
21
|
-
@set.order_values.each_with_object({}) do |node, keyset|
|
|
22
|
-
keyset[node.value.name.to_sym] = node.direction
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# Filter the newest records
|
|
27
|
-
def filter_newest = @set.where(filter_newest_query, **@latest)
|
|
28
|
-
|
|
29
|
-
# Append the missing keyset keys if the set is restricted by select
|
|
30
|
-
def apply_select
|
|
31
|
-
@set.select(*@keyset.keys)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Set with selected columns?
|
|
35
|
-
def select? = !@set.select_values.empty?
|
|
36
|
-
|
|
37
|
-
# Typecast the latest attributes
|
|
38
|
-
def typecast_latest(latest)
|
|
39
|
-
@set.model.new(latest).slice(latest.keys)
|
|
40
|
-
.to_hash.transform_keys(&:to_sym)
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
data/lib/pagy/keyset/sequel.rb
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# See Pagy API documentation: https://ddnexus.github.io/pagy/docs/api/keyset
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
class Pagy
|
|
5
|
-
class Keyset
|
|
6
|
-
# Keyset adapter for sequel
|
|
7
|
-
class Sequel < Keyset
|
|
8
|
-
protected
|
|
9
|
-
|
|
10
|
-
# Get the keyset attributes from the record
|
|
11
|
-
def keyset_attributes_from(record) = record.to_hash.slice(*@keyset.keys)
|
|
12
|
-
|
|
13
|
-
# Get the hash of quoted keyset identifiersAdd commentMore actions
|
|
14
|
-
def quoted_identifiers(table)
|
|
15
|
-
db = @set.db
|
|
16
|
-
@keyset.to_h { |column| [column, "#{db.quote_identifier(table)}.#{db.quote_identifier(column)}"] }
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# Extract the keyset from the set
|
|
20
|
-
def extract_keyset
|
|
21
|
-
return {} unless @set.opts[:order]
|
|
22
|
-
|
|
23
|
-
@set.opts[:order].each_with_object({}) do |item, keyset|
|
|
24
|
-
case item
|
|
25
|
-
when Symbol
|
|
26
|
-
keyset[item] = :asc
|
|
27
|
-
when ::Sequel::SQL::OrderedExpression
|
|
28
|
-
keyset[item.expression] = item.descending ? :desc : :asc
|
|
29
|
-
else
|
|
30
|
-
raise TypeError, "#{item.class.inspect} is not a supported Sequel::SQL::OrderedExpression"
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# Filter the newest records
|
|
36
|
-
def filter_newest = @set.where(::Sequel.lit(filter_newest_query, **@latest))
|
|
37
|
-
|
|
38
|
-
# Append the missing keyset keys if the set is restricted by select
|
|
39
|
-
def apply_select
|
|
40
|
-
selected = @set.opts[:select]
|
|
41
|
-
@set.select_append(*@keyset.keys.reject { |c| selected.include?(c) })
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# Set with selected columns?
|
|
45
|
-
def select? = !@set.opts[:select].nil?
|
|
46
|
-
|
|
47
|
-
# Typecast the latest attributes
|
|
48
|
-
def typecast_latest(latest)
|
|
49
|
-
model = @set.opts[:model]
|
|
50
|
-
model.unrestrict_primary_key if (restricted_pk = model.restrict_primary_key?)
|
|
51
|
-
latest = model.new(latest).to_hash.slice(*latest.keys.map(&:to_sym))
|
|
52
|
-
model.restrict_primary_key if restricted_pk
|
|
53
|
-
latest
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|