name-tamer 0.2.14 → 0.2.15

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
  SHA1:
3
- metadata.gz: 5db87ceb78cbdd1c4f46a674c0514430799dac05
4
- data.tar.gz: 9269bd1897a577ec14ba3b8f792060ef27b5ccc0
3
+ metadata.gz: 8dece3dacb2fbd41e1c31931973b534a36868789
4
+ data.tar.gz: bc65a4149e6d28126cab01d3093bbfdb9670e46e
5
5
  SHA512:
6
- metadata.gz: 76db6dcdfb49fcd3cc449df4bcad7cfecef6a2bae6753b9799794866938e7ac571c9f3b7a424e3c119828814fca3a759296f9af4a51c2c12482801066920a440
7
- data.tar.gz: 2523f85e57a9fb721cb91f099a4a844fddd3be306b911ae7799f96bd42cd5bad99b582de0967a74d04feaa1fe66b014e3137a98b504103231eac3d33d1e44ff0
6
+ metadata.gz: 951fce5bc9a6493145c24ebb8cc08791b5941334f5c38ea649d4e12d5f5e0ba3ec849486a40ef2916d7eb3f7d3da77215df38008f490b9627620e3f8a6408caa
7
+ data.tar.gz: 7297d3ac2c61e7907d117d0ed6d0548c26f283cb08029cf4bd5bcd9c6cee274c4e7b71cb6ba4994dc1a8b3d776fc2df4c27f44161f10a0ec3c161a3ed318f34d
data/.hound.yml CHANGED
@@ -1,27 +1,6 @@
1
- LineLength:
2
- Description: 'Limit lines to 120 characters.'
3
- Max: 120
4
- Enabled: true
5
-
6
- MethodLength:
7
- Description: 'Avoid methods longer than 10 lines of code.'
8
- Max: 23
9
- Enabled: true
10
-
11
- Documentation:
12
- Description: 'Document classes and non-namespace modules.'
13
- Enabled: false
14
-
15
- FileName:
16
- Description: 'Use snake_case for source file names.'
17
- Enabled: false
18
-
19
- DotPosition:
20
- Description: 'Checks the position of the dot in multi-line method calls.'
21
- EnforcedStyle: leading
22
- # EnforcedStyle: trailing
23
- Enabled: true
24
-
25
- StringLiterals:
26
- EnforcedStyle: single_quotes
27
- Enabled: true
1
+ ---
2
+ ruby:
3
+ enabled: true
4
+ config_file: .rubocop.yml
5
+ coffee_script:
6
+ enabled: true
@@ -1,4 +1,30 @@
1
- inherit_from: .hound.yml
1
+ LineLength:
2
+ Description: 'Limit lines to 120 characters.'
3
+ Max: 120
4
+ Enabled: true
5
+
6
+ MethodLength:
7
+ Description: 'Avoid methods longer than 10 lines of code.'
8
+ Max: 23
9
+ Enabled: true
10
+
11
+ Documentation:
12
+ Description: 'Document classes and non-namespace modules.'
13
+ Enabled: false
14
+
15
+ FileName:
16
+ Description: 'Use snake_case for source file names.'
17
+ Enabled: false
18
+
19
+ DotPosition:
20
+ Description: 'Checks the position of the dot in multi-line method calls.'
21
+ EnforcedStyle: leading
22
+ # EnforcedStyle: trailing
23
+ Enabled: true
24
+
25
+ StringLiterals:
26
+ EnforcedStyle: single_quotes
27
+ Enabled: true
2
28
 
3
29
  CyclomaticComplexity:
4
30
  Description: 'Avoid complex methods.'
@@ -7,4 +33,4 @@ CyclomaticComplexity:
7
33
  ClassLength:
8
34
  Description: 'Avoid classes longer than 100 lines of code.'
9
35
  CountComments: false # count full line comments?
10
- Max: 321
36
+ Max: 331
@@ -1 +1 @@
1
- 2.1.2
1
+ 2.2.0
@@ -1,25 +1,34 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- name-tamer (0.2.13)
4
+ name-tamer (0.2.14)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- coveralls (0.7.2)
10
- multi_json (~> 1.3)
11
- rest-client (= 1.6.7)
12
- simplecov (>= 0.7)
13
- term-ansicolor (= 1.2.2)
14
- thor (= 0.18.1)
9
+ ast (2.0.0)
10
+ astrolabe (1.3.0)
11
+ parser (>= 2.2.0.pre.3, < 3.0)
12
+ coveralls (0.7.11)
13
+ multi_json (~> 1.10)
14
+ rest-client (>= 1.6.8, < 2)
15
+ simplecov (~> 0.9.1)
16
+ term-ansicolor (~> 1.3)
17
+ thor (~> 0.19.1)
15
18
  diff-lcs (1.2.5)
16
19
  docile (1.1.5)
17
20
  gem-release (0.7.3)
18
21
  mime-types (2.4.3)
19
22
  multi_json (1.10.1)
23
+ netrc (0.10.3)
24
+ parser (2.2.0.3)
25
+ ast (>= 1.1, < 3.0)
26
+ powerpack (0.1.0)
27
+ rainbow (2.0.0)
20
28
  rake (10.4.2)
21
- rest-client (1.6.7)
22
- mime-types (>= 1.16)
29
+ rest-client (1.7.3)
30
+ mime-types (>= 1.16, < 3.0)
31
+ netrc (~> 0.7)
23
32
  rspec (2.99.0)
24
33
  rspec-core (~> 2.99.0)
25
34
  rspec-expectations (~> 2.99.0)
@@ -27,16 +36,23 @@ GEM
27
36
  rspec-core (2.99.2)
28
37
  rspec-expectations (2.99.2)
29
38
  diff-lcs (>= 1.1.3, < 2.0)
30
- rspec-mocks (2.99.2)
31
- simplecov (0.9.1)
39
+ rspec-mocks (2.99.3)
40
+ rubocop (0.29.1)
41
+ astrolabe (~> 1.3)
42
+ parser (>= 2.2.0.1, < 3.0)
43
+ powerpack (~> 0.1)
44
+ rainbow (>= 1.99.1, < 3.0)
45
+ ruby-progressbar (~> 1.4)
46
+ ruby-progressbar (1.7.1)
47
+ simplecov (0.9.2)
32
48
  docile (~> 1.1.0)
33
49
  multi_json (~> 1.0)
34
- simplecov-html (~> 0.8.0)
35
- simplecov-html (0.8.0)
36
- term-ansicolor (1.2.2)
37
- tins (~> 0.8)
38
- thor (0.18.1)
39
- tins (0.13.2)
50
+ simplecov-html (~> 0.9.0)
51
+ simplecov-html (0.9.0)
52
+ term-ansicolor (1.3.0)
53
+ tins (~> 1.0)
54
+ thor (0.19.1)
55
+ tins (1.3.4)
40
56
 
41
57
  PLATFORMS
42
58
  ruby
@@ -48,4 +64,5 @@ DEPENDENCIES
48
64
  name-tamer!
49
65
  rake (~> 10)
50
66
  rspec (~> 2)
67
+ rubocop (~> 0)
51
68
  simplecov (~> 0.7, >= 0.7.1)
@@ -1,31 +1,31 @@
1
- # encoding: utf-8
2
- require 'csv'
3
-
4
- desc 'Build prefixes and suffixes'
5
- task :adfixes do
6
- pp = []
7
- po = []
8
- sp = []
9
- so = []
10
-
11
- CSV.foreach("#{File.dirname(__FILE__)}/prefixes.csv", headers:true) do |row|
12
- if row[2] == 'person'
13
- pp << row[0]
14
- else
15
- po << row[0]
16
- end
17
- end
18
-
19
- CSV.foreach("#{File.dirname(__FILE__)}/suffixes.csv", headers:true) do |row|
20
- if row[2] == 'person'
21
- sp << row[0]
22
- else
23
- so << row[0]
24
- end
25
- end
26
-
27
- puts "'" + pp.join("', '") + "'"
28
- puts "'" + po.join("', '") + "'"
29
- puts "'" + sp.join("', '") + "'"
30
- puts "'" + so.join("', '") + "'"
31
- end
1
+ # encoding: utf-8
2
+ require 'csv'
3
+
4
+ desc 'Build prefixes and suffixes'
5
+ task :adfixes do
6
+ pp = []
7
+ po = []
8
+ sp = []
9
+ so = []
10
+
11
+ CSV.foreach("#{File.dirname(__FILE__)}/prefixes.csv", headers: true) do |row|
12
+ if row[2] == 'person'
13
+ pp << row[0]
14
+ else
15
+ po << row[0]
16
+ end
17
+ end
18
+
19
+ CSV.foreach("#{File.dirname(__FILE__)}/suffixes.csv", headers: true) do |row|
20
+ if row[2] == 'person'
21
+ sp << row[0]
22
+ else
23
+ so << row[0]
24
+ end
25
+ end
26
+
27
+ puts "'" + pp.join("', '") + "'"
28
+ puts "'" + po.join("', '") + "'"
29
+ puts "'" + sp.join("', '") + "'"
30
+ puts "'" + so.join("', '") + "'"
31
+ end
@@ -211,24 +211,32 @@ class NameTamer
211
211
  def name_wrangle
212
212
  # Fix case if all caps or all lowercase
213
213
  if @last_name.nil?
214
- lowercase = @nice_name.downcase
215
- uppercase = @nice_name.upcase
216
- fix_case = false
217
-
218
- if @contact_type == :organization
219
- fix_case = true if @nice_name == uppercase && @nice_name.length > 4
220
- else
221
- fix_case = true if [uppercase, lowercase].include?(@nice_name)
222
- end
214
+ name_wrangle_single_name
215
+ else
216
+ name_wrangle_split_name
217
+ end
218
+ end
219
+
220
+ def name_wrangle_single_name
221
+ lowercase = @nice_name.downcase
222
+ uppercase = @nice_name.upcase
223
+ fix_case = false
223
224
 
224
- @nice_name = name_case(lowercase) if fix_case
225
+ if @contact_type == :organization
226
+ fix_case = true if @nice_name == uppercase && @nice_name.length > 4
225
227
  else
226
- # It's a person if we've split the name, so no organization logic here
227
- lowercase = @last_name.downcase
228
- uppercase = @last_name.upcase
229
- @last_name = name_case(lowercase) if [uppercase, lowercase].include?(@last_name)
230
- @nice_name = "#{@remainder} #{@last_name}"
228
+ fix_case = true if [uppercase, lowercase].include?(@nice_name)
231
229
  end
230
+
231
+ @nice_name = name_case(lowercase) if fix_case
232
+ end
233
+
234
+ def name_wrangle_split_name
235
+ # It's a person if we've split the name, so no organization logic here
236
+ lowercase = @last_name.downcase
237
+ uppercase = @last_name.upcase
238
+ @last_name = name_case(lowercase) if [uppercase, lowercase].include?(@last_name)
239
+ @nice_name = "#{@remainder} #{@last_name}"
232
240
  end
233
241
 
234
242
  # Conjoin compound names with non-breaking spaces
@@ -256,30 +264,38 @@ class NameTamer
256
264
  def remove_middle_names
257
265
  return unless @contact_type == :person
258
266
 
259
- parts = @simple_name.split
260
- first_name = nil
261
- last_name = nil
267
+ first_name, parts = find_first_usable_name(@simple_name.split)
268
+ last_name, _ = find_last_usable_name(parts)
269
+
270
+ return unless first_name || last_name
271
+
272
+ separator = first_name && last_name ? ' ' : ''
273
+ @simple_name = "#{first_name}#{separator}#{last_name}"
274
+ end
275
+
276
+ def find_first_usable_name(parts)
277
+ part = nil
262
278
 
263
- # Find first usable name
264
279
  parts.each_index do |i|
265
280
  part = parts[i]
266
281
  next if part.gsub(FILTER_COMPAT, '').empty?
267
- first_name = part
268
- parts = parts.slice(i + 1, parts.length) # don't use "slice!"
282
+ parts = parts.slice(i + 1, parts.length) # don't use "slice!"
269
283
  break
270
284
  end
271
285
 
272
- # Find last usable name
273
- parts.reverse_each do |part|
274
- next if part.gsub(FILTER_COMPAT, '').empty?
275
- last_name = part
286
+ [part, parts]
287
+ end
288
+
289
+ def find_last_usable_name(parts)
290
+ part = nil
291
+
292
+ parts.reverse_each do |p|
293
+ next if p.gsub(FILTER_COMPAT, '').empty?
294
+ part = p
276
295
  break
277
296
  end
278
297
 
279
- return unless first_name || last_name
280
-
281
- separator = first_name && last_name ? ' ' : ''
282
- @simple_name = "#{first_name}#{separator}#{last_name}"
298
+ part
283
299
  end
284
300
 
285
301
  def remove_periods_from_initials
@@ -299,17 +315,8 @@ class NameTamer
299
315
  #--------------------------------------------------------
300
316
 
301
317
  def initialize(new_name, args = {})
302
- @name = new_name || ''
303
- args_ct = args[:contact_type]
304
-
305
- if args_ct
306
- ct = args_ct.is_a?(Symbol) ? args_ct : args_ct.dup
307
- ct = ct.to_s unless [String, Symbol].include? ct.class
308
- ct.downcase! if ct.class == String
309
- ct = ct.to_sym
310
- ct = nil unless [:person, :organization].include? ct
311
- @contact_type = ct
312
- end
318
+ @name = new_name || ''
319
+ @contact_type = contact_type_from args
313
320
 
314
321
  @tidy_name = nil
315
322
  @nice_name = nil
@@ -322,6 +329,19 @@ class NameTamer
322
329
  @adfix_found = false
323
330
  end
324
331
 
332
+ def contact_type_from(args)
333
+ args_ct = args[:contact_type]
334
+ return unless args_ct
335
+
336
+ ct = args_ct.is_a?(Symbol) ? args_ct : args_ct.dup
337
+ ct = ct.to_s unless [String, Symbol].include? ct.class
338
+ ct.downcase! if ct.class == String
339
+ ct = ct.to_sym
340
+ ct = nil unless [:person, :organization].include? ct
341
+
342
+ ct
343
+ end
344
+
325
345
  # If we don't know the contact type, what's our best guess?
326
346
  def contact_type_best_effort
327
347
  if @contact_type
@@ -335,34 +355,33 @@ class NameTamer
335
355
 
336
356
  # We pass to this routine either prefixes or suffixes
337
357
  def remove_outermost_adfix(adfix_type, name_part)
338
- adfixes = ADFIX_PATTERNS[adfix_type]
358
+ ct, parts = find_contact_type_and_parts(ADFIX_PATTERNS[adfix_type], name_part)
359
+
360
+ return name_part unless @adfix_found
361
+
362
+ # If we've found a diagnostic adfix then set the contact type
363
+ self.contact_type = ct
364
+
365
+ # The remainder of the name will be in parts[0] or parts[2] depending
366
+ # on whether this is a prefix or a suffix.
367
+ # We'll also remove any trailing commas we've exposed.
368
+ (parts[0] + parts[2]).gsub(/\s*,\s*$/, '')
369
+ end
370
+
371
+ def find_contact_type_and_parts(adfixes, name_part)
339
372
  ct = contact_type_best_effort
340
373
  parts = name_part.partition adfixes[ct]
341
374
  @adfix_found = !parts[1].empty?
342
375
 
376
+ return [ct, parts] if @contact_type || @adfix_found
377
+
343
378
  # If the contact type is indeterminate and we didn't find a diagnostic adfix
344
379
  # for a person then try again for an organization
345
- if @contact_type.nil?
346
- unless @adfix_found
347
- ct = :organization
348
- parts = name_part.partition adfixes[ct]
349
- @adfix_found = !parts[1].empty?
350
- end
351
- end
352
-
353
- if @adfix_found
354
- # If we've found a diagnostic adfix then set the contact type
355
- self.contact_type = ct
356
-
357
- # The remainder of the name will be in parts[0] or parts[2] depending
358
- # on whether this is a prefix or a suffix.
359
- # We'll also remove any trailing commas we've exposed.
360
- result = (parts[0] + parts[2]).gsub(/\s*,\s*$/, '')
361
- else
362
- result = name_part
363
- end
380
+ ct = :organization
381
+ parts = name_part.partition adfixes[ct]
382
+ @adfix_found = !parts[1].empty?
364
383
 
365
- result
384
+ [ct, parts]
366
385
  end
367
386
 
368
387
  # Original Version of NameCase:
@@ -1,3 +1,3 @@
1
1
  class NameTamer
2
- VERSION = '0.2.14'
2
+ VERSION = '0.2.15'
3
3
  end
@@ -107,6 +107,11 @@ class String
107
107
  end
108
108
  end
109
109
 
110
+ fix_apostrophe_modifiers!
111
+ self # Allows chaining
112
+ end
113
+
114
+ def fix_apostrophe_modifiers!
110
115
  %w(Dell D).each do |modifier|
111
116
  gsub!(/(.#{modifier}')(\w)/) { |_| "#{Regexp.last_match[1].rstrip.downcase}#{Regexp.last_match[2]}" }
112
117
  end
@@ -229,10 +234,10 @@ class String
229
234
  '¼' => '¼', '½' => '½', '¾' => '¾', '¿' => '¿', 'À' => 'À',
230
235
  'Ã�' => 'Á', 'Â' => 'Â', 'Ã' => 'Ã', 'Ä' => 'Ä', 'Ã…' => 'Å',
231
236
  'Æ' => 'Æ', 'Ç' => 'Ç', 'È' => 'È', 'É' => 'É', 'Ê' => 'Ê',
232
- 'Ë' => 'Ë', 'ÃŒ' => 'Ì', 'Ã�' => 'Í', 'ÃŽ' => 'Î', 'Ã�' => 'Ï',
233
- 'Ã�' => 'Ð', 'Ñ' => 'Ñ', 'Ã’' => 'Ò', 'Ó' => 'Ó', 'Ô' => 'Ô',
237
+ 'Ë' => 'Ë', 'ÃŒ' => 'Ì', "\xC3\x8D" => 'Í', 'ÃŽ' => 'Î', "\xC3\x8F" => 'Ï',
238
+ "\xC3\x90" => 'Ð', 'Ñ' => 'Ñ', 'Ã’' => 'Ò', 'Ó' => 'Ó', 'Ô' => 'Ô',
234
239
  'Õ' => 'Õ', 'Ö' => 'Ö', '×' => '×', 'Ø' => 'Ø', 'Ù' => 'Ù',
235
- 'Ú' => 'Ú', 'Û' => 'Û', 'Ãœ' => 'Ü', 'Ã�' => 'Ý', 'Þ' => 'Þ',
240
+ 'Ú' => 'Ú', 'Û' => 'Û', 'Ãœ' => 'Ü', "\xC3\x9D" => 'Ý', 'Þ' => 'Þ',
236
241
  'ß' => 'ß', 'à' => 'à', 'á' => 'á', 'â' => 'â', 'ã' => 'ã',
237
242
  'ä' => 'ä', 'Ã¥' => 'å', 'æ' => 'æ', 'ç' => 'ç', 'è' => 'è',
238
243
  'é' => 'é', 'ê' => 'ê', 'ë' => 'ë', 'ì' => 'ì', 'í' => 'í',
@@ -7,8 +7,8 @@ Gem::Specification.new do |spec|
7
7
  spec.version = NameTamer::VERSION
8
8
  spec.authors = ['Xenapto']
9
9
  spec.email = ['developers@xenapto.com']
10
- spec.description = %q(Useful methods for taming names)
11
- spec.summary = %q(Example: NameTamer['Mr. John Q. Smith III, MD'].simple_name # => John Smith)
10
+ spec.description = 'Useful methods for taming names'
11
+ spec.summary = "Example: NameTamer['Mr. John Q. Smith III, MD'].simple_name # => John Smith"
12
12
  spec.homepage = 'https://github.com/Xenapto/name-tamer'
13
13
  spec.license = 'MIT'
14
14
 
@@ -23,4 +23,5 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency 'gem-release', '~> 0'
24
24
  spec.add_development_dependency 'simplecov', '~> 0.7', '>= 0.7.1' # https://github.com/colszowka/simplecov/issues/281
25
25
  spec.add_development_dependency 'coveralls', '~> 0'
26
+ spec.add_development_dependency 'rubocop', '~> 0'
26
27
  end
@@ -161,7 +161,7 @@ describe NameTamer do
161
161
  { n: 'Hermann Müller', t: :person, nn: 'Hermann Müller', sn: 'Hermann Müller', s: 'hermann-muller' },
162
162
  { n: 'b-to-v Partners AG', t: :organization, nn: 'b-to-v Partners', sn: 'b-to-v Partners', s: 'b-to-v-partners' },
163
163
  { n: '*', t: :person, nn: '*', sn: '*', s: '_' },
164
- { n: '* *', t: :person, nn: '* *', sn: '* *', s: '_' },
164
+ { n: '* *', t: :person, nn: '* *', sn: '*', s: '_' },
165
165
  { n: '* Olga *', t: :person, nn: '* Olga *', sn: 'Olga', s: 'olga' },
166
166
  { n: '* Olga Bedia García *', t: :person, nn: '* Olga Bedia García *', sn: 'Olga García', s: 'olga-garcia' },
167
167
  { n: 'Jose “Pepe” García', t: :organization, nn: 'Jose “Pepe” García', sn: 'Jose Pepe García',
@@ -190,9 +190,9 @@ describe NameTamer do
190
190
  { n: '’%80', t: :person, nn: '’%80', sn: '’%80', s: '’80' }, # Encoding::CompatibilityError
191
191
  { n: "John Smith\u{FEFF}\u{200B}\u{200C}\u{200D}\u{2063}", t: :person,
192
192
  nn: 'John Smith', sn: 'John Smith', s: 'john-smith' }, # Zero-width characters
193
- { n: 'Herman Melville ,CLP', t: :person, nn:'Herman Melville', sn:'Herman Melville', s:'herman-melville'},
194
- { n: 'Melville ,Herman', t: :person, nn:'Herman Melville', sn:'Herman Melville', s:'herman-melville'},
195
- { n: "John\x00 Smith", t: :person, nn: 'John Smith', sn: 'John Smith', s: 'john-smith'}
193
+ { n: 'Herman Melville ,CLP', t: :person, nn: 'Herman Melville', sn: 'Herman Melville', s: 'herman-melville' },
194
+ { n: 'Melville ,Herman', t: :person, nn: 'Herman Melville', sn: 'Herman Melville', s: 'herman-melville' },
195
+ { n: "John\x00 Smith", t: :person, nn: 'John Smith', sn: 'John Smith', s: 'john-smith' }
196
196
  ]
197
197
  end
198
198
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: name-tamer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.14
4
+ version: 0.2.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Xenapto
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-10 00:00:00.000000000 Z
11
+ date: 2015-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -100,6 +100,20 @@ dependencies:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
102
  version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: rubocop
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
103
117
  description: Useful methods for taming names
104
118
  email:
105
119
  - developers@xenapto.com
@@ -146,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
160
  version: '0'
147
161
  requirements: []
148
162
  rubyforge_project:
149
- rubygems_version: 2.2.2
163
+ rubygems_version: 2.4.5
150
164
  signing_key:
151
165
  specification_version: 4
152
166
  summary: 'Example: NameTamer[''Mr. John Q. Smith III, MD''].simple_name # => John