mods_display 1.3.4 → 1.4.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: db5aacb765a91a03b8fe5fbb6c41b52ab0cb2f94467808f5e896f9b95c5b72ad
4
- data.tar.gz: b0572788c7868f49d98340668a28e71dde9cd41f676927436ce2ec9d09f24f83
3
+ metadata.gz: cd385f9d4aea6c14524378831877c327c6fdfd2664356e148b457af9c26a5623
4
+ data.tar.gz: b66857f71c766dc6edb03b8783d1d63486e94c63c8e9a71a0474f6b5a11d44cc
5
5
  SHA512:
6
- metadata.gz: 283a91d3efc90f2cdac50c2adae6133e758084ed454bbc9c79000567d9f83696e15369089290609c709e2c38b4e9e02a19d264297ff48e529aaf232bfd02f773
7
- data.tar.gz: a22877a514a7379219856dc941dfca980eb23aa7c8b0d2e8f12a8d023300dee4655ca1ef7e87e3ec36fe980c524eb07af848425d8b920b5d41324ae995871751
6
+ metadata.gz: 6b4760e8eee0c1eef22badaf5087b4095c4c88766c3b128bbaa1e841e2b1aa34294ced0be7199875b6aa57cdf1b3385dd5c11d624f4ce818afcc7fa4f1da25ab
7
+ data.tar.gz: 93c93c4249b55816c9716b1c632d0b4c5b5a2874365e33139fbbf6cd9421f01d3aa9800d347c72ae7837bcf98ef763650e8151a3cab547cecb287a72ff7a9ace
data/.rubocop.yml CHANGED
@@ -29,4 +29,10 @@ RSpec/MultipleExpectations:
29
29
  Enabled: false
30
30
 
31
31
  RSpec/ExampleLength:
32
+ Enabled: false
33
+
34
+ Naming/MethodName:
35
+ Enabled: false
36
+
37
+ Naming/VariableName:
32
38
  Enabled: false
@@ -64,12 +64,12 @@ module ModsDisplay
64
64
  element.place.respond_to?(:placeTerm)
65
65
 
66
66
  if unencoded_place_terms?(element)
67
- element.place.placeTerm.select do |term|
67
+ element.xpath('mods:place/mods:placeTerm', mods: MODS_NS).select do |term|
68
68
  !term.attributes['type'].respond_to?(:value) ||
69
69
  term.attributes['type'].value == 'text'
70
70
  end.compact
71
71
  else
72
- element.place.placeTerm.map do |term|
72
+ element.xpath('mods:place/mods:placeTerm', mods: MODS_NS).map do |term|
73
73
  next unless term.attributes['type'].respond_to?(:value) &&
74
74
  term.attributes['type'].value == 'code' &&
75
75
  term.attributes['authority'].respond_to?(:value) &&
@@ -84,7 +84,7 @@ module ModsDisplay
84
84
  end
85
85
 
86
86
  def unencoded_place_terms?(element)
87
- element.place.placeTerm.any? do |term|
87
+ element.xpath('mods:place/mods:placeTerm', mods: MODS_NS).any? do |term|
88
88
  !term.attributes['type'].respond_to?(:value) ||
89
89
  term.attributes['type'].value == 'text'
90
90
  end
@@ -8,12 +8,8 @@ module ModsDisplay
8
8
  # { role1 label => [ ModsDisplay:Name:Person, ModsDisplay:Name:Person, ...], role2 label => [ ModsDisplay:Name:Person, ModsDisplay:Name:Person, ...] }
9
9
  def fields
10
10
  return_fields = @values.map do |value|
11
- name_identifiers = value.element_children.select { |child| child.name == 'nameIdentifier' }
12
- person = if value.displayForm.length.positive?
13
- ModsDisplay::Name::Person.new(name: element_text(value.displayForm), name_identifiers: name_identifiers)
14
- elsif !name_parts(value).empty?
15
- ModsDisplay::Name::Person.new(name: name_parts(value), name_identifiers: name_identifiers)
16
- end
11
+ name_parts = ModsDisplay::NameFormatter.format(value)
12
+ person = name_parts ? ModsDisplay::Name::Person.new(name: name_parts, name_identifiers: value.xpath('mods:nameIdentifier', mods: MODS_NS)) : nil
17
13
  # The person may have multiple roles, so we have to divide them up into an array
18
14
  role_labels(value).collect do |role_label|
19
15
  ModsDisplay::Values.new(label: displayLabel(value) || role_label, values: [person]) if person
@@ -50,10 +46,10 @@ module ModsDisplay
50
46
 
51
47
  def role_labels(element)
52
48
  default_label = I18n.t('mods_display.associated_with')
53
- return [default_label] unless element.role.present? && element.role.roleTerm.present?
49
+ return [default_label] unless element.xpath('mods:role/mods:roleTerm', mods: MODS_NS).present?
54
50
 
55
- element.role.collect do |role|
56
- codes, text = role.roleTerm.partition { |term| term['type'] == 'code' }
51
+ element.xpath('mods:role', mods: MODS_NS).collect do |role|
52
+ codes, text = role.xpath('mods:roleTerm', mods: MODS_NS).partition { |term| term['type'] == 'code' }
57
53
 
58
54
  # prefer mappable role term codes
59
55
  label = codes.map { |term| relator_codes[term.text.downcase] }.first
@@ -70,76 +66,6 @@ module ModsDisplay
70
66
  element_text(element).capitalize.sub(/[.,:;]+$/, '')
71
67
  end
72
68
 
73
- def role?(element)
74
- element.respond_to?(:role) && !element.role.empty?
75
- end
76
-
77
- def primary?(element)
78
- element.attributes['usage'].respond_to?(:value) &&
79
- element.attributes['usage'].value == 'primary'
80
- end
81
-
82
- def name_parts(element)
83
- output = [unqualified_name_parts(element),
84
- qualified_name_parts(element, 'family'),
85
- qualified_name_parts(element, 'given')].flatten.compact.join(', ')
86
- terms = qualified_name_parts(element, 'termsOfAddress')
87
- unless terms.empty?
88
- term_delimiter = ', '
89
- term_delimiter = ' ' if name_part_begins_with_roman_numeral?(terms.first)
90
- output = [output, terms.join(', ')].flatten.compact.join(term_delimiter)
91
- end
92
- dates = qualified_name_parts(element, 'date')
93
- output = [output, qualified_name_parts(element, 'date')].flatten.compact.join(', ') unless dates.empty?
94
- output
95
- end
96
-
97
- def unqualified_name_parts(element)
98
- element.namePart.map do |part|
99
- element_text(part) unless part.attributes['type']
100
- end.compact
101
- end
102
-
103
- def qualified_name_parts(element, type)
104
- element.namePart.map do |part|
105
- if part.attributes['type'].respond_to?(:value) &&
106
- part.attributes['type'].value == type
107
- element_text(part)
108
- end
109
- end.compact
110
- end
111
-
112
- def name_part_begins_with_roman_numeral?(part)
113
- first_part = part.split(/\s|,/).first.strip
114
- first_part.chars.all? do |char|
115
- %w[I X C L V].include? char
116
- end
117
- end
118
-
119
- def unencoded_role_term(element)
120
- roles = element.role.map do |role|
121
- role.roleTerm.find do |term|
122
- term.attributes['type'].respond_to?(:value) &&
123
- term.attributes['type'].value == 'text'
124
- end
125
- end.compact
126
- if roles.empty?
127
- roles = element.role.map do |role|
128
- role.roleTerm.find do |term|
129
- !term.attributes['type'].respond_to?(:value)
130
- end
131
- end.compact
132
- end
133
- roles.map { |t| element_text(t) }
134
- end
135
-
136
- def unencoded_role_term?(element)
137
- element.role.roleTerm.any? do |term|
138
- !term.attributes['type'].respond_to?(:value) ||
139
- term.attributes['type'].value == 'text'
140
- end
141
- end
142
-
143
69
  # Consolidate all names under label headings
144
70
  def consolidate_under_labels(fields)
145
71
  results = {}
@@ -194,7 +120,7 @@ module ModsDisplay
194
120
 
195
121
  def orcid_identifier(name_identifiers)
196
122
  orcid = name_identifiers.select do |name_identifier|
197
- name_identifier.attribute('type')&.value == 'orcid'
123
+ name_identifier.get_attribute('type') == 'orcid'
198
124
  end
199
125
  orcid.first&.text
200
126
  end
@@ -10,8 +10,8 @@ module ModsDisplay
10
10
 
11
11
  def fields
12
12
  @fields ||= begin
13
- return_fields = @values.map do |value|
14
- next if related_item_is_a_collection?(value)
13
+ return_fields = RelatedItemValue.for_values(@values).map do |value|
14
+ next if value.collection?
15
15
  next unless render_nested_related_item?(value)
16
16
 
17
17
  related_item_mods_object(value)
@@ -63,7 +63,7 @@ module ModsDisplay
63
63
 
64
64
  def related_item_label(item)
65
65
  return displayLabel(item) if displayLabel(item)
66
- return I18n.t('mods_display.constituent') if related_item_is_a_constituent?(item)
66
+ return I18n.t('mods_display.constituent') if item.constituent?
67
67
 
68
68
  I18n.t('mods_display.host')
69
69
  end
@@ -5,8 +5,8 @@ module ModsDisplay
5
5
  include ModsDisplay::RelatedItemConcerns
6
6
 
7
7
  def fields
8
- return_fields = @values.map do |value|
9
- next if related_item_is_a_collection?(value)
8
+ return_fields = RelatedItemValue.for_values(@values).map do |value|
9
+ next if value.collection?
10
10
  next if render_nested_related_item?(value)
11
11
 
12
12
  text = related_item_value(value)
@@ -25,15 +25,14 @@ module ModsDisplay
25
25
  end
26
26
 
27
27
  def related_item_value(item)
28
- if related_item_is_a_location?(item)
29
- element_text(item.location)
30
- elsif related_item_is_a_reference?(item)
28
+ if item.location?
29
+ element_text(item.location_nodeset)
30
+ elsif item.reference?
31
31
  reference_title(item)
32
- elsif item.titleInfo.any?
33
- title = element_text(item.titleInfo)
32
+ elsif item.titleInfo_nodeset.any?
33
+ title = element_text(item.titleInfo_nodeset)
34
34
  location = nil
35
- location = element_text(item.location.url) if item.location.length.positive? &&
36
- item.location.url.length.positive?
35
+ location = element_text(item.location_url_nodeset) if item.location_url_nodeset.length.positive?
37
36
 
38
37
  return if title.empty?
39
38
 
@@ -42,31 +41,18 @@ module ModsDisplay
42
41
  else
43
42
  title
44
43
  end
45
- elsif item.note.any?
46
- citation = item.note.find { |note| note['type'] == 'preferred citation' }
44
+ elsif item.note_nodeset.any?
45
+ citation = item.note_nodeset.find { |note| note['type'] == 'preferred citation' }
47
46
 
48
47
  element_text(citation) if citation
49
48
  end
50
49
  end
51
50
 
52
51
  def reference_title(item)
53
- [item.titleInfo,
52
+ [item.titleInfo_nodeset,
54
53
  item.originInfo.dateOther,
55
54
  item.part.detail.number,
56
- item.note].flatten.compact.map!(&:text).map!(&:strip).join(' ')
57
- end
58
-
59
- def related_item_is_a_location?(item)
60
- !related_item_is_a_collection?(item) &&
61
- !related_item_is_a_reference?(item) &&
62
- item.location.length.positive? &&
63
- item.titleInfo.empty?
64
- end
65
-
66
- def related_item_is_a_reference?(item)
67
- !related_item_is_a_collection?(item) &&
68
- item.attributes['type'].respond_to?(:value) &&
69
- item.attributes['type'].value == 'isReferencedBy'
55
+ item.note_nodeset].flatten.compact.map!(&:text).map!(&:strip).join(' ')
70
56
  end
71
57
 
72
58
  def related_item_label(item)
@@ -74,9 +60,9 @@ module ModsDisplay
74
60
  displayLabel(item)
75
61
  else
76
62
  case
77
- when related_item_is_a_location?(item)
63
+ when item.location?
78
64
  return I18n.t('mods_display.location')
79
- when related_item_is_a_reference?(item)
65
+ when item.reference?
80
66
  return I18n.t('mods_display.referenced_by')
81
67
  end
82
68
  I18n.t('mods_display.related_item')
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ModsDisplay
4
+ class NameFormatter
5
+ def self.format(element)
6
+ new(element).format
7
+ end
8
+
9
+ def initialize(element)
10
+ @element = element
11
+ end
12
+
13
+ def format
14
+ return element_text(display_form_nodeset) if display_form_nodeset.present?
15
+ return name_parts if name_parts.present?
16
+
17
+ nil
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :element
23
+
24
+ def name_parts
25
+ @name_parts ||= begin
26
+ output = [unqualified_name_parts(name_part_nodeset),
27
+ qualified_name_parts(name_part_nodeset, 'family'),
28
+ qualified_name_parts(name_part_nodeset, 'given')].flatten.compact.join(', ')
29
+ terms = qualified_name_parts(name_part_nodeset, 'termsOfAddress')
30
+ unless terms.empty?
31
+ term_delimiter = ', '
32
+ term_delimiter = ' ' if name_part_begins_with_roman_numeral?(terms.first)
33
+ output = [output, terms.join(', ')].flatten.compact.join(term_delimiter)
34
+ end
35
+ dates = qualified_name_parts(name_part_nodeset, 'date')
36
+ output = [output, dates].flatten.compact.join(', ') unless dates.empty?
37
+ output
38
+ end
39
+ end
40
+
41
+ def unqualified_name_parts(name_part_nodeset)
42
+ name_part_nodeset.map do |part|
43
+ element_text(part) unless part.attributes['type']
44
+ end.compact
45
+ end
46
+
47
+ def qualified_name_parts(name_part_nodeset, type)
48
+ name_part_nodeset.map do |part|
49
+ element_text(part) if part.get_attribute('type') == type
50
+ end.compact
51
+ end
52
+
53
+ def name_part_begins_with_roman_numeral?(part)
54
+ first_part = part.split(/\s|,/).first.strip
55
+ first_part.chars.all? do |char|
56
+ %w[I X C L V].include? char
57
+ end
58
+ end
59
+
60
+ def element_text(element)
61
+ element.text.strip
62
+ end
63
+
64
+ def name_part_nodeset
65
+ @name_part_nodeset ||= element.xpath('mods:namePart', mods: MODS_NS)
66
+ end
67
+
68
+ def display_form_nodeset
69
+ @display_form_nodeset ||= element.xpath('mods:displayForm', mods: MODS_NS)
70
+ end
71
+ end
72
+ end
@@ -5,25 +5,60 @@ module ModsDisplay
5
5
  private
6
6
 
7
7
  def render_nested_related_item?(item)
8
- related_item_is_a_constituent?(item) || related_item_is_host?(item)
8
+ item.constituent? || item.host?
9
9
  end
10
10
 
11
- def related_item_is_a_collection?(item)
12
- item.respond_to?(:titleInfo) &&
13
- item.respond_to?(:typeOfResource) &&
14
- !item.typeOfResource.attributes.empty? &&
15
- item.typeOfResource.attributes.first.key?('collection') &&
16
- item.typeOfResource.attributes.first['collection'].value == 'yes'
17
- end
11
+ class RelatedItemValue < SimpleDelegator
12
+ def collection?
13
+ @collection ||= typeOfResource_nodeset.first&.get_attribute('collection') == 'yes'
14
+ end
18
15
 
19
- def related_item_is_a_constituent?(item)
20
- item.attributes['type'].respond_to?(:value) &&
21
- item.attributes['type'].value == 'constituent'
22
- end
16
+ def constituent?
17
+ @constituent ||= type_attribute == 'constituent'
18
+ end
19
+
20
+ def host?
21
+ @host ||= type_attribute == 'host'
22
+ end
23
+
24
+ def location?
25
+ @location ||= !collection? &&
26
+ !reference? &&
27
+ location_nodeset.length.positive? &&
28
+ titleInfo_nodeset.empty?
29
+ end
30
+
31
+ def reference?
32
+ @reference ||= !collection? && type_attribute == 'isReferencedBy'
33
+ end
34
+
35
+ def typeOfResource_nodeset
36
+ @typeOfResource_nodeset ||= xpath('mods:typeOfResource', mods: MODS_NS)
37
+ end
38
+
39
+ def location_nodeset
40
+ @location_nodeset ||= xpath('mods:location', mods: MODS_NS)
41
+ end
42
+
43
+ def location_url_nodeset
44
+ @location_url_nodeset ||= xpath('mods:location/mods:url', mods: MODS_NS)
45
+ end
46
+
47
+ def titleInfo_nodeset
48
+ @titleInfo_nodeset ||= xpath('mods:titleInfo', mods: MODS_NS)
49
+ end
50
+
51
+ def note_nodeset
52
+ @note_nodeset ||= xpath('mods:note', mods: MODS_NS)
53
+ end
54
+
55
+ def type_attribute
56
+ @type_attribute ||= get_attribute('type')
57
+ end
23
58
 
24
- def related_item_is_host?(item)
25
- item.attributes['type'].respond_to?(:value) &&
26
- item.attributes['type'].value == 'host'
59
+ def self.for_values(values)
60
+ values.map { |value| new(value) }
61
+ end
27
62
  end
28
63
  end
29
64
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ModsDisplay
4
- VERSION = '1.3.4'
4
+ VERSION = '1.4.0'
5
5
  end
data/lib/mods_display.rb CHANGED
@@ -5,6 +5,7 @@ require 'mods_display/html'
5
5
  require 'mods_display/country_codes'
6
6
  require 'mods_display/relator_codes'
7
7
  require 'mods_display/related_item_concerns'
8
+ require 'mods_display/name_formatter'
8
9
  require 'mods_display/fields/field'
9
10
  require 'mods_display/fields/abstract'
10
11
  require 'mods_display/fields/access_condition'
@@ -40,6 +41,8 @@ I18n::Backend::Simple.include I18n::Backend::Fallbacks
40
41
  I18n.load_path += Dir["#{File.expand_path('..', __dir__)}/config/locales/*.yml"]
41
42
  I18n.backend.load_translations
42
43
 
44
+ MODS_NS = 'http://www.loc.gov/mods/v3'
45
+
43
46
  begin
44
47
  require 'rails'
45
48
  rescue LoadError
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mods_display
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.4
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jessie Keck
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-11-01 00:00:00.000000000 Z
11
+ date: 2023-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: stanford-mods
@@ -223,6 +223,7 @@ files:
223
223
  - lib/mods_display/fields/title.rb
224
224
  - lib/mods_display/fields/values.rb
225
225
  - lib/mods_display/html.rb
226
+ - lib/mods_display/name_formatter.rb
226
227
  - lib/mods_display/related_item_concerns.rb
227
228
  - lib/mods_display/relator_codes.rb
228
229
  - lib/mods_display/version.rb
@@ -245,7 +246,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
245
246
  - !ruby/object:Gem::Version
246
247
  version: '0'
247
248
  requirements: []
248
- rubygems_version: 3.4.10
249
+ rubygems_version: 3.3.7
249
250
  signing_key:
250
251
  specification_version: 4
251
252
  summary: The MODS Display gem allows implementers to configure a customized display