titlify 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +8 -0
- data/.yaropts +1 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +35 -0
- data/Guardfile +5 -0
- data/README.markdown +48 -0
- data/lib/titlify.rb +27 -0
- data/lib/titlify/data/smart_format_rules.rb +45 -0
- data/lib/titlify/string_extensions.rb +19 -0
- data/lib/titlify/titlecase.rb +134 -0
- data/lib/titlify/version.rb +5 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/titlify_spec.rb +36 -0
- data/titlify.gemspec +24 -0
- metadata +62 -0
data/.gitignore
ADDED
data/.yaropts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--no-private lib/**/*.rb - README.markdown
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
titlify (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.1.3)
|
10
|
+
ffi (1.0.11)
|
11
|
+
guard (1.0.0)
|
12
|
+
ffi (>= 0.5.0)
|
13
|
+
thor (~> 0.14.6)
|
14
|
+
guard-rspec (0.6.0)
|
15
|
+
guard (>= 0.10.0)
|
16
|
+
rake (0.8.7)
|
17
|
+
rspec (2.8.0)
|
18
|
+
rspec-core (~> 2.8.0)
|
19
|
+
rspec-expectations (~> 2.8.0)
|
20
|
+
rspec-mocks (~> 2.8.0)
|
21
|
+
rspec-core (2.8.0)
|
22
|
+
rspec-expectations (2.8.0)
|
23
|
+
diff-lcs (~> 1.1.2)
|
24
|
+
rspec-mocks (2.8.0)
|
25
|
+
thor (0.14.6)
|
26
|
+
|
27
|
+
PLATFORMS
|
28
|
+
ruby
|
29
|
+
|
30
|
+
DEPENDENCIES
|
31
|
+
guard
|
32
|
+
guard-rspec
|
33
|
+
rake
|
34
|
+
rspec
|
35
|
+
titlify!
|
data/Guardfile
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
Titlify
|
2
|
+
=======
|
3
|
+
|
4
|
+
The best damn titlecase function. (Or at least on its way.)
|
5
|
+
|
6
|
+
Credits
|
7
|
+
-------
|
8
|
+
The most thorough titlecasing function I found was Patrick Hogan's in his [sterile gem](https://github.com/pbhogan/sterile). I started with his titlecasing function and expanded to include some more logic to bring it closer to the AP guidelines and handle more fringe cases.
|
9
|
+
|
10
|
+
Usage
|
11
|
+
-----
|
12
|
+
|
13
|
+
Titlify provides functionality both as class methods on the Titlify module and as extensions to the String class.
|
14
|
+
|
15
|
+
Titlify.titlify("make title") # => "Make Title"
|
16
|
+
|
17
|
+
"make title".titlify # => "Make Title"
|
18
|
+
|
19
|
+
title = "make title"
|
20
|
+
title.titlify!
|
21
|
+
title # => "Make Title"
|
22
|
+
|
23
|
+
|
24
|
+
Titlecase
|
25
|
+
---------
|
26
|
+
|
27
|
+
Format text appropriately for titles. This method is much smarter than ActiveSupport's titlecase. The algorithm is based on work done by John Gruber et al (http://daringfireball.net/2008/08/title_case_update). It gets closer to the AP standard for title capitalization, including proper support for small words and handles a variety of edge cases.
|
28
|
+
|
29
|
+
"Q&A with Steve Jobs: 'That's what happens in technology'".titlify
|
30
|
+
# => "Q&A With Steve Jobs: 'That's What Happens in Technology'"
|
31
|
+
|
32
|
+
"Small word at end is nothing to be afraid of".titlify
|
33
|
+
# => "Small Word at End Is Nothing to Be Afraid Of"
|
34
|
+
|
35
|
+
|
36
|
+
Installation
|
37
|
+
------------
|
38
|
+
__Not Yet Published__
|
39
|
+
|
40
|
+
Install with RubyGems:
|
41
|
+
|
42
|
+
gem install titlify
|
43
|
+
|
44
|
+
License
|
45
|
+
-------
|
46
|
+
|
47
|
+
Copyright (c) 2012 Josh Hepworth, released under the MIT License.
|
48
|
+
http://www.opensource.org/licenses/mit-license
|
data/lib/titlify.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Copyright (c) 2011 Patrick Hogan
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
|
25
|
+
require "titlify/titlecase"
|
26
|
+
|
27
|
+
require "titlify/string_extensions"
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Titlify
|
4
|
+
# @private
|
5
|
+
class Data
|
6
|
+
def self.smart_format_rules
|
7
|
+
[
|
8
|
+
["'tain't", "’tain’t"],
|
9
|
+
["'twere", "’twere"],
|
10
|
+
["'twas", "’twas"],
|
11
|
+
["'tis", "’tis"],
|
12
|
+
["'twill", "’twill"],
|
13
|
+
["'til", "’til"],
|
14
|
+
["'bout", "’bout"],
|
15
|
+
["'nuff", "’nuff"],
|
16
|
+
["'round", "’round"],
|
17
|
+
["'cause", "’cause"],
|
18
|
+
["'cos", "’cos"],
|
19
|
+
["i'm", "i’m"],
|
20
|
+
['--"', "—”"],
|
21
|
+
["--'", "—’"],
|
22
|
+
["--", "—"],
|
23
|
+
["...", "…"],
|
24
|
+
["(tm)", "™"],
|
25
|
+
["(TM)", "™"],
|
26
|
+
["(c)", "©"],
|
27
|
+
["(r)", "®"],
|
28
|
+
["(R)", "®"],
|
29
|
+
[/s\'([^a-zA-Z0-9])/, "s’\\1"],
|
30
|
+
[/"([:;])/, "”\\1"],
|
31
|
+
[/\'s$/, "’s"],
|
32
|
+
[/\'(\d\d(?:’|\')?s)/, "’\\1"],
|
33
|
+
[/(\s|\A|"|\(|\[)\'/, "\\1‘"],
|
34
|
+
[/(\d+)"/, "\\1′"],
|
35
|
+
[/(\d+)\'/, "\\1″"],
|
36
|
+
[/(\S)\'([^\'\s])/, "\\1’\\2"],
|
37
|
+
[/(\s|\A|\(|\[)"(?!\s)/, "\\1“\\2"],
|
38
|
+
[/"(\s|\S|\Z)/, "”\\1"],
|
39
|
+
[/\'([\s.]|\Z)/, "’\\1"],
|
40
|
+
[/(\d+)x(\d+)/, "\\1×\\2"],
|
41
|
+
[/([a-z])'(t|d|s|ll|re|ve)(\b)/i, "\\1’\\2\\3"]
|
42
|
+
]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Titlify
|
4
|
+
|
5
|
+
module StringExtensions
|
6
|
+
def self.included(base)
|
7
|
+
Titlify.methods(false).each do |method|
|
8
|
+
eval("def #{method}(*args, &block); Titlify.#{method}(self, *args, &block); end")
|
9
|
+
eval("def #{method}!(*args, &block); replace Titlify.#{method}(self, *args, &block); end")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
class String
|
18
|
+
include Titlify::StringExtensions
|
19
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Titlify
|
4
|
+
|
5
|
+
class << self
|
6
|
+
|
7
|
+
# Format text appropriately for titles. This method is much smarter
|
8
|
+
# than ActiveSupport's +titlecase+. The algorithm is based on work done
|
9
|
+
# by John Gruber et al (http://daringfireball.net/2008/08/title_case_update)
|
10
|
+
def titlify(string)
|
11
|
+
|
12
|
+
lsquo = [8216].pack("U")
|
13
|
+
rsquo = [8217].pack("U")
|
14
|
+
ldquo = [8220].pack("U")
|
15
|
+
rdquo = [8221].pack("U")
|
16
|
+
ndash = [8211].pack("U")
|
17
|
+
|
18
|
+
string.strip!
|
19
|
+
string.gsub!(/\s+/, " ")
|
20
|
+
string.downcase! unless string =~ /[[:lower:]]/
|
21
|
+
|
22
|
+
small_words = %w{ a an and as at(?!&t) but by en for if in nor of on or the to v[.]? via vs[.]? }.join("|")
|
23
|
+
apos = / (?: ['#{rsquo}] [[:lower:]]* )? /xu
|
24
|
+
|
25
|
+
string.gsub!(
|
26
|
+
/
|
27
|
+
\b
|
28
|
+
([_\*]*)
|
29
|
+
(?:
|
30
|
+
([A-Z][\.]) # Acronyms with periods in them
|
31
|
+
){2,100}
|
32
|
+
([_\*]*)
|
33
|
+
\b?
|
34
|
+
/xi
|
35
|
+
) do |m|
|
36
|
+
m.gsub(/\./, "").upcase
|
37
|
+
end
|
38
|
+
|
39
|
+
string.gsub!(
|
40
|
+
/
|
41
|
+
\b
|
42
|
+
([_\*]*)
|
43
|
+
(?:
|
44
|
+
( [-\+\w]+ [@.\:\/] [-\w@.\:\/]+ #{apos} ) # URL, domain, or email
|
45
|
+
|
|
46
|
+
( (?i: #{small_words} ) #{apos} ) # or small word, case-insensitive
|
47
|
+
|
|
48
|
+
( [[:alpha:]] [[:lower:]'#{rsquo}()\[\]{}]* #{apos} ) # or word without internal caps
|
49
|
+
|
|
50
|
+
( [[:alpha:]] [[:alpha:]'#{rsquo}()\[\]{}]* #{apos} ) # or some other word
|
51
|
+
)
|
52
|
+
([_\*]*)
|
53
|
+
\b
|
54
|
+
/xu
|
55
|
+
) do
|
56
|
+
($1 ? $1 : "") +
|
57
|
+
($2 ? $2 : ($3 ? $3.downcase : ($4 ? $4.downcase.capitalize : $5))) +
|
58
|
+
($6 ? $6 : "")
|
59
|
+
end
|
60
|
+
|
61
|
+
if RUBY_VERSION < "1.9.0"
|
62
|
+
string.gsub!(
|
63
|
+
/
|
64
|
+
\b
|
65
|
+
([:alpha:]+)
|
66
|
+
(#{ndash})
|
67
|
+
([:alpha:]+)
|
68
|
+
\b
|
69
|
+
/xu
|
70
|
+
) do
|
71
|
+
$1.downcase.capitalize + $2 + $1.downcase.capitalize
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
string.gsub!(
|
76
|
+
/
|
77
|
+
(
|
78
|
+
\A [[:punct:]]* # start of title
|
79
|
+
| [:.;?!][ ]+ # or of subsentence
|
80
|
+
| [ ]['"#{ldquo}#{lsquo}(\[][ ]* # or of inserted subphrase
|
81
|
+
)
|
82
|
+
( #{small_words} ) # followed by a small-word
|
83
|
+
\b
|
84
|
+
/xiu
|
85
|
+
) do
|
86
|
+
$1 + $2.downcase.capitalize
|
87
|
+
end
|
88
|
+
|
89
|
+
string.gsub!(
|
90
|
+
/
|
91
|
+
\b
|
92
|
+
( #{small_words} ) # small-word
|
93
|
+
(?=
|
94
|
+
[[:punct:]]* \Z # at the end of the title
|
95
|
+
|
|
96
|
+
['"#{rsquo}#{rdquo})\]] [ ] # or of an inserted subphrase
|
97
|
+
)
|
98
|
+
/xu
|
99
|
+
) do
|
100
|
+
$1.downcase.capitalize
|
101
|
+
end
|
102
|
+
|
103
|
+
string.gsub!(
|
104
|
+
/
|
105
|
+
(
|
106
|
+
\b
|
107
|
+
[[:alpha:]] # single first letter
|
108
|
+
[\-#{ndash}] # followed by a dash
|
109
|
+
)
|
110
|
+
( [[:alpha:]] ) # followed by a letter
|
111
|
+
/xu
|
112
|
+
) do
|
113
|
+
$1 + $2.downcase
|
114
|
+
end
|
115
|
+
|
116
|
+
string.gsub!(/q&a/i, 'Q&A')
|
117
|
+
|
118
|
+
string
|
119
|
+
end
|
120
|
+
alias_method :titlecase, :titlify
|
121
|
+
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
# Lazy load smart formatting rules
|
126
|
+
def smart_format_rules
|
127
|
+
@smart_format_rules ||= begin
|
128
|
+
require "titlify/data/smart_format_rules"
|
129
|
+
Data.smart_format_rules
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Titlify do
|
4
|
+
it "titlecases a string object" do
|
5
|
+
title = "this is the title of the post".titlify
|
6
|
+
title.should eq("This Is the Title of the Post")
|
7
|
+
end
|
8
|
+
|
9
|
+
it "titlecases a string object in place" do
|
10
|
+
title = "this is the title of the post"
|
11
|
+
title.titlify!
|
12
|
+
title.should eq("This Is the Title of the Post")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "properly titlecases a mixed-case word" do
|
16
|
+
title = "the iPhone is the bestest phone".titlify
|
17
|
+
title.should eq("The iPhone Is the Bestest Phone")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "properly titlecases a word with abbreviations with and without periods" do
|
21
|
+
title = "there's a big AT&T monster in DOD for the DOJ".titlify
|
22
|
+
title.should eq("There's a Big AT&T Monster in DOD for the DOJ")
|
23
|
+
title = "there's a big AT&T monster in d.o.d. for the n.a.s.a.".titlify
|
24
|
+
title.should eq("There's a Big AT&T Monster in DOD for the NASA")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "capitalizes the first letter after a hyphen" do
|
28
|
+
title = "that shit-faced guy fell over the curb".titlify
|
29
|
+
title.should eq("That Shit-Faced Guy Fell Over the Curb")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "capitalizes the first word following a colon" do
|
33
|
+
title = "the big guns: a little man's tale".titlify
|
34
|
+
title.should eq("The Big Guns: A Little Man's Tale")
|
35
|
+
end
|
36
|
+
end
|
data/titlify.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
$:.push File.expand_path("../lib", __FILE__)
|
4
|
+
require "titlify/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "titlify"
|
8
|
+
s.version = Titlify::VERSION
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.authors = ["Josh Hepworth"]
|
11
|
+
s.email = ["josh@friendsoftheweb.com"]
|
12
|
+
s.homepage = "http://github.com/fotw/titlify"
|
13
|
+
s.summary = %q{Gonna be the best damn titlecasing function around.}
|
14
|
+
s.description = s.summary
|
15
|
+
|
16
|
+
s.rubyforge_project = "titlify"
|
17
|
+
|
18
|
+
# s.add_dependency("nokogiri")
|
19
|
+
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
23
|
+
s.require_paths = ["lib"]
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: titlify
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Josh Hepworth
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-02-14 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Gonna be the best damn titlecasing function around.
|
15
|
+
email:
|
16
|
+
- josh@friendsoftheweb.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- .gitignore
|
22
|
+
- .yaropts
|
23
|
+
- Gemfile
|
24
|
+
- Gemfile.lock
|
25
|
+
- Guardfile
|
26
|
+
- README.markdown
|
27
|
+
- lib/titlify.rb
|
28
|
+
- lib/titlify/data/smart_format_rules.rb
|
29
|
+
- lib/titlify/string_extensions.rb
|
30
|
+
- lib/titlify/titlecase.rb
|
31
|
+
- lib/titlify/version.rb
|
32
|
+
- spec/spec_helper.rb
|
33
|
+
- spec/titlify_spec.rb
|
34
|
+
- titlify.gemspec
|
35
|
+
homepage: http://github.com/fotw/titlify
|
36
|
+
licenses: []
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
requirements: []
|
54
|
+
rubyforge_project: titlify
|
55
|
+
rubygems_version: 1.8.11
|
56
|
+
signing_key:
|
57
|
+
specification_version: 3
|
58
|
+
summary: Gonna be the best damn titlecasing function around.
|
59
|
+
test_files:
|
60
|
+
- spec/spec_helper.rb
|
61
|
+
- spec/titlify_spec.rb
|
62
|
+
has_rdoc:
|