Module: Padrino::Helpers::FormatHelpers

Defined in:
lib/padrino-helpers/format_helpers.rb

Overview

Helpers related to formatting or manipulating text within templates.

Instance Method Summary collapse

Instance Method Details

#distance_of_time_in_words(from_time, to_time = 0, include_seconds = false, options = {}) ⇒ String

Reports the approximate distance in time between two Time or Date objects or integers as seconds. Set include_seconds to true if you want more detailed approximations when distance < 1 min, 29 secs Distances are reported based on the following table:

0 <-> 29 secs                                                           # => less than a minute
30 secs <-> 1 min, 29 secs                                              # => 1 minute
1 min, 30 secs <-> 44 mins, 29 secs                                     # => [2..44] minutes
44 mins, 30 secs <-> 89 mins, 29 secs                                   # => about 1 hour
89 mins, 29 secs <-> 23 hrs, 59 mins, 29 secs                           # => about [2..24] hours
23 hrs, 59 mins, 29 secs <-> 47 hrs, 59 mins, 29 secs                   # => 1 day
47 hrs, 59 mins, 29 secs <-> 29 days, 23 hrs, 59 mins, 29 secs          # => [2..29] days
29 days, 23 hrs, 59 mins, 30 secs <-> 59 days, 23 hrs, 59 mins, 29 secs # => about 1 month
59 days, 23 hrs, 59 mins, 30 secs <-> 1 yr minus 1 sec                  # => [2..12] months
1 yr <-> 1 yr, 3 months                                                 # => about 1 year
1 yr, 3 months <-> 1 yr, 9 months                                       # => over 1 year
1 yr, 9 months <-> 2 yr minus 1 sec                                     # => almost 2 years
2 yrs <-> max time or date                                              # => (same rules as 1 yr)

With include_seconds = true and the difference < 1 minute 29 seconds:

0-4   secs      # => less than 5 seconds
5-9   secs      # => less than 10 seconds
10-19 secs      # => less than 20 seconds
20-39 secs      # => half a minute
40-59 secs      # => less than a minute
60-89 secs      # => 1 minute

Examples:

from_time = Time.now
distance_of_time_in_words(from_time, from_time + 50.minutes)        # => about 1 hour
distance_of_time_in_words(from_time, 50.minutes.from_now)           # => about 1 hour
distance_of_time_in_words(from_time, from_time + 15.seconds)        # => less than a minute
distance_of_time_in_words(from_time, from_time + 15.seconds, true)  # => less than 20 seconds
distance_of_time_in_words(from_time, 3.years.from_now)              # => about 3 years
distance_of_time_in_words(from_time, from_time + 60.hours)          # => about 3 days
distance_of_time_in_words(from_time, from_time + 45.seconds, true)  # => less than a minute
distance_of_time_in_words(from_time, from_time - 45.seconds, true)  # => less than a minute
distance_of_time_in_words(from_time, 76.seconds.from_now)           # => 1 minute
distance_of_time_in_words(from_time, from_time + 1.year + 3.days)   # => about 1 year
distance_of_time_in_words(from_time, from_time + 3.years + 6.months) # => over 3 years
distance_of_time_in_words(from_time, from_time + 4.years + 9.days + 30.minutes + 5.seconds) # => about 4 years
to_time = Time.now + 6.years + 19.days
distance_of_time_in_words(from_time, to_time, true)     # => about 6 years
distance_of_time_in_words(to_time, from_time, true)     # => about 6 years
distance_of_time_in_words(Time.now, Time.now)           # => less than a minute

Parameters:

  • from_time (Time)

    The time to be compared against to_time in order to approximate the distance.

  • to_time (Time) (defaults to: 0)

    The time to be compared against from_time in order to approximate the distance.

  • include_seconds (Boolean) (defaults to: false)

    Set true for more detailed approximations.

  • options (Hash) (defaults to: {})

    Flags for the approximation.

Options Hash (options):

  • :locale (String)

    The translation locale to be used for approximating the time.

Returns:

  • (String)

    The time formatted as a relative string.



286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'lib/padrino-helpers/format_helpers.rb', line 286

def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false, options = {})
  from_time = from_time.to_time if from_time.respond_to?(:to_time)
  to_time = to_time.to_time if to_time.respond_to?(:to_time)
  distance_in_minutes = (((to_time.to_i - from_time.to_i).abs)/60).round
  distance_in_seconds = ((to_time.to_i - from_time.to_i).abs).round

  phrase, locals =
    case distance_in_minutes
      when 0..1
        if include_seconds
          case distance_in_seconds
            when 0..4   then [:less_than_x_seconds, :count => 5 ]
            when 5..9   then [:less_than_x_seconds, :count => 10]
            when 10..19 then [:less_than_x_seconds, :count => 20]
            when 20..39 then [:half_a_minute                    ]
            when 40..59 then [:less_than_x_minutes, :count => 1 ]
            else             [:x_minutes,           :count => 1 ]
          end
        else
          distance_in_minutes == 0 ?
            [:less_than_x_minutes, :count => 1] :
            [:x_minutes, :count => distance_in_minutes]
        end
      when 2..44           then [:x_minutes,      :count => distance_in_minutes                       ]
      when 45..89          then [:about_x_hours,  :count => 1                                         ]
      when 90..1439        then [:about_x_hours,  :count => (distance_in_minutes.to_f / 60.0).round   ]
      when 1440..2529      then [:x_days,         :count => 1                                         ]
      when 2530..43199     then [:x_days,         :count => (distance_in_minutes.to_f / 1440.0).round ]
      when 43200..86399    then [:about_x_months, :count => 1                                         ]
      when 86400..525599   then [:x_months,       :count => (distance_in_minutes.to_f / 43200.0).round]
      else
        distance_in_years           = distance_in_minutes / 525600
        minute_offset_for_leap_year = (distance_in_years / 4) * 1440
        remainder                   = ((distance_in_minutes - minute_offset_for_leap_year) % 525600)
        if remainder < 131400
          [:about_x_years,  :count => distance_in_years]
        elsif remainder < 394200
          [:over_x_years,   :count => distance_in_years]
        else
          [:almost_x_years, :count => distance_in_years + 1]
        end
    end

  I18n.translate phrase, :count => locals[:count], :locale => options[:locale], :scope => :'datetime.distance_in_words'
end

#escape_html(text) ⇒ String Also known as: h, sanitize_html

Returns escaped text to protect against malicious content.

Examples:

escape_html("<b>Hey<b>") => "&lt;b&gt;Hey&lt;b;gt;"
h("Me & Bob") => "Me &amp; Bob"

Parameters:

  • text (String)

    Unsanitized HTML string that needs to be escaped.

Returns:

  • (String)

    HTML with escaped characters.



19
20
21
# File 'lib/padrino-helpers/format_helpers.rb', line 19

def escape_html(text)
  Rack::Utils.escape_html(text).html_safe
end

#h!(text, blank_text = '&nbsp;') ⇒ String

Returns escaped text to protect against malicious content.

Examples:

h!("Me & Bob") => "Me &amp; Bob"
h!("", "Whoops") => "Whoops"

Parameters:

  • text (String)

    Unsanitized HTML string that needs to be escaped.

  • blank_text (String) (defaults to: '&nbsp;')

    Text to return if escaped text is blank.

Returns:

  • (String)

    HTML with escaped characters or the value specified if blank.



39
40
41
42
# File 'lib/padrino-helpers/format_helpers.rb', line 39

def h!(text, blank_text = '&nbsp;')
  return blank_text.html_safe if text.nil? || text.empty?
  h(text)
end

#highlight(text, words, options = {}) ⇒ String

Highlights one or more words everywhere in text by inserting it into a :highlighter string.

The highlighter can be customized by passing :highlighter as a single-quoted string with 1 where the phrase is to be inserted.

Examples:

highlight('Lorem ipsum dolor sit amet', 'dolor')
# => Lorem ipsum <strong class="highlight">dolor</strong> sit amet

highlight('Lorem ipsum dolor sit amet', 'dolor', :highlighter => '<span class="custom">\1</span>')
# => Lorem ipsum <strong class="custom">dolor</strong> sit amet

Parameters:

  • text (String)

    The text that will be searched.

  • words (String)

    The words to be highlighted in the text.

  • options (Hash) (defaults to: {})

    Formatting options for the highlight.

Options Hash (options):

  • :highlighter (String) — default: '<strong class="highlight">\1</strong>'

    The html pattern for wrapping the highlighted words.

Returns:

  • (String)

    The text with the words specified wrapped with highlighted spans.



216
217
218
219
220
221
222
223
224
225
# File 'lib/padrino-helpers/format_helpers.rb', line 216

def highlight(text, words, *args)
  options = { :highlighter => '<strong class="highlight">\1</strong>' }.update(args.last.is_a?(Hash) ? args.pop : {})

  if text.empty? || words.empty?
    text
  else
    match = Array(words).map { |p| Regexp.escape(p) }.join('|')
    text.gsub(/(#{match})(?!(?:[^<]*?)(?:["'])[^<>]*>)/i, options[:highlighter])
  end
end

#js_escape_html(html_content) ⇒ String Also known as: escape_javascript

Used in xxxx.js.erb files to escape html so that it can be passed to javascript from Padrino.

Examples:

js_escape_html("<h1>Hey</h1>")

Parameters:

  • html (String)

    The HTML content to be escaped into javascript compatible format.

Returns:

  • (String)

    The html escaped for javascript passing.



362
363
364
365
366
367
368
# File 'lib/padrino-helpers/format_helpers.rb', line 362

def js_escape_html(html_content)
  return '' unless html_content
  javascript_mapping = { '\\' => '\\\\', '</' => '<\/', "\r\n" => '\n', "\n" => '\n', "\r" => '\n', '"' => '\\"', "'" => "\\'" }
  escaped_content = html_content.gsub(/(\\|<\/|\r\n|[\n\r"'])/){ |m| javascript_mapping[m] }
  escaped_content = escaped_content.html_safe if html_content.html_safe?
  escaped_content
end

#pluralize(count, singular, plural = nil) ⇒ String

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 inflector to determine the plural form.

Examples:

pluralize(2, 'person') => '2 people'

Parameters:

  • count (Integer)

    The count which determines pluralization.

  • singular (String)

    The word to be pluralized if appropriate based on count.

  • plural (String) (defaults to: nil)

    Explicit pluralized word to be used; if not specified uses inflector.

Returns:

  • (String)

    The properly pluralized word.



105
106
107
# File 'lib/padrino-helpers/format_helpers.rb', line 105

def pluralize(count, singular, plural = nil)
  "#{count || 0} " + ((count == 1 || count == '1') ? singular : (plural || singular.pluralize))
end

#simple_format(text, options = {}) ⇒ String

Returns text transformed into HTML using simple formatting rules. Two or more consecutive newlines(nn) are considered as a paragraph and wrapped in <p> or your own 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.

Examples:

simple_format("hello\nworld") # => "<p>hello<br/>world</p>"
simple_format("hello\nworld", :tag => :div, :class => :foo) # => "<div class="foo">hello<br/>world</div>"

Parameters:

  • text (String)

    The simple text to be formatted.

  • options (Hash) (defaults to: {})

    Formatting options for the text. Can accept html options for the wrapper tag.

Options Hash (options):

  • :tag (Symbol) — default: p

    The html tag to use for formatting newlines.

Returns:

  • (String)

    The text formatted as simple HTML.



77
78
79
80
81
82
83
84
85
86
87
# File 'lib/padrino-helpers/format_helpers.rb', line 77

def simple_format(text, options={})
  t = options.delete(:tag) || :p
  start_tag = tag(t, options, true)
  text = escape_html(text.to_s.dup) unless text.html_safe?
  text.gsub!(/\r\n?/, "\n")                      # \r\n and \r -> \n
  text.gsub!(/\n\n+/, "</#{t}>\n\n#{start_tag}") # 2+ newline  -> paragraph
  text.gsub!(/([^\n]\n)(?=[^\n])/, '\1<br />')   # 1 newline   -> br
  text.insert 0, start_tag
  text << "</#{t}>"
  text.html_safe
end

#strip_tags(html) ⇒ String

Strips all HTML tags from the html.

Examples:

strip_tags("<b>Hey</b>") => "Hey"

Parameters:

  • html (String)

    The HTML for which to strip tags.

Returns:

  • (String)

    HTML with tags stripped.



55
56
57
# File 'lib/padrino-helpers/format_helpers.rb', line 55

def strip_tags(html)
  html.gsub(/<\/?[^>]*>/, "") if html
end

#time_ago_in_words(from_time, include_seconds = false) ⇒ String

Like distance_of_time_in_words, but where to_time is fixed to Time.now.

Examples:

time_ago_in_words(3.minutes.from_now)  # => 3 minutes
time_ago_in_words(Time.now - 15.hours) # => 15 hours
time_ago_in_words(Time.now)            # => less than a minute

Parameters:

  • from_time (Time)

    The time to be compared against now in order to approximate the distance.

  • include_seconds (Boolean) (defaults to: false)

    Set true for more detailed approximations.

Returns:

  • (String)

    The time formatted as a relative string.



347
348
349
# File 'lib/padrino-helpers/format_helpers.rb', line 347

def time_ago_in_words(from_time, include_seconds = false)
  distance_of_time_in_words(from_time, Time.now, include_seconds)
end

#truncate(text, options = {}) ⇒ String

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.

Examples:

truncate("Once upon a time in a world far far away", :length => 8) => "Once upon..."

Parameters:

  • text (String)

    The text to be truncated.

  • options (Hash) (defaults to: {})

    Formatting options for the truncation.

Options Hash (options):

  • :length (Integer) — default: 30

    The number of characters before truncation occurs.

  • :omission (String) — default: "..."

    The characters that are placed after the truncated text.

Returns:

  • (String)

    The text truncated after the given number of characters.



127
128
129
130
131
132
133
134
# File 'lib/padrino-helpers/format_helpers.rb', line 127

def truncate(text, options={})
  options = { :length => 30, :omission => "..." }.update(options)
  if text
    len = options[:length] - options[:omission].length
    chars = text
    (chars.length > options[:length] ? chars[0...len] + options[:omission] : text).to_s
  end
end

#truncate_words(text, options = {}) ⇒ String

Truncates words of a given text after a given :length if number of words in text is more than :length (defaults to 30). The last words will be replaced with the :omission (defaults to “…”) for a total number of words not exceeding :length.

Examples:

truncate_words("Once upon a time in a world far far away", :length => 8) => "Once upon a time in a world far..."

Parameters:

  • text (String)

    The text to be truncated.

  • options (Hash) (defaults to: {})

    Formatting options for the truncation.

Options Hash (options):

  • :length (Integer) — default: 30

    The number of words before truncation occurs.

  • :omission (String) — default: "..."

    The characters that are placed after the truncated text.

Returns:

  • (String)

    The text truncated after the given number of words.



154
155
156
157
158
159
160
# File 'lib/padrino-helpers/format_helpers.rb', line 154

def truncate_words(text, options={})
  options = { :length => 30, :omission => "..." }.update(options)
  if text
    words = text.split()
    words[0..(options[:length]-1)].join(' ') + (words.length > options[:length] ? options[:omission] : '')
  end
end

#word_wrap(text, options = {}) ⇒ String

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).

Examples:

word_wrap('Once upon a time', :line_width => 8) => "Once upon\na time"

Parameters:

  • text (String)

    The text to be wrapped.

  • options (Hash) (defaults to: {})

    Formatting options for the wrapping.

Options Hash (options):

  • :line_width (Integer) — default: 80

    The line width before a wrap should occur.

Returns:

  • (String)

    The text with line wraps for lines longer then line_width.



179
180
181
182
183
184
185
186
187
188
189
# File 'lib/padrino-helpers/format_helpers.rb', line 179

def word_wrap(text, *args)
  options = args.last.is_a?(Hash) ? args.pop : {}
  unless args.empty?
    options[:line_width] = args[0] || 80
  end
  options = { :line_width => 80 }.update(options)

  text.split("\n").map do |line|
    line.length > options[:line_width] ? line.gsub(/(.{1,#{options[:line_width]}})(\s+|$)/, "\\1\n").strip : line
  end * "\n"
end