Gruber-style Title Case in Ruby

Posted by Ben Jackson Wed, 21 May 2008 16:11:00 GMT

As requested by hivelogic:

module TitleCase
  SMALL_WORDS = %w(a an and as at but by en for if in of on or the to v[.]? via vs[.]?)

  def self.convert input
    # downcase everything first, then capitalize 
    input.gsub!(/\b(\w)/) { $1.capitalize }
    input.gsub!(/(\b)(#{SMALL_WORDS.join("|")})(\b)/i) { "#{$1}#{$2.downcase}#{$3}" }

    # If the first/last word in the title is a small word, then capitalize it:
    input.sub!(/^(#{SMALL_WORDS.join("|")})\b/i) { $1.capitalize }
    input.sub!(/\b(#{SMALL_WORDS.join("|")})$/i) { $1.capitalize }

    # "v." and "vs.":
    input.gsub!(/ V(s?). /i){ "v#{$1}." }

    # 'S (otherwise you get "the SEC'S decision")
    input.gsub!(/(['’])S\b/i){"#{$1}s"}

    # "AT&T" and "Q&A", which get tripped up by 
    # self-contained small words "at" and "a"
    input.gsub!(/\b(AT&T|Q&A)\b/i){ $1.upcase }    

    input
  end
end

# some brief tests
puts TitleCase.convert("The book is On the table")
puts TitleCase.convert("the book is on the table")

# and the edge cases
puts TitleCase.convert("at&t u-verse marks one-year anniversary of giving los angeles")
puts TitleCase.convert("the SEC'S decision")

Let me know of any bugs in the comments. Enjoy.

Posted in ,  | Tags , ,  | no comments | no trackbacks