arclight 1.0.0 → 1.6.2
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/.github/workflows/ruby.yml +22 -15
- data/.gitignore +1 -0
- data/.rubocop.yml +185 -26
- data/.solr_wrapper +2 -1
- data/README.md +4 -8
- data/app/assets/stylesheets/arclight/application.scss +1 -0
- data/app/assets/stylesheets/arclight/build.scss +4 -0
- data/app/assets/stylesheets/arclight/modules/hierarchy_and_online_contents.scss +22 -18
- data/app/assets/stylesheets/arclight/modules/icons.scss +9 -4
- data/app/assets/stylesheets/arclight/modules/layout.scss +23 -14
- data/app/assets/stylesheets/arclight/modules/mastheads.scss +14 -45
- data/app/assets/stylesheets/arclight/modules/search_form.scss +9 -0
- data/app/assets/stylesheets/arclight/modules/search_results.scss +15 -16
- data/app/assets/stylesheets/arclight/modules/truncator.scss +2 -0
- data/app/components/arclight/access_component.rb +1 -1
- data/app/components/arclight/bookmark_component.html.erb +1 -1
- data/app/components/arclight/breadcrumb_component.rb +17 -7
- data/app/components/arclight/breadcrumbs_hierarchy_component.html.erb +2 -2
- data/app/components/arclight/breadcrumbs_hierarchy_component.rb +1 -1
- data/app/components/arclight/collection_context_component.rb +1 -1
- data/app/components/arclight/collection_info_component.rb +1 -1
- data/app/components/arclight/collection_sidebar_component.rb +2 -4
- data/app/components/arclight/document_collection_hierarchy_component.html.erb +8 -4
- data/app/components/arclight/document_component.html.erb +1 -1
- data/app/components/arclight/document_components_hierarchy_component.html.erb +5 -17
- data/app/components/arclight/document_components_hierarchy_component.rb +7 -1
- data/app/components/arclight/document_download_component.rb +1 -1
- data/app/components/arclight/embed_component.rb +2 -2
- data/app/components/arclight/expand_hierarchy_button_component.html.erb +5 -0
- data/app/components/arclight/expand_hierarchy_button_component.rb +16 -0
- data/app/components/arclight/group_component.html.erb +6 -2
- data/app/components/arclight/group_component.rb +1 -1
- data/app/components/arclight/index_metadata_field_component.html.erb +1 -2
- data/app/components/arclight/masthead_component.html.erb +8 -6
- data/app/components/arclight/metadata_section_component.rb +1 -1
- data/app/components/arclight/oembed_viewer_component.rb +1 -1
- data/app/components/arclight/online_content_filter_component.html.erb +1 -1
- data/app/components/arclight/online_content_filter_component.rb +2 -4
- data/app/components/arclight/online_status_indicator_component.rb +1 -1
- data/app/components/arclight/repository_breadcrumb_component.html.erb +1 -1
- data/app/components/arclight/repository_breadcrumb_component.rb +1 -1
- data/app/components/arclight/repository_location_component.html.erb +2 -2
- data/app/components/arclight/search_bar_component.html.erb +3 -1
- data/app/components/arclight/search_bar_component.rb +1 -1
- data/app/components/arclight/search_result_breadcrumbs_component.html.erb +6 -3
- data/app/components/arclight/search_result_title_component.html.erb +5 -3
- data/app/helpers/arclight/ead_format_helpers.rb +87 -0
- data/app/helpers/arclight_helper.rb +11 -0
- data/app/models/arclight/document_downloads.rb +1 -1
- data/app/models/arclight/parent.rb +3 -10
- data/app/models/arclight/parents.rb +6 -4
- data/app/models/concerns/arclight/solr_document.rb +14 -4
- data/app/views/catalog/_document_list.html.erb +8 -0
- data/app/views/catalog/_group.html.erb +1 -1
- data/app/views/shared/_main_menu_links.html.erb +1 -1
- data/arclight.gemspec +1 -2
- data/lib/arclight/normalized_date.rb +5 -10
- data/lib/arclight/normalized_id.rb +4 -2
- data/lib/arclight/repository.rb +1 -1
- data/lib/arclight/traject/ead2_component_config.rb +57 -14
- data/lib/arclight/traject/ead2_config.rb +57 -15
- data/lib/arclight/version.rb +1 -1
- data/lib/generators/arclight/install_generator.rb +41 -4
- data/lib/generators/arclight/templates/arclight.scss +6 -5
- data/lib/generators/arclight/templates/catalog_controller.rb +48 -5
- data/lib/generators/arclight/templates/config/locales/arclight.en.yml +8 -0
- data/lib/generators/arclight/templates/config/repositories.yml +2 -2
- data/package.json +6 -5
- data/solr/conf/schema.xml +13 -7
- data/solr/conf/solrconfig.xml +61 -44
- data/tasks/arclight.rake +9 -2
- data/template.rb +5 -5
- metadata +18 -21
|
@@ -23,13 +23,34 @@ module Arclight
|
|
|
23
23
|
.scrub!(:strip).to_html
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
+
# rubocop:disable Metrics/AbcSize
|
|
26
27
|
def ead_to_html_scrubber
|
|
27
28
|
Loofah::Scrubber.new do |node|
|
|
28
29
|
format_render_attributes(node) if node.attr('render').present?
|
|
30
|
+
convert_to_span(node) if CONVERT_TO_SPAN_TAGS.include? node.name
|
|
31
|
+
convert_to_br(node) if CONVERT_TO_BR_TAG.include? node.name
|
|
32
|
+
format_links(node) if %w[extptr extref extrefloc ptr ref].include? node.name
|
|
29
33
|
format_lists(node) if %w[list chronlist].include? node.name
|
|
34
|
+
format_indexes(node) if node.name == 'index'
|
|
35
|
+
format_tables(node) if node.name == 'table'
|
|
30
36
|
node
|
|
31
37
|
end
|
|
32
38
|
end
|
|
39
|
+
# rubocop:enable Metrics/AbcSize
|
|
40
|
+
|
|
41
|
+
# Tags that should be converted to <span> tags because of formatting conflicts between XML and HTML
|
|
42
|
+
CONVERT_TO_SPAN_TAGS = ['title'].freeze
|
|
43
|
+
|
|
44
|
+
# Tags that should be converted to HTML <br/> tags
|
|
45
|
+
CONVERT_TO_BR_TAG = ['lb'].freeze
|
|
46
|
+
|
|
47
|
+
def convert_to_span(node)
|
|
48
|
+
node.name = 'span'
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def convert_to_br(node)
|
|
52
|
+
node.name = 'br'
|
|
53
|
+
end
|
|
33
54
|
|
|
34
55
|
def condense_whitespace(str)
|
|
35
56
|
str.squish.strip.gsub(/>[\n\s]+</, '><')
|
|
@@ -91,6 +112,17 @@ module Arclight
|
|
|
91
112
|
end
|
|
92
113
|
end
|
|
93
114
|
|
|
115
|
+
def format_links(node)
|
|
116
|
+
node.remove_attribute('target')
|
|
117
|
+
node.remove_attribute('type')
|
|
118
|
+
if %w[extptr extref extrefloc].include? node.name
|
|
119
|
+
node['target'] = '_blank'
|
|
120
|
+
node['class'] = 'external-link'
|
|
121
|
+
end
|
|
122
|
+
node.content = node['title'] if (%w[extptr ptr].include? node.name) && node['title'].present?
|
|
123
|
+
node.name = 'a' if node['href'].present?
|
|
124
|
+
end
|
|
125
|
+
|
|
94
126
|
def format_lists(node)
|
|
95
127
|
format_simple_lists(node) if node.name == 'list' && node['type'] != 'deflist'
|
|
96
128
|
format_deflists(node) if node.name == 'list' && node['type'] == 'deflist'
|
|
@@ -218,5 +250,60 @@ module Arclight
|
|
|
218
250
|
end
|
|
219
251
|
multi_events.each { |event_node| event_node.name = 'div' }
|
|
220
252
|
end
|
|
253
|
+
|
|
254
|
+
# Format EAD <index> elements
|
|
255
|
+
def format_indexes(node)
|
|
256
|
+
index_head = node.at_css('head')
|
|
257
|
+
index_head&.name = 'h3'
|
|
258
|
+
index_head&.add_class('index-head')
|
|
259
|
+
index_head['id'] = ['index-', index_head.text].join.parameterize if index_head.present?
|
|
260
|
+
format_indexentries(node)
|
|
261
|
+
node.name = 'div'
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# Grab all of the <indexentry> children as a nodeset, move them into
|
|
265
|
+
# a <table>, wrap each entry in a <tr> & each value in a <td>.
|
|
266
|
+
def format_indexentries(node)
|
|
267
|
+
indexentries = node.css('indexentry')
|
|
268
|
+
return if indexentries.blank?
|
|
269
|
+
|
|
270
|
+
indexentries.first.previous = '<table class="table indexentries" />'
|
|
271
|
+
indexentries.map do |i|
|
|
272
|
+
i.parent = node.at_css('table.table.indexentries')
|
|
273
|
+
i.wrap('<tr/>')
|
|
274
|
+
i.element_children.map { |c| c.wrap('<td/>') }
|
|
275
|
+
# Assuming two columns in an index, create a blank cell for entries
|
|
276
|
+
# with a missing value.
|
|
277
|
+
i.add_child('<td/>') if i.element_children.count == 1
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# Format EAD <table> elements, converting <tgroup> to HTML <table>.
|
|
282
|
+
# Ignoring <colspec>, @colname, @colwidth complex rendering
|
|
283
|
+
# logic for now.
|
|
284
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
285
|
+
def format_tables(node)
|
|
286
|
+
node.remove_attribute('frame')
|
|
287
|
+
node.name = 'div' if node.css('tgroup').present?
|
|
288
|
+
format_table_head(node)
|
|
289
|
+
tgroups = node.css('tgroup')
|
|
290
|
+
tgroups&.map do |t|
|
|
291
|
+
t.name = 'table'
|
|
292
|
+
t.remove_attribute('cols')
|
|
293
|
+
t.add_class('table')
|
|
294
|
+
t.css('row').map { |r| r.name = 'tr' }
|
|
295
|
+
t.css('thead entry').map { |e| e.name = 'th' }
|
|
296
|
+
t.css('tbody entry').map { |e| e.name = 'td' }
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
|
300
|
+
|
|
301
|
+
def format_table_head(node)
|
|
302
|
+
table_head = node.at_css('head')
|
|
303
|
+
return if table_head.blank?
|
|
304
|
+
|
|
305
|
+
table_head.name = 'h3'
|
|
306
|
+
table_head.add_class('table-head')
|
|
307
|
+
end
|
|
221
308
|
end
|
|
222
309
|
end
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
module ArclightHelper
|
|
6
6
|
include Arclight::EadFormatHelpers
|
|
7
7
|
include Arclight::FieldConfigHelpers
|
|
8
|
+
include Blacklight::DocumentHelperBehavior
|
|
8
9
|
include Blacklight::LayoutHelperBehavior
|
|
9
10
|
|
|
10
11
|
def repository_collections_path(repository)
|
|
@@ -91,6 +92,16 @@ module ArclightHelper
|
|
|
91
92
|
end
|
|
92
93
|
end
|
|
93
94
|
|
|
95
|
+
##
|
|
96
|
+
# Override of BL core https://github.com/projectblacklight/blacklight/blob/v8.1.0/app/helpers/blacklight/document_helper_behavior.rb#L55
|
|
97
|
+
# Remove document_type check. It isn't a method on arclight documents
|
|
98
|
+
# Check if the document is in the user's bookmarks
|
|
99
|
+
# @param [Blacklight::Document] document
|
|
100
|
+
# @return [Boolean]
|
|
101
|
+
def bookmarked?(document)
|
|
102
|
+
current_bookmarks.any? { |x| x.document_id == document.id }
|
|
103
|
+
end
|
|
104
|
+
|
|
94
105
|
def current_context_document
|
|
95
106
|
@document
|
|
96
107
|
end
|
|
@@ -7,6 +7,9 @@ module Arclight
|
|
|
7
7
|
class Parent
|
|
8
8
|
attr_reader :id, :label, :eadid, :level
|
|
9
9
|
|
|
10
|
+
alias global_id id
|
|
11
|
+
Arclight.deprecation.deprecate_methods(self, global_id: 'Call `id` instead')
|
|
12
|
+
|
|
10
13
|
def initialize(id:, label:, eadid:, level:)
|
|
11
14
|
@id = id
|
|
12
15
|
@label = label
|
|
@@ -17,15 +20,5 @@ module Arclight
|
|
|
17
20
|
def collection?
|
|
18
21
|
level == 'collection'
|
|
19
22
|
end
|
|
20
|
-
|
|
21
|
-
##
|
|
22
|
-
# Concatenates the eadid and the id, to return an "id" in the context of
|
|
23
|
-
# Blacklight and Solr
|
|
24
|
-
# @return [String]
|
|
25
|
-
def global_id
|
|
26
|
-
return id if eadid == id
|
|
27
|
-
|
|
28
|
-
"#{eadid}#{id}"
|
|
29
|
-
end
|
|
30
23
|
end
|
|
31
24
|
end
|
|
@@ -5,10 +5,11 @@ module Arclight
|
|
|
5
5
|
# Object for parsing and formalizing Solr_Ead "Parents"
|
|
6
6
|
# https://github.com/awead/solr_ead/blob/8cf7ffaa66e0e4c9c0b12f5646d6c2e20984cd99/lib/solr_ead/behaviors.rb#L54-L57
|
|
7
7
|
class Parents
|
|
8
|
-
attr_reader :ids, :labels, :levels
|
|
8
|
+
attr_reader :ids, :legacy_ids, :labels, :levels
|
|
9
9
|
|
|
10
|
-
def initialize(ids:, labels:, eadid:, levels:)
|
|
10
|
+
def initialize(ids:, legacy_ids:, labels:, eadid:, levels:)
|
|
11
11
|
@ids = ids
|
|
12
|
+
@legacy_ids = legacy_ids
|
|
12
13
|
@labels = labels
|
|
13
14
|
@eadid = eadid
|
|
14
15
|
@levels = levels
|
|
@@ -21,17 +22,18 @@ module Arclight
|
|
|
21
22
|
##
|
|
22
23
|
# @return [Array[Arclight::Parent]]
|
|
23
24
|
def as_parents
|
|
24
|
-
ids.map.with_index { |id, idx| Arclight::Parent.new(id: id, label: labels[idx], eadid: eadid, level: levels[idx]) }
|
|
25
|
+
(ids.presence || legacy_ids).map.with_index { |id, idx| Arclight::Parent.new(id: id, label: labels[idx], eadid: eadid, level: levels[idx]) }
|
|
25
26
|
end
|
|
26
27
|
|
|
27
28
|
##
|
|
28
29
|
# @param [SolrDocument] document
|
|
29
30
|
def self.from_solr_document(document)
|
|
30
31
|
ids = document.parent_ids
|
|
32
|
+
legacy_ids = document.legacy_parent_ids.map { |legacy_id| document.root == legacy_id ? legacy_id : "#{document.root}#{legacy_id}" }
|
|
31
33
|
labels = document.parent_labels
|
|
32
34
|
eadid = document.eadid
|
|
33
35
|
levels = document.parent_levels
|
|
34
|
-
new(ids: ids, labels: labels, eadid: eadid, levels: levels)
|
|
36
|
+
new(ids: ids, legacy_ids: legacy_ids, labels: labels, eadid: eadid, levels: levels)
|
|
35
37
|
end
|
|
36
38
|
end
|
|
37
39
|
end
|
|
@@ -7,11 +7,15 @@ module Arclight
|
|
|
7
7
|
extend ActiveSupport::Concern
|
|
8
8
|
|
|
9
9
|
included do
|
|
10
|
-
attribute :
|
|
10
|
+
attribute :collection_id, :string, '_root_'
|
|
11
|
+
Arclight.deprecation.deprecate_methods(self, collection_id: 'Use `root` instead')
|
|
12
|
+
attribute :parent_ids, :array, 'parent_ids_ssim'
|
|
13
|
+
attribute :legacy_parent_ids, :array, 'parent_ssim'
|
|
14
|
+
Arclight.deprecation.deprecate_methods(self, legacy_parent_ids: 'Use `parent_ids` instead')
|
|
11
15
|
attribute :parent_labels, :array, 'parent_unittitles_ssm'
|
|
12
16
|
attribute :parent_levels, :array, 'parent_levels_ssm'
|
|
13
17
|
attribute :unitid, :string, 'unitid_ssm'
|
|
14
|
-
attribute :extent, :
|
|
18
|
+
attribute :extent, :array, 'extent_ssm'
|
|
15
19
|
attribute :abstract, :string, 'abstract_html_tesm'
|
|
16
20
|
attribute :scope, :string, 'scopecontent_html_tesm'
|
|
17
21
|
attribute :creator, :string, 'creator_ssm'
|
|
@@ -48,6 +52,7 @@ module Arclight
|
|
|
48
52
|
def normalized_eadid
|
|
49
53
|
Arclight::NormalizedId.new(eadid).to_s
|
|
50
54
|
end
|
|
55
|
+
Arclight.deprecation.deprecate_methods(self, normalized_eadid: 'Use `root` instead')
|
|
51
56
|
|
|
52
57
|
def repository
|
|
53
58
|
first('repository_ssm') || collection&.first('repository_ssm')
|
|
@@ -111,8 +116,13 @@ module Arclight
|
|
|
111
116
|
end
|
|
112
117
|
|
|
113
118
|
def containers
|
|
114
|
-
# NOTE:
|
|
115
|
-
fetch('containers_ssim', []).
|
|
119
|
+
# NOTE: Keep uppercase characters if present, but upcase the first if not already
|
|
120
|
+
containers_field = fetch('containers_ssim', []).reject(&:empty?)
|
|
121
|
+
return [] if containers_field.blank?
|
|
122
|
+
|
|
123
|
+
containers_field.map do |container|
|
|
124
|
+
container.dup.sub!(/\A./, &:upcase)
|
|
125
|
+
end
|
|
116
126
|
end
|
|
117
127
|
|
|
118
128
|
# @return [Array<String>] with embedded highlights using <em>...</em>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<% # Override to conditionally add id="documents" on div. When documents are grouped it causes duplicate id issues %>
|
|
2
|
+
<% # https://github.com/projectblacklight/blacklight/blob/v8.1.0/app/views/catalog/_document_list.html.erb %>
|
|
3
|
+
<% # container for all documents in index list view -%>
|
|
4
|
+
<% view_config = local_assigns[:view_config] || blacklight_config&.view_config(document_index_view_type) %>
|
|
5
|
+
<div <%= 'id="documents"'.html_safe unless grouped? %> class="al-document-listings documents-<%= view_config&.key || document_index_view_type %>">
|
|
6
|
+
<% document_presenters = documents.map { |doc| document_presenter(doc) } -%>
|
|
7
|
+
<%= render view_config.document_component.with_collection(document_presenters, partials: view_config.partials, counter_offset: @response&.start || 0) %>
|
|
8
|
+
</div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
<% # container for all groups in index view -%>
|
|
2
|
-
<div class='al-grouped-results'>
|
|
2
|
+
<div id="documents" class='al-grouped-results'>
|
|
3
3
|
<%= render (blacklight_config.view_config(document_index_view_type).group_component || Arclight::GroupComponent).with_collection(@response.groups) %>
|
|
4
4
|
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<li class="nav-item <%= repositories_active_class %>">
|
|
2
2
|
<%= link_to t('arclight.routes.repositories'), arclight_engine.repositories_path, class: 'nav-link' %>
|
|
3
3
|
</li>
|
|
4
|
-
<li class="nav-item
|
|
4
|
+
<li class="nav-item ms-3 <%= collection_active_class %>">
|
|
5
5
|
<%= link_to t('arclight.routes.collections'), arclight_engine.collections_path, class: 'nav-link' %>
|
|
6
6
|
</li>
|
data/arclight.gemspec
CHANGED
|
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
|
|
|
26
26
|
|
|
27
27
|
spec.add_dependency 'blacklight', '>= 8.0.0', '< 9'
|
|
28
28
|
spec.add_dependency 'gretel'
|
|
29
|
-
spec.add_dependency 'rails', '
|
|
29
|
+
spec.add_dependency 'rails', '>= 7.1', '< 9'
|
|
30
30
|
spec.add_dependency 'traject', '~> 3.0'
|
|
31
31
|
spec.add_dependency 'traject_plus', '~> 2.0'
|
|
32
32
|
|
|
@@ -43,5 +43,4 @@ Gem::Specification.new do |spec|
|
|
|
43
43
|
spec.add_development_dependency 'selenium-webdriver'
|
|
44
44
|
spec.add_development_dependency 'simplecov'
|
|
45
45
|
spec.add_development_dependency 'solr_wrapper'
|
|
46
|
-
spec.add_development_dependency 'webdrivers'
|
|
47
46
|
end
|
|
@@ -39,16 +39,11 @@ module Arclight
|
|
|
39
39
|
|
|
40
40
|
# @see http://www2.archivists.org/standards/DACS/part_I/chapter_2/4_date for rules
|
|
41
41
|
def normalize
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
else
|
|
48
|
-
result = nil
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
result&.strip
|
|
42
|
+
result = []
|
|
43
|
+
result << inclusive if inclusive.present?
|
|
44
|
+
result << other if other.present?
|
|
45
|
+
result << "bulk #{bulk}" if bulk.present?
|
|
46
|
+
result.compact.map(&:strip).join(', ').presence
|
|
52
47
|
end
|
|
53
48
|
end
|
|
54
49
|
end
|
|
@@ -5,9 +5,11 @@ require 'arclight/exceptions'
|
|
|
5
5
|
module Arclight
|
|
6
6
|
##
|
|
7
7
|
# A simple utility class to normalize identifiers
|
|
8
|
-
# to be used around the application for linking
|
|
9
8
|
class NormalizedId
|
|
10
|
-
|
|
9
|
+
# Accepts unused kwargs from the ead2_config.rb id to_field directive
|
|
10
|
+
# (:title and :repository) so that applications can provide a custom
|
|
11
|
+
# id_normalizer class to traject to form the collection id from these attributes.
|
|
12
|
+
def initialize(id, **_kwargs)
|
|
11
13
|
@id = id
|
|
12
14
|
end
|
|
13
15
|
|
data/lib/arclight/repository.rb
CHANGED
|
@@ -29,6 +29,7 @@ settings do
|
|
|
29
29
|
provide 'title_normalizer', 'Arclight::NormalizedTitle'
|
|
30
30
|
provide 'reader_class_name', 'Arclight::Traject::NokogiriNamespacelessReader'
|
|
31
31
|
provide 'logger', Logger.new($stderr)
|
|
32
|
+
provide 'component_identifier_format', '%<root_id>s_%<ref_id>s'
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
NAME_ELEMENTS = %w[corpname famname name persname].freeze
|
|
@@ -60,6 +61,7 @@ DID_SEARCHABLE_NOTES_FIELDS = %w[
|
|
|
60
61
|
abstract
|
|
61
62
|
materialspec
|
|
62
63
|
physloc
|
|
64
|
+
note
|
|
63
65
|
].freeze
|
|
64
66
|
|
|
65
67
|
# ==================
|
|
@@ -67,7 +69,9 @@ DID_SEARCHABLE_NOTES_FIELDS = %w[
|
|
|
67
69
|
#
|
|
68
70
|
# NOTE: All fields should be stored in Solr
|
|
69
71
|
# ==================
|
|
70
|
-
to_field 'ref_ssi' do |record, accumulator,
|
|
72
|
+
to_field 'ref_ssi' do |record, accumulator, context|
|
|
73
|
+
next if context.output_hash['ref_ssi']
|
|
74
|
+
|
|
71
75
|
accumulator << if record.attribute('id').blank?
|
|
72
76
|
strategy = Arclight::MissingIdStrategy.selected
|
|
73
77
|
hexdigest = strategy.new(record).to_hexdigest
|
|
@@ -82,7 +86,7 @@ to_field 'ref_ssi' do |record, accumulator, _context|
|
|
|
82
86
|
record['id'] = hexdigest
|
|
83
87
|
hexdigest
|
|
84
88
|
else
|
|
85
|
-
record.attribute('id')&.value&.strip&.gsub('.', '-')
|
|
89
|
+
record.attribute('id')&.value&.strip&.gsub('.', '-') # rubocop:disable Style/SafeNavigationChainLength
|
|
86
90
|
end
|
|
87
91
|
end
|
|
88
92
|
to_field 'ref_ssm' do |_record, accumulator, context|
|
|
@@ -90,10 +94,14 @@ to_field 'ref_ssm' do |_record, accumulator, context|
|
|
|
90
94
|
end
|
|
91
95
|
|
|
92
96
|
to_field 'id' do |_record, accumulator, context|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
+
next if context.output_hash['id']
|
|
98
|
+
|
|
99
|
+
data = {
|
|
100
|
+
root_id: settings[:root].output_hash['id']&.first,
|
|
101
|
+
ref_id: context.output_hash['ref_ssi']&.first
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
accumulator << (settings[:component_identifier_format] % data)
|
|
97
105
|
end
|
|
98
106
|
|
|
99
107
|
to_field 'title_filing_ssi', extract_xpath('./did/unittitle'), first_only
|
|
@@ -131,6 +139,11 @@ to_field 'parent_ssi' do |_record, accumulator, _context|
|
|
|
131
139
|
accumulator.concat settings[:parent].output_hash['ref_ssi'] || settings[:parent].output_hash['id']
|
|
132
140
|
end
|
|
133
141
|
|
|
142
|
+
to_field 'parent_ids_ssim' do |_record, accumulator, _context|
|
|
143
|
+
accumulator.concat(settings[:parent].output_hash['parent_ids_ssim'] || [])
|
|
144
|
+
accumulator.concat settings[:parent].output_hash['id']
|
|
145
|
+
end
|
|
146
|
+
|
|
134
147
|
to_field 'parent_unittitles_ssm' do |_rec, accumulator, _context|
|
|
135
148
|
accumulator.concat(settings[:parent].output_hash['parent_unittitles_ssm'] || [])
|
|
136
149
|
accumulator.concat settings[:parent].output_hash['normalized_title_ssm'] || []
|
|
@@ -155,12 +168,42 @@ to_field 'collection_ssim' do |_record, accumulator, _context|
|
|
|
155
168
|
accumulator.concat settings[:root].output_hash['normalized_title_ssm']
|
|
156
169
|
end
|
|
157
170
|
|
|
158
|
-
|
|
159
|
-
to_field '
|
|
171
|
+
# This accumulates direct text from a physdesc, ignoring child elements handled elsewhere
|
|
172
|
+
to_field 'physdesc_tesim', extract_xpath('./did/physdesc', to_text: false) do |_record, accumulator|
|
|
173
|
+
accumulator.map! do |element|
|
|
174
|
+
physdesc = []
|
|
175
|
+
element.children.map do |child|
|
|
176
|
+
next if child.instance_of?(Nokogiri::XML::Element)
|
|
177
|
+
|
|
178
|
+
physdesc << child.text&.strip unless child.text&.strip&.empty?
|
|
179
|
+
end.flatten
|
|
180
|
+
physdesc.join(' ') unless physdesc.empty?
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
to_field 'extent_ssm' do |record, accumulator|
|
|
185
|
+
physdescs = record.xpath('./did/physdesc')
|
|
186
|
+
extents_per_physdesc = physdescs.map do |physdesc|
|
|
187
|
+
extents = physdesc.xpath('./extent').map { |e| e.text.strip }
|
|
188
|
+
# Join extents within the same physdesc with an empty string
|
|
189
|
+
extents.join(' ') unless extents.empty?
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Add each physdesc separately to the accumulator
|
|
193
|
+
accumulator.concat(extents_per_physdesc)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
to_field 'extent_tesim' do |_record, accumulator, context|
|
|
197
|
+
accumulator.concat context.output_hash['extent_ssm'] || []
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
to_field 'physfacet_tesim', extract_xpath('./did/physdesc/physfacet')
|
|
201
|
+
to_field 'dimensions_tesim', extract_xpath('./did/physdesc/dimensions')
|
|
202
|
+
|
|
203
|
+
to_field 'indexes_html_tesm', extract_xpath('./index', to_text: false)
|
|
204
|
+
to_field 'indexes_tesim', extract_xpath('./index')
|
|
160
205
|
|
|
161
|
-
to_field 'creator_ssm', extract_xpath('./did/origination')
|
|
162
206
|
to_field 'creator_ssim', extract_xpath('./did/origination')
|
|
163
|
-
to_field 'creators_ssim', extract_xpath('./did/origination')
|
|
164
207
|
to_field 'creator_sort' do |record, accumulator|
|
|
165
208
|
accumulator << record.xpath('./did/origination').map(&:text).join(', ')
|
|
166
209
|
end
|
|
@@ -214,7 +257,7 @@ to_field 'digital_objects_ssm', extract_xpath('./dao|./did/dao', to_text: false)
|
|
|
214
257
|
end
|
|
215
258
|
end
|
|
216
259
|
|
|
217
|
-
to_field '
|
|
260
|
+
to_field 'date_range_isim', extract_xpath('./did/unitdate/@normal', to_text: false) do |_record, accumulator|
|
|
218
261
|
range = Arclight::YearRange.new
|
|
219
262
|
next range.years if accumulator.blank?
|
|
220
263
|
|
|
@@ -225,6 +268,7 @@ end
|
|
|
225
268
|
|
|
226
269
|
NAME_ELEMENTS.map do |selector|
|
|
227
270
|
to_field 'names_ssim', extract_xpath("./controlaccess/#{selector}"), unique
|
|
271
|
+
to_field 'names_ssim', extract_xpath(".//#{selector}"), unique
|
|
228
272
|
to_field "#{selector}_ssim", extract_xpath(".//#{selector}")
|
|
229
273
|
end
|
|
230
274
|
|
|
@@ -244,8 +288,6 @@ to_field 'access_subjects_ssm' do |_record, accumulator, context|
|
|
|
244
288
|
accumulator.concat(context.output_hash.fetch('access_subjects_ssim', []))
|
|
245
289
|
end
|
|
246
290
|
|
|
247
|
-
to_field 'acqinfo_ssim', extract_xpath('/ead/archdesc/acqinfo/*[local-name()!="head"]')
|
|
248
|
-
to_field 'acqinfo_ssim', extract_xpath('/ead/archdesc/descgrp/acqinfo/*[local-name()!="head"]')
|
|
249
291
|
to_field 'acqinfo_ssim', extract_xpath('./acqinfo/*[local-name()!="head"]')
|
|
250
292
|
to_field 'acqinfo_ssim', extract_xpath('./descgrp/acqinfo/*[local-name()!="head"]')
|
|
251
293
|
|
|
@@ -263,8 +305,8 @@ SEARCHABLE_NOTES_FIELDS.map do |selector|
|
|
|
263
305
|
end
|
|
264
306
|
DID_SEARCHABLE_NOTES_FIELDS.map do |selector|
|
|
265
307
|
to_field "#{selector}_html_tesm", extract_xpath("./did/#{selector}", to_text: false)
|
|
308
|
+
to_field "#{selector}_tesim", extract_xpath("./did/#{selector}")
|
|
266
309
|
end
|
|
267
|
-
to_field 'did_note_ssm', extract_xpath('./did/note')
|
|
268
310
|
|
|
269
311
|
# =============================
|
|
270
312
|
# Each component child document
|
|
@@ -280,6 +322,7 @@ to_field 'components' do |record, accumulator, context|
|
|
|
280
322
|
provide :counter, context.settings[:counter]
|
|
281
323
|
provide :depth, context.settings[:depth].to_i + 1
|
|
282
324
|
provide :component_traject_config, context.settings[:component_traject_config]
|
|
325
|
+
provide :component_identifier_format, context.settings[:component_identifier_format]
|
|
283
326
|
end
|
|
284
327
|
|
|
285
328
|
i.load_config_file(context.settings[:component_traject_config])
|
|
@@ -6,6 +6,7 @@ require 'traject/nokogiri_reader'
|
|
|
6
6
|
require 'traject_plus'
|
|
7
7
|
require 'traject_plus/macros'
|
|
8
8
|
require 'arclight/level_label'
|
|
9
|
+
require 'arclight/normalized_id'
|
|
9
10
|
require 'arclight/normalized_date'
|
|
10
11
|
require 'arclight/normalized_title'
|
|
11
12
|
require 'active_model/conversion' ## Needed for Arclight::Repository
|
|
@@ -48,14 +49,18 @@ DID_SEARCHABLE_NOTES_FIELDS = %w[
|
|
|
48
49
|
abstract
|
|
49
50
|
materialspec
|
|
50
51
|
physloc
|
|
52
|
+
note
|
|
51
53
|
].freeze
|
|
52
54
|
|
|
53
55
|
settings do
|
|
56
|
+
provide 'component_traject_config', File.join(__dir__, 'ead2_component_config.rb')
|
|
57
|
+
provide 'id_normalizer', 'Arclight::NormalizedId'
|
|
58
|
+
provide 'date_normalizer', 'Arclight::NormalizedDate'
|
|
59
|
+
provide 'title_normalizer', 'Arclight::NormalizedTitle'
|
|
54
60
|
provide 'reader_class_name', 'Arclight::Traject::NokogiriNamespacelessReader'
|
|
55
61
|
provide 'solr_writer.commit_on_close', 'true'
|
|
56
62
|
provide 'repository', ENV.fetch('REPOSITORY_ID', nil)
|
|
57
63
|
provide 'logger', Logger.new($stderr)
|
|
58
|
-
provide 'component_traject_config', File.join(__dir__, 'ead2_component_config.rb')
|
|
59
64
|
end
|
|
60
65
|
|
|
61
66
|
each_record do |_record, context|
|
|
@@ -72,7 +77,14 @@ end
|
|
|
72
77
|
# NOTE: All fields should be stored in Solr
|
|
73
78
|
# ==================
|
|
74
79
|
|
|
75
|
-
to_field 'id'
|
|
80
|
+
to_field 'id' do |record, accumulator|
|
|
81
|
+
id = record.at_xpath('/ead/eadheader/eadid')&.text
|
|
82
|
+
unitid = record.at_xpath('/ead/archdesc/did/unitid')&.text
|
|
83
|
+
title = record.at_xpath('/ead/archdesc/did/unittitle')&.text
|
|
84
|
+
repository = settings['repository']
|
|
85
|
+
accumulator << settings['id_normalizer'].constantize.new(id, unitid: unitid, title: title, repository: repository).to_s
|
|
86
|
+
end
|
|
87
|
+
|
|
76
88
|
to_field 'title_filing_ssi', extract_xpath('/ead/eadheader/filedesc/titlestmt/titleproper[@type="filing"]')
|
|
77
89
|
to_field 'title_ssm', extract_xpath('/ead/archdesc/did/unittitle')
|
|
78
90
|
to_field 'title_tesim', extract_xpath('/ead/archdesc/did/unittitle')
|
|
@@ -100,22 +112,18 @@ end
|
|
|
100
112
|
to_field 'unitid_ssm', extract_xpath('/ead/archdesc/did/unitid')
|
|
101
113
|
to_field 'unitid_tesim', extract_xpath('/ead/archdesc/did/unitid')
|
|
102
114
|
|
|
103
|
-
to_field '
|
|
104
|
-
|
|
115
|
+
to_field 'normalized_date_ssm' do |_record, accumulator, context|
|
|
116
|
+
accumulator << settings['date_normalizer'].constantize.new(
|
|
105
117
|
context.output_hash['unitdate_inclusive_ssm'],
|
|
106
118
|
context.output_hash['unitdate_bulk_ssim'],
|
|
107
119
|
context.output_hash['unitdate_other_ssim']
|
|
108
120
|
).to_s
|
|
109
|
-
title = context.output_hash['title_ssm'].first
|
|
110
|
-
accumulator << Arclight::NormalizedTitle.new(title, dates).to_s
|
|
111
121
|
end
|
|
112
122
|
|
|
113
|
-
to_field '
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
context.output_hash['unitdate_other_ssim']
|
|
118
|
-
).to_s
|
|
123
|
+
to_field 'normalized_title_ssm' do |_record, accumulator, context|
|
|
124
|
+
title = context.output_hash['title_ssm']&.first
|
|
125
|
+
date = context.output_hash['normalized_date_ssm']&.first
|
|
126
|
+
accumulator << settings['title_normalizer'].constantize.new(title, date).to_s
|
|
119
127
|
end
|
|
120
128
|
|
|
121
129
|
to_field 'collection_title_tesim' do |_record, accumulator, context|
|
|
@@ -185,11 +193,41 @@ to_field 'digital_objects_ssm', extract_xpath('/ead/archdesc/did/dao|/ead/archde
|
|
|
185
193
|
end
|
|
186
194
|
end
|
|
187
195
|
|
|
188
|
-
|
|
189
|
-
to_field '
|
|
196
|
+
# This accumulates direct text from a physdesc, ignoring child elements handled elsewhere
|
|
197
|
+
to_field 'physdesc_tesim', extract_xpath('/ead/archdesc/did/physdesc', to_text: false) do |_record, accumulator|
|
|
198
|
+
accumulator.map! do |element|
|
|
199
|
+
physdesc = []
|
|
200
|
+
element.children.map do |child|
|
|
201
|
+
next if child.instance_of?(Nokogiri::XML::Element)
|
|
202
|
+
|
|
203
|
+
physdesc << child.text&.strip unless child.text&.strip&.empty?
|
|
204
|
+
end.flatten
|
|
205
|
+
physdesc.join(' ') unless physdesc.empty?
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
to_field 'extent_ssm' do |record, accumulator|
|
|
210
|
+
physdescs = record.xpath('/ead/archdesc/did/physdesc')
|
|
211
|
+
extents_per_physdesc = physdescs.map do |physdesc|
|
|
212
|
+
extents = physdesc.xpath('./extent').map { |e| e.text.strip }
|
|
213
|
+
# Join extents within the same physdesc with an empty string
|
|
214
|
+
extents.join(' ') unless extents.empty?
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# Add each physdesc separately to the accumulator
|
|
218
|
+
accumulator.concat(extents_per_physdesc)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
to_field 'extent_tesim' do |_record, accumulator, context|
|
|
222
|
+
accumulator.concat context.output_hash['extent_ssm'] || []
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
to_field 'physfacet_tesim', extract_xpath('/ead/archdesc/did/physdesc/physfacet')
|
|
226
|
+
to_field 'dimensions_tesim', extract_xpath('/ead/archdesc/did/physdesc/dimensions')
|
|
227
|
+
|
|
190
228
|
to_field 'genreform_ssim', extract_xpath('/ead/archdesc/controlaccess/genreform')
|
|
191
229
|
|
|
192
|
-
to_field '
|
|
230
|
+
to_field 'date_range_isim', extract_xpath('/ead/archdesc/did/unitdate/@normal', to_text: false) do |_record, accumulator|
|
|
193
231
|
range = Arclight::YearRange.new
|
|
194
232
|
next range.years if accumulator.blank?
|
|
195
233
|
|
|
@@ -198,6 +236,9 @@ to_field 'date_range_ssim', extract_xpath('/ead/archdesc/did/unitdate/@normal',
|
|
|
198
236
|
accumulator.replace range.years
|
|
199
237
|
end
|
|
200
238
|
|
|
239
|
+
to_field 'indexes_html_tesm', extract_xpath('/ead/archdesc/index', to_text: false)
|
|
240
|
+
to_field 'indexes_tesim', extract_xpath('/ead/archdesc/index')
|
|
241
|
+
|
|
201
242
|
SEARCHABLE_NOTES_FIELDS.map do |selector|
|
|
202
243
|
to_field "#{selector}_html_tesm", extract_xpath("/ead/archdesc/#{selector}/*[local-name()!='head']", to_text: false) do |_record, accumulator|
|
|
203
244
|
accumulator.map!(&:to_html)
|
|
@@ -208,6 +249,7 @@ end
|
|
|
208
249
|
|
|
209
250
|
DID_SEARCHABLE_NOTES_FIELDS.map do |selector|
|
|
210
251
|
to_field "#{selector}_html_tesm", extract_xpath("/ead/archdesc/did/#{selector}", to_text: false)
|
|
252
|
+
to_field "#{selector}_tesim", extract_xpath("/ead/archdesc/did/#{selector}")
|
|
211
253
|
end
|
|
212
254
|
|
|
213
255
|
NAME_ELEMENTS.map do |selector|
|
data/lib/arclight/version.rb
CHANGED