capitalize-names 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a8e58cd8d2216549bc0bd47a2f3ce851abbcf8eed7e404a84ec43593b81fe959
4
- data.tar.gz: 77f0ce726f15d3ca5e793be5485c282b71fac70a9b7bd01df4d0c648fcb4e66b
3
+ metadata.gz: d5c58d13e6411f8264d9b0ea09069999d61bdd1fa5fb3abc0fa08eb2c2bf42aa
4
+ data.tar.gz: cead79413582058ea0c34f3f67efdcf323d4cfd62f78b9e61000f7b9b719ab09
5
5
  SHA512:
6
- metadata.gz: e6dd722c7e906cef3d58c203da2a52d2274ddc115dd902169b02f6f80c34f3ff81c2484a3f86ca11a6cf41f0ffabad3a3dbe48911daa2b899dc539cf0e0c4738
7
- data.tar.gz: f438bda12d9d4eac554b297f9e4044f4c7663197e32ed355fcb2701a1d1048252088057f82b19c2c8b3838bfe64468e18857251e7f62d872065333dd615cbf7f
6
+ metadata.gz: 480a2b269eb27e44d8999e2e9753e7edf0f35a9e3dd1416d7c21269b4a8813622486c084d038f24db5438e0d7e666fc2bfc61a5b754b20955ae9051f92eb5f74
7
+ data.tar.gz: b0bcf24008f2b9d107284964582b20b17d7c52d7861ff563ee5c38f1fe548c3e999bb4a2c46c11779b5ee3998f1862c514fddb646ce5d4de0452b54c94b735f1
@@ -1,100 +1,171 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CapitalizeNames
2
4
  class Capitalizer
3
- attr_accessor :name
4
-
5
- HYPHEN = /(\s*-\s*)/
6
-
7
- MC = /^Mc(\w)(?=\w)/i
8
- MAC = /^Mac(\w)(?=\w)/i
9
- O_APOSTROPHE = /^O'(\w)(?=\w)/i
10
-
11
- def initialize(name)
5
+ attr_reader :name, :options
6
+
7
+ NAME = %r{
8
+ ( # start capture
9
+ (?: # start first name token
10
+ (?:(?:van\ )|(?:de\ (?:la\ )?)|(?:dit\ ))? # optionally match one of van, de, de la, dit and space
11
+ (?:[[:alnum:]]|'|\(|\))+ # match any unicode character, number, apostrophe or bracket
12
+ ) # end first name token
13
+ (?: # start optional additional name tokens
14
+ - # additional name tokens start with -
15
+ (?: # start additional name token
16
+ (?:(?:van\ )|(?:de\ (?:la\ )?)|(?:dit\ ))? # optionally match one of van, de, de la, dit and space
17
+ (?:[[:alnum:]]|'|\(|\))+ # match any unicode character, number, apostrophe or bracket
18
+ ) # end additional name token
19
+ )* # end optional additional name tokens
20
+ ) # end capture
21
+ }ix
22
+
23
+ MC = /(?<=\A|-)Mc(\w)(?=\w)/i
24
+ MAC = /(?<=\A|-)Mac(\w)(?=\w)/i
25
+ O_APOSTROPHE = /(?<=\A|-)O'(\w)(?=\w)/i
26
+ VAN_SPACE = /(?<=\A|-)Van /i
27
+ DE_LA_SPACE = /(?<=\A|-)De La /i
28
+ DE_SPACE = /(?<=\A|-)De /i
29
+ DIT_SPACE = /(?<=\A|-)Dit /i
30
+
31
+ VALID_FORMATS = [:fullname, :firstname, :givenname, :lastname, :surname]
32
+
33
+ DEFAULT_OPTIONS = {
34
+ format: :fullname,
35
+ skip_mc: false,
36
+ skip_mac: false,
37
+ skip_o_apostrophe: false,
38
+ skip_van_space: false,
39
+ skip_de_space: false,
40
+ skip_de_la_space: false,
41
+ skip_dit_space: false,
42
+ }
43
+
44
+ SUFFIX_MAP = CapitalizeNames::SUFFIXES.each_with_object({}) { |suffix, map| map[suffix.downcase] = suffix }
45
+ SURNAME_MAP = CapitalizeNames::SURNAMES.each_with_object({}) { |surname, map| map[surname.downcase] = surname }
46
+
47
+ def initialize(name, options = {})
12
48
  @name = name
49
+ @options = DEFAULT_OPTIONS.merge(options)
13
50
  end
14
51
 
15
52
  def capitalize!
16
53
  can_process?
17
- _capitalize
54
+ capitalize_name
18
55
  end
19
56
 
20
57
  def capitalize
21
- begin
22
- capitalize!
23
- rescue CapitalizeNames::Errors::GenericError
24
- name
25
- end
58
+ capitalize!
59
+ rescue CapitalizeNames::Errors::GenericError
60
+ name
26
61
  end
27
62
 
28
63
  private
29
- def can_process?
30
- raise CapitalizeNames::Errors::InvalidName, "Cannot capitalize nil" unless name
31
- true
64
+
65
+ def can_process?
66
+ raise CapitalizeNames::Errors::InvalidName, "Cannot capitalize nil" unless name
67
+
68
+ true
69
+ end
70
+
71
+ def name_format
72
+ @name_format ||= validate_name_format
73
+ end
74
+
75
+ def validate_name_format
76
+ unless VALID_FORMATS.include?(options[:format])
77
+ raise CapitalizeNames::Errors::InvalidOption,
78
+ "Invalid format: #{@options[:format]}, must be one of #{VALID_FORMATS.join(", ")}"
32
79
  end
33
80
 
34
- def surname_suffix_position?(position, name, surname_or_suffix)
35
- # surname/suffix must be:
36
- # 1. at start of name or after a space or a -
37
- # -and-
38
- # 2. followed by the end of string or a space or a -
39
- (
40
- (position == 0) || \
41
- (
42
- position > 0 && (name[position-1] == ' ' || name[position-1] == '-')
43
- )
44
- ) && (
45
- (name.length == position+surname_or_suffix.length) || \
46
- (name[position+surname_or_suffix.length] == ' ') || (name[position+surname_or_suffix.length] == '-')
47
- )
81
+ options[:format]
82
+ end
83
+
84
+ def tokenize_name
85
+ name.split(NAME).map do |token|
86
+ {
87
+ value: token,
88
+ is_name: token.match?(NAME),
89
+ }
48
90
  end
91
+ end
49
92
 
50
- def _capitalize
51
- _name = name
93
+ def suffix?(str)
94
+ SUFFIX_MAP.key?(str.downcase)
95
+ end
52
96
 
53
- hyphens = []
97
+ def surname?(str)
98
+ SURNAME_MAP.key?(str.downcase)
99
+ end
54
100
 
55
- while (match = _name.match(HYPHEN)) do
56
- _start = match.begin(1)
57
- _end = match.end(1)
58
- _value = match[1]
101
+ def capitalize_str(str, surname_rules)
102
+ str.split(/(\s|-)/).map do |word|
103
+ next word if word.match?(/(\s|-)/)
59
104
 
60
- if _start == 0
61
- _name = _name[_end..-1]
62
- else
63
- _name = _name[0..._start] << ' ' << _name[_end..-1]
64
- end
105
+ output = word.capitalize
106
+ next output unless surname_rules
107
+ next capitalize_surname(output) if surname?(output)
65
108
 
66
- hyphens << [_start, _end, _value]
67
- end
109
+ output = output.gsub(MC) { "Mc#{Regexp.last_match(1).upcase}" } unless options[:skip_mc]
110
+ output = output.gsub(MAC) { "Mac#{Regexp.last_match(1).upcase}" } unless options[:skip_mac]
111
+ output = output.gsub(O_APOSTROPHE) { "O'#{Regexp.last_match(1).upcase}" } unless options[:skip_o_apostrophe]
68
112
 
69
- _name = _name.split.map{ |w|
70
- w.mb_chars.capitalize.to_str
71
- }.map{ |w|
72
- w.gsub(MC) { "Mc#{$1.upcase}" }\
73
- .gsub(MAC) { "Mac#{$1.upcase}" }\
74
- .gsub(O_APOSTROPHE) { "O'#{$1.upcase}" }
75
- }
113
+ output
114
+ end.join("")
115
+ end
116
+
117
+ def capitalize_givenname(str)
118
+ capitalize_str(str, false)
119
+ end
76
120
 
77
- _name = _name.join(" ")
121
+ def capitalize_suffix(str)
122
+ SUFFIX_MAP[str.downcase]
123
+ end
124
+
125
+ def capitalize_surname(str)
126
+ SURNAME_MAP[str.downcase]
127
+ end
128
+
129
+ def capitalize_lastname(str)
130
+ return capitalize_suffix(str) if suffix?(str)
131
+
132
+ output = capitalize_str(str, true)
133
+
134
+ output = output.gsub(VAN_SPACE, "van ") unless options[:skip_van_space]
135
+ output = output.gsub(DIT_SPACE, "dit ") unless options[:skip_dit_space]
136
+
137
+ if output.match?(DE_LA_SPACE)
138
+ output = output.gsub(DE_LA_SPACE, "de la ") unless options[:skip_de_la_space]
139
+ else
140
+ output = output.gsub(DE_SPACE, "de ") unless options[:skip_de_space]
141
+ end
78
142
 
79
- hyphens.reverse.each do |_start, _end, _value|
80
- if _start == 0
81
- _name = _value << _name
143
+ output
144
+ end
145
+
146
+ def capitalize_name
147
+ tokens = tokenize_name
148
+
149
+ has_capitalized_last_name = false
150
+
151
+ tokens.reverse.map do |token|
152
+ token_value = token[:value]
153
+ next token_value unless token[:is_name]
154
+
155
+ case name_format
156
+ when :firstname, :givenname
157
+ capitalize_givenname(token_value)
158
+ when :lastname, :surname
159
+ capitalize_lastname(token_value)
160
+ else
161
+ if has_capitalized_last_name
162
+ capitalize_givenname(token_value)
82
163
  else
83
- _name = _name[0..._start] << _value << (_name[_start+1..-1] || "")
164
+ has_capitalized_last_name = !suffix?(token_value)
165
+ capitalize_lastname(token_value)
84
166
  end
85
167
  end
86
-
87
- _name = _name.gsub("Van ", "van ").gsub("De ", "de ").gsub("Dit ", "dit ")
88
- _name << " "
89
-
90
- (CapitalizeNames::SURNAMES + CapitalizeNames::SUFFIXES).each do |surname_or_suffix|
91
- position = _name.downcase.index(surname_or_suffix.downcase)
92
- if position and surname_suffix_position?(position, _name, surname_or_suffix)
93
- _name = _name[0...position] << surname_or_suffix << _name[position+surname_or_suffix.length..-1]
94
- end
95
- end
96
-
97
- _name[0...-1]
98
- end
168
+ end.reverse.join("")
169
+ end
99
170
  end
100
- end
171
+ end
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CapitalizeNames
2
4
  module Errors
3
- class GenericError < Exception; end
5
+ class GenericError < StandardError; end
4
6
  class InvalidName < GenericError; end
7
+ class InvalidOption < GenericError; end
5
8
  end
6
9
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CapitalizeNames
2
4
  SUFFIXES = [
3
5
  "II",
@@ -17,6 +19,6 @@ module CapitalizeNames
17
19
  "4th",
18
20
  "(4th)",
19
21
  "5th",
20
- "(5th)"
22
+ "(5th)",
21
23
  ]
22
- end
24
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CapitalizeNames
2
4
  SURNAMES = [
3
5
  "ApShaw",
@@ -330,6 +332,7 @@ module CapitalizeNames
330
332
  "Mackartee",
331
333
  "Mackay",
332
334
  "Macken",
335
+ "Mackenzie",
333
336
  "Mackert",
334
337
  "Mackey",
335
338
  "Mackie",
@@ -584,6 +587,6 @@ module CapitalizeNames
584
587
  "VonSeldern",
585
588
  "VonSpringer",
586
589
  "VonVeyelmann",
587
- "VonZweidorff"
590
+ "VonZweidorff",
588
591
  ]
589
- end
592
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CapitalizeNames
2
- VERSION = "1.1.0"
4
+ VERSION = "1.2.0"
3
5
  end
@@ -1,20 +1,19 @@
1
- #based on http://dzone.com/snippets/capitalize-proper-names
2
- require 'capitalize_names/errors'
3
- require 'capitalize_names/capitalizer'
4
- require 'capitalize_names/suffixes'
5
- require 'capitalize_names/surnames'
6
- require 'active_support/core_ext/string/multibyte'
1
+ # frozen_string_literal: true
7
2
 
8
- module CapitalizeNames
3
+ # originally based on http://dzone.com/snippets/capitalize-proper-names
4
+ require "capitalize_names/errors"
5
+ require "capitalize_names/suffixes"
6
+ require "capitalize_names/surnames"
7
+ require "capitalize_names/capitalizer"
9
8
 
9
+ module CapitalizeNames
10
10
  class << self
11
-
12
- def capitalize!(name)
13
- Capitalizer.new(name).capitalize!
11
+ def capitalize!(name, options = {})
12
+ Capitalizer.new(name, options).capitalize!
14
13
  end
15
14
 
16
- def capitalize(name)
17
- Capitalizer.new(name).capitalize
15
+ def capitalize(name, options = {})
16
+ Capitalizer.new(name, options).capitalize
18
17
  end
19
18
  end
20
- end
19
+ end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capitalize-names
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kyle Tate
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-20 00:00:00.000000000 Z
11
+ date: 2022-07-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: activesupport
14
+ name: minitest
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '3'
20
- type: :runtime
19
+ version: '0'
20
+ type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '3'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -39,7 +39,21 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: minitest
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop-shopify
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - ">="
@@ -68,24 +82,23 @@ homepage: http://github.com/infiton/capitalize-names
68
82
  licenses:
69
83
  - MIT
70
84
  metadata: {}
71
- post_install_message:
85
+ post_install_message:
72
86
  rdoc_options: []
73
87
  require_paths:
74
88
  - lib
75
89
  required_ruby_version: !ruby/object:Gem::Requirement
76
90
  requirements:
77
- - - ">"
91
+ - - ">="
78
92
  - !ruby/object:Gem::Version
79
- version: '2.0'
93
+ version: '2.4'
80
94
  required_rubygems_version: !ruby/object:Gem::Requirement
81
95
  requirements:
82
96
  - - ">="
83
97
  - !ruby/object:Gem::Version
84
98
  version: '0'
85
99
  requirements: []
86
- rubyforge_project:
87
- rubygems_version: 2.7.6
88
- signing_key:
100
+ rubygems_version: 3.3.7
101
+ signing_key:
89
102
  specification_version: 4
90
103
  summary: Capitalizes names; handles edge cases.
91
104
  test_files: []