mods_display 1.4.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -0
  3. data/README.md +10 -18
  4. data/app/components/mods_display/row_field_component.html.erb +11 -0
  5. data/app/components/mods_display/row_field_component.rb +43 -0
  6. data/app/helpers/mods_display/record_helper.rb +20 -0
  7. data/config/locales/en.yml +3 -0
  8. data/lib/mods_display/fields/access_condition.rb +5 -5
  9. data/lib/mods_display/fields/cartographics.rb +7 -9
  10. data/lib/mods_display/fields/collection.rb +14 -14
  11. data/lib/mods_display/fields/contact.rb +7 -7
  12. data/lib/mods_display/fields/contents.rb +5 -1
  13. data/lib/mods_display/fields/copyright_date.rb +9 -0
  14. data/lib/mods_display/fields/date_captured.rb +9 -0
  15. data/lib/mods_display/fields/date_created.rb +9 -0
  16. data/lib/mods_display/fields/date_issued.rb +9 -0
  17. data/lib/mods_display/fields/date_modified.rb +9 -0
  18. data/lib/mods_display/fields/date_other.rb +26 -0
  19. data/lib/mods_display/fields/date_valid.rb +9 -0
  20. data/lib/mods_display/fields/description.rb +6 -3
  21. data/lib/mods_display/fields/edition.rb +22 -0
  22. data/lib/mods_display/fields/extent.rb +4 -4
  23. data/lib/mods_display/fields/field.rb +54 -8
  24. data/lib/mods_display/fields/form.rb +4 -4
  25. data/lib/mods_display/fields/frequency.rb +19 -0
  26. data/lib/mods_display/fields/genre.rb +5 -2
  27. data/lib/mods_display/fields/geo.rb +2 -2
  28. data/lib/mods_display/fields/identifier.rb +5 -2
  29. data/lib/mods_display/fields/imprint.rb +13 -36
  30. data/lib/mods_display/fields/issuance.rb +19 -0
  31. data/lib/mods_display/fields/language.rb +4 -4
  32. data/lib/mods_display/fields/location.rb +5 -5
  33. data/lib/mods_display/fields/name.rb +8 -7
  34. data/lib/mods_display/fields/nested_related_item.rb +45 -37
  35. data/lib/mods_display/fields/note.rb +10 -7
  36. data/lib/mods_display/fields/place.rb +35 -0
  37. data/lib/mods_display/fields/publisher.rb +21 -0
  38. data/lib/mods_display/fields/reference_title.rb +30 -0
  39. data/lib/mods_display/fields/related_item.rb +59 -40
  40. data/lib/mods_display/fields/resource_type.rb +7 -4
  41. data/lib/mods_display/fields/subject.rb +3 -3
  42. data/lib/mods_display/fields/title.rb +46 -30
  43. data/lib/mods_display/fields/values.rb +1 -0
  44. data/lib/mods_display/html.rb +25 -10
  45. data/lib/mods_display/version.rb +1 -1
  46. data/lib/mods_display.rb +13 -0
  47. data/mods_display.gemspec +1 -1
  48. metadata +21 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cd385f9d4aea6c14524378831877c327c6fdfd2664356e148b457af9c26a5623
4
- data.tar.gz: b66857f71c766dc6edb03b8783d1d63486e94c63c8e9a71a0474f6b5a11d44cc
3
+ metadata.gz: 4152dce7ec61d92e04a5cddf9c5c152c414eeb725c05b975be1ec66eeadc2fa7
4
+ data.tar.gz: '087502061c3666fe0b4eec7c00a2a93e9532610cb4b35d7de6555a3dd7d2a8c8'
5
5
  SHA512:
6
- metadata.gz: 6b4760e8eee0c1eef22badaf5087b4095c4c88766c3b128bbaa1e841e2b1aa34294ced0be7199875b6aa57cdf1b3385dd5c11d624f4ce818afcc7fa4f1da25ab
7
- data.tar.gz: 93c93c4249b55816c9716b1c632d0b4c5b5a2874365e33139fbbf6cd9421f01d3aa9800d347c72ae7837bcf98ef763650e8151a3cab547cecb287a72ff7a9ace
6
+ metadata.gz: 1843e6a4f59a79c0f54f757e9c99820af6235681eea8a2c494bb40a6291db2f0408b6af26a6b8541bd91348cd1572c87329e510c12713df2afe9e72aea1a6baa
7
+ data.tar.gz: b4f433ae7fe636d51b92222cf64e8cbabdadcdc3aca05333165d9f0699957a59f94a4d254efad3e43e908f2b8991d12d7e70a652cdd10b15e639a7317b98d889
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/README.md CHANGED
@@ -1,6 +1,15 @@
1
1
  # ModsDisplay
2
2
 
3
- A gem for displaying MODS Metadata in a configurable way.
3
+ A gem for displaying MODS Metadata in a configurable way.
4
+
5
+ This gem is used to centralize the display logic of MODS metadata by creating html fragments such as
6
+
7
+ ```
8
+ <dt>Publisher</dt>
9
+ <dd>Diagon Alley Publications</dd>
10
+ ```
11
+
12
+ which can be styled in consuming apps such as SearchWorks or Exhibits.
4
13
 
5
14
  ## Demo
6
15
 
@@ -20,23 +29,6 @@ Or install it yourself as:
20
29
 
21
30
  $ gem install mods_display
22
31
 
23
- ## Release/Upgrade Notes
24
-
25
- #### v0.5.0
26
- There are three major changes in this version.
27
-
28
- 1. RelatedItem nodes with a type of `constituent` or `host` are now treated separately and will render the full MODS display of any nested metadata. If accessing the `ModsDisplay::Values` directly through their accessors (e.g. custom grouping), this new metadata is available under `.nested_related_items`.
29
- * _**Note:** You may want to style and add some javascript toggling behavior (see exhibits for an example)._
30
- 2. Name nodes are now grouped/labeled by their role. If you were iterating over the names and splitting them out by their labels, that will need to change.
31
- 3. Table of contents/Summaries are now split on `--` and rendered as an unordered list.
32
- * _**Note:** You may want to style this list._
33
-
34
- #### v0.3.0
35
-
36
- Labels now have internationalization support. We have added colons to the english labels due to certain languages' punctuation rules requiring different spacing between the label and colon.
37
-
38
- Given that fact, you will want to update any pre 0.3.0 code that searches for elements by label in a way that would fail with the presence of a colon.
39
-
40
32
  ## Contributing
41
33
 
42
34
  1. Fork it
@@ -0,0 +1,11 @@
1
+ <% values.each do |value| %>
2
+ <tr>
3
+ <% if label %>
4
+ <%= tag.th label, **label_html_attributes %>
5
+ <% end %>
6
+
7
+ <%= tag.td **value_html_attributes do %>
8
+ <%= value %>
9
+ <% end %>
10
+ </tr>
11
+ <% end %>
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ModsDisplay
4
+ class RowFieldComponent < ViewComponent::Base
5
+ with_collection_parameter :field
6
+
7
+ def initialize(field:, delimiter: nil, label_html_attributes: {}, value_html_attributes: {}, value_transformer: nil)
8
+ super
9
+
10
+ @field = field
11
+ @delimiter = delimiter
12
+ @value_transformer = value_transformer
13
+ @label_html_attributes = label_html_attributes
14
+ @value_html_attributes = value_html_attributes
15
+ end
16
+
17
+ attr_reader :field, :delimiter, :label_html_attributes, :value_html_attributes
18
+
19
+ def render?
20
+ field.values.any?(&:present?)
21
+ end
22
+
23
+ def format_value(value)
24
+ if @value_transformer
25
+ @value_transformer.call(value)
26
+ else
27
+ helpers.format_mods_html(value, field: field)
28
+ end
29
+ end
30
+
31
+ def values
32
+ if delimiter
33
+ [safe_join(field.values.select(&:present?).map { |value| format_value(value) }, delimiter)]
34
+ else
35
+ field.values.select(&:present?).map { |value| format_value(value) }
36
+ end
37
+ end
38
+
39
+ def label
40
+ field.label&.sub(/:$/, '')
41
+ end
42
+ end
43
+ end
@@ -17,6 +17,14 @@ module ModsDisplay
17
17
  render component.new(field: field, delimiter: delimiter, value_transformer: block)
18
18
  end
19
19
 
20
+ def mods_record_definition_field(field, delimiter: nil, label_html_attributes: {}, &block)
21
+ render ModsDisplay::FieldComponent.new(field: field, delimiter: delimiter, label_html_attributes: label_html_attributes, value_transformer: block)
22
+ end
23
+
24
+ def mods_record_row_field(field, delimiter: ', ', &block)
25
+ render ModsDisplay::RowFieldComponent.new(field: field, delimiter: delimiter, value_transformer: block)
26
+ end
27
+
20
28
  # this returns a role's label and the display names for ModsDisplay:Name:Person
21
29
  def mods_name_field(field)
22
30
  mods_record_field(field) do |name|
@@ -41,12 +49,24 @@ module ModsDisplay
41
49
  end
42
50
  end
43
51
 
52
+ def mods_subject_row_field(field, delimiter: nil, &block)
53
+ mods_record_row_field(field, delimiter: delimiter) do |subject_line|
54
+ safe_join(link_mods_subjects(subject_line, &block), ' > ')
55
+ end
56
+ end
57
+
44
58
  def mods_genre_field(field, &block)
45
59
  mods_record_field(field) do |genre_line|
46
60
  link_to_mods_subject(genre_line, &block)
47
61
  end
48
62
  end
49
63
 
64
+ def mods_genre_row_field(field, delimiter: nil, &block)
65
+ mods_record_row_field(field, delimiter: delimiter) do |genre_line|
66
+ link_to_mods_subject(genre_line, &block)
67
+ end
68
+ end
69
+
50
70
  # @private
51
71
  def link_mods_genres(genre, &block)
52
72
  link_buffer = []
@@ -17,11 +17,14 @@ en:
17
17
  creation_production_credits: "Creation/Production credits:"
18
18
  date_captured: "Date captured:"
19
19
  date_created: "Date created:"
20
+ date_issued: "Publication date:"
20
21
  date_modified: "Date modified:"
22
+ date_other: "Other date:"
21
23
  date_sequential_designation: "Date/Sequential designation:"
22
24
  date_valid: "Date valid:"
23
25
  digital_origin: "Digital origin:"
24
26
  doi: "DOI:"
27
+ edition: "Edition:"
25
28
  extent: "Extent:"
26
29
  form: "Form:"
27
30
  frequency: "Frequency:"
@@ -51,10 +51,10 @@ module ModsDisplay
51
51
  }.freeze
52
52
 
53
53
  def fields
54
- return_fields = @values.map do |value|
54
+ return_fields = @stanford_mods_elements.map do |stanford_mods_element|
55
55
  ModsDisplay::Values.new(
56
- label: displayLabel(value) || access_label(value),
57
- values: [process_access_statement(value)],
56
+ label: displayLabel(stanford_mods_element) || access_label(stanford_mods_element),
57
+ values: [process_access_statement(stanford_mods_element)],
58
58
  field: self
59
59
  )
60
60
  end
@@ -85,7 +85,7 @@ module ModsDisplay
85
85
  def license_statement(element)
86
86
  element_text = element_text(element)
87
87
  legacy_matches = element_text.match(/^(?<code>.*) (?<type>.*):(?<description>.*)$/)
88
- return legacy_license_statement(element, legacy_matches) if legacy_matches
88
+ return legacy_license_statement(legacy_matches) if legacy_matches
89
89
 
90
90
  matches = element_text.match(/^This work is licensed under a (.+?)\.$/)
91
91
  return linked_licensed_statement(element, matches) if matches && element['xlink:href'].present?
@@ -97,7 +97,7 @@ module ModsDisplay
97
97
  "This work is licensed under a <a href='#{element['xlink:href']}'>#{matches[1]}</a>."
98
98
  end
99
99
 
100
- def legacy_license_statement(_element, matches)
100
+ def legacy_license_statement(matches)
101
101
  code = matches[:code].downcase
102
102
  type = matches[:type].downcase
103
103
  description = license_description(code, type) || matches[:description]
@@ -3,22 +3,20 @@
3
3
  module ModsDisplay
4
4
  class Cartographics < Field
5
5
  def fields
6
- return nil if @values.nil?
6
+ return nil if @stanford_mods_elements.nil?
7
7
 
8
8
  return_fields = []
9
- @values.each do |value|
10
- next unless value.respond_to?(:cartographics)
9
+ @stanford_mods_elements.each do |subject_element|
10
+ next unless subject_element.respond_to?(:cartographics)
11
11
 
12
- value.cartographics.each do |field|
12
+ subject_element.cartographics.each do |field|
13
13
  scale = field.scale.empty? ? 'Scale not given' : element_text(field.scale)
14
14
  projection = field.projection.empty? ? nil : element_text(field.projection)
15
15
  coordinates = field.coordinates.empty? ? nil : element_text(field.coordinates)
16
- post_scale = if [projection,
17
- coordinates].compact.length.positive?
18
- [projection, coordinates].compact.join(' ')
19
- end
16
+ post_scale = [projection, coordinates].compact.join(' ') if [projection, coordinates].compact.length.positive?
17
+
20
18
  return_fields << ModsDisplay::Values.new(
21
- label: (displayLabel(field) || label || I18n.t('mods_display.map_data')),
19
+ label: displayLabel(field) || label || I18n.t('mods_display.map_data'),
22
20
  values: [[scale, post_scale].compact.join(' ; ')]
23
21
  )
24
22
  end
@@ -5,18 +5,18 @@ module ModsDisplay
5
5
  # Collection class to parse collection data out of Mods relatedItem fields
6
6
  ###
7
7
  class Collection < Field
8
- def collection_label(value)
9
- displayLabel(value) || I18n.t('mods_display.collection')
8
+ def collection_label(related_item_element)
9
+ displayLabel(related_item_element) || I18n.t('mods_display.collection')
10
10
  end
11
11
 
12
12
  def fields
13
13
  return_fields = []
14
- @values.each do |value|
15
- next unless related_item_is_a_collection?(value)
14
+ @stanford_mods_elements.each do |related_item_element|
15
+ next unless related_item_is_a_collection?(related_item_element)
16
16
 
17
17
  return_fields << ModsDisplay::Values.new(
18
- label: collection_label(value),
19
- values: [element_text(value.titleInfo)]
18
+ label: collection_label(related_item_element),
19
+ values: [element_text(related_item_element.titleInfo)]
20
20
  )
21
21
  end
22
22
  collapse_fields(return_fields)
@@ -24,17 +24,17 @@ module ModsDisplay
24
24
 
25
25
  private
26
26
 
27
- def related_item_is_a_collection?(value)
28
- value.respond_to?(:titleInfo) && resource_type_is_collection?(value)
27
+ def related_item_is_a_collection?(related_item_element)
28
+ related_item_element.respond_to?(:titleInfo) && resource_type_is_collection?(related_item_element)
29
29
  end
30
30
 
31
- def resource_type_is_collection?(value)
32
- return false unless value.respond_to?(:typeOfResource)
33
- return false unless value.typeOfResource.attributes.length.positive?
31
+ def resource_type_is_collection?(related_item_element)
32
+ return false unless related_item_element.respond_to?(:typeOfResource)
33
+ return false unless related_item_element.typeOfResource.attributes.length.positive?
34
34
 
35
- value.typeOfResource.attributes.length.positive? &&
36
- value.typeOfResource.attributes.first.key?('collection') &&
37
- value.typeOfResource.attributes.first['collection'].value == 'yes'
35
+ related_item_element.typeOfResource.attributes.length.positive? &&
36
+ related_item_element.typeOfResource.attributes.first.key?('collection') &&
37
+ related_item_element.typeOfResource.attributes.first['collection'].value == 'yes'
38
38
  end
39
39
  end
40
40
  end
@@ -3,10 +3,10 @@
3
3
  module ModsDisplay
4
4
  class Contact < Field
5
5
  def fields
6
- return_fields = contact_fields.map do |value|
6
+ return_fields = contact_elements.map do |contact_element|
7
7
  ModsDisplay::Values.new(
8
- label: displayLabel(value) || I18n.t('mods_display.contact'),
9
- values: [element_text(value)]
8
+ label: displayLabel(contact_element) || I18n.t('mods_display.contact'),
9
+ values: [element_text(contact_element)]
10
10
  )
11
11
  end
12
12
  collapse_fields(return_fields)
@@ -14,10 +14,10 @@ module ModsDisplay
14
14
 
15
15
  private
16
16
 
17
- def contact_fields
18
- @values.select do |value|
19
- value.attributes['type'].respond_to?(:value) &&
20
- value.attributes['type'].value.downcase == 'contact'
17
+ def contact_elements
18
+ @stanford_mods_elements.select do |note_element|
19
+ note_element.attributes['type'].respond_to?(:value) &&
20
+ note_element.attributes['type'].value.downcase == 'contact'
21
21
  end
22
22
  end
23
23
  end
@@ -4,7 +4,11 @@ module ModsDisplay
4
4
  class Contents < Field
5
5
  def to_html(view_context = ApplicationController.renderer)
6
6
  f = fields.map do |field|
7
- ModsDisplay::Values.new(label: field.label, values: [field.values.join("\n\n")], field: self)
7
+ ModsDisplay::Values.new(
8
+ label: field.label,
9
+ values: [field.values.join("\n\n")],
10
+ field: self
11
+ )
8
12
  end
9
13
 
10
14
  helpers = view_context.respond_to?(:simple_format) ? view_context : ApplicationController.new.view_context
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ModsDisplay
4
+ class CopyrightDate < Field
5
+ def fields
6
+ date_fields(:copyrightDate)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ModsDisplay
4
+ class DateCaptured < Field
5
+ def fields
6
+ date_fields(:dateCaptured)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ModsDisplay
4
+ class DateCreated < Field
5
+ def fields
6
+ date_fields(:dateCreated)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ModsDisplay
4
+ class DateIssued < Field
5
+ def fields
6
+ date_fields(:dateIssued)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ModsDisplay
4
+ class DateModified < Field
5
+ def fields
6
+ date_fields(:dateModified)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ModsDisplay
4
+ class DateOther < Field
5
+ def fields
6
+ date_fields(:dateOther)
7
+ end
8
+
9
+ private
10
+
11
+ # this is called from the Field.select_best_date method
12
+ # @param date [Stanford::Mods::Imprint::Date]
13
+ def qualified_value_with_type(date)
14
+ type = type_attribute_value(date)
15
+ type ? "#{date.qualified_value} (#{type})" : date.qualified_value
16
+ end
17
+
18
+ def type_attribute_value(date)
19
+ if date.is_a?(Stanford::Mods::Imprint::DateRange)
20
+ date.start.value.type || date.stop.value.type
21
+ else
22
+ date.value.type
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ModsDisplay
4
+ class DateValid < Field
5
+ def fields
6
+ date_fields(:dateValid)
7
+ end
8
+ end
9
+ end
@@ -3,8 +3,11 @@
3
3
  module ModsDisplay
4
4
  class Description < Field
5
5
  def fields
6
- return_fields = description_fields.map do |value|
7
- ModsDisplay::Values.new(label: description_label(value), values: [element_text(value)])
6
+ return_fields = description_fields.map do |element|
7
+ ModsDisplay::Values.new(
8
+ label: description_label(element),
9
+ values: [element_text(element)]
10
+ )
8
11
  end
9
12
  collapse_fields(return_fields)
10
13
  end
@@ -16,7 +19,7 @@ module ModsDisplay
16
19
  private
17
20
 
18
21
  def description_fields
19
- @values.children.select do |child|
22
+ @stanford_mods_elements.children.select do |child|
20
23
  labels.keys.include?(child.name.to_sym)
21
24
  end
22
25
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ModsDisplay
4
+ class Edition < Field
5
+ def fields
6
+ return_fields = @stanford_mods_elements.map do |origin_info_element|
7
+ edition_value = Stanford::Mods::Imprint.new(origin_info_element).edition_vals_str
8
+ next unless edition_value.present?
9
+
10
+ # remove trailing spaces (thanks MARC, for catalog card formatting!)
11
+ edition_value.gsub!(%r{ */$}, '')
12
+
13
+ ModsDisplay::Values.new(
14
+ label: I18n.t('mods_display.edition'),
15
+ values: [edition_value],
16
+ field: self
17
+ )
18
+ end.compact
19
+ collapse_fields(return_fields)
20
+ end
21
+ end
22
+ end
@@ -3,20 +3,20 @@
3
3
  module ModsDisplay
4
4
  class Extent < Field
5
5
  def fields
6
- return [] unless extent_fields.present?
6
+ return [] unless extent_elements.present?
7
7
 
8
8
  [
9
9
  ModsDisplay::Values.new(
10
10
  label: I18n.t('mods_display.extent'),
11
- values: extent_fields.map { |x| element_text(x) }
11
+ values: extent_elements.map { |x| element_text(x) }
12
12
  )
13
13
  ]
14
14
  end
15
15
 
16
16
  private
17
17
 
18
- def extent_fields
19
- @values.map(&:extent).flatten
18
+ def extent_elements
19
+ @stanford_mods_elements.map(&:extent).flatten
20
20
  end
21
21
  end
22
22
  end
@@ -1,16 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ModsDisplay
4
+ # superclass for processing stanford-mods elements into ModsDisplay::Values retrieved by the fields method
5
+ # by consuming applications.
4
6
  class Field
5
- def initialize(values)
6
- @values = values
7
+ # @stanford_mods_elements is an array of Nokogiri::XML::Element-ish objects from stanford-mods
8
+ # per ModsDisplay::HTML::MODS_DISPLAY_FIELD_MAPPING
9
+ def initialize(stanford_mods_elements)
10
+ @stanford_mods_elements = stanford_mods_elements
7
11
  end
8
12
 
9
13
  def fields
10
- return_fields = @values.map do |value|
14
+ return_fields = @stanford_mods_elements.map do |stanford_mods_element|
11
15
  ModsDisplay::Values.new(
12
- label: displayLabel(value) || label,
13
- values: [element_text(value)],
16
+ label: displayLabel(stanford_mods_element) || label,
17
+ values: [element_text(stanford_mods_element)],
14
18
  field: self
15
19
  )
16
20
  end
@@ -18,9 +22,9 @@ module ModsDisplay
18
22
  end
19
23
 
20
24
  def label
21
- return nil if @values.nil?
25
+ return nil if @stanford_mods_elements.nil?
22
26
 
23
- displayLabel(@values.first)
27
+ displayLabel(@stanford_mods_elements.first)
24
28
  end
25
29
 
26
30
  def to_html(view_context = ApplicationController.renderer)
@@ -50,12 +54,54 @@ module ModsDisplay
50
54
  display_fields.slice_when { |before, after| before.label != after.label }.map do |group|
51
55
  next group.first if group.length == 1
52
56
 
53
- ModsDisplay::Values.new(label: group.first.label, values: group.map(&:values).flatten(1))
57
+ ModsDisplay::Values.new(
58
+ label: group.first.label,
59
+ values: group.map(&:values).flatten(1)
60
+ )
54
61
  end
55
62
  end
56
63
 
57
64
  def element_text(element)
58
65
  element.xpath('.//text()').to_html.strip
59
66
  end
67
+
68
+ # used for originInfo date fields, e.g. DateCreated, DateIssued ...
69
+ def date_fields(date_symbol)
70
+ return_fields = @stanford_mods_elements.map do |origin_info_element|
71
+ date_values = Stanford::Mods::Imprint.new(origin_info_element).dates([date_symbol])
72
+ next unless date_values.present?
73
+
74
+ ModsDisplay::Values.new(
75
+ label: I18n.t("mods_display.#{date_symbol.to_s.underscore}"),
76
+ values: select_best_date(date_values),
77
+ field: self
78
+ )
79
+ end.compact
80
+ collapse_fields(return_fields)
81
+ end
82
+
83
+ # used for originInfo dates, e.g. for Imprint, DateCreated, DateIssued, etc.
84
+ def select_best_date(dates)
85
+ # ensure dates are unique with respect to their base values
86
+ dates = dates.group_by(&:base_value).map do |_value, group|
87
+ group.first if group.one?
88
+
89
+ # if one of the duplicates wasn't encoded, use that one (see:
90
+ # https://consul.stanford.edu/display/chimera/MODS+display+rules#MODSdisplayrules-3b.%3CoriginInfo%3E),
91
+ # otherwise just randomly pick the last in the group
92
+ group.reject(&:encoding).first || group.last
93
+ end
94
+
95
+ # if any single dates are already part of a range, discard them
96
+ range_base_values = dates.select { |date| date.is_a?(Stanford::Mods::Imprint::DateRange) }
97
+ .map(&:base_values).flatten
98
+ dates = dates.reject { |date| range_base_values.include?(date.base_value) }
99
+
100
+ # for DateOther field (but not for Imprint field), include the type attribute value in parens
101
+ return dates.map { |date| qualified_value_with_type(date) } if instance_of?(ModsDisplay::DateOther)
102
+
103
+ # output formatted dates with qualifiers, CE/BCE, etc.
104
+ dates.map(&:qualified_value)
105
+ end
60
106
  end
61
107
  end
@@ -3,20 +3,20 @@
3
3
  module ModsDisplay
4
4
  class Form < Field
5
5
  def fields
6
- return [] unless form_fields.present?
6
+ return [] unless form_elements.present?
7
7
 
8
8
  [
9
9
  ModsDisplay::Values.new(
10
10
  label: I18n.t('mods_display.form'),
11
- values: form_fields.map { |x| element_text(x) }.uniq { |x| x.downcase.gsub(/\s/, '').gsub(/[[:punct:]]/, '') }
11
+ values: form_elements.map { |x| element_text(x) }.uniq { |x| x.downcase.gsub(/\s/, '').gsub(/[[:punct:]]/, '') }
12
12
  )
13
13
  ]
14
14
  end
15
15
 
16
16
  private
17
17
 
18
- def form_fields
19
- @values.map(&:form).flatten
18
+ def form_elements
19
+ @stanford_mods_elements.map(&:form).flatten
20
20
  end
21
21
  end
22
22
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ModsDisplay
4
+ class Frequency < Field
5
+ def fields
6
+ return_fields = @stanford_mods_elements.map do |origin_info_element|
7
+ frequency_value = origin_info_element.frequency&.text&.strip
8
+ next unless frequency_value.present?
9
+
10
+ ModsDisplay::Values.new(
11
+ label: I18n.t('mods_display.frequency'),
12
+ values: [frequency_value],
13
+ field: self
14
+ )
15
+ end.compact
16
+ collapse_fields(return_fields)
17
+ end
18
+ end
19
+ end
@@ -3,8 +3,11 @@
3
3
  module ModsDisplay
4
4
  class Genre < Field
5
5
  def fields
6
- return_fields = @values.map do |value|
7
- ModsDisplay::Values.new(label: displayLabel(value) || label, values: [element_text(value).capitalize].flatten)
6
+ return_fields = @stanford_mods_elements.map do |genre_element|
7
+ ModsDisplay::Values.new(
8
+ label: displayLabel(genre_element) || label,
9
+ values: [element_text(genre_element).capitalize].flatten
10
+ )
8
11
  end
9
12
  collapse_fields(return_fields)
10
13
  end
@@ -25,8 +25,8 @@ module ModsDisplay
25
25
  end
26
26
 
27
27
  def geo_extensions
28
- @geo_values ||= @values.select do |value|
29
- displayLabel(value) =~ /^geo:?$/
28
+ @geo_values ||= @stanford_mods_elements.select do |extension_element|
29
+ displayLabel(extension_element) =~ /^geo:?$/
30
30
  end
31
31
  end
32
32
  end