capitalize-names 1.0.5 → 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
- SHA1:
3
- metadata.gz: 952173c8584a6003c41afbb6fed489192388cd33
4
- data.tar.gz: 0d041067c287a94e95b37793a937049cf1968dcd
2
+ SHA256:
3
+ metadata.gz: d5c58d13e6411f8264d9b0ea09069999d61bdd1fa5fb3abc0fa08eb2c2bf42aa
4
+ data.tar.gz: cead79413582058ea0c34f3f67efdcf323d4cfd62f78b9e61000f7b9b719ab09
5
5
  SHA512:
6
- metadata.gz: 13356663ebb5fc5153cecb45dfe0222061bcefe27a21ec4c93c9e5abad001dac72f235215c2ec1927690a4e0904952675096661df6e0b49a96793b03e6238f4e
7
- data.tar.gz: 9733023e31a9859ba77b4c4f04e9ff872be83d7cb2c13b4801ecf29c6f705529e7dc4620e10a0a2206075c29b2283794f69ce4a280b8aa78bcf2dbd39d6a1456
6
+ metadata.gz: 480a2b269eb27e44d8999e2e9753e7edf0f35a9e3dd1416d7c21269b4a8813622486c084d038f24db5438e0d7e666fc2bfc61a5b754b20955ae9051f92eb5f74
7
+ data.tar.gz: b0bcf24008f2b9d107284964582b20b17d7c52d7861ff563ee5c38f1fe548c3e999bb4a2c46c11779b5ee3998f1862c514fddb646ce5d4de0452b54c94b735f1
@@ -1,84 +1,171 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CapitalizeNames
2
4
  class Capitalizer
3
- attr_accessor :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
4
30
 
5
- MC = /^Mc(\w)(?=\w)/i
6
- MAC = /^Mac(\w)(?=\w)/i
7
- O_APOSTROPHE = /^O'(\w)(?=\w)/i
31
+ VALID_FORMATS = [:fullname, :firstname, :givenname, :lastname, :surname]
8
32
 
9
- def initialize(name)
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 = {})
10
48
  @name = name
49
+ @options = DEFAULT_OPTIONS.merge(options)
11
50
  end
12
51
 
13
52
  def capitalize!
14
53
  can_process?
15
- _capitalize
54
+ capitalize_name
16
55
  end
17
56
 
18
57
  def capitalize
19
- begin
20
- capitalize!
21
- rescue CapitalizeNames::Errors::GenericError
22
- name
23
- end
58
+ capitalize!
59
+ rescue CapitalizeNames::Errors::GenericError
60
+ name
24
61
  end
25
62
 
26
63
  private
27
- def can_process?
28
- raise CapitalizeNames::Errors::InvalidName, "Cannot capitalize nil" unless name
29
- 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(", ")}"
30
79
  end
31
80
 
32
- def surname_suffix_position?(position, name, surname_or_suffix)
33
- # surname/suffix must be:
34
- # 1. at start of name or after a space or a -
35
- # -and-
36
- # 2. followed by the end of string or a space or a -
37
- (
38
- (position == 0) || \
39
- (
40
- position > 0 && (name[position-1] == ' ' || name[position-1] == '-')
41
- )
42
- ) && (
43
- (name.length == position+surname_or_suffix.length) || \
44
- (name[position+surname_or_suffix.length] == ' ') || (name[position+surname_or_suffix.length] == '-')
45
- )
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
+ }
46
90
  end
91
+ end
47
92
 
48
- def _capitalize
49
- _name = name
93
+ def suffix?(str)
94
+ SUFFIX_MAP.key?(str.downcase)
95
+ end
50
96
 
51
- hyphens_index = []
97
+ def surname?(str)
98
+ SURNAME_MAP.key?(str.downcase)
99
+ end
52
100
 
53
- while _name.index('-') do
54
- index = _name.index('-')
55
- hyphens_index << index
56
- _name = _name[0...index] << ' ' << _name[index+1..-1]
57
- end
101
+ def capitalize_str(str, surname_rules)
102
+ str.split(/(\s|-)/).map do |word|
103
+ next word if word.match?(/(\s|-)/)
58
104
 
59
- _name = _name.split.map{ |w|
60
- w.mb_chars.capitalize.to_str
61
- }.map{ |w|
62
- w.gsub(MC) { "Mc#{$1.upcase}" }\
63
- .gsub(MAC) { "Mac#{$1.upcase}" }\
64
- .gsub(O_APOSTROPHE) { "O'#{$1.upcase}" }
65
- }
105
+ output = word.capitalize
106
+ next output unless surname_rules
107
+ next capitalize_surname(output) if surname?(output)
66
108
 
67
- _name = _name.join(' ')
68
- hyphens_index.each do |idx|
69
- _name = _name[0...idx] << '-' << (_name[idx+1..-1] || "")
70
- end
71
-
72
- _name = _name.gsub("Van ", "van ").gsub("De ", "de ").gsub("Dit ", "dit ")
73
- _name << ' '
74
-
75
- (CapitalizeNames::SURNAMES + CapitalizeNames::SUFFIXES).each do |surname_or_suffix|
76
- position = _name.downcase.index(surname_or_suffix.downcase)
77
- if position and surname_suffix_position?(position, _name, surname_or_suffix)
78
- _name = _name[0...position] << surname_or_suffix << _name[position+surname_or_suffix.length..-1]
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]
112
+
113
+ output
114
+ end.join("")
115
+ end
116
+
117
+ def capitalize_givenname(str)
118
+ capitalize_str(str, false)
119
+ end
120
+
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
142
+
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)
163
+ else
164
+ has_capitalized_last_name = !suffix?(token_value)
165
+ capitalize_lastname(token_value)
79
166
  end
80
167
  end
81
- _name.strip
82
- end
168
+ end.reverse.join("")
169
+ end
83
170
  end
84
- 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.0.5"
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,43 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capitalize-names
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
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: 2016-04-17 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
- name: minitest
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
- - - "~>"
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
+ - - ">="
32
53
  - !ruby/object:Gem::Version
33
- version: 5.8.4
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop-shopify
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
34
62
  type: :development
35
63
  prerelease: false
36
64
  version_requirements: !ruby/object:Gem::Requirement
37
65
  requirements:
38
- - - "~>"
66
+ - - ">="
39
67
  - !ruby/object:Gem::Version
40
- version: 5.8.4
68
+ version: '0'
41
69
  description: 'A simple gem to capitalize names, based off of: http://dzone.com/snippets/capitalize-proper-names'
42
70
  email: kbt.tate@gmail.com
43
71
  executables: []
@@ -54,24 +82,23 @@ homepage: http://github.com/infiton/capitalize-names
54
82
  licenses:
55
83
  - MIT
56
84
  metadata: {}
57
- post_install_message:
85
+ post_install_message:
58
86
  rdoc_options: []
59
87
  require_paths:
60
88
  - lib
61
89
  required_ruby_version: !ruby/object:Gem::Requirement
62
90
  requirements:
63
- - - "~>"
91
+ - - ">="
64
92
  - !ruby/object:Gem::Version
65
- version: '2.0'
93
+ version: '2.4'
66
94
  required_rubygems_version: !ruby/object:Gem::Requirement
67
95
  requirements:
68
96
  - - ">="
69
97
  - !ruby/object:Gem::Version
70
98
  version: '0'
71
99
  requirements: []
72
- rubyforge_project:
73
- rubygems_version: 2.4.5.1
74
- signing_key:
100
+ rubygems_version: 3.3.7
101
+ signing_key:
75
102
  specification_version: 4
76
103
  summary: Capitalizes names; handles edge cases.
77
104
  test_files: []