# See Pagy::Frontend API documentation: https://ddnexus.github.io/pagy/api/frontend # encoding: utf-8 # frozen_string_literal: true require 'yaml' class Pagy PAGE_PLACEHOLDER = '__pagy_page__' # string used for search and replace, hardcoded also in the pagy.js file # I18n static hash loaded at startup, used as default alternative to the i18n gem. # see https://ddnexus.github.io/pagy/api/frontend#i18n I18n = eval(Pagy.root.join('locales', 'utils', 'i18n.rb').read) #rubocop:disable Security/Eval module Helpers # This works with all Rack-based frameworks (Sinatra, Padrino, Rails, ...) def pagy_url_for(page, pagy, url=false) p_vars = pagy.vars; params = request.GET.merge(p_vars[:params]); params[p_vars[:page_param].to_s] = page "#{request.base_url if url}#{request.path}?#{Rack::Utils.build_nested_query(pagy_get_params(params))}#{p_vars[:anchor]}" end # Sub-method called only by #pagy_url_for: here for easy customization of params by overriding def pagy_get_params(params) params end end # All the code here has been optimized for performance: it may not look very pretty # (as most code dealing with many long strings), but its performance makes it very sexy! ;) module Frontend include Helpers EMPTY = '' # EMPTY + 'string' is almost as fast as +'string' but is also 1.9 compatible MARK = PAGE_PLACEHOLDER # backward compatibility in case of helper-overriding in legacy apps # Generic pagination: it returns the html with the series of links to the pages def pagy_nav(pagy) link, p_prev, p_next = pagy_link_proc(pagy), pagy.prev, pagy.next html = EMPTY + (p_prev ? %(#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'} ) : %(#{pagy_t('pagy.nav.prev')} )) pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36] html << if item.is_a?(Integer); %(#{link.call item} ) # page link elsif item.is_a?(String) ; %(#{item} ) # current page elsif item == :gap ; %(#{pagy_t('pagy.nav.gap')} ) # page gap end end html << (p_next ? %(#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'}) : %(#{pagy_t('pagy.nav.next')})) %() end # Return examples: "Displaying items 41-60 of 324 in total" of "Displaying Products 41-60 of 324 in total" def pagy_info(pagy, item_name=nil) path = if (count = pagy.count) == 0 ; 'pagy.info.no_items' else pagy.pages == 1 ? 'pagy.info.single_page' : 'pagy.info.multiple_pages' end pagy_t(path, item_name: item_name || pagy_t(pagy.vars[:i18n_key], count: count), count: count, from: pagy.from, to: pagy.to) end # Returns a performance optimized proc to generate the HTML links # Benchmarked on a 20 link nav: it is ~22x faster and uses ~18x less memory than rails' link_to def pagy_link_proc(pagy, link_extra='') p_prev, p_next = pagy.prev, pagy.next a, b = %("} end # Similar to I18n.t: just ~18x faster using ~10x less memory # (@pagy_locale explicitly initilized in order to avoid warning) def pagy_t(path, vars={}) Pagy::I18n.t(@pagy_locale||=nil, path, vars) end end end