feat(view): add Prism, ViewHelpers and PaginationHelpers
This commit is contained in:
1 parent
17c4602543
commit
d673a50ed4
4 files changed
+128
No files matched your search
@@ -0,0 +1,26 @@
|
||||
require_relative 'tag_builder'
|
||||
require_relative 'form_builder'
|
||||
require_relative 'form_helpers'
|
||||
require_relative 'url_helpers'
|
||||
require_relative 'content_for_helpers'
|
||||
require_relative 'cache_helpers'
|
||||
require_relative 'pagination_helpers'
|
||||
require_relative 'asset_helpers'
|
||||
|
||||
module Prism
|
||||
module ViewHelpers
|
||||
include TagBuilder
|
||||
include FormHelpers
|
||||
include UrlHelpers
|
||||
include ContentForHelpers
|
||||
include CacheHelpers
|
||||
include PaginationHelpers
|
||||
include AssetHelpers
|
||||
end
|
||||
|
||||
module Template
|
||||
class Context
|
||||
include ViewHelpers
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,47 @@
|
||||
module Prism
|
||||
# Renders page links for an `Orm::Relation` that has been through
|
||||
# `.page(n)`. Deliberately decoupled from the router/request: the caller
|
||||
# supplies `path` (a Proc mapping a page number to a URL string), so the
|
||||
# helper works for `/posts?page=n`, `/blog/:id/comments?page=n`, or
|
||||
# anything else without knowing about routes itself.
|
||||
module PaginationHelpers
|
||||
def paginate(relation, path:, window: 2)
|
||||
return '' if relation.total_pages <= 1
|
||||
|
||||
links = +''
|
||||
links << pagination_nav_link('Previous', relation.prev_page, path)
|
||||
pagination_page_numbers(relation, window).each do |page|
|
||||
links << if page == :gap
|
||||
content_tag(:span, '...', class: 'page-gap')
|
||||
else
|
||||
pagination_page_link(page, relation.current_page, path)
|
||||
end
|
||||
end
|
||||
links << pagination_nav_link('Next', relation.next_page, path)
|
||||
"#{tag(:nav, class: 'pagination')}#{links}</nav>"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def pagination_page_numbers(relation, window)
|
||||
total = relation.total_pages
|
||||
current = relation.current_page
|
||||
visible = (1..total).select { |page| page == 1 || page == total || (page - current).abs <= window }
|
||||
|
||||
visible.each_with_object([]) do |page, result|
|
||||
result << :gap if result.any? && result.last != :gap && page - result.last != 1
|
||||
result << page
|
||||
end
|
||||
end
|
||||
|
||||
def pagination_page_link(page, current_page, path)
|
||||
classes = page == current_page ? 'page-link current' : 'page-link'
|
||||
content_tag(:a, page.to_s, href: path.call(page), class: classes)
|
||||
end
|
||||
|
||||
def pagination_nav_link(text, target_page, path)
|
||||
return content_tag(:span, text, class: 'page-link disabled') unless target_page
|
||||
content_tag(:a, text, href: path.call(target_page), class: 'page-link')
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,38 @@
|
||||
module Prism
|
||||
# HTML tag construction shared by every other view helper. `tag` and the
|
||||
# content-returning form of `content_tag` are meant to be used from a
|
||||
# `<%== %>` template tag (they hand back an already-escaped string);
|
||||
# the block form of `content_tag` is meant to be used from a plain
|
||||
# `<% %>` tag and appends itself to the template's output buffer, same
|
||||
# as `form_for` (see Prism::Template::Context#capture).
|
||||
module TagBuilder
|
||||
def tag(name, attributes = {})
|
||||
"<#{name}#{html_attributes(attributes)}>"
|
||||
end
|
||||
|
||||
def content_tag(name, content = nil, attributes = {})
|
||||
if block_given?
|
||||
attributes = content if content.is_a?(Hash)
|
||||
inner = capture { yield }
|
||||
@__out << "<#{name}#{html_attributes(attributes)}>#{inner}</#{name}>"
|
||||
nil
|
||||
else
|
||||
"<#{name}#{html_attributes(attributes)}>#{escape_html(content.to_s)}</#{name}>"
|
||||
end
|
||||
end
|
||||
|
||||
def html_attributes(attributes)
|
||||
return '' if attributes.nil? || attributes.empty?
|
||||
attributes.filter_map { |key, value| html_attribute(key, value) }.join
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def html_attribute(key, value)
|
||||
return nil if value.nil? || value == false
|
||||
name = key.to_s.tr('_', '-')
|
||||
return %( #{name}="#{name}") if value == true
|
||||
%( #{name}="#{escape_html(value.to_s)}")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,17 @@
|
||||
module Prism
|
||||
module UrlHelpers
|
||||
def link_to(text, url, attributes = {})
|
||||
content_tag(:a, text, attributes.merge(href: url))
|
||||
end
|
||||
|
||||
def button_to(text, url, method: :post, form: {}, **button_attrs)
|
||||
verb = method.to_s.upcase
|
||||
markup = +"<form action=\"#{escape_html(url)}\" method=\"post\"#{html_attributes(form.merge(class: [form[:class], 'button-to'].compact.join(' ')))}>"
|
||||
markup << hidden_method_field(verb) unless verb == 'POST'
|
||||
markup << csrf_hidden_field
|
||||
markup << content_tag(:button, text, { type: 'submit' }.merge(button_attrs))
|
||||
markup << '</form>'
|
||||
markup
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in new issue
Block a user