Module: Ramaze::Helper::Formatting

Defined in:
lib/ramaze/helper/formatting.rb

Constant Summary

FORMATTING_NUMBER_COUNTER =
{
  0  => 'no',
  2  => 'two',
  3  => 'three',
  4  => 'four',
  5  => 'five',
  6  => 'six',
  7  => 'seven',
  8  => 'eight',
  9  => 'nine',
  10 => 'ten'
}
%r{
  (                          # leading text
    <\w+.*?>|                # leading HTML tag, or
    [^=!:'"/]|               # leading punctuation, or
    ^                        # beginning of line
  )
  (
    (?:https?://)|           # protocol spec, or
    (?:www\.)                # www.*
  )
  (
    [-\w]+                   # subdomain or domain
    (?:\.[-\w]+)*            # remaining subdomains or domain
    (?::\d+)?                # port
    (?:/(?:[~\w\+@%=\(\)-]|(?:[,.;:'][^\s<$]))*)* # path
    (?:\?[\w\+@%&=.;:-]+)?   # query string
    (?:\#[\w\-]*)?           # trailing anchor
  )
  ([[:punct:]]|<|$|)         # trailing text
}x

Class Method Summary (collapse)

Instance Method Summary (collapse)

Class Method Details

Turns all urls into clickable links. If a block is given, each url is yielded and the result is used as the link text.



138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/ramaze/helper/formatting.rb', line 138

def auto_link(text, opts = {})
  html_options = ' ' + opts.map{|k,v| "#{k}='#{v}'"}.join(' ') if opts.any?
  text.gsub(AUTO_LINK_RE) do
    all, a, b, c, d = $&, $1, $2, $3, $4
    if a =~ /<a\s/i # don't replace URL's that are already linked
      all
    else
      text = b + c
      text = yield(text) if block_given?
      %(#{a}<a href="#{b=="www."?"http://www.":b}#{c}"#{html_options}>#{text}</a>#{d})
    end
  end
end

+ (Object) nl2br(string, xhtml = true)

takes a string and optional argument for outputting compliance HTML instead of XHTML.

Examples:

nl2br "a\nb\n\c" #=> 'a<br />b<br />c'


159
160
161
162
# File 'lib/ramaze/helper/formatting.rb', line 159

def nl2br(string, xhtml = true)
  br = xhtml ? '<br />' : '<br>'
  string.gsub(/\n/, br)
end

+ (Object) number_counter(count, item, items = nil)

Answers with a representation of given +count+ with correct grammar. If no +items+ argument is given, and the +count+ argument is not 1, then we first check whether the +item+ argument responds to #pluralize (for example if you are using Sequel). If this doesn't work we append 's' to the +item+ argument.

Examples:

usage

number_counter(0, 'comment') # => 'no comments'
number_counter(1, 'comment') # => 'one comment'
number_counter(2, 'comment') # => '2 comments'


33
34
35
36
37
38
39
40
41
42
43
# File 'lib/ramaze/helper/formatting.rb', line 33

def number_counter(count, item, items = nil)
  count, item = count.to_i, item.to_s

  if count == 1
    "one #{item}"
  else
    items ||= item.respond_to?(:pluralize) ? item.pluralize : "#{item}s"
    prefix = FORMATTING_NUMBER_COUNTER[count] || count
    "#{prefix} #{items}"
  end
end

+ (Object) number_format(n, delimiter = ',')

Format a floating number nicely for display.

Examples:

number_format(123.123)           # => '123.123'
number_format(123456.12345)      # => '123,456.12345'
number_format(123456.12345, '.') # => '123.456,12345'


52
53
54
55
56
# File 'lib/ramaze/helper/formatting.rb', line 52

def number_format(n, delimiter = ',')
  delim_l, delim_r = delimiter == ',' ? %w[, .] : %w[. ,]
  h, r = n.to_s.split('.')
  [h.reverse.scan(/\d{1,3}/).join(delim_l).reverse, r].compact.join(delim_r)
end

+ (Object) obfuscate_email(email, text = nil)



164
165
166
167
168
169
170
# File 'lib/ramaze/helper/formatting.rb', line 164

def obfuscate_email(email, text = nil)
  obfuscated = []
  email.to_s.each_byte{|c| obfuscated << "&#%03d" % c }
  joined = obfuscated.join

  %(<a href="mailto:#{joined}">#{text || joined}</a>)
end

+ (Object) ordinal(number)

Answer with the ordinal version of a number.

Examples:

ordinal(1)   # => "1st"
ordinal(2)   # => "2nd"
ordinal(3)   # => "3rd"
ordinal(13)  # => "13th"
ordinal(33)  # => "33rd"
ordinal(100) # => "100th"
ordinal(133) # => "133rd"


69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/ramaze/helper/formatting.rb', line 69

def ordinal(number)
  number = number.to_i

  case number % 100
  when 11..13; "#{number}th"
  else
    case number % 10
    when 1; "#{number}st"
    when 2; "#{number}nd"
    when 3; "#{number}rd"
    else    "#{number}th"
    end
  end
end

+ (Object) tagcloud(tags, min = 0.5, max = 1.5)

Returns Hash with tags as keys and their weight as value.

Example: tags = %w[ruby ruby code ramaze] tagcloud(tags) # => "ramaze"=>0.75, "ruby"=>1.0

The weight can be influenced by adjusting the +min+ and +max+ parameters, please make sure that +max+ is larger than +min+ to get meaningful output.

This is not thought as immediate output to your template but rather to help either implementing your own algorithm or using the result as input for your tagcloud.

Examples:

tagcloud(tags).each do |tag, weight|
  style = "font-size: %0.2fem" % weight
  %a{:style => style, :href => Rs(tag)}= h(tag)
end


193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/ramaze/helper/formatting.rb', line 193

def tagcloud(tags, min = 0.5, max = 1.5)
  result = {}
  total = tags.size.to_f
  diff = max - min

  tags.uniq.each do |tag|
    count = tags.respond_to?(:count) ? tags.count(tag) : tags.select{|t| t==tag }.size
    result[tag] = ((count / total) * diff) + min
  end

  result
end

+ (Object) time_diff(from_time, to_time = Time.now, include_seconds = false)

stolen and adapted from rails



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
# File 'lib/ramaze/helper/formatting.rb', line 85

def time_diff(from_time, to_time = Time.now, include_seconds = false)
  distance_in_minutes = (((to_time - from_time).abs)/60).round
  distance_in_seconds = ((to_time - from_time).abs).round if include_seconds

  case distance_in_minutes
    when 0..1
      return (distance_in_minutes == 0) ? 'less than a minute' : '1 minute' unless include_seconds
      case distance_in_seconds
        when 0..4   then 'less than 5 seconds'
        when 5..9   then 'less than 10 seconds'
        when 10..19 then 'less than 20 seconds'
        when 20..39 then 'half a minute'
        when 40..59 then 'less than a minute'
        else             '1 minute'
      end

    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..525959   then "#{(distance_in_minutes / 43200).round} months"
    when 525960..1051919 then 'about 1 year'
    else                      "over #{(distance_in_minutes / 525960).round} years"
  end
end

Instance Method Details

Turns all urls into clickable links. If a block is given, each url is yielded and the result is used as the link text.



138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/ramaze/helper/formatting.rb', line 138

def auto_link(text, opts = {})
  html_options = ' ' + opts.map{|k,v| "#{k}='#{v}'"}.join(' ') if opts.any?
  text.gsub(AUTO_LINK_RE) do
    all, a, b, c, d = $&, $1, $2, $3, $4
    if a =~ /<a\s/i # don't replace URL's that are already linked
      all
    else
      text = b + c
      text = yield(text) if block_given?
      %(#{a}<a href="#{b=="www."?"http://www.":b}#{c}"#{html_options}>#{text}</a>#{d})
    end
  end
end


151
# File 'lib/ramaze/helper/formatting.rb', line 151

alias autolink auto_link

- (Object) nl2br(string, xhtml = true) (private)

takes a string and optional argument for outputting compliance HTML instead of XHTML.

Examples:

nl2br "a\nb\n\c" #=> 'a<br />b<br />c'


159
160
161
162
# File 'lib/ramaze/helper/formatting.rb', line 159

def nl2br(string, xhtml = true)
  br = xhtml ? '<br />' : '<br>'
  string.gsub(/\n/, br)
end

- (Object) number_counter(count, item, items = nil) (private)

Answers with a representation of given +count+ with correct grammar. If no +items+ argument is given, and the +count+ argument is not 1, then we first check whether the +item+ argument responds to #pluralize (for example if you are using Sequel). If this doesn't work we append 's' to the +item+ argument.

Examples:

usage

number_counter(0, 'comment') # => 'no comments'
number_counter(1, 'comment') # => 'one comment'
number_counter(2, 'comment') # => '2 comments'


33
34
35
36
37
38
39
40
41
42
43
# File 'lib/ramaze/helper/formatting.rb', line 33

def number_counter(count, item, items = nil)
  count, item = count.to_i, item.to_s

  if count == 1
    "one #{item}"
  else
    items ||= item.respond_to?(:pluralize) ? item.pluralize : "#{item}s"
    prefix = FORMATTING_NUMBER_COUNTER[count] || count
    "#{prefix} #{items}"
  end
end

- (Object) number_format(n, delimiter = ',') (private)

Format a floating number nicely for display.

Examples:

number_format(123.123)           # => '123.123'
number_format(123456.12345)      # => '123,456.12345'
number_format(123456.12345, '.') # => '123.456,12345'


52
53
54
55
56
# File 'lib/ramaze/helper/formatting.rb', line 52

def number_format(n, delimiter = ',')
  delim_l, delim_r = delimiter == ',' ? %w[, .] : %w[. ,]
  h, r = n.to_s.split('.')
  [h.reverse.scan(/\d{1,3}/).join(delim_l).reverse, r].compact.join(delim_r)
end

- (Object) obfuscate_email(email, text = nil) (private)



164
165
166
167
168
169
170
# File 'lib/ramaze/helper/formatting.rb', line 164

def obfuscate_email(email, text = nil)
  obfuscated = []
  email.to_s.each_byte{|c| obfuscated << "&#%03d" % c }
  joined = obfuscated.join

  %(<a href="mailto:#{joined}">#{text || joined}</a>)
end

- (Object) ordinal(number) (private)

Answer with the ordinal version of a number.

Examples:

ordinal(1)   # => "1st"
ordinal(2)   # => "2nd"
ordinal(3)   # => "3rd"
ordinal(13)  # => "13th"
ordinal(33)  # => "33rd"
ordinal(100) # => "100th"
ordinal(133) # => "133rd"


69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/ramaze/helper/formatting.rb', line 69

def ordinal(number)
  number = number.to_i

  case number % 100
  when 11..13; "#{number}th"
  else
    case number % 10
    when 1; "#{number}st"
    when 2; "#{number}nd"
    when 3; "#{number}rd"
    else    "#{number}th"
    end
  end
end

- (Object) tagcloud(tags, min = 0.5, max = 1.5) (private)

Returns Hash with tags as keys and their weight as value.

Example: tags = %w[ruby ruby code ramaze] tagcloud(tags) # => "ramaze"=>0.75, "ruby"=>1.0

The weight can be influenced by adjusting the +min+ and +max+ parameters, please make sure that +max+ is larger than +min+ to get meaningful output.

This is not thought as immediate output to your template but rather to help either implementing your own algorithm or using the result as input for your tagcloud.

Examples:

tagcloud(tags).each do |tag, weight|
  style = "font-size: %0.2fem" % weight
  %a{:style => style, :href => Rs(tag)}= h(tag)
end


193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/ramaze/helper/formatting.rb', line 193

def tagcloud(tags, min = 0.5, max = 1.5)
  result = {}
  total = tags.size.to_f
  diff = max - min

  tags.uniq.each do |tag|
    count = tags.respond_to?(:count) ? tags.count(tag) : tags.select{|t| t==tag }.size
    result[tag] = ((count / total) * diff) + min
  end

  result
end

- (Object) time_diff(from_time, to_time = Time.now, include_seconds = false) (private)

stolen and adapted from rails



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
# File 'lib/ramaze/helper/formatting.rb', line 85

def time_diff(from_time, to_time = Time.now, include_seconds = false)
  distance_in_minutes = (((to_time - from_time).abs)/60).round
  distance_in_seconds = ((to_time - from_time).abs).round if include_seconds

  case distance_in_minutes
    when 0..1
      return (distance_in_minutes == 0) ? 'less than a minute' : '1 minute' unless include_seconds
      case distance_in_seconds
        when 0..4   then 'less than 5 seconds'
        when 5..9   then 'less than 10 seconds'
        when 10..19 then 'less than 20 seconds'
        when 20..39 then 'half a minute'
        when 40..59 then 'less than a minute'
        else             '1 minute'
      end

    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..525959   then "#{(distance_in_minutes / 43200).round} months"
    when 525960..1051919 then 'about 1 year'
    else                      "over #{(distance_in_minutes / 525960).round} years"
  end
end