/
format_helpers.rb
121 lines (106 loc) · 5.31 KB
/
format_helpers.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
module Padrino
module Helpers
module FormatHelpers
# Returns escaped text to protect against malicious content
def escape_html(text)
Rack::Utils.escape_html(text)
end
alias h escape_html
alias sanitize_html escape_html
# Returns escaped text to protect against malicious content
# Returns blank if the text is empty
def h!(text, blank_text = ' ')
return blank_text if text.nil? || text.empty?
h text
end
# Returns text transformed into HTML using simple formatting rules. Two or more consecutive newlines(\n\n) are considered
# as a paragraph and wrapped in <p> tags. One newline (\n) is considered as a linebreak and a <br /> tag is appended.
# This method does not remove the newlines from the text.
# simple_format("hello\nworld") # => "<p>hello<br/>world</p>"
def simple_format(text, html_options={})
start_tag = tag('p', html_options.merge(:open => true))
text = text.to_s.dup
text.gsub!(/\r\n?/, "\n") # \r\n and \r -> \n
text.gsub!(/\n\n+/, "</p>\n\n#{start_tag}") # 2+ newline -> paragraph
text.gsub!(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
text.insert 0, start_tag
text << "</p>"
end
# Attempts to pluralize the singular word unless count is 1. If plural is supplied, it will use that when count is > 1,
# otherwise it will use the Inflector to determine the plural form
# pluralize(2, 'person') => '2 people'
def pluralize(count, singular, plural = nil)
"#{count || 0} " + ((count == 1 || count == '1') ? singular : (plural || singular.pluralize))
end
# Truncates a given text after a given :length if text is longer than :length (defaults to 30).
# The last characters will be replaced with the :omission (defaults to "…") for a total length not exceeding :length.
# truncate("Once upon a time in a world far far away", :length => 8) => "Once upon..."
def truncate(text, *args)
options = args.extract_options!
options.reverse_merge!(:length => 30, :omission => "...")
if text
len = options[:length] - options[:omission].length
chars = text
(chars.length > options[:length] ? chars[0...len] + options[:omission] : text).to_s
end
end
# Wraps the text into lines no longer than line_width width.
# This method breaks on the first whitespace character that does not exceed line_width (which is 80 by default).
# word_wrap('Once upon a time', :line_width => 8) => "Once upon\na time"
def word_wrap(text, *args)
options = args.extract_options!
unless args.blank?
options[:line_width] = args[0] || 80
end
options.reverse_merge!(:line_width => 80)
text.split("\n").collect do |line|
line.length > options[:line_width] ? line.gsub(/(.{1,#{options[:line_width]}})(\s+|$)/, "\\1\n").strip : line
end * "\n"
end
# Smart time helper which returns relative text representing times for recent dates
# and absolutes for dates that are far removed from the current date
# time_in_words(10.days.ago) => '10 days ago'
def time_in_words(date)
date = date.to_date
date = Date.parse(date, true) unless /Date.*/ =~ date.class.to_s
days = (date - Date.today).to_i
return 'today' if days >= 0 and days < 1
return 'tomorrow' if days >= 1 and days < 2
return 'yesterday' if days >= -1 and days < 0
return "in #{days} days" if days.abs < 60 and days > 0
return "#{days.abs} days ago" if days.abs < 60 and days < 0
return date.strftime('%A, %B %e') if days.abs < 182
return date.strftime('%A, %B %e, %Y')
end
alias time_ago time_in_words
# Returns relative time in words referencing the given date
# relative_time_ago(Time.now) => 'about a minute ago'
def relative_time_ago(from_time)
distance_in_minutes = (((Time.now - from_time.to_time).abs)/60).round
case distance_in_minutes
when 0..1 then 'about a minute'
when 2..44 then "#{distance_in_minutes} minutes"
when 45..89 then 'about 1 hour'
when 90..1439 then "about #{(distance_in_minutes.to_f / 60.0).round} hours"
when 1440..2879 then '1 day'
when 2880..43199 then "#{(distance_in_minutes / 1440).round} days"
when 43200..86399 then 'about 1 month'
when 86400..525599 then "#{(distance_in_minutes / 43200).round} months"
when 525600..1051199 then 'about 1 year'
else "over #{(distance_in_minutes / 525600).round} years"
end
end
# Used in xxxx.js.erb files to escape html so that it can be passed to javascript from Padrino
# js_escape_html("<h1>Hey</h1>")
def js_escape_html(html_content)
return '' unless html_content
javascript_mapping = { '\\' => '\\\\', '</' => '<\/', "\r\n" => '\n', "\n" => '\n' }
javascript_mapping.merge("\r" => '\n', '"' => '\\"', "'" => "\\'")
escaped_string = html_content.gsub(/(\\|<\/|\r\n|[\n\r"'])/) { javascript_mapping[$1] }
"\"#{escaped_string}\""
end
alias escape_javascript js_escape_html
alias escape_for_javascript js_escape_html
end
end
end