Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

388 lines (336 sloc) 12.835 kB
module Serve #:nodoc:
# Many of the methods here have been extracted in some form from Rails
module EscapeHelpers
HTML_ESCAPE = { '&' => '&amp;', '>' => '&gt;', '<' => '&lt;', '"' => '&quot;' }
JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003E', '<' => '\u003C' }
# A utility method for escaping HTML tag characters.
# This method is also aliased as <tt>h</tt>.
#
# In your ERb templates, use this method to escape any unsafe content. For example:
# <%=h @person.name %>
#
# ==== Example:
# puts html_escape("is a > 0 & a < 10?")
# # => is a &gt; 0 &amp; a &lt; 10?
def html_escape(s)
s.to_s.gsub(/[&"><]/) { |special| HTML_ESCAPE[special] }
end
alias h html_escape
# A utility method for escaping HTML entities in JSON strings.
# This method is also aliased as <tt>j</tt>.
#
# In your ERb templates, use this method to escape any HTML entities:
# <%=j @person.to_json %>
#
# ==== Example:
# puts json_escape("is a > 0 & a < 10?")
# # => is a \u003E 0 \u0026 a \u003C 10?
def json_escape(s)
s.to_s.gsub(/[&"><]/) { |special| JSON_ESCAPE[special] }
end
alias j json_escape
end
module ContentHelpers
def content_for(symbol, content = nil, &block)
content = capture(&block) if block_given?
set_content_for(symbol, content) if content
get_content_for(symbol) unless content
end
def content_for?(symbol)
!(get_content_for(symbol)).nil?
end
def get_content_for(symbol = :content)
if symbol.to_s.intern == :content
@content
else
instance_variable_get("@content_for_#{symbol}")
end
end
def set_content_for(symbol, value)
instance_variable_set("@content_for_#{symbol}", value)
end
def capture_erb(&block)
buffer = ""
old_buffer, @_out_buf = @_out_buf, buffer
yield
buffer
ensure
@_out_buf = old_buffer
end
alias capture_rhtml capture_erb
alias capture_erubis capture_erb
def capture(&block)
capture_method = "capture_#{script_extension}"
if respond_to? capture_method
send capture_method, &block
else
raise "Capture not supported for `#{script_extension}' template (#{engine_name})"
end
end
private
def engine_name
Tilt[script_extension].to_s
end
def script_extension
parser.script_extension
end
end
module FlashHelpers
def flash
@flash ||= {}
end
end
module ParamHelpers
# Key based access to query parameters. Keys can be strings or symbols.
def params
@params ||= request.params
end
# Extract the value for a bool param. Handy for rendering templates in
# different states.
def boolean_param(key, default = false)
key = key.to_s.intern
value = params[key]
return default if value.blank?
case value.strip.downcase
when 'true', '1' then true
when 'false', '0' then false
else raise 'Invalid value'
end
end
end
module RenderHelpers
def render(partial, options={})
if partial.is_a?(Hash)
options = options.merge(partial)
partial = options.delete(:partial)
end
template = options.delete(:template)
case
when partial
render_partial(partial, options)
when template
render_template(template)
else
raise "render options not supported #{options.inspect}"
end
end
def render_partial(partial, options={})
render_template(partial, options.merge(partial: true))
end
def render_template(template, options={})
path = parser.template_path
if template =~ %r{^/}
template = template[1..-1]
path = @root_path
end
filename = template_filename(path, template, partial: options[:partial])
if filename && File.file?(filename)
parser.parse(File.read(filename), File.extname(filename).split(".").last, options[:locals])
else
raise "File does not exist #{filename.inspect}"
end
end
private
def template_filename(path, template, options)
template_path = File.dirname(template)
template_file = File.basename(template)
template_file = "_" + template_file if options[:partial]
route = Serve::Router.resolve(path, File.join(template_path, template_file))
(route && File.join(path, route))
end
def extname(filename)
/(\.[a-z]+\.[a-z]+)$/.match(filename)
$1 || File.extname(filename) || ''
end
end
module TagHelpers
def content_tag(name, content, html_options={})
%{<#{name}#{html_attributes(html_options)}>#{content}</#{name}>}
end
def tag(name, html_options={})
%{<#{name}#{html_attributes(html_options)} />}
end
def image_tag(src, html_options = {})
tag(:img, html_options.merge({src: src}))
end
def image(name, options = {})
image_tag(ensure_path(ensure_extension(name, 'png'), 'images'), options)
end
def javascript_tag(content = nil, html_options = {})
content_tag(:script, javascript_cdata_section(content), html_options.merge(type: "text/javascript"))
end
def link_to(name, href, html_options = {})
html_options = html_options.stringify_keys
confirm = html_options.delete("confirm")
onclick = "if (!confirm('#{html_escape(confirm)}')) return false;" if confirm
content_tag(:a, name, html_options.merge(href: href, onclick: onclick))
end
def link_to_function(name, *args, &block)
html_options = extract_options!(args)
function = args[0] || ''
onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function}; return false;"
href = html_options[:href] || '#'
content_tag(:a, name, html_options.merge(href: href, onclick: onclick))
end
def mail_to(email_address, name = nil, html_options = {})
html_options = html_options.stringify_keys
encode = html_options.delete("encode").to_s
cc, bcc, subject, body = html_options.delete("cc"), html_options.delete("bcc"), html_options.delete("subject"), html_options.delete("body")
string = ''
extras = ''
extras << "cc=#{CGI.escape(cc).gsub("+", "%20")}&" unless cc.nil?
extras << "bcc=#{CGI.escape(bcc).gsub("+", "%20")}&" unless bcc.nil?
extras << "body=#{CGI.escape(body).gsub("+", "%20")}&" unless body.nil?
extras << "subject=#{CGI.escape(subject).gsub("+", "%20")}&" unless subject.nil?
extras = "?" << extras.gsub!(/&?$/,"") unless extras.empty?
email_address = email_address.to_s
email_address_obfuscated = email_address.dup
email_address_obfuscated.gsub!(/@/, html_options.delete("replace_at")) if html_options.has_key?("replace_at")
email_address_obfuscated.gsub!(/\./, html_options.delete("replace_dot")) if html_options.has_key?("replace_dot")
if encode == "javascript"
"document.write('#{content_tag("a", name || email_address_obfuscated, html_options.merge({ "href" => "mailto:"+email_address+extras }))}');".each_byte do |c|
string << sprintf("%%%x", c)
end
"<script type=\"#{Mime::JS}\">eval(decodeURIComponent('#{string}'))</script>"
elsif encode == "hex"
email_address_encoded = ''
email_address_obfuscated.each_byte do |c|
email_address_encoded << sprintf("&#%d;", c)
end
protocol = 'mailto:'
protocol.each_byte { |c| string << sprintf("&#%d;", c) }
email_address.each_byte do |c|
char = c.chr
string << (char =~ /\w/ ? sprintf("%%%x", c) : char)
end
content_tag "a", name || email_address_encoded, html_options.merge({ "href" => "#{string}#{extras}" })
else
content_tag "a", name || email_address_obfuscated, html_options.merge({ "href" => "mailto:#{email_address}#{extras}" })
end
end
# Generates JavaScript script tags for the sources given as arguments.
#
# If the .js extension is not given, it will be appended to the source.
#
# Examples
# javascript_include_tag 'application' # =>
# <script src="/javascripts/application.js" type="text/javascript" />
#
# javascript_include_tag 'https://cdn/jquery.js' # =>
# <script src="https://cdn/jquery.js" type="text/javascript" />
#
# javascript_include_tag 'application', 'books' # =>
# <script src="/javascripts/application.js" type="text/javascript" />
# <script src="/javascripts/books.js" type="text/javascript" />
#
def javascript_include_tag(*sources)
options = extract_options!(sources)
sources.map do |source|
content_tag('script', '', {
'type' => 'text/javascript',
'src' => ensure_path(ensure_extension(source, 'js'), 'javascripts')
}.merge(options))
end.join("\n")
end
# Generates stylesheet link tags for the sources given as arguments.
#
# If the .css extension is not given, it will be appended to the source.
#
# Examples
# stylesheet_link_tag 'screen' # =>
# <link href="/stylesheets/screen.css" media="screen" rel="stylesheet" type="text/css" />
#
# stylesheet_link_tag 'print', :media => 'print' # =>
# <link href="/stylesheets/print.css" media="print" rel="stylesheet" type="text/css" />
#
# stylesheet_link_tag 'application', 'books', 'authors' # =>
# <link href="/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />
# <link href="/stylesheets/books.css" media="screen" rel="stylesheet" type="text/css" />
# <link href="/stylesheets/authors.css" media="screen" rel="stylesheet" type="text/css" />
#
def stylesheet_link_tag(*sources)
options = extract_options!(sources)
sources.map do |source|
tag('link', {
'rel' => 'stylesheet',
'type' => 'text/css',
'media' => 'screen',
'href' => ensure_path(ensure_extension(source, 'css'), 'stylesheets')
}.merge(options))
end.join("\n")
end
private
def cdata_section(content)
"<![CDATA[#{content}]]>"
end
def javascript_cdata_section(content) #:nodoc:
"\n//#{cdata_section("\n#{content}\n//")}\n"
end
def html_attributes(options)
unless options.blank?
attrs = []
options.each_pair do |key, value|
if value == true
attrs << %(#{key}="#{key}") if value
else
attrs << %(#{key}="#{value}") unless value.nil?
end
end
" #{attrs.sort * ' '}" unless attrs.empty?
end
end
# Ensures a proper extension is appended to the filename.
#
# If a URI with the http or https scheme name is given, it is assumed
# to be absolute and will not be altered.
#
# Examples
# ensure_extension('screen', 'css') => 'screen.css'
# ensure_extension('screen.css', 'css') => 'screen.css'
# ensure_extension('jquery.min', 'js') => 'jquery.min.js'
# ensure_extension('https://cdn/jquery', 'js') => 'https://cdn/jquery'
#
def ensure_extension(source, extension)
if source =~ /^https?:/ || source.end_with?(".#{extension}")
return source
end
"#{source}.#{extension}"
end
# Ensures the proper path to the given source.
#
# If the source begins at the root of the public directory or is a URI
# with the http or https scheme name, it is assumed to be absolute and
# will not be altered.
#
# Examples
# ensure_path('screen.css', 'stylesheets') => '/stylesheets/screen.css'
# ensure_path('/screen.css', 'stylesheets') => '/screen.css'
# ensure_path('http://cdn/jquery.js', 'javascripts') => 'http://cdn/jquery.js'
#
def ensure_path(source, path)
if source =~ /^(\/|https?)/
return source
end
File.join('', path, source)
end
# Returns a hash of options if they exist at the end of an array.
#
# This is useful when working with splats.
#
# Examples
# extract_options!([1, 2, { :name => 'sunny' }]) => { :name => 'sunny' }
# extract_options!([1, 2, 3]) => {}
#
def extract_options!(array)
array.last.instance_of?(Hash) ? array.pop : {}
end
end
module ViewHelpers #:nodoc:
include EscapeHelpers
include ContentHelpers
include FlashHelpers
include ParamHelpers
include RenderHelpers
include TagHelpers
end
end
Jump to Line
Something went wrong with that request. Please try again.