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.
- checksums.yaml +4 -4
- data/README.md +21 -16
- data/lib/cocina_display/cocina_record.rb +33 -72
- data/lib/cocina_display/concerns/access.rb +71 -0
- data/lib/cocina_display/concerns/contributors.rb +60 -41
- data/lib/cocina_display/concerns/events.rb +51 -25
- data/lib/cocina_display/concerns/forms.rb +134 -0
- data/lib/cocina_display/concerns/identifiers.rb +11 -3
- data/lib/cocina_display/concerns/subjects.rb +91 -0
- data/lib/cocina_display/contributor.rb +66 -11
- data/lib/cocina_display/dates/date.rb +9 -8
- data/lib/cocina_display/dates/date_range.rb +8 -0
- data/lib/cocina_display/events/event.rb +78 -0
- data/lib/cocina_display/events/imprint.rb +101 -0
- data/lib/cocina_display/events/location.rb +56 -0
- data/lib/cocina_display/marc_relator_codes.rb +314 -0
- data/lib/cocina_display/subject.rb +127 -0
- data/lib/cocina_display/title_builder.rb +2 -1
- data/lib/cocina_display/utils.rb +45 -6
- data/lib/cocina_display/version.rb +1 -1
- data/script/find_records.rb +85 -0
- metadata +27 -11
- data/lib/cocina_display/imprint.rb +0 -123
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
|
+
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-
|
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:
|
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:
|
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/
|
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
|