cocina_display 0.4.0 → 0.6.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.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocina_display
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Budak
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-07-09 00:00:00.000000000 Z
11
+ date: 2025-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: janeway-jsonpath
@@ -28,22 +28,16 @@ dependencies:
28
28
  name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '8.0'
34
31
  - - ">="
35
32
  - !ruby/object:Gem::Version
36
- version: 8.0.2
33
+ version: '7'
37
34
  type: :runtime
38
35
  prerelease: false
39
36
  version_requirements: !ruby/object:Gem::Requirement
40
37
  requirements:
41
- - - "~>"
42
- - !ruby/object:Gem::Version
43
- version: '8.0'
44
38
  - - ">="
45
39
  - !ruby/object:Gem::Version
46
- version: 8.0.2
40
+ version: '7'
47
41
  - !ruby/object:Gem::Dependency
48
42
  name: edtf
49
43
  requirement: !ruby/object:Gem::Requirement
@@ -162,6 +156,20 @@ dependencies:
162
156
  - - ">="
163
157
  - !ruby/object:Gem::Version
164
158
  version: 1.9.1
159
+ - !ruby/object:Gem::Dependency
160
+ name: purl_fetcher-client
161
+ requirement: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - "~>"
164
+ - !ruby/object:Gem::Version
165
+ version: '3.1'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - "~>"
171
+ - !ruby/object:Gem::Version
172
+ version: '3.1'
165
173
  description:
166
174
  email:
167
175
  - budak@stanford.edu
@@ -176,18 +184,26 @@ files:
176
184
  - Rakefile
177
185
  - lib/cocina_display.rb
178
186
  - lib/cocina_display/cocina_record.rb
187
+ - lib/cocina_display/concerns/access.rb
179
188
  - lib/cocina_display/concerns/contributors.rb
180
189
  - lib/cocina_display/concerns/events.rb
190
+ - lib/cocina_display/concerns/forms.rb
181
191
  - lib/cocina_display/concerns/identifiers.rb
192
+ - lib/cocina_display/concerns/subjects.rb
182
193
  - lib/cocina_display/concerns/titles.rb
183
194
  - lib/cocina_display/contributor.rb
184
195
  - lib/cocina_display/dates/date.rb
185
196
  - lib/cocina_display/dates/date_range.rb
186
- - lib/cocina_display/imprint.rb
197
+ - lib/cocina_display/events/event.rb
198
+ - lib/cocina_display/events/imprint.rb
199
+ - lib/cocina_display/events/location.rb
187
200
  - lib/cocina_display/marc_country_codes.rb
201
+ - lib/cocina_display/marc_relator_codes.rb
202
+ - lib/cocina_display/subject.rb
188
203
  - lib/cocina_display/title_builder.rb
189
204
  - lib/cocina_display/utils.rb
190
205
  - lib/cocina_display/version.rb
206
+ - script/find_records.rb
191
207
  - sig/cocina_display.rbs
192
208
  homepage: https://sul-dlss.github.io/cocina_display/
193
209
  licenses:
@@ -1,123 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "edtf"
4
- require "active_support"
5
- require "active_support/core_ext/enumerable"
6
- require "active_support/core_ext/object/blank"
7
-
8
- require_relative "utils"
9
- require_relative "marc_country_codes"
10
- require_relative "dates/date"
11
- require_relative "dates/date_range"
12
-
13
- module CocinaDisplay
14
- # Wrapper for Cocina events used to generate an imprint statement for display.
15
- class Imprint
16
- # Parse Cocina dates and convert any non-single dates to DateRange objects.
17
- # This ensures that we can correctly deduplicate ranges against single dates.
18
- # @param cocina_dates [Array<Hash>] Array of Cocina date hashes
19
- # @return [Array<CocinaDisplay::Dates::Date | CocinaDisplay::Dates::DateRange>]
20
- def self.parse_dates(cocina_dates)
21
- cocina_dates.map { |cd| CocinaDisplay::Dates::Date.from_cocina(cd) }.filter(&:parsable?).compact
22
- end
23
-
24
- attr_reader :cocina, :dates
25
-
26
- # Initialize the imprint with Cocina event data.
27
- # @param cocina [Hash] Cocina structured data for a single event
28
- def initialize(cocina)
29
- @cocina = cocina
30
- @dates = self.class.parse_dates(Array(cocina["date"]))
31
- end
32
-
33
- # The entire imprint statement formatted as a string for display.
34
- # @return [String]
35
- def display_str
36
- place_pub = Utils.compact_and_join([place_str, publisher_str], delimiter: " : ")
37
- edition_place_pub = Utils.compact_and_join([edition_str, place_pub], delimiter: " - ")
38
- Utils.compact_and_join([edition_place_pub, date_str], delimiter: ", ")
39
- end
40
-
41
- # Were any of the dates encoded?
42
- # Used to detect which event(s) most likely represent the actual imprint(s).
43
- def date_encoding?
44
- @dates.any?(&:encoding?)
45
- end
46
-
47
- private
48
-
49
- # The date portion of the imprint statement, comprising all unique dates.
50
- # @return [String]
51
- def date_str
52
- Utils.compact_and_join(unique_dates_for_display.map(&:qualified_value))
53
- end
54
-
55
- # The editions portion of the imprint statement, combining all edition notes.
56
- # @return [String]
57
- def edition_str
58
- Utils.compact_and_join(Janeway.enum_for("$.note[?@.type == 'edition'].value", cocina))
59
- end
60
-
61
- # The place of publication, combining all location values.
62
- # @return [String]
63
- def place_str
64
- Utils.compact_and_join(locations_for_display, delimiter: " : ")
65
- end
66
-
67
- # The publisher information, combining all name values for publishers.
68
- # @return [String]
69
- def publisher_str
70
- Utils.compact_and_join(Janeway.enum_for("$.contributor[?@.role[?@.value == 'publisher']].name[*].value", cocina), delimiter: " : ")
71
- end
72
-
73
- # Get the place name for a location, decoding from MARC if necessary.
74
- # Ignores the unknown/"various locations" country codes and returns nil.
75
- # @param location [Hash] A location hash parsed from Cocina
76
- # @return [String] The decoded location name
77
- # @return [nil] If no valid location value is found
78
- def decoded_location(location)
79
- return location["value"] if location["value"].present?
80
-
81
- if location.dig("source", "code") == "marccountry" &&
82
- location["code"].present? &&
83
- ["xx", "vp"].exclude?(location["code"])
84
- CocinaDisplay::MARC_COUNTRY[location["code"]]
85
- end
86
- end
87
-
88
- # Filter locations to display according to predefined rules.
89
- # 1. Prefer unencoded locations (plain value) over encoded ones
90
- # 2. If no unencoded locations but there are MARC country codes, decode them
91
- # 3. Keep only unique locations after decoding
92
- def locations_for_display
93
- unencoded_locs, encoded_locs = Array(cocina["location"]).partition { |loc| loc["value"].present? }
94
- locs_for_display = unencoded_locs.presence || encoded_locs
95
- locs_for_display.map { |loc| decoded_location(loc) }.compact_blank.uniq
96
- end
97
-
98
- # Filter dates for uniqueness using base value according to predefined rules.
99
- # 1. For a group of dates with the same base value, choose a single one
100
- # 2. Prefer unencoded dates over encoded ones when choosing a single date
101
- # 3. Remove date ranges that duplicate any unencoded non-range dates
102
- # @return [Array<CocinaDisplay::Dates::Date>]
103
- # @see CocinaDisplay::Dates::Date#base_value
104
- # @see https://consul.stanford.edu/display/chimera/MODS+display+rules#MODSdisplayrules-3b.%3CoriginInfo%3E
105
- def unique_dates_for_display
106
- # Choose a single date for each group with the same base value
107
- deduped_dates = dates.group_by(&:base_value).map do |base_value, group|
108
- if (unencoded = group.reject(&:encoding?)).any?
109
- unencoded.first
110
- else
111
- group.first
112
- end
113
- end
114
-
115
- # Remove any ranges that duplicate part of an unencoded non-range date
116
- ranges, singles = deduped_dates.partition { |date| date.is_a?(CocinaDisplay::Dates::DateRange) }
117
- unencoded_singles_dates = singles.reject(&:encoding?).flat_map(&:to_a)
118
- ranges.reject! { |range| unencoded_singles_dates.any? { |date| range.as_interval.include?(date) } }
119
-
120
- (singles + ranges).sort
121
- end
122
- end
123
- end