Module: Titleize

Extended by:
Titleize
Included in:
Titleize
Defined in:
lib/titleize.rb,
lib/titleize/version.rb

Overview

Adds String#titleize for creating properly capitalized titles. It can be called as Titleize.titleize or “a string”.titleize.

titlecase is included as an alias for titleize.

If loaded in a Rails environment, it modifies Inflector.titleize.

Constant Summary collapse

SMALL_WORDS =
%w{a an and as at but by en for if in of on or the to v v. via vs vs.}
VERSION =
"1.4.1"

Instance Method Summary collapse

Instance Method Details

#phrases(title) ⇒ Object

Splits a title into an array based on punctuation.

"simple title"              # => ["simple title"]
"more complicated: titling" # => ["more complicated:", "titling"]


60
61
62
63
64
65
66
67
# File 'lib/titleize.rb', line 60

def phrases(title)
  phrases = [[]]
  title.split.each do |word|
    phrases.last << word
    phrases << [] if ends_with_punctuation?(word) && !small_word?(word)
  end
  phrases.reject(&:empty?).map { |phrase| phrase.join " " }
end

#titleize(title) ⇒ Object

Capitalizes most words to create a nicer looking title string.

The list of “small words” which are not capped comes from the New York Times Manual of Style, plus ‘vs’ and ‘v’.

"notes on a scandal" # => "Notes on a Scandal"
"the good german"    # => "The Good German"


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
# File 'lib/titleize.rb', line 20

def titleize(title)
  title = title.dup
  title.downcase! unless title[/[[:lower:]]/]  # assume all-caps need fixing

  phrases(title).map do |phrase|
    words = phrase.split
    words.map.with_index do |word, index|
      def word.capitalize
        # like String#capitalize, but it starts with the first letter
        self.sub(/[[:alpha:]].*/) {|subword| subword.capitalize}
      end

      case word
      when /[[:alpha:]]\.[[:alpha:]]/  # words with dots in, like "example.com"
        word
      when /[-‑]/  # hyphenated word (regular and non-breaking)
        word.split(/([-‑])/).map do |part|
          SMALL_WORDS.include?(part) ? part : part.capitalize
        end.join
      when /^[[:alpha:]].*[[:upper:]]/ # non-first letter capitalized already
        word
      when /^[[:digit:]]/  # first character is a number
        word
      when *(SMALL_WORDS + SMALL_WORDS.map {|small| small.capitalize })
        if index == 0 || index == words.size - 1
          word.capitalize
        else
          word.downcase
        end
      else
        word.capitalize
      end
    end.join(" ")
  end.join(" ")
end