arclight 0.3.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.
Files changed (240) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc +11 -4
  3. data/.github/workflows/ruby.yml +51 -0
  4. data/.gitignore +1 -0
  5. data/.rspec +0 -1
  6. data/.rubocop.yml +498 -21
  7. data/.rubocop_todo.yml +69 -86
  8. data/.solr_wrapper +2 -1
  9. data/CONTRIBUTING.md +5 -5
  10. data/CONTRIBUTORS.md +1 -1
  11. data/Gemfile +15 -10
  12. data/README.md +22 -17
  13. data/app/assets/images/blacklight/bookmark.svg +1 -1
  14. data/app/assets/images/blacklight/collection.svg +1 -1
  15. data/app/assets/images/blacklight/compact.svg +1 -1
  16. data/app/assets/images/blacklight/container.svg +1 -1
  17. data/app/assets/images/blacklight/ead.svg +1 -1
  18. data/app/assets/images/blacklight/file.svg +1 -1
  19. data/app/assets/images/blacklight/folder.svg +1 -1
  20. data/app/assets/images/blacklight/list.svg +1 -1
  21. data/app/assets/images/blacklight/online.svg +1 -1
  22. data/app/assets/images/blacklight/pdf.svg +1 -1
  23. data/app/assets/images/blacklight/repository.svg +1 -1
  24. data/app/assets/javascripts/arclight/arclight.js +4 -8
  25. data/app/assets/javascripts/arclight/oembed_controller.js +58 -0
  26. data/app/assets/javascripts/arclight/truncate_controller.js +27 -0
  27. data/app/assets/stylesheets/arclight/application.scss +3 -5
  28. data/app/assets/stylesheets/arclight/build.scss +4 -0
  29. data/app/assets/stylesheets/arclight/modules/hierarchy_and_online_contents.scss +108 -130
  30. data/app/assets/stylesheets/arclight/modules/icons.scss +20 -0
  31. data/app/assets/stylesheets/arclight/modules/layout.scss +129 -100
  32. data/app/assets/stylesheets/arclight/modules/mastheads.scss +23 -96
  33. data/app/assets/stylesheets/arclight/modules/repositories.scss +2 -2
  34. data/app/assets/stylesheets/arclight/modules/repository_card.scss +4 -48
  35. data/app/assets/stylesheets/arclight/modules/search_form.scss +9 -0
  36. data/app/assets/stylesheets/arclight/modules/search_results.scss +95 -45
  37. data/app/assets/stylesheets/arclight/modules/show_collection.scss +5 -32
  38. data/app/assets/stylesheets/arclight/modules/truncator.scss +58 -0
  39. data/app/assets/stylesheets/arclight/variables.scss +7 -4
  40. data/app/components/arclight/access_component.html.erb +14 -0
  41. data/app/components/arclight/access_component.rb +25 -0
  42. data/app/components/arclight/bookmark_component.html.erb +25 -0
  43. data/app/components/arclight/bookmark_component.rb +9 -0
  44. data/app/components/arclight/breadcrumb_component.rb +50 -0
  45. data/app/components/arclight/breadcrumbs_hierarchy_component.html.erb +34 -0
  46. data/app/components/arclight/breadcrumbs_hierarchy_component.rb +25 -0
  47. data/app/components/arclight/collection_context_component.html.erb +12 -0
  48. data/app/components/arclight/collection_context_component.rb +27 -0
  49. data/app/components/arclight/collection_info_component.html.erb +28 -0
  50. data/app/components/arclight/collection_info_component.rb +26 -0
  51. data/app/components/arclight/collection_sidebar_component.html.erb +15 -0
  52. data/app/components/arclight/collection_sidebar_component.rb +39 -0
  53. data/app/{views/catalog/_search_results_repository.html.erb → components/arclight/constraints_component.html.erb} +2 -1
  54. data/app/components/arclight/constraints_component.rb +17 -0
  55. data/app/components/arclight/document_collection_context_component.html.erb +29 -0
  56. data/app/components/arclight/document_collection_context_component.rb +28 -0
  57. data/app/components/arclight/document_collection_hierarchy_component.html.erb +50 -0
  58. data/app/components/arclight/document_collection_hierarchy_component.rb +62 -0
  59. data/app/components/arclight/document_component.html.erb +39 -0
  60. data/app/components/arclight/document_component.rb +49 -0
  61. data/app/components/arclight/document_components_hierarchy_component.html.erb +20 -0
  62. data/app/components/arclight/document_components_hierarchy_component.rb +34 -0
  63. data/app/components/arclight/document_download_component.html.erb +24 -0
  64. data/app/components/arclight/document_download_component.rb +71 -0
  65. data/app/components/arclight/embed_component.html.erb +10 -0
  66. data/app/components/arclight/embed_component.rb +43 -0
  67. data/app/components/arclight/expand_hierarchy_button_component.html.erb +5 -0
  68. data/app/components/arclight/expand_hierarchy_button_component.rb +16 -0
  69. data/app/components/arclight/group_component.html.erb +34 -0
  70. data/app/components/arclight/group_component.rb +23 -0
  71. data/app/components/arclight/header_component.html.erb +5 -0
  72. data/app/components/arclight/header_component.rb +10 -0
  73. data/app/components/arclight/index_metadata_field_component.html.erb +16 -0
  74. data/app/components/arclight/index_metadata_field_component.rb +20 -0
  75. data/app/components/arclight/masthead_component.html.erb +17 -0
  76. data/app/components/arclight/masthead_component.rb +10 -0
  77. data/app/components/arclight/metadata_section_component.html.erb +13 -0
  78. data/app/components/arclight/metadata_section_component.rb +22 -0
  79. data/app/components/arclight/oembed_viewer_component.html.erb +5 -0
  80. data/app/components/arclight/oembed_viewer_component.rb +16 -0
  81. data/app/components/arclight/online_content_filter_component.html.erb +15 -0
  82. data/app/components/arclight/online_content_filter_component.rb +17 -0
  83. data/app/components/arclight/online_status_indicator_component.rb +19 -0
  84. data/app/components/arclight/repository_breadcrumb_component.html.erb +10 -0
  85. data/app/components/arclight/repository_breadcrumb_component.rb +17 -0
  86. data/app/components/arclight/repository_location_component.html.erb +20 -0
  87. data/app/components/arclight/repository_location_component.rb +10 -0
  88. data/app/components/arclight/search_bar_component.html.erb +27 -0
  89. data/app/components/arclight/search_bar_component.rb +32 -0
  90. data/app/components/arclight/search_result_breadcrumbs_component.html.erb +6 -0
  91. data/app/components/arclight/search_result_breadcrumbs_component.rb +37 -0
  92. data/app/components/arclight/search_result_component.html.erb +20 -0
  93. data/app/components/arclight/search_result_component.rb +18 -0
  94. data/app/components/arclight/search_result_title_component.html.erb +15 -0
  95. data/app/components/arclight/search_result_title_component.rb +15 -0
  96. data/app/components/arclight/sidebar_component.html.erb +9 -0
  97. data/app/components/arclight/sidebar_component.rb +19 -0
  98. data/app/components/arclight/upper_metadata_layout_component.rb +10 -0
  99. data/app/components/blacklight/icons/bookmark_component.rb +12 -0
  100. data/app/components/blacklight/icons/collection_component.rb +14 -0
  101. data/app/components/blacklight/icons/compact_component.rb +12 -0
  102. data/app/components/blacklight/icons/container_component.rb +14 -0
  103. data/app/components/blacklight/icons/ead_component.rb +12 -0
  104. data/app/components/blacklight/icons/file_component.rb +14 -0
  105. data/app/components/blacklight/icons/folder_component.rb +12 -0
  106. data/app/components/blacklight/icons/online_component.rb +15 -0
  107. data/app/components/blacklight/icons/pdf_component.rb +12 -0
  108. data/app/components/blacklight/icons/repository_component.rb +12 -0
  109. data/app/controllers/arclight/repositories_controller.rb +4 -4
  110. data/app/{controllers/concerns → helpers}/arclight/ead_format_helpers.rb +91 -7
  111. data/app/helpers/arclight/field_config_helpers.rb +26 -0
  112. data/app/helpers/arclight_helper.rb +24 -251
  113. data/app/models/arclight/document_downloads.rb +12 -15
  114. data/app/models/arclight/parent.rb +6 -8
  115. data/app/models/arclight/parents.rb +7 -4
  116. data/app/models/arclight/requests/aeon_external_request.rb +1 -1
  117. data/app/models/arclight/requests/aeon_web_ead.rb +8 -3
  118. data/app/models/arclight/requests/google_form.rb +8 -3
  119. data/app/models/concerns/arclight/catalog.rb +25 -15
  120. data/app/models/concerns/arclight/search_behavior.rb +12 -26
  121. data/app/models/concerns/arclight/solr_document.rb +80 -73
  122. data/app/presenters/arclight/show_presenter.rb +34 -7
  123. data/app/views/arclight/_requests.html.erb +2 -2
  124. data/app/views/arclight/repositories/_repository.html.erb +21 -40
  125. data/app/views/arclight/repositories/index.html.erb +3 -1
  126. data/app/views/arclight/repositories/show.html.erb +4 -6
  127. data/app/views/arclight/requests/_aeon_external_request_endpoint.html.erb +4 -5
  128. data/app/views/arclight/requests/_aeon_web_ead.html.erb +3 -4
  129. data/app/views/arclight/requests/_google_form.html.erb +4 -6
  130. data/app/views/catalog/_document_list.html.erb +8 -0
  131. data/app/views/catalog/_group.html.erb +2 -19
  132. data/app/views/catalog/_group_toggle.html.erb +1 -1
  133. data/app/views/catalog/_search_results_header.html.erb +3 -0
  134. data/app/views/catalog/hierarchy.html.erb +19 -0
  135. data/app/views/catalog/index.html.erb +16 -7
  136. data/app/views/shared/_breadcrumbs.html.erb +2 -14
  137. data/app/views/shared/_main_menu_links.html.erb +1 -1
  138. data/arclight.gemspec +17 -15
  139. data/config/breadcrumbs.rb +24 -0
  140. data/config/i18n-tasks.yml +9 -8
  141. data/config/importmap.rb +3 -0
  142. data/config/locales/arclight.en.yml +31 -30
  143. data/config/routes.rb +1 -1
  144. data/docker-compose.yml +16 -0
  145. data/lib/arclight/digital_object.rb +2 -1
  146. data/lib/arclight/engine.rb +18 -37
  147. data/lib/arclight/exceptions.rb +1 -0
  148. data/lib/arclight/hash_absolute_xpath.rb +2 -1
  149. data/lib/arclight/normalized_date.rb +5 -10
  150. data/lib/arclight/normalized_id.rb +6 -2
  151. data/lib/arclight/normalized_title.rb +2 -0
  152. data/lib/arclight/repository.rb +46 -57
  153. data/lib/arclight/routes/hierarchy.rb +19 -0
  154. data/lib/arclight/routes.rb +8 -0
  155. data/lib/arclight/traject/ead2_component_config.rb +335 -0
  156. data/lib/arclight/traject/ead2_config.rb +120 -298
  157. data/lib/arclight/version.rb +1 -1
  158. data/lib/arclight/year_range.rb +4 -3
  159. data/lib/arclight.rb +6 -1
  160. data/lib/generators/arclight/install_generator.rb +97 -11
  161. data/lib/generators/arclight/templates/arclight.scss +6 -3
  162. data/lib/generators/arclight/templates/catalog_controller.rb +193 -163
  163. data/lib/generators/arclight/templates/config/locales/arclight.en.yml +61 -0
  164. data/lib/generators/arclight/templates/config/repositories.yml +22 -29
  165. data/lib/tasks/index.rake +14 -17
  166. data/package.json +13 -14
  167. data/solr/conf/schema.xml +49 -39
  168. data/solr/conf/solrconfig.xml +78 -58
  169. data/tasks/arclight.rake +17 -9
  170. data/template.rb +6 -7
  171. metadata +159 -127
  172. data/.babelrc +0 -3
  173. data/.travis.yml +0 -28
  174. data/app/assets/javascripts/arclight/collection_navigation.js +0 -100
  175. data/app/assets/javascripts/arclight/collection_scrollspy.js +0 -6
  176. data/app/assets/javascripts/arclight/context_navigation.js +0 -374
  177. data/app/assets/javascripts/arclight/oembed_viewer.js +0 -46
  178. data/app/assets/javascripts/arclight/truncator.js.erb +0 -29
  179. data/app/assets/stylesheets/arclight/bootstrap_overrides.scss +0 -26
  180. data/app/assets/stylesheets/arclight/modules/context_navigation.scss +0 -75
  181. data/app/controllers/concerns/arclight/field_config_helpers.rb +0 -102
  182. data/app/factories/blacklight_field_configuration_factory.rb +0 -30
  183. data/app/views/arclight/repositories/_in_person_repository.html.erb +0 -19
  184. data/app/views/arclight/repositories/_repository_contact.html.erb +0 -9
  185. data/app/views/arclight/viewers/_oembed.html.erb +0 -8
  186. data/app/views/catalog/_access_contents.html.erb +0 -15
  187. data/app/views/catalog/_arclight_abstract_or_scope.html.erb +0 -5
  188. data/app/views/catalog/_arclight_bookmark_control.html.erb +0 -38
  189. data/app/views/catalog/_arclight_document_header_icon.html.erb +0 -1
  190. data/app/views/catalog/_arclight_document_index_header.html.erb +0 -13
  191. data/app/views/catalog/_arclight_document_index_header_hierarchy_default.html.erb +0 -0
  192. data/app/views/catalog/_arclight_document_index_header_online_contents_default.html.erb +0 -0
  193. data/app/views/catalog/_arclight_index_compact_default.html.erb +0 -22
  194. data/app/views/catalog/_arclight_index_default.html.erb +0 -45
  195. data/app/views/catalog/_arclight_index_group_document_compact_default.html.erb +0 -19
  196. data/app/views/catalog/_arclight_index_group_document_default.html.erb +0 -18
  197. data/app/views/catalog/_arclight_online_content_indicator.html.erb +0 -3
  198. data/app/views/catalog/_arclight_rangelimit.html.erb +0 -24
  199. data/app/views/catalog/_arclight_viewer_default.html.erb +0 -1
  200. data/app/views/catalog/_collection_contents.html.erb +0 -4
  201. data/app/views/catalog/_collection_context.html.erb +0 -15
  202. data/app/views/catalog/_collection_context_nav.html.erb +0 -12
  203. data/app/views/catalog/_collection_online_contents.html.erb +0 -17
  204. data/app/views/catalog/_component_context.html.erb +0 -5
  205. data/app/views/catalog/_containers.html.erb +0 -3
  206. data/app/views/catalog/_context_card.html.erb +0 -27
  207. data/app/views/catalog/_context_sidebar.html.erb +0 -8
  208. data/app/views/catalog/_custom_metadata.html.erb +0 -16
  209. data/app/views/catalog/_document_downloads.html.erb +0 -14
  210. data/app/views/catalog/_group_header_compact_default.html.erb +0 -15
  211. data/app/views/catalog/_group_header_default.html.erb +0 -20
  212. data/app/views/catalog/_home.html.erb +0 -1
  213. data/app/views/catalog/_index_breadcrumb_default.html.erb +0 -6
  214. data/app/views/catalog/_index_collection_context_default.html.erb +0 -53
  215. data/app/views/catalog/_index_default.html.erb +0 -17
  216. data/app/views/catalog/_index_header.html.erb +0 -7
  217. data/app/views/catalog/_index_header_online_contents_default.html.erb +0 -1
  218. data/app/views/catalog/_index_online_contents_default.html.erb +0 -6
  219. data/app/views/catalog/_online_content_label.html.erb +0 -5
  220. data/app/views/catalog/_search_form.html.erb +0 -34
  221. data/app/views/catalog/_search_results.html.erb +0 -28
  222. data/app/views/catalog/_show_actions_box_default.html.erb +0 -27
  223. data/app/views/catalog/_show_breadcrumbs_default.html.erb +0 -6
  224. data/app/views/catalog/_show_collection.html.erb +0 -66
  225. data/app/views/catalog/_show_default.html.erb +0 -70
  226. data/app/views/catalog/_show_upper_metadata_collection.html.erb +0 -1
  227. data/app/views/catalog/_show_upper_metadata_default.html.erb +0 -14
  228. data/app/views/catalog/_sort_and_per_page.html.erb +0 -8
  229. data/app/views/catalog/_within_collection_dropdown.html.erb +0 -26
  230. data/app/views/layouts/catalog_result.html.erb +0 -7
  231. data/app/views/shared/_context_sidebar.html.erb +0 -8
  232. data/app/views/shared/_header_navbar.html.erb +0 -61
  233. data/app/views/shared/_show_breadcrumbs.html.erb +0 -27
  234. data/lib/arclight/viewer.rb +0 -45
  235. data/lib/arclight/viewers/oembed.rb +0 -57
  236. data/lib/generators/arclight/templates/arclight.js +0 -2
  237. data/solr/conf/scripts.conf +0 -24
  238. data/vendor/assets/javascripts/responsiveTruncator.js +0 -69
  239. data/vendor/assets/javascripts/stickyfill.js +0 -480
  240. /data/app/assets/images/{blacklight → arclight}/logo.png +0 -0
@@ -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
@@ -13,7 +14,6 @@ require 'active_support/core_ext/array/wrap'
13
14
  require 'arclight/digital_object'
14
15
  require 'arclight/year_range'
15
16
  require 'arclight/repository'
16
- require 'arclight/missing_id_strategy'
17
17
  require 'arclight/traject/nokogiri_namespaceless_reader'
18
18
 
19
19
  # rubocop:disable Style/MixinUsage
@@ -49,12 +49,17 @@ DID_SEARCHABLE_NOTES_FIELDS = %w[
49
49
  abstract
50
50
  materialspec
51
51
  physloc
52
+ note
52
53
  ].freeze
53
54
 
54
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'
55
60
  provide 'reader_class_name', 'Arclight::Traject::NokogiriNamespacelessReader'
56
61
  provide 'solr_writer.commit_on_close', 'true'
57
- provide 'repository', ENV['REPOSITORY_ID']
62
+ provide 'repository', ENV.fetch('REPOSITORY_ID', nil)
58
63
  provide 'logger', Logger.new($stderr)
59
64
  end
60
65
 
@@ -68,12 +73,21 @@ end
68
73
 
69
74
  # ==================
70
75
  # Top level document
76
+ #
77
+ # NOTE: All fields should be stored in Solr
71
78
  # ==================
72
79
 
73
- to_field 'id', extract_xpath('/ead/eadheader/eadid'), strip, gsub('.', '-')
74
- to_field 'title_filing_si', extract_xpath('/ead/eadheader/filedesc/titlestmt/titleproper[@type="filing"]')
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
+
88
+ to_field 'title_filing_ssi', extract_xpath('/ead/eadheader/filedesc/titlestmt/titleproper[@type="filing"]')
75
89
  to_field 'title_ssm', extract_xpath('/ead/archdesc/did/unittitle')
76
- to_field 'title_teim', extract_xpath('/ead/archdesc/did/unittitle')
90
+ to_field 'title_tesim', extract_xpath('/ead/archdesc/did/unittitle')
77
91
  to_field 'ead_ssi', extract_xpath('/ead/eadheader/eadid')
78
92
 
79
93
  to_field 'unitdate_ssm', extract_xpath('/ead/archdesc/did/unitdate')
@@ -87,7 +101,7 @@ to_field 'level_ssm' do |_record, accumulator|
87
101
  end
88
102
 
89
103
  # Keep the original top-level archdesc/@level for Level facet in addition to 'Collection'
90
- to_field 'level_sim' do |record, accumulator|
104
+ to_field 'level_ssim' do |record, accumulator|
91
105
  level = record.at_xpath('/ead/archdesc').attribute('level')&.value
92
106
  other_level = record.at_xpath('/ead/archdesc').attribute('otherlevel')&.value
93
107
 
@@ -96,37 +110,27 @@ to_field 'level_sim' do |record, accumulator|
96
110
  end
97
111
 
98
112
  to_field 'unitid_ssm', extract_xpath('/ead/archdesc/did/unitid')
99
- to_field 'unitid_teim', extract_xpath('/ead/archdesc/did/unitid')
100
- to_field 'collection_unitid_ssm', extract_xpath('/ead/archdesc/did/unitid')
101
-
102
- to_field 'normalized_title_ssm' do |_record, accumulator, context|
103
- dates = Arclight::NormalizedDate.new(
104
- context.output_hash['unitdate_inclusive_ssm'],
105
- context.output_hash['unitdate_bulk_ssim'],
106
- context.output_hash['unitdate_other_ssim']
107
- ).to_s
108
- title = context.output_hash['title_ssm'].first
109
- accumulator << Arclight::NormalizedTitle.new(title, dates).to_s
110
- end
113
+ to_field 'unitid_tesim', extract_xpath('/ead/archdesc/did/unitid')
111
114
 
112
115
  to_field 'normalized_date_ssm' do |_record, accumulator, context|
113
- accumulator << Arclight::NormalizedDate.new(
116
+ accumulator << settings['date_normalizer'].constantize.new(
114
117
  context.output_hash['unitdate_inclusive_ssm'],
115
118
  context.output_hash['unitdate_bulk_ssim'],
116
119
  context.output_hash['unitdate_other_ssim']
117
120
  ).to_s
118
121
  end
119
122
 
120
- to_field 'collection_ssm' do |_record, accumulator, context|
121
- accumulator.concat context.output_hash.fetch('normalized_title_ssm', [])
122
- end
123
- to_field 'collection_sim' do |_record, accumulator, context|
124
- accumulator.concat context.output_hash.fetch('normalized_title_ssm', [])
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
125
127
  end
126
- to_field 'collection_ssi' do |_record, accumulator, context|
128
+
129
+ to_field 'collection_title_tesim' do |_record, accumulator, context|
127
130
  accumulator.concat context.output_hash.fetch('normalized_title_ssm', [])
128
131
  end
129
- to_field 'collection_title_tesim' do |_record, accumulator, context|
132
+
133
+ to_field 'collection_ssim' do |_record, accumulator, context|
130
134
  accumulator.concat context.output_hash.fetch('normalized_title_ssm', [])
131
135
  end
132
136
 
@@ -134,39 +138,30 @@ to_field 'repository_ssm' do |_record, accumulator, context|
134
138
  accumulator << context.clipboard[:repository]
135
139
  end
136
140
 
137
- to_field 'repository_sim' do |_record, accumulator, context|
141
+ to_field 'repository_ssim' do |_record, accumulator, context|
138
142
  accumulator << context.clipboard[:repository]
139
143
  end
140
144
 
141
145
  to_field 'geogname_ssm', extract_xpath('/ead/archdesc/controlaccess/geogname')
142
- to_field 'geogname_sim', extract_xpath('/ead/archdesc/controlaccess/geogname')
146
+ to_field 'geogname_ssim', extract_xpath('/ead/archdesc/controlaccess/geogname')
143
147
 
144
148
  to_field 'creator_ssm', extract_xpath('/ead/archdesc/did/origination')
145
- to_field 'creator_sim', extract_xpath('/ead/archdesc/did/origination')
146
149
  to_field 'creator_ssim', extract_xpath('/ead/archdesc/did/origination')
147
150
  to_field 'creator_sort' do |record, accumulator|
148
151
  accumulator << record.xpath('/ead/archdesc/did/origination').map { |c| c.text.strip }.join(', ')
149
152
  end
150
153
 
151
- to_field 'creator_persname_ssm', extract_xpath('/ead/archdesc/did/origination/persname')
152
154
  to_field 'creator_persname_ssim', extract_xpath('/ead/archdesc/did/origination/persname')
153
- to_field 'creator_corpname_ssm', extract_xpath('/ead/archdesc/did/origination/corpname')
154
- to_field 'creator_corpname_sim', extract_xpath('/ead/archdesc/did/origination/corpname')
155
155
  to_field 'creator_corpname_ssim', extract_xpath('/ead/archdesc/did/origination/corpname')
156
- to_field 'creator_famname_ssm', extract_xpath('/ead/archdesc/did/origination/famname')
157
156
  to_field 'creator_famname_ssim', extract_xpath('/ead/archdesc/did/origination/famname')
158
157
 
159
- to_field 'persname_sim', extract_xpath('//persname')
160
-
161
158
  to_field 'creators_ssim' do |_record, accumulator, context|
162
- accumulator.concat context.output_hash['creator_persname_ssm'] if context.output_hash['creator_persname_ssm']
163
- accumulator.concat context.output_hash['creator_corpname_ssm'] if context.output_hash['creator_corpname_ssm']
164
- accumulator.concat context.output_hash['creator_famname_ssm'] if context.output_hash['creator_famname_ssm']
159
+ accumulator.concat context.output_hash['creator_persname_ssim'] if context.output_hash['creator_persname_ssim']
160
+ accumulator.concat context.output_hash['creator_corpname_ssim'] if context.output_hash['creator_corpname_ssim']
161
+ accumulator.concat context.output_hash['creator_famname_ssim'] if context.output_hash['creator_famname_ssim']
165
162
  end
166
163
 
167
- to_field 'places_sim', extract_xpath('/ead/archdesc/controlaccess/geogname')
168
164
  to_field 'places_ssim', extract_xpath('/ead/archdesc/controlaccess/geogname')
169
- to_field 'places_ssm', extract_xpath('/ead/archdesc/controlaccess/geogname')
170
165
 
171
166
  to_field 'access_terms_ssm', extract_xpath('/ead/archdesc/userestrict/*[local-name()!="head"]')
172
167
 
@@ -198,12 +193,41 @@ to_field 'digital_objects_ssm', extract_xpath('/ead/archdesc/did/dao|/ead/archde
198
193
  end
199
194
  end
200
195
 
201
- to_field 'extent_ssm', extract_xpath('/ead/archdesc/did/physdesc/extent')
202
- to_field 'extent_teim', extract_xpath('/ead/archdesc/did/physdesc/extent')
203
- to_field 'genreform_sim', extract_xpath('/ead/archdesc/controlaccess/genreform')
204
- to_field 'genreform_ssm', extract_xpath('/ead/archdesc/controlaccess/genreform')
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
205
224
 
206
- to_field 'date_range_sim', extract_xpath('/ead/archdesc/did/unitdate/@normal', to_text: false) do |_record, accumulator|
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
+
228
+ to_field 'genreform_ssim', extract_xpath('/ead/archdesc/controlaccess/genreform')
229
+
230
+ to_field 'date_range_isim', extract_xpath('/ead/archdesc/did/unitdate/@normal', to_text: false) do |_record, accumulator|
207
231
  range = Arclight::YearRange.new
208
232
  next range.years if accumulator.blank?
209
233
 
@@ -212,283 +236,81 @@ to_field 'date_range_sim', extract_xpath('/ead/archdesc/did/unitdate/@normal', t
212
236
  accumulator.replace range.years
213
237
  end
214
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
+
215
242
  SEARCHABLE_NOTES_FIELDS.map do |selector|
216
- to_field "#{selector}_ssm", extract_xpath("/ead/archdesc/#{selector}/*[local-name()!='head']", to_text: false)
243
+ to_field "#{selector}_html_tesm", extract_xpath("/ead/archdesc/#{selector}/*[local-name()!='head']", to_text: false) do |_record, accumulator|
244
+ accumulator.map!(&:to_html)
245
+ end
217
246
  to_field "#{selector}_heading_ssm", extract_xpath("/ead/archdesc/#{selector}/head") unless selector == 'prefercite'
218
- to_field "#{selector}_teim", extract_xpath("/ead/archdesc/#{selector}/*[local-name()!='head']")
247
+ to_field "#{selector}_tesim", extract_xpath("/ead/archdesc/#{selector}/*[local-name()!='head']")
219
248
  end
220
249
 
221
250
  DID_SEARCHABLE_NOTES_FIELDS.map do |selector|
222
- to_field "#{selector}_ssm", extract_xpath("/ead/archdesc/did/#{selector}", to_text: false)
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}")
223
253
  end
224
254
 
225
255
  NAME_ELEMENTS.map do |selector|
226
256
  to_field 'names_coll_ssim', extract_xpath("/ead/archdesc/controlaccess/#{selector}")
227
- to_field 'names_ssim', extract_xpath("//#{selector}")
228
- to_field "#{selector}_ssm", extract_xpath("//#{selector}")
257
+ to_field 'names_ssim', extract_xpath("//#{selector}"), unique
258
+ to_field "#{selector}_ssim", extract_xpath("//#{selector}"), unique
229
259
  end
230
260
 
231
- to_field 'corpname_sim', extract_xpath('//corpname')
232
-
233
- to_field 'language_sim', extract_xpath('/ead/archdesc/did/langmaterial')
234
- to_field 'language_ssm', extract_xpath('/ead/archdesc/did/langmaterial')
261
+ to_field 'language_ssim', extract_xpath('/ead/archdesc/did/langmaterial')
235
262
 
236
263
  to_field 'descrules_ssm', extract_xpath('/ead/eadheader/profiledesc/descrules')
237
264
 
238
- # =============================
239
- # Each component child document
240
- # <c> <c01> <c12>
241
- # =============================
242
-
243
- compose 'components', ->(record, accumulator, _context) { accumulator.concat record.xpath('//*[is_component(.)]', NokogiriXpathExtensions.new) } do
244
- to_field 'ref_ssi' do |record, accumulator, context|
245
- accumulator << if record.attribute('id').blank?
246
- strategy = Arclight::MissingIdStrategy.selected
247
- hexdigest = strategy.new(record).to_hexdigest
248
- parent_id = context.clipboard[:parent].output_hash['id'].first
249
- logger.warn('MISSING ID WARNING') do
250
- [
251
- "A component in #{parent_id} did not have an ID so one was minted using the #{strategy} strategy.",
252
- "The ID of this document will be #{parent_id}#{hexdigest}."
253
- ].join(' ')
254
- end
255
- record['id'] = hexdigest
256
- hexdigest
257
- else
258
- record.attribute('id')&.value&.strip&.gsub('.', '-')
259
- end
260
- end
261
- to_field 'ref_ssm' do |_record, accumulator, context|
262
- accumulator.concat context.output_hash['ref_ssi']
263
- end
264
-
265
- to_field 'id' do |_record, accumulator, context|
266
- accumulator << [
267
- context.clipboard[:parent].output_hash['id'],
268
- context.output_hash['ref_ssi']
269
- ].join('')
270
- end
271
-
272
- to_field 'ead_ssi' do |_record, accumulator, context|
273
- accumulator << context.clipboard[:parent].output_hash['ead_ssi'].first
274
- end
275
-
276
- to_field 'title_filing_si', extract_xpath('./did/unittitle'), first_only
277
- to_field 'title_ssm', extract_xpath('./did/unittitle')
278
- to_field 'title_teim', extract_xpath('./did/unittitle')
279
-
280
- to_field 'unitdate_bulk_ssim', extract_xpath('./did/unitdate[@type="bulk"]')
281
- to_field 'unitdate_inclusive_ssm', extract_xpath('./did/unitdate[@type="inclusive"]')
282
- to_field 'unitdate_other_ssim', extract_xpath('./did/unitdate[not(@type)]')
283
-
284
- to_field 'normalized_title_ssm' do |_record, accumulator, context|
285
- dates = Arclight::NormalizedDate.new(
286
- context.output_hash['unitdate_inclusive_ssm'],
287
- context.output_hash['unitdate_bulk_ssim'],
288
- context.output_hash['unitdate_other_ssim']
289
- ).to_s
290
- title = context.output_hash['title_ssm']&.first
291
- accumulator << Arclight::NormalizedTitle.new(title, dates).to_s
292
- end
293
-
294
- to_field 'normalized_date_ssm' do |_record, accumulator, context|
295
- accumulator << Arclight::NormalizedDate.new(
296
- context.output_hash['unitdate_inclusive_ssm'],
297
- context.output_hash['unitdate_bulk_ssim'],
298
- context.output_hash['unitdate_other_ssim']
299
- ).to_s
300
- end
301
-
302
- to_field 'component_level_isim' do |record, accumulator|
303
- accumulator << 1 + NokogiriXpathExtensions.new.is_component(record.ancestors).count
304
- end
305
-
306
- to_field 'parent_ssim' do |record, accumulator, context|
307
- accumulator << context.clipboard[:parent].output_hash['id'].first
308
- accumulator.concat NokogiriXpathExtensions.new.is_component(record.ancestors).reverse.map { |n| n.attribute('id')&.value }
309
- end
310
-
311
- to_field 'parent_ssi' do |_record, accumulator, context|
312
- accumulator << context.output_hash['parent_ssim'].last
313
- end
314
-
315
- to_field 'parent_unittitles_ssm' do |_rec, accumulator, context|
316
- # top level document
317
- accumulator.concat context.clipboard[:parent].output_hash['normalized_title_ssm']
318
- parent_ssim = context.output_hash['parent_ssim']
319
- components = context.clipboard[:parent].output_hash['components']
320
-
321
- # other components
322
- if parent_ssim && components
323
- ancestors = parent_ssim.drop(1).map { |x| [x] }
324
- accumulator.concat components.select { |c| ancestors.include? c['ref_ssi'] }.flat_map { |c| c['normalized_title_ssm'] }
325
- end
326
- end
327
-
328
- to_field 'parent_unittitles_teim' do |_record, accumulator, context|
329
- accumulator.concat context.output_hash['parent_unittitles_ssm']
330
- end
331
-
332
- to_field 'parent_levels_ssm' do |_record, accumulator, context|
333
- ## Top level document
334
- accumulator.concat context.clipboard[:parent].output_hash['level_ssm']
335
- ## Other components
336
- context.output_hash['parent_ssim']&.drop(1)&.each do |id|
337
- accumulator.concat Array
338
- .wrap(context.clipboard[:parent].output_hash['components'])
339
- .select { |c| c['ref_ssi'] == [id] }.map { |c| c['level_ssm'] }.flatten
340
- end
341
- end
342
-
343
- to_field 'unitid_ssm', extract_xpath('./did/unitid')
344
- to_field 'collection_unitid_ssm' do |_record, accumulator, context|
345
- accumulator.concat Array.wrap(context.clipboard[:parent].output_hash['unitid_ssm'])
346
- end
347
- to_field 'repository_ssm' do |_record, accumulator, context|
348
- accumulator << context.clipboard[:parent].clipboard[:repository]
349
- end
350
- to_field 'repository_sim' do |_record, accumulator, context|
351
- accumulator << context.clipboard[:parent].clipboard[:repository]
352
- end
353
- to_field 'collection_ssm' do |_record, accumulator, context|
354
- accumulator.concat context.clipboard[:parent].output_hash['normalized_title_ssm']
355
- end
356
- to_field 'collection_sim' do |_record, accumulator, context|
357
- accumulator.concat context.clipboard[:parent].output_hash['normalized_title_ssm']
358
- end
359
- to_field 'collection_ssi' do |_record, accumulator, context|
360
- accumulator.concat context.clipboard[:parent].output_hash['normalized_title_ssm']
361
- end
362
-
363
- to_field 'extent_ssm', extract_xpath('./did/physdesc/extent')
364
- to_field 'extent_teim', extract_xpath('./did/physdesc/extent')
365
-
366
- to_field 'creator_ssm', extract_xpath('./did/origination')
367
- to_field 'creator_ssim', extract_xpath('./did/origination')
368
- to_field 'creators_ssim', extract_xpath('./did/origination')
369
- to_field 'creator_sort' do |record, accumulator|
370
- accumulator << record.xpath('./did/origination').map(&:text).join(', ')
371
- end
372
- to_field 'collection_creator_ssm' do |_record, accumulator, context|
373
- accumulator.concat Array.wrap(context.clipboard[:parent].output_hash['creator_ssm'])
374
- end
375
- to_field 'has_online_content_ssim', extract_xpath('.//dao') do |_record, accumulator|
376
- accumulator.replace([accumulator.any?])
377
- end
378
- to_field 'child_component_count_isim' do |record, accumulator|
379
- accumulator << NokogiriXpathExtensions.new.is_component(record.children).count
380
- end
381
-
382
- to_field 'ref_ssm' do |record, accumulator|
383
- accumulator << record.attribute('id')
384
- end
385
-
386
- to_field 'level_ssm' do |record, accumulator|
387
- level = record.attribute('level')&.value
388
- other_level = record.attribute('otherlevel')&.value
389
- accumulator << Arclight::LevelLabel.new(level, other_level).to_s
390
- end
265
+ # count all descendant components from the top-level
266
+ to_field 'total_component_count_is', first_only do |record, accumulator|
267
+ accumulator << record.xpath('//c|//c01|//c02|//c03|//c04|//c05|//c06|//c07|//c08|//c09|//c10|//c11|//c12').count
268
+ end
391
269
 
392
- to_field 'level_sim' do |_record, accumulator, context|
393
- next unless context.output_hash['level_ssm']
270
+ # count all digital objects from the top-level
271
+ to_field 'online_item_count_is', first_only do |record, accumulator|
272
+ accumulator << record.xpath('//dao').count
273
+ end
394
274
 
395
- accumulator.concat context.output_hash['level_ssm']&.map(&:capitalize)
396
- end
275
+ to_field 'component_level_isim' do |_record, accumulator, _context|
276
+ accumulator << 0
277
+ end
397
278
 
398
- to_field 'sort_ii' do |_record, accumulator, context|
399
- accumulator.replace([context.position])
400
- end
279
+ to_field 'sort_isi' do |_record, accumulator, _context|
280
+ accumulator << 0
281
+ end
401
282
 
402
- # Get the <accessrestrict> from the closest ancestor that has one (includes top-level)
403
- to_field 'parent_access_restrict_ssm' do |record, accumulator|
404
- accumulator.concat Array
405
- .wrap(record.xpath('(./ancestor::*/accessrestrict)[last()]/*[local-name()!="head"]')
406
- .map(&:text))
407
- end
283
+ # =============================
284
+ # Each component child document
285
+ # <c> <c01> <c12>
286
+ # =============================
408
287
 
409
- # Get the <userestrict> from self OR the closest ancestor that has one (includes top-level)
410
- to_field 'parent_access_terms_ssm' do |record, accumulator|
411
- accumulator.concat Array
412
- .wrap(record.xpath('(./ancestor-or-self::*/userestrict)[last()]/*[local-name()!="head"]')
413
- .map(&:text))
414
- end
288
+ to_field 'components' do |record, accumulator, context|
289
+ child_components = record.xpath("/ead/archdesc/dsc/c|#{('/ead/archdesc/dsc/c01'..'/ead/archdesc/dsc/c12').to_a.join('|')}")
290
+ next unless child_components.any?
415
291
 
416
- to_field 'digital_objects_ssm', extract_xpath('./dao|./did/dao', to_text: false) do |_record, accumulator|
417
- accumulator.map! do |dao|
418
- label = dao.attributes['title']&.value ||
419
- dao.xpath('daodesc/p')&.text
420
- href = (dao.attributes['href'] || dao.attributes['xlink:href'])&.value
421
- Arclight::DigitalObject.new(label: label, href: href).to_json
292
+ counter = Class.new do
293
+ def increment
294
+ @counter ||= 0
295
+ @counter += 1
422
296
  end
423
- end
424
-
425
- to_field 'date_range_sim', extract_xpath('./did/unitdate/@normal', to_text: false) do |_record, accumulator|
426
- range = Arclight::YearRange.new
427
- next range.years if accumulator.blank?
428
-
429
- ranges = accumulator.map(&:to_s)
430
- range << range.parse_ranges(ranges)
431
- accumulator.replace range.years
432
- end
433
-
434
- NAME_ELEMENTS.map do |selector|
435
- to_field 'names_ssim', extract_xpath("./controlaccess/#{selector}")
436
- to_field "#{selector}_ssm", extract_xpath(".//#{selector}")
437
- end
438
-
439
- to_field 'geogname_sim', extract_xpath('./controlaccess/geogname')
440
- to_field 'geogname_ssm', extract_xpath('./controlaccess/geogname')
441
- to_field 'places_ssim', extract_xpath('./controlaccess/geogname')
442
-
443
- to_field 'access_subjects_ssim', extract_xpath('./controlaccess', to_text: false) do |_record, accumulator|
444
- accumulator.map! do |element|
445
- %w[subject function occupation genreform].map do |selector|
446
- element.xpath(".//#{selector}").map(&:text)
447
- end
448
- end.flatten!
449
- end
450
-
451
- to_field 'access_subjects_ssm' do |_record, accumulator, context|
452
- accumulator.concat(context.output_hash.fetch('access_subjects_ssim', []))
453
- end
454
-
455
- to_field 'acqinfo_ssim', extract_xpath('/ead/archdesc/acqinfo/*[local-name()!="head"]')
456
- to_field 'acqinfo_ssim', extract_xpath('/ead/archdesc/descgrp/acqinfo/*[local-name()!="head"]')
457
- to_field 'acqinfo_ssim', extract_xpath('./acqinfo/*[local-name()!="head"]')
458
- to_field 'acqinfo_ssim', extract_xpath('./descgrp/acqinfo/*[local-name()!="head"]')
459
-
460
- to_field 'language_ssm', extract_xpath('./did/langmaterial')
461
- to_field 'containers_ssim' do |record, accumulator|
462
- record.xpath('./did/container').each do |node|
463
- accumulator << [node.attribute('type'), node.text].join(' ').strip
297
+ end.new
298
+
299
+ component_indexer = Traject::Indexer::NokogiriIndexer.new.tap do |i|
300
+ i.settings do
301
+ provide :parent, context
302
+ provide :root, context
303
+ provide :counter, counter
304
+ provide :depth, 1
305
+ provide :logger, context.settings[:logger]
306
+ provide :component_traject_config, context.settings[:component_traject_config]
464
307
  end
465
- end
466
308
 
467
- SEARCHABLE_NOTES_FIELDS.map do |selector|
468
- to_field "#{selector}_ssm", extract_xpath("./#{selector}/*[local-name()!='head']", to_text: false)
469
- to_field "#{selector}_heading_ssm", extract_xpath("./#{selector}/head")
470
- to_field "#{selector}_teim", extract_xpath("./#{selector}/*[local-name()!='head']")
471
- end
472
- DID_SEARCHABLE_NOTES_FIELDS.map do |selector|
473
- to_field "#{selector}_ssm", extract_xpath("./did/#{selector}", to_text: false)
309
+ i.load_config_file(context.settings[:component_traject_config])
474
310
  end
475
- to_field 'did_note_ssm', extract_xpath('./did/note')
476
- end
477
311
 
478
- each_record do |_record, context|
479
- context.output_hash['components'] &&= context.output_hash['components'].select { |c| c.keys.any? }
480
- end
481
-
482
- ##
483
- # Used for evaluating xpath components to find
484
- class NokogiriXpathExtensions
485
- # rubocop:disable Naming/PredicateName, Style/FormatString
486
- def is_component(node_set)
487
- node_set.find_all do |node|
488
- component_elements = (1..12).map { |i| "c#{'%02d' % i}" }
489
- component_elements.push 'c'
490
- component_elements.include? node.name
491
- end
312
+ child_components.each do |child_component|
313
+ output = component_indexer.map_record(child_component)
314
+ accumulator << output if output.keys.any?
492
315
  end
493
- # rubocop:enable Naming/PredicateName, Style/FormatString
494
316
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Arclight
4
- VERSION = '0.3.0'
4
+ VERSION = '1.6.2'
5
5
  end
@@ -18,7 +18,6 @@ module Arclight
18
18
  def initialize(dates = nil)
19
19
  @years = []
20
20
  self << parse_ranges(dates) if dates.present?
21
- self
22
21
  end
23
22
 
24
23
  # @return [String] a concise, human-readable version of the year range, including gaps
@@ -77,13 +76,14 @@ module Arclight
77
76
  # Deals with making a human-readable range for years with 1 or more gaps.
78
77
  # It involves detection of streaks between the gaps.
79
78
  # @return [String] 1999-2000, 2002 for 1999, 2000, 2002
80
- def to_s_with_gaps # rubocop: disable Metrics/AbcSize, Metrics/MethodLength
79
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
80
+ def to_s_with_gaps
81
81
  raise ArgumentError if years.blank? || years.length < 2
82
82
 
83
83
  results = []
84
84
  streak = [years[0]]
85
85
  i = streak.first
86
- years[1..-1].each do |j|
86
+ years[1..].each do |j|
87
87
  i += 1
88
88
  if i == j
89
89
  streak << j
@@ -100,6 +100,7 @@ module Arclight
100
100
  results << to_s_for_streak(streak)
101
101
  results.join(', ')
102
102
  end
103
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
103
104
 
104
105
  def to_s_for_streak(streak)
105
106
  return streak.min.to_s if streak.min == streak.max
data/lib/arclight.rb CHANGED
@@ -5,6 +5,11 @@ require 'arclight/engine'
5
5
  require 'arclight/repository'
6
6
  require 'arclight/year_range'
7
7
 
8
+ # :nodoc:
8
9
  module Arclight
9
- # Your code goes here...
10
+ autoload :Routes, 'arclight/routes'
11
+
12
+ def self.deprecation
13
+ @deprecation ||= ActiveSupport::Deprecation.new('2.0', 'Arclight')
14
+ end
10
15
  end