arclight 0.5.0 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (216) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc +11 -4
  3. data/.github/workflows/ruby.yml +24 -11
  4. data/.rspec +0 -1
  5. data/.rubocop.yml +286 -2
  6. data/.rubocop_todo.yml +18 -195
  7. data/CONTRIBUTING.md +5 -5
  8. data/Gemfile +12 -12
  9. data/README.md +18 -12
  10. data/app/assets/javascripts/arclight/arclight.js +3 -7
  11. data/app/assets/javascripts/arclight/oembed_viewer.js +64 -39
  12. data/app/assets/javascripts/arclight/truncate_controller.js +27 -0
  13. data/app/assets/stylesheets/arclight/application.scss +1 -5
  14. data/app/assets/stylesheets/arclight/modules/hierarchy_and_online_contents.scss +104 -130
  15. data/app/assets/stylesheets/arclight/modules/icons.scss +14 -3
  16. data/app/assets/stylesheets/arclight/modules/layout.scss +120 -100
  17. data/app/assets/stylesheets/arclight/modules/mastheads.scss +15 -57
  18. data/app/assets/stylesheets/arclight/modules/repositories.scss +2 -2
  19. data/app/assets/stylesheets/arclight/modules/repository_card.scss +4 -48
  20. data/app/assets/stylesheets/arclight/modules/search_results.scss +86 -35
  21. data/app/assets/stylesheets/arclight/modules/show_collection.scss +5 -32
  22. data/app/assets/stylesheets/arclight/modules/truncator.scss +56 -0
  23. data/app/assets/stylesheets/arclight/variables.scss +7 -4
  24. data/app/components/arclight/access_component.html.erb +14 -0
  25. data/app/components/arclight/access_component.rb +25 -0
  26. data/app/components/arclight/bookmark_component.html.erb +25 -0
  27. data/app/components/arclight/bookmark_component.rb +9 -0
  28. data/app/components/arclight/breadcrumb_component.rb +40 -0
  29. data/app/components/arclight/breadcrumbs_hierarchy_component.html.erb +34 -0
  30. data/app/components/arclight/breadcrumbs_hierarchy_component.rb +25 -0
  31. data/app/components/arclight/collection_context_component.html.erb +12 -0
  32. data/app/components/arclight/collection_context_component.rb +27 -0
  33. data/app/components/arclight/collection_info_component.html.erb +28 -0
  34. data/app/components/arclight/collection_info_component.rb +26 -0
  35. data/app/components/arclight/collection_sidebar_component.html.erb +15 -0
  36. data/app/components/arclight/collection_sidebar_component.rb +41 -0
  37. data/app/{views/catalog/_search_results_repository.html.erb → components/arclight/constraints_component.html.erb} +2 -1
  38. data/app/components/arclight/constraints_component.rb +17 -0
  39. data/app/components/arclight/document_collection_context_component.html.erb +29 -0
  40. data/app/components/arclight/document_collection_context_component.rb +28 -0
  41. data/app/components/arclight/document_collection_hierarchy_component.html.erb +46 -0
  42. data/app/components/arclight/document_collection_hierarchy_component.rb +62 -0
  43. data/app/components/arclight/document_component.html.erb +39 -0
  44. data/app/components/arclight/document_component.rb +49 -0
  45. data/app/components/arclight/document_components_hierarchy_component.html.erb +32 -0
  46. data/app/components/arclight/document_components_hierarchy_component.rb +28 -0
  47. data/app/components/arclight/document_download_component.html.erb +24 -0
  48. data/app/components/arclight/document_download_component.rb +71 -0
  49. data/app/components/arclight/embed_component.html.erb +10 -0
  50. data/app/components/arclight/embed_component.rb +43 -0
  51. data/app/components/arclight/group_component.html.erb +30 -0
  52. data/app/components/arclight/group_component.rb +23 -0
  53. data/app/components/arclight/header_component.html.erb +5 -0
  54. data/app/components/arclight/header_component.rb +10 -0
  55. data/app/components/arclight/index_metadata_field_component.html.erb +17 -0
  56. data/app/components/arclight/index_metadata_field_component.rb +20 -0
  57. data/app/components/arclight/masthead_component.html.erb +15 -0
  58. data/app/components/arclight/masthead_component.rb +10 -0
  59. data/app/components/arclight/metadata_section_component.html.erb +13 -0
  60. data/app/components/arclight/metadata_section_component.rb +22 -0
  61. data/app/components/arclight/oembed_viewer_component.html.erb +5 -0
  62. data/app/components/arclight/oembed_viewer_component.rb +16 -0
  63. data/app/components/arclight/online_content_filter_component.html.erb +15 -0
  64. data/app/components/arclight/online_content_filter_component.rb +19 -0
  65. data/app/components/arclight/online_status_indicator_component.rb +19 -0
  66. data/app/components/arclight/repository_breadcrumb_component.html.erb +10 -0
  67. data/app/components/arclight/repository_breadcrumb_component.rb +17 -0
  68. data/app/components/arclight/repository_location_component.html.erb +20 -0
  69. data/app/components/arclight/repository_location_component.rb +10 -0
  70. data/app/components/arclight/search_bar_component.html.erb +25 -0
  71. data/app/components/arclight/search_bar_component.rb +32 -0
  72. data/app/components/arclight/search_result_breadcrumbs_component.html.erb +3 -0
  73. data/app/components/arclight/search_result_breadcrumbs_component.rb +37 -0
  74. data/app/components/arclight/search_result_component.html.erb +20 -0
  75. data/app/components/arclight/search_result_component.rb +24 -0
  76. data/app/components/arclight/search_result_title_component.html.erb +13 -0
  77. data/app/components/arclight/search_result_title_component.rb +15 -0
  78. data/app/components/arclight/sidebar_component.html.erb +9 -0
  79. data/app/components/arclight/sidebar_component.rb +19 -0
  80. data/app/components/arclight/upper_metadata_layout_component.rb +10 -0
  81. data/app/components/blacklight/icons/bookmark_component.rb +12 -0
  82. data/app/components/blacklight/icons/collection_component.rb +14 -0
  83. data/app/components/blacklight/icons/compact_component.rb +12 -0
  84. data/app/components/blacklight/icons/container_component.rb +14 -0
  85. data/app/components/blacklight/icons/ead_component.rb +12 -0
  86. data/app/components/blacklight/icons/file_component.rb +14 -0
  87. data/app/components/blacklight/icons/folder_component.rb +12 -0
  88. data/app/components/blacklight/icons/online_component.rb +15 -0
  89. data/app/components/blacklight/icons/pdf_component.rb +12 -0
  90. data/app/components/blacklight/icons/repository_component.rb +12 -0
  91. data/app/controllers/arclight/repositories_controller.rb +4 -4
  92. data/app/{controllers/concerns → helpers}/arclight/ead_format_helpers.rb +4 -7
  93. data/app/helpers/arclight/field_config_helpers.rb +26 -0
  94. data/app/helpers/arclight_helper.rb +15 -253
  95. data/app/models/arclight/document_downloads.rb +12 -15
  96. data/app/models/arclight/parent.rb +5 -0
  97. data/app/models/arclight/parents.rb +2 -1
  98. data/app/models/arclight/requests/aeon_external_request.rb +1 -1
  99. data/app/models/arclight/requests/aeon_web_ead.rb +8 -3
  100. data/app/models/arclight/requests/google_form.rb +8 -3
  101. data/app/models/concerns/arclight/catalog.rb +25 -15
  102. data/app/models/concerns/arclight/search_behavior.rb +12 -26
  103. data/app/models/concerns/arclight/solr_document.rb +70 -73
  104. data/app/presenters/arclight/show_presenter.rb +34 -7
  105. data/app/views/arclight/_requests.html.erb +2 -2
  106. data/app/views/arclight/repositories/_repository.html.erb +21 -40
  107. data/app/views/arclight/repositories/index.html.erb +3 -1
  108. data/app/views/arclight/repositories/show.html.erb +4 -6
  109. data/app/views/arclight/requests/_aeon_external_request_endpoint.html.erb +4 -5
  110. data/app/views/arclight/requests/_aeon_web_ead.html.erb +2 -3
  111. data/app/views/arclight/requests/_google_form.html.erb +4 -6
  112. data/app/views/catalog/_group.html.erb +1 -18
  113. data/app/views/catalog/_group_toggle.html.erb +1 -1
  114. data/app/views/catalog/_search_results_header.html.erb +3 -0
  115. data/app/views/catalog/hierarchy.html.erb +19 -0
  116. data/app/views/catalog/index.html.erb +16 -7
  117. data/app/views/shared/_breadcrumbs.html.erb +2 -14
  118. data/app/views/shared/_main_menu_links.html.erb +1 -1
  119. data/arclight.gemspec +7 -6
  120. data/config/breadcrumbs.rb +24 -0
  121. data/config/i18n-tasks.yml +9 -8
  122. data/config/importmap.rb +3 -0
  123. data/config/locales/arclight.en.yml +31 -30
  124. data/config/routes.rb +1 -1
  125. data/docker-compose.yml +16 -0
  126. data/lib/arclight/digital_object.rb +2 -1
  127. data/lib/arclight/engine.rb +18 -31
  128. data/lib/arclight/exceptions.rb +1 -0
  129. data/lib/arclight/hash_absolute_xpath.rb +2 -1
  130. data/lib/arclight/normalized_id.rb +2 -0
  131. data/lib/arclight/normalized_title.rb +2 -0
  132. data/lib/arclight/repository.rb +43 -54
  133. data/lib/arclight/routes/hierarchy.rb +19 -0
  134. data/lib/arclight/routes.rb +8 -0
  135. data/lib/arclight/traject/ead2_component_config.rb +292 -0
  136. data/lib/arclight/traject/ead2_config.rb +66 -287
  137. data/lib/arclight/version.rb +1 -1
  138. data/lib/arclight/year_range.rb +4 -3
  139. data/lib/arclight.rb +6 -1
  140. data/lib/generators/arclight/install_generator.rb +59 -21
  141. data/lib/generators/arclight/templates/arclight.scss +4 -3
  142. data/lib/generators/arclight/templates/catalog_controller.rb +150 -169
  143. data/lib/generators/arclight/templates/config/locales/arclight.en.yml +53 -0
  144. data/lib/generators/arclight/templates/config/repositories.yml +20 -27
  145. data/lib/tasks/index.rake +14 -17
  146. data/package.json +11 -13
  147. data/solr/conf/schema.xml +40 -36
  148. data/solr/conf/solrconfig.xml +33 -31
  149. data/tasks/arclight.rake +8 -7
  150. data/template.rb +0 -1
  151. metadata +111 -104
  152. data/.babelrc +0 -3
  153. data/app/assets/javascripts/arclight/collection_navigation.js +0 -100
  154. data/app/assets/javascripts/arclight/collection_scrollspy.js +0 -6
  155. data/app/assets/javascripts/arclight/context_navigation.js +0 -351
  156. data/app/assets/javascripts/arclight/truncator.js.erb +0 -29
  157. data/app/assets/stylesheets/arclight/bootstrap_overrides.scss +0 -26
  158. data/app/assets/stylesheets/arclight/modules/context_navigation.scss +0 -75
  159. data/app/controllers/concerns/arclight/field_config_helpers.rb +0 -102
  160. data/app/factories/blacklight_field_configuration_factory.rb +0 -30
  161. data/app/views/arclight/repositories/_in_person_repository.html.erb +0 -19
  162. data/app/views/arclight/repositories/_repository_contact.html.erb +0 -9
  163. data/app/views/arclight/viewers/_oembed.html.erb +0 -8
  164. data/app/views/catalog/_access_contents.html.erb +0 -15
  165. data/app/views/catalog/_arclight_abstract_or_scope.html.erb +0 -5
  166. data/app/views/catalog/_arclight_bookmark_control.html.erb +0 -38
  167. data/app/views/catalog/_arclight_document_header_icon.html.erb +0 -1
  168. data/app/views/catalog/_arclight_document_index_header.html.erb +0 -13
  169. data/app/views/catalog/_arclight_document_index_header_hierarchy_default.html.erb +0 -0
  170. data/app/views/catalog/_arclight_document_index_header_online_contents_default.html.erb +0 -0
  171. data/app/views/catalog/_arclight_index_compact_default.html.erb +0 -22
  172. data/app/views/catalog/_arclight_index_default.html.erb +0 -45
  173. data/app/views/catalog/_arclight_index_group_document_compact_default.html.erb +0 -19
  174. data/app/views/catalog/_arclight_index_group_document_default.html.erb +0 -18
  175. data/app/views/catalog/_arclight_online_content_indicator.html.erb +0 -3
  176. data/app/views/catalog/_arclight_rangelimit.html.erb +0 -24
  177. data/app/views/catalog/_arclight_viewer_default.html.erb +0 -1
  178. data/app/views/catalog/_collection_contents.html.erb +0 -4
  179. data/app/views/catalog/_collection_context.html.erb +0 -15
  180. data/app/views/catalog/_collection_context_nav.html.erb +0 -12
  181. data/app/views/catalog/_collection_online_contents.html.erb +0 -17
  182. data/app/views/catalog/_component_context.html.erb +0 -5
  183. data/app/views/catalog/_containers.html.erb +0 -3
  184. data/app/views/catalog/_context_card.html.erb +0 -27
  185. data/app/views/catalog/_context_sidebar.html.erb +0 -8
  186. data/app/views/catalog/_custom_metadata.html.erb +0 -16
  187. data/app/views/catalog/_document_downloads.html.erb +0 -14
  188. data/app/views/catalog/_group_header_compact_default.html.erb +0 -15
  189. data/app/views/catalog/_group_header_default.html.erb +0 -20
  190. data/app/views/catalog/_home.html.erb +0 -1
  191. data/app/views/catalog/_index_breadcrumb_default.html.erb +0 -6
  192. data/app/views/catalog/_index_collection_context_default.html.erb +0 -53
  193. data/app/views/catalog/_index_default.html.erb +0 -17
  194. data/app/views/catalog/_index_header.html.erb +0 -7
  195. data/app/views/catalog/_index_header_online_contents_default.html.erb +0 -1
  196. data/app/views/catalog/_index_online_contents_default.html.erb +0 -6
  197. data/app/views/catalog/_online_content_label.html.erb +0 -5
  198. data/app/views/catalog/_search_form.html.erb +0 -38
  199. data/app/views/catalog/_search_results.html.erb +0 -28
  200. data/app/views/catalog/_show_actions_box_default.html.erb +0 -27
  201. data/app/views/catalog/_show_breadcrumbs_default.html.erb +0 -6
  202. data/app/views/catalog/_show_collection.html.erb +0 -66
  203. data/app/views/catalog/_show_default.html.erb +0 -70
  204. data/app/views/catalog/_show_upper_metadata_collection.html.erb +0 -1
  205. data/app/views/catalog/_show_upper_metadata_default.html.erb +0 -14
  206. data/app/views/catalog/_sort_and_per_page.html.erb +0 -8
  207. data/app/views/catalog/_within_collection_dropdown.html.erb +0 -26
  208. data/app/views/layouts/catalog_result.html.erb +0 -7
  209. data/app/views/shared/_context_sidebar.html.erb +0 -8
  210. data/app/views/shared/_header_navbar.html.erb +0 -61
  211. data/app/views/shared/_show_breadcrumbs.html.erb +0 -27
  212. data/lib/arclight/viewer.rb +0 -45
  213. data/lib/arclight/viewers/oembed.rb +0 -57
  214. data/solr/conf/scripts.conf +0 -24
  215. data/vendor/assets/javascripts/responsiveTruncator.js +0 -69
  216. data/vendor/assets/javascripts/stickyfill.js +0 -480
@@ -0,0 +1,292 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+ require 'traject'
5
+ require 'traject/nokogiri_reader'
6
+ require 'traject_plus'
7
+ require 'traject_plus/macros'
8
+ require 'arclight/level_label'
9
+ require 'arclight/normalized_date'
10
+ require 'arclight/normalized_title'
11
+ require 'active_model/conversion' ## Needed for Arclight::Repository
12
+ require 'active_support/core_ext/array/wrap'
13
+ require 'arclight/digital_object'
14
+ require 'arclight/year_range'
15
+ require 'arclight/missing_id_strategy'
16
+ require 'arclight/traject/nokogiri_namespaceless_reader'
17
+
18
+ # rubocop:disable Style/MixinUsage
19
+ extend TrajectPlus::Macros
20
+ # rubocop:enable Style/MixinUsage
21
+
22
+ settings do
23
+ # provide 'root' # the root EAD collection indexing context
24
+ # provide 'parent' # the immediate parent component (or collection) indexing context
25
+ # provide 'counter' # a global component counter to provide a global sort order for nested components
26
+ # provide 'depth' # the current nesting depth of the component
27
+ provide 'component_traject_config', __FILE__
28
+ provide 'date_normalizer', 'Arclight::NormalizedDate'
29
+ provide 'title_normalizer', 'Arclight::NormalizedTitle'
30
+ provide 'reader_class_name', 'Arclight::Traject::NokogiriNamespacelessReader'
31
+ provide 'logger', Logger.new($stderr)
32
+ end
33
+
34
+ NAME_ELEMENTS = %w[corpname famname name persname].freeze
35
+
36
+ SEARCHABLE_NOTES_FIELDS = %w[
37
+ accessrestrict
38
+ accruals
39
+ altformavail
40
+ appraisal
41
+ arrangement
42
+ bibliography
43
+ bioghist
44
+ custodhist
45
+ fileplan
46
+ note
47
+ odd
48
+ originalsloc
49
+ otherfindaid
50
+ phystech
51
+ prefercite
52
+ processinfo
53
+ relatedmaterial
54
+ scopecontent
55
+ separatedmaterial
56
+ userestrict
57
+ ].freeze
58
+
59
+ DID_SEARCHABLE_NOTES_FIELDS = %w[
60
+ abstract
61
+ materialspec
62
+ physloc
63
+ ].freeze
64
+
65
+ # ==================
66
+ # Component elements
67
+ #
68
+ # NOTE: All fields should be stored in Solr
69
+ # ==================
70
+ to_field 'ref_ssi' do |record, accumulator, _context|
71
+ accumulator << if record.attribute('id').blank?
72
+ strategy = Arclight::MissingIdStrategy.selected
73
+ hexdigest = strategy.new(record).to_hexdigest
74
+ parent_id = settings[:parent].output_hash['id'].first
75
+ root_id = settings[:root].output_hash['id'].first
76
+ logger.warn('MISSING ID WARNING') do
77
+ [
78
+ "A component in #{parent_id} did not have an ID so one was minted using the #{strategy} strategy.",
79
+ "The ID of this document will be #{root_id}#{hexdigest}."
80
+ ].join(' ')
81
+ end
82
+ record['id'] = hexdigest
83
+ hexdigest
84
+ else
85
+ record.attribute('id')&.value&.strip&.gsub('.', '-')
86
+ end
87
+ end
88
+ to_field 'ref_ssm' do |_record, accumulator, context|
89
+ accumulator.concat context.output_hash['ref_ssi']
90
+ end
91
+
92
+ to_field 'id' do |_record, accumulator, context|
93
+ accumulator << [
94
+ settings[:root].output_hash['id'],
95
+ context.output_hash['ref_ssi']
96
+ ].join
97
+ end
98
+
99
+ to_field 'title_filing_ssi', extract_xpath('./did/unittitle'), first_only
100
+ to_field 'title_ssm', extract_xpath('./did/unittitle')
101
+ to_field 'title_tesim', extract_xpath('./did/unittitle')
102
+
103
+ to_field 'unitdate_bulk_ssim', extract_xpath('./did/unitdate[@type="bulk"]')
104
+ to_field 'unitdate_inclusive_ssm', extract_xpath('./did/unitdate[@type="inclusive"]')
105
+ to_field 'unitdate_other_ssim', extract_xpath('./did/unitdate[not(@type)]')
106
+
107
+ to_field 'normalized_date_ssm' do |_record, accumulator, context|
108
+ accumulator << settings['date_normalizer'].constantize.new(
109
+ context.output_hash['unitdate_inclusive_ssm'],
110
+ context.output_hash['unitdate_bulk_ssim'],
111
+ context.output_hash['unitdate_other_ssim']
112
+ ).to_s
113
+ end
114
+
115
+ to_field 'normalized_title_ssm' do |_record, accumulator, context|
116
+ title = context.output_hash['title_ssm']&.first
117
+ date = context.output_hash['normalized_date_ssm']&.first
118
+ accumulator << settings['title_normalizer'].constantize.new(title, date).to_s
119
+ end
120
+
121
+ to_field 'component_level_isim' do |_record, accumulator|
122
+ accumulator << (settings[:depth] || 1)
123
+ end
124
+
125
+ to_field 'parent_ssim' do |_record, accumulator, _context|
126
+ accumulator.concat(settings[:parent].output_hash['parent_ssim'] || [])
127
+ accumulator.concat settings[:parent].output_hash['ref_ssi'] || settings[:parent].output_hash['id']
128
+ end
129
+
130
+ to_field 'parent_ssi' do |_record, accumulator, _context|
131
+ accumulator.concat settings[:parent].output_hash['ref_ssi'] || settings[:parent].output_hash['id']
132
+ end
133
+
134
+ to_field 'parent_unittitles_ssm' do |_rec, accumulator, _context|
135
+ accumulator.concat(settings[:parent].output_hash['parent_unittitles_ssm'] || [])
136
+ accumulator.concat settings[:parent].output_hash['normalized_title_ssm'] || []
137
+ end
138
+
139
+ to_field 'parent_unittitles_tesim' do |_record, accumulator, context|
140
+ accumulator.concat context.output_hash['parent_unittitles_ssm']
141
+ end
142
+
143
+ to_field 'parent_levels_ssm' do |_record, accumulator, _context|
144
+ ## Top level document
145
+ accumulator.concat settings[:parent].output_hash['parent_levels_ssm'] || []
146
+ accumulator.concat settings[:parent].output_hash['level_ssm'] || []
147
+ end
148
+
149
+ to_field 'unitid_ssm', extract_xpath('./did/unitid')
150
+ to_field 'repository_ssim' do |_record, accumulator, _context|
151
+ accumulator << settings[:root].clipboard[:repository]
152
+ end
153
+
154
+ to_field 'collection_ssim' do |_record, accumulator, _context|
155
+ accumulator.concat settings[:root].output_hash['normalized_title_ssm']
156
+ end
157
+
158
+ to_field 'extent_ssm', extract_xpath('./did/physdesc/extent')
159
+ to_field 'extent_tesim', extract_xpath('./did/physdesc/extent')
160
+
161
+ to_field 'creator_ssm', extract_xpath('./did/origination')
162
+ to_field 'creator_ssim', extract_xpath('./did/origination')
163
+ to_field 'creators_ssim', extract_xpath('./did/origination')
164
+ to_field 'creator_sort' do |record, accumulator|
165
+ accumulator << record.xpath('./did/origination').map(&:text).join(', ')
166
+ end
167
+ to_field 'has_online_content_ssim', extract_xpath('.//dao') do |_record, accumulator|
168
+ accumulator.replace([accumulator.any?])
169
+ end
170
+ to_field 'child_component_count_isi' do |record, accumulator|
171
+ accumulator << record.xpath('c|c01|c02|c03|c04|c05|c06|c07|c08|c09|c10|c11|c12').count
172
+ end
173
+
174
+ to_field 'ref_ssm' do |record, accumulator|
175
+ accumulator << record.attribute('id')
176
+ end
177
+
178
+ to_field 'level_ssm' do |record, accumulator|
179
+ level = record.attribute('level')&.value
180
+ other_level = record.attribute('otherlevel')&.value
181
+ accumulator << Arclight::LevelLabel.new(level, other_level).to_s
182
+ end
183
+
184
+ to_field 'level_ssim' do |_record, accumulator, context|
185
+ next unless context.output_hash['level_ssm']
186
+
187
+ accumulator.concat context.output_hash['level_ssm']&.map(&:capitalize)
188
+ end
189
+
190
+ to_field 'sort_isi' do |_record, accumulator, _context|
191
+ accumulator.replace([settings[:counter].increment])
192
+ end
193
+
194
+ # Get the <accessrestrict> from the closest ancestor that has one (includes top-level)
195
+ to_field 'parent_access_restrict_tesm' do |record, accumulator|
196
+ accumulator.concat Array
197
+ .wrap(record.xpath('(./ancestor::*/accessrestrict)[last()]/*[local-name()!="head"]')
198
+ .map(&:text))
199
+ end
200
+
201
+ # Get the <userestrict> from self OR the closest ancestor that has one (includes top-level)
202
+ to_field 'parent_access_terms_tesm' do |record, accumulator|
203
+ accumulator.concat Array
204
+ .wrap(record.xpath('(./ancestor-or-self::*/userestrict)[last()]/*[local-name()!="head"]')
205
+ .map(&:text))
206
+ end
207
+
208
+ to_field 'digital_objects_ssm', extract_xpath('./dao|./did/dao', to_text: false) do |_record, accumulator|
209
+ accumulator.map! do |dao|
210
+ label = dao.attributes['title']&.value ||
211
+ dao.xpath('daodesc/p')&.text
212
+ href = (dao.attributes['href'] || dao.attributes['xlink:href'])&.value
213
+ Arclight::DigitalObject.new(label: label, href: href).to_json
214
+ end
215
+ end
216
+
217
+ to_field 'date_range_ssim', extract_xpath('./did/unitdate/@normal', to_text: false) do |_record, accumulator|
218
+ range = Arclight::YearRange.new
219
+ next range.years if accumulator.blank?
220
+
221
+ ranges = accumulator.map(&:to_s)
222
+ range << range.parse_ranges(ranges)
223
+ accumulator.replace range.years
224
+ end
225
+
226
+ NAME_ELEMENTS.map do |selector|
227
+ to_field 'names_ssim', extract_xpath("./controlaccess/#{selector}"), unique
228
+ to_field "#{selector}_ssim", extract_xpath(".//#{selector}")
229
+ end
230
+
231
+ to_field 'geogname_ssim', extract_xpath('./controlaccess/geogname')
232
+ to_field 'geogname_ssm', extract_xpath('./controlaccess/geogname')
233
+ to_field 'places_ssim', extract_xpath('./controlaccess/geogname')
234
+
235
+ to_field 'access_subjects_ssim', extract_xpath('./controlaccess', to_text: false) do |_record, accumulator|
236
+ accumulator.map! do |element|
237
+ %w[subject function occupation genreform].map do |selector|
238
+ element.xpath(".//#{selector}").map(&:text)
239
+ end
240
+ end.flatten!
241
+ end
242
+
243
+ to_field 'access_subjects_ssm' do |_record, accumulator, context|
244
+ accumulator.concat(context.output_hash.fetch('access_subjects_ssim', []))
245
+ end
246
+
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
+ to_field 'acqinfo_ssim', extract_xpath('./acqinfo/*[local-name()!="head"]')
250
+ to_field 'acqinfo_ssim', extract_xpath('./descgrp/acqinfo/*[local-name()!="head"]')
251
+
252
+ to_field 'language_ssim', extract_xpath('./did/langmaterial')
253
+ to_field 'containers_ssim' do |record, accumulator|
254
+ record.xpath('./did/container').each do |node|
255
+ accumulator << [node.attribute('type'), node.text].join(' ').strip
256
+ end
257
+ end
258
+
259
+ SEARCHABLE_NOTES_FIELDS.map do |selector|
260
+ to_field "#{selector}_html_tesm", extract_xpath("./#{selector}/*[local-name()!='head']", to_text: false)
261
+ to_field "#{selector}_heading_ssm", extract_xpath("./#{selector}/head")
262
+ to_field "#{selector}_tesim", extract_xpath("./#{selector}/*[local-name()!='head']")
263
+ end
264
+ DID_SEARCHABLE_NOTES_FIELDS.map do |selector|
265
+ to_field "#{selector}_html_tesm", extract_xpath("./did/#{selector}", to_text: false)
266
+ end
267
+ to_field 'did_note_ssm', extract_xpath('./did/note')
268
+
269
+ # =============================
270
+ # Each component child document
271
+ # <c> <c01> <c12>
272
+ # =============================
273
+
274
+ to_field 'components' do |record, accumulator, context|
275
+ child_components = record.xpath('c|c01|c02|c03|c04|c05|c06|c07|c08|c09|c10|c11|c12')
276
+ component_indexer = Traject::Indexer::NokogiriIndexer.new.tap do |i|
277
+ i.settings do
278
+ provide :parent, context
279
+ provide :root, context.settings[:root]
280
+ provide :counter, context.settings[:counter]
281
+ provide :depth, context.settings[:depth].to_i + 1
282
+ provide :component_traject_config, context.settings[:component_traject_config]
283
+ end
284
+
285
+ i.load_config_file(context.settings[:component_traject_config])
286
+ end
287
+
288
+ child_components.each do |child_component|
289
+ output = component_indexer.map_record(child_component)
290
+ accumulator << output if output.keys.any?
291
+ end
292
+ end