capitalize-names 1.1.0 → 1.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.
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: []