cocina_display 1.6.0 → 1.7.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 +1 -1
- data/lib/cocina_display/cocina_record.rb +2 -1
- data/lib/cocina_display/concerns/contributors.rb +5 -6
- data/lib/cocina_display/concerns/events.rb +10 -3
- data/lib/cocina_display/concerns/structural.rb +12 -0
- data/lib/cocina_display/concerns/titles.rb +3 -3
- data/lib/cocina_display/contributors/contributor.rb +7 -0
- data/lib/cocina_display/events/location.rb +7 -7
- data/lib/cocina_display/json_backed_record.rb +19 -1
- data/lib/cocina_display/title.rb +22 -30
- data/lib/cocina_display/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 46cfe681a820ad5986d0503157b5add9a8cb089af31e3afaba0ed2964d33bda6
|
|
4
|
+
data.tar.gz: b60af2ecc9cfdc031e57ae98cb1093aa3b111a5c14dda40b71814e07a9f2d941
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2c010edefb699c21c82a3c426befcb16e4fa0e72aeeda6e77c2ed8eba9fa1aa6e365e889fda6f94f6d118a3bde2a968e4ece610f918995721c14a1fc6fc5b723
|
|
7
|
+
data.tar.gz: fa61cbcd25787c2ec552fff17f5282e425ff5b46d03f0b60476c017faab41f7f059bd7630e54c2fc753a6330cf87a41c12bda20fbd3bd602e567264cfa6b133b
|
data/README.md
CHANGED
|
@@ -40,7 +40,7 @@ There is also a helper method to fetch the Cocina JSON for a given DRUID over HT
|
|
|
40
40
|
The `CocinaRecord` class provides some methods to access common fields, as well as an underlying hash representation parsed from the JSON.
|
|
41
41
|
|
|
42
42
|
```ruby
|
|
43
|
-
> record.
|
|
43
|
+
> record.short_title
|
|
44
44
|
=> "Bugatti Type 51A. Road & Track Salon January 1957"
|
|
45
45
|
> record.content_type
|
|
46
46
|
=> "image"
|
|
@@ -60,7 +60,8 @@ module CocinaDisplay
|
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
# Primary processing label for the object.
|
|
63
|
-
# @note
|
|
63
|
+
# @note For public Cocina fetched via PURL, this is generated at publish time from the title. It will have the same value as #display_title.
|
|
64
|
+
# @see https://github.com/sul-dlss/cocina_display/issues/205#issuecomment-3781393715
|
|
64
65
|
# @return [String, nil]
|
|
65
66
|
def label
|
|
66
67
|
cocina_doc["label"]
|
|
@@ -108,13 +108,11 @@ module CocinaDisplay
|
|
|
108
108
|
end
|
|
109
109
|
|
|
110
110
|
# All contributors for the object, including authors, editors, etc.
|
|
111
|
-
#
|
|
111
|
+
# @note Does not include contributors attached to events.
|
|
112
112
|
# @return [Array<Contributor>]
|
|
113
113
|
def contributors
|
|
114
|
-
@contributors ||=
|
|
115
|
-
|
|
116
|
-
path("$.description.event.*.contributor.*")
|
|
117
|
-
).map { |c| CocinaDisplay::Contributors::Contributor.new(c) }
|
|
114
|
+
@contributors ||= path("$.description.contributor.*")
|
|
115
|
+
.map { |c| CocinaDisplay::Contributors::Contributor.new(c) }
|
|
118
116
|
end
|
|
119
117
|
|
|
120
118
|
# All contributors with an "author" role.
|
|
@@ -142,7 +140,8 @@ module CocinaDisplay
|
|
|
142
140
|
contributors.find(&:primary?).presence || contributors.find { |c| !c.role? }.presence || contributors.first
|
|
143
141
|
end
|
|
144
142
|
|
|
145
|
-
#
|
|
143
|
+
# Contributors other than the main contributor.
|
|
144
|
+
# Also excludes the contributor (usually publisher) coming from an imprint event.
|
|
146
145
|
# @return [Array<Contributor>]
|
|
147
146
|
def additional_contributors
|
|
148
147
|
return [] if contributors.empty? || contributors.one?
|
|
@@ -63,8 +63,8 @@ module CocinaDisplay
|
|
|
63
63
|
# String for displaying the imprint statement(s).
|
|
64
64
|
# @return [String, nil]
|
|
65
65
|
# @see CocinaDisplay::Imprint#to_s
|
|
66
|
-
# @example
|
|
67
|
-
#
|
|
66
|
+
# @example bt553vr2845
|
|
67
|
+
# "New York : Meridian Book, 1993, c1967"
|
|
68
68
|
def imprint_str
|
|
69
69
|
imprint_events.map(&:to_s).compact_blank.join("; ")
|
|
70
70
|
end
|
|
@@ -73,7 +73,14 @@ module CocinaDisplay
|
|
|
73
73
|
# Considers locations for all publication, creation, and capture events.
|
|
74
74
|
# @return [Array<String>]
|
|
75
75
|
def publication_places
|
|
76
|
-
publication_events.flat_map { |event| event.locations.map(&:to_s) }
|
|
76
|
+
publication_events.flat_map { |event| event.locations.map(&:to_s) }.compact_blank.uniq
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# List of countries of publication as strings.
|
|
80
|
+
# Considers locations for all publication, creation, and capture events.
|
|
81
|
+
# @return [Array<String>]
|
|
82
|
+
def publication_countries
|
|
83
|
+
publication_events.flat_map { |event| event.locations.map(&:country_name) }.compact_blank.uniq
|
|
77
84
|
end
|
|
78
85
|
|
|
79
86
|
# All root level events associated with the object.
|
|
@@ -43,6 +43,18 @@ module CocinaDisplay
|
|
|
43
43
|
def containing_collections
|
|
44
44
|
path("$.structural.isMemberOf.*").map { |druid| druid.delete_prefix("druid:") }
|
|
45
45
|
end
|
|
46
|
+
|
|
47
|
+
def virtual_object?
|
|
48
|
+
return false if path("$.structural.contains.*").any?
|
|
49
|
+
|
|
50
|
+
path("$.structural.hasMemberOrders.*.members.*").any?
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def virtual_object_members
|
|
54
|
+
return [] unless virtual_object?
|
|
55
|
+
|
|
56
|
+
path("$.structural.hasMemberOrders.*.members.*").map { |druid| druid.delete_prefix("druid:") }
|
|
57
|
+
end
|
|
46
58
|
end
|
|
47
59
|
end
|
|
48
60
|
end
|
|
@@ -2,11 +2,11 @@ module CocinaDisplay
|
|
|
2
2
|
module Concerns
|
|
3
3
|
# Methods for finding and formatting titles.
|
|
4
4
|
module Titles
|
|
5
|
-
# The
|
|
5
|
+
# The short title for the object, without subtitle, part name, etc.
|
|
6
6
|
# If there are multiple primary titles, uses the first.
|
|
7
|
-
# @see CocinaDisplay::Title#
|
|
7
|
+
# @see CocinaDisplay::Title#short_title
|
|
8
8
|
# @return [String, nil]
|
|
9
|
-
def
|
|
9
|
+
def short_title
|
|
10
10
|
primary_title&.short_title
|
|
11
11
|
end
|
|
12
12
|
|
|
@@ -72,6 +72,13 @@ module CocinaDisplay
|
|
|
72
72
|
roles.any?
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
+
# String representation of the contributor's role(s).
|
|
76
|
+
# @return [String, nil]
|
|
77
|
+
# @example "author, editor, publisher"
|
|
78
|
+
def display_role
|
|
79
|
+
roles.map(&:to_s).join(", ") if role?
|
|
80
|
+
end
|
|
81
|
+
|
|
75
82
|
# The primary display name for the contributor as a string.
|
|
76
83
|
# @param with_date [Boolean] Include life dates, if present
|
|
77
84
|
# @return [String, nil]
|
|
@@ -22,7 +22,7 @@ module CocinaDisplay
|
|
|
22
22
|
# Decodes a MARC country code if present and no value was present.
|
|
23
23
|
# @return [String, nil]
|
|
24
24
|
def to_s
|
|
25
|
-
cocina["value"] ||
|
|
25
|
+
cocina["value"] || country_name
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
# Is there an unencoded value (name) for this location?
|
|
@@ -31,6 +31,12 @@ module CocinaDisplay
|
|
|
31
31
|
cocina["value"].present?
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
# Decoded country name if the location is encoded with a MARC country code.
|
|
35
|
+
# @return [String, nil]
|
|
36
|
+
def country_name
|
|
37
|
+
Location.marc_countries[code] if marc_country? && valid_country_code?
|
|
38
|
+
end
|
|
39
|
+
|
|
34
40
|
private
|
|
35
41
|
|
|
36
42
|
# A code, like a MARC country code, representing the location.
|
|
@@ -39,12 +45,6 @@ module CocinaDisplay
|
|
|
39
45
|
cocina["code"]
|
|
40
46
|
end
|
|
41
47
|
|
|
42
|
-
# Decoded country name if the location is encoded with a MARC country code.
|
|
43
|
-
# @return [String, nil]
|
|
44
|
-
def decoded_country
|
|
45
|
-
Location.marc_countries[code] if marc_country? && valid_country_code?
|
|
46
|
-
end
|
|
47
|
-
|
|
48
48
|
# Is this a decodable country code?
|
|
49
49
|
# Excludes blank values and "xx" (unknown) and "vp" (various places).
|
|
50
50
|
# @return [Boolean]
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module CocinaDisplay
|
|
4
|
+
# Superclass for metadata records backed by a Cocina JSON document.
|
|
4
5
|
class JsonBackedRecord
|
|
5
6
|
# The parsed Cocina document.
|
|
6
7
|
# @return [Hash]
|
|
7
8
|
attr_reader :cocina_doc
|
|
8
9
|
|
|
9
|
-
# Initialize a
|
|
10
|
+
# Initialize a record with a Cocina document hash.
|
|
10
11
|
# @param cocina_doc [Hash]
|
|
11
12
|
def initialize(cocina_doc)
|
|
12
13
|
@cocina_doc = cocina_doc
|
|
@@ -23,5 +24,22 @@ module CocinaDisplay
|
|
|
23
24
|
def path(path_expression)
|
|
24
25
|
Janeway.enum_for(path_expression, cocina_doc)
|
|
25
26
|
end
|
|
27
|
+
|
|
28
|
+
# Flattened, normalized aggregation of all node texts in the Cocina document.
|
|
29
|
+
# @note Used for 'all search' fields in indexing.
|
|
30
|
+
# @return [String]
|
|
31
|
+
def text
|
|
32
|
+
node_texts.compact.join(" ").gsub(/\s+/, " ").strip
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
# Array of all node values/codes except those under "source" keys.
|
|
38
|
+
# Used to build flattened text representation.
|
|
39
|
+
# @note Source values are omitted because they usually indicate ontologies/vocabularies.
|
|
40
|
+
# @return [Array<String>]
|
|
41
|
+
def node_texts
|
|
42
|
+
path("$..['code', 'value']").map { |node, _p, _i, path| node unless path.to_s.include?("['source']") }
|
|
43
|
+
end
|
|
26
44
|
end
|
|
27
45
|
end
|
data/lib/cocina_display/title.rb
CHANGED
|
@@ -61,15 +61,14 @@ module CocinaDisplay
|
|
|
61
61
|
# The long form of the title, including subtitle, part name, etc.
|
|
62
62
|
# @note This corresponds to the entire MARC 245 field.
|
|
63
63
|
# @return [String, nil]
|
|
64
|
-
# @example "M. de Courville [estampe]"
|
|
64
|
+
# @example "M. de Courville : [estampe]"
|
|
65
65
|
def full_title
|
|
66
66
|
full_title_str.presence || cocina["value"]
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
-
# The long form of the title,
|
|
69
|
+
# The long form of the title, without trailing punctuation.
|
|
70
70
|
# @note This corresponds to the entire MARC 245 field.
|
|
71
71
|
# @return [String, nil]
|
|
72
|
-
# @example "M. de Courville : [estampe]"
|
|
73
72
|
def display_title
|
|
74
73
|
display_title_str.presence || cocina["value"]
|
|
75
74
|
end
|
|
@@ -81,7 +80,7 @@ module CocinaDisplay
|
|
|
81
80
|
def sort_title
|
|
82
81
|
return "\u{10FFFF}" unless full_title
|
|
83
82
|
|
|
84
|
-
|
|
83
|
+
full_title[nonsorting_chars_str.length..]
|
|
85
84
|
.unicode_normalize(:nfd) # Prevent accents being stripped
|
|
86
85
|
.gsub(/[[:punct:]]*/, "")
|
|
87
86
|
.gsub(/\W{2,}/, " ") # Collapse whitespace after removing punctuation
|
|
@@ -90,37 +89,33 @@ module CocinaDisplay
|
|
|
90
89
|
|
|
91
90
|
private
|
|
92
91
|
|
|
93
|
-
# Generate the short title by joining main title and nonsorting characters
|
|
92
|
+
# Generate the short title by joining main title and nonsorting characters.
|
|
94
93
|
# @return [String, nil]
|
|
95
94
|
def short_title_str
|
|
96
|
-
|
|
95
|
+
nonsorting_chars_str + main_title_str # pre-formatted padding
|
|
97
96
|
end
|
|
98
97
|
|
|
99
|
-
# Generate the full title by joining all title components with
|
|
98
|
+
# Generate the full title by joining all title components with punctuation.
|
|
100
99
|
# @return [String, nil]
|
|
101
100
|
def full_title_str
|
|
102
|
-
|
|
101
|
+
title_str = main_subtitle_str
|
|
102
|
+
title_str = Utils.compact_and_join([main_subtitle_str, parts_str], delimiter: ". ") unless main_subtitle_str.end_with?(parts_str)
|
|
103
|
+
title_str = nonsorting_chars_str + title_str # pre-formatted padding
|
|
104
|
+
title_str = Utils.compact_and_join([names_str, title_str], delimiter: ". ") if names_str.present?
|
|
105
|
+
title_str += "." unless title_str&.match?(/[[:punct:]]\z/)
|
|
106
|
+
title_str.presence
|
|
103
107
|
end
|
|
104
108
|
|
|
105
|
-
#
|
|
106
|
-
# @return [String]
|
|
107
|
-
def
|
|
108
|
-
|
|
109
|
+
# Generate the display title by stripping trailing punctuation from the full title.
|
|
110
|
+
# @return [String, nil]
|
|
111
|
+
def display_title_str
|
|
112
|
+
full_title_str&.sub(/[\.,;:\/\\]+\z/, "")
|
|
109
113
|
end
|
|
110
114
|
|
|
111
|
-
#
|
|
112
|
-
# - Join main title and subtitle with " : "
|
|
113
|
-
# - Join part name/number/label with ", "
|
|
114
|
-
# - Join part string with preceding title with ". "
|
|
115
|
-
# - Prepend preformatted nonsorting characters
|
|
116
|
-
# - Prepend associated names with ". "
|
|
115
|
+
# The main title and subtitle, joined together with a colon.
|
|
117
116
|
# @return [String, nil]
|
|
118
|
-
def
|
|
119
|
-
|
|
120
|
-
title_str = Utils.compact_and_join([title_str, parts_str(delimiter: ", ")], delimiter: ". ")
|
|
121
|
-
title_str = nonsorting_chars_str + title_str # pre-formatted padding
|
|
122
|
-
title_str = Utils.compact_and_join([names_str, title_str], delimiter: ". ") if names_str.present?
|
|
123
|
-
title_str.presence
|
|
117
|
+
def main_subtitle_str
|
|
118
|
+
Utils.compact_and_join([main_title_str, subtitle_str], delimiter: " : ")
|
|
124
119
|
end
|
|
125
120
|
|
|
126
121
|
# All nonsorting characters joined together with padding applied.
|
|
@@ -142,15 +137,14 @@ module CocinaDisplay
|
|
|
142
137
|
Utils.compact_and_join(Array(title_components["subtitle"]))
|
|
143
138
|
end
|
|
144
139
|
|
|
145
|
-
# The part name, number, and label components, joined together.
|
|
146
|
-
# Default delimiter is a space, but can be overridden.
|
|
140
|
+
# The part name, number, and label components, joined together with commas.
|
|
147
141
|
# @return [String, nil]
|
|
148
|
-
def parts_str
|
|
142
|
+
def parts_str
|
|
149
143
|
Utils.compact_and_join(
|
|
150
144
|
Array(title_components["part number"] || @part_numbers) +
|
|
151
145
|
Array(title_components["part name"]) +
|
|
152
146
|
[@part_label],
|
|
153
|
-
delimiter:
|
|
147
|
+
delimiter: ", "
|
|
154
148
|
)
|
|
155
149
|
end
|
|
156
150
|
|
|
@@ -198,8 +192,6 @@ module CocinaDisplay
|
|
|
198
192
|
I18n.t(type&.parameterize&.underscore, scope: "cocina_display.field_label.title", default: :title)
|
|
199
193
|
end
|
|
200
194
|
|
|
201
|
-
private
|
|
202
|
-
|
|
203
195
|
# Add or remove padding from nonsorting portion of the title.
|
|
204
196
|
# @param value [String]
|
|
205
197
|
# @return [String]
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cocina_display
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nick Budak
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: janeway-jsonpath
|
|
@@ -296,7 +296,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
296
296
|
- !ruby/object:Gem::Version
|
|
297
297
|
version: '0'
|
|
298
298
|
requirements: []
|
|
299
|
-
rubygems_version:
|
|
299
|
+
rubygems_version: 4.0.4
|
|
300
300
|
specification_version: 4
|
|
301
301
|
summary: Helpers for rendering Cocina metadata
|
|
302
302
|
test_files: []
|