mods_display 0.6.0 → 0.9.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c2d5c102f64b65d4313c4aad186328f17edf6475908f360762591ec4ded1f044
4
- data.tar.gz: fefe5bd0aa2a29fe4cb60ad94e40840a3a1fe4a12b30ffccfc08b32361d04a5b
3
+ metadata.gz: 04b5809a32a151c63f3c9423f8917046060c12ed6a88a64e30b018f89256f144
4
+ data.tar.gz: a2104c15cdec18e265fd19349fece71736a2e92f2c0bceb8288d7977a4ffa2a0
5
5
  SHA512:
6
- metadata.gz: 5230f9bda246de22ebaaab5d01f3dc8a6d02f7a92f56a6caa1aa8e7d39039d8cb2d2fd8f39e8797d0757fb49dea269e680191ba9d495ae45ddf20cdfbfb3ae55
7
- data.tar.gz: 5d5144f39760608dcb3a628022d1e8335e54b23a0c6e2b172c7705c68bd1a2fc12fa8b3155635c77bae9c74842bb3aeefc61639ea3c717f0495df7860faf6853
6
+ metadata.gz: 7f4505c49261d1a76e3f1ba8da36fce97a396c5a680de93ac61293d45aefde35716463172e0e92c29e90cbef2a8ed11b65ef9fa2787028e6f8be36f31dadf582
7
+ data.tar.gz: afbf6a24b41cdc0c097f66b7ff7173501cfd1de626c1ed850e54c6e85319edd4af4484b46612e7828622b78469536ce8d859a8e1068bacb2461ac4d2c8385b25
@@ -0,0 +1,24 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ jobs:
10
+ tests:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ ruby: [2.6, 2.7, 3.0]
15
+ steps:
16
+ - uses: actions/checkout@v2
17
+ - name: Set up Ruby
18
+ uses: ruby/setup-ruby@v1
19
+ with:
20
+ ruby-version: ${{ matrix.ruby }}
21
+ - name: Install dependencies
22
+ run: bundle install
23
+ - name: Run tests
24
+ run: bundle exec rake
data/lib/mods_display.rb CHANGED
@@ -49,3 +49,14 @@ require 'i18n/backend/fallbacks'
49
49
  I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
50
50
  I18n.load_path += Dir["#{File.expand_path('../..', __FILE__)}/config/locales/*.yml"]
51
51
  I18n.backend.load_translations
52
+
53
+ # load Rails/Railtie
54
+ begin
55
+ require 'rails'
56
+ rescue LoadError
57
+ #do nothing
58
+ end
59
+
60
+ if defined? ::Rails::Railtie
61
+ require 'mods_display/railtie'
62
+ end
@@ -1,5 +1,53 @@
1
1
  module ModsDisplay
2
2
  class AccessCondition < Field
3
+ LICENSES = {
4
+ 'cc-none' => { desc: '' },
5
+ 'cc-by' => {
6
+ link: 'http://creativecommons.org/licenses/by/3.0/',
7
+ desc: 'This work is licensed under a Creative Commons Attribution 3.0 Unported License'
8
+ },
9
+ 'cc-by-sa' => {
10
+ link: 'http://creativecommons.org/licenses/by-sa/3.0/',
11
+ desc: 'This work is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License'
12
+ },
13
+ 'cc-by-nd' => {
14
+ link: 'http://creativecommons.org/licenses/by-nd/3.0/',
15
+ desc: 'This work is licensed under a Creative Commons Attribution-No Derivative Works 3.0 Unported License'
16
+ },
17
+ 'cc-by-nc' => {
18
+ link: 'http://creativecommons.org/licenses/by-nc/3.0/',
19
+ desc: 'This work is licensed under a Creative Commons Attribution-Noncommercial 3.0 Unported License'
20
+ },
21
+ 'cc-by-nc-sa' => {
22
+ link: 'http://creativecommons.org/licenses/by-nc-sa/3.0/',
23
+ desc: 'This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License'
24
+ },
25
+ 'cc-by-nc-nd' => {
26
+ link: 'http://creativecommons.org/licenses/by-nc-nd/3.0/',
27
+ desc: 'This work is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License'
28
+ },
29
+ 'cc-pdm' => {
30
+ link: 'http://creativecommons.org/publicdomain/mark/1.0/',
31
+ desc: 'This work is in the public domain per Creative Commons Public Domain Mark 1.0'
32
+ },
33
+ 'odc-odc-pddl' => {
34
+ link: 'http://opendatacommons.org/licenses/pddl/',
35
+ desc: 'This work is licensed under a Open Data Commons Public Domain Dedication and License (PDDL)'
36
+ },
37
+ 'odc-pddl' => {
38
+ link: 'http://opendatacommons.org/licenses/pddl/',
39
+ desc: 'This work is licensed under a Open Data Commons Public Domain Dedication and License (PDDL)'
40
+ },
41
+ 'odc-odc-by' => {
42
+ link: 'http://opendatacommons.org/licenses/by/',
43
+ desc: 'This work is licensed under a Open Data Commons Attribution License'
44
+ },
45
+ 'odc-odc-odbl' => {
46
+ link: 'http://opendatacommons.org/licenses/odbl/',
47
+ desc: 'This work is licensed under a Open Data Commons Open Database License (ODbL)'
48
+ }
49
+ }.freeze
50
+
3
51
  def fields
4
52
  return_fields = @values.map do |value|
5
53
  ModsDisplay::Values.new(
@@ -28,26 +76,35 @@ module ModsDisplay
28
76
  end
29
77
 
30
78
  def license_statement(element)
31
- element.text[/^(.*) (.*):(.*)$/]
32
- output = "<div class='#{[Regexp.last_match(1), Regexp.last_match(2)].join('-').downcase}'>"
33
- if license_link(Regexp.last_match(1), Regexp.last_match(2))
34
- link = "<a href='#{license_link(Regexp.last_match(1), Regexp.last_match(2))}'>#{Regexp.last_match(3).strip}</a>"
35
- output << link
36
- else
37
- output << Regexp.last_match(3).strip
38
- end
79
+ matches = element.text.match(/^(?<code>.*) (?<type>.*):(?<description>.*)$/)
80
+
81
+ return "<div>#{element.text}</div>" unless matches
82
+
83
+ code = matches[:code].downcase
84
+ type = matches[:type].downcase
85
+ description = license_description(code, type) || matches[:description]
86
+ url = license_url(code, type)
87
+ output = "<div class='#{code}-#{type}'>"
88
+ output << if url
89
+ "<a href='#{url}'>#{description}</a>"
90
+ else
91
+ description
92
+ end
39
93
  output << '</div>'
40
94
  end
41
95
 
42
- def license_code_urls
43
- { 'cc' => 'http://creativecommons.org/licenses/',
44
- 'odc' => 'http://opendatacommons.org/licenses/' }
96
+ def license_url(code, type)
97
+ key = "#{code}-#{type}"
98
+ return unless LICENSES.key?(key)
99
+
100
+ LICENSES[key][:link]
45
101
  end
46
102
 
47
- def license_link(code, type)
48
- code = code.downcase
49
- return unless license_code_urls.key?(code)
50
- "#{license_code_urls[code]}#{type.downcase}#{"/#{@config.cc_license_version}/" if code == 'cc'}"
103
+ def license_description(code, type)
104
+ key = "#{code}-#{type}"
105
+ return unless LICENSES.key?(key) && LICENSES[key][:desc]
106
+
107
+ LICENSES[key][:desc]
51
108
  end
52
109
 
53
110
  def access_label(element)
@@ -68,6 +68,8 @@ module ModsDisplay
68
68
  date_fields.map do |date_field|
69
69
  if date_is_w3cdtf?(date_field)
70
70
  process_w3cdtf_date(date_field)
71
+ elsif date_is_iso8601?(date_field)
72
+ process_iso8601_date(date_field)
71
73
  else
72
74
  date_field
73
75
  end
@@ -158,6 +160,10 @@ module ModsDisplay
158
160
  field_is_encoded?(date_field, 'w3cdtf')
159
161
  end
160
162
 
163
+ def date_is_iso8601?(date_field)
164
+ field_is_encoded?(date_field, 'iso8601')
165
+ end
166
+
161
167
  def process_w3cdtf_date(date_field)
162
168
  date_field = date_field.clone
163
169
  date_field.content = begin
@@ -174,6 +180,16 @@ module ModsDisplay
174
180
  date_field
175
181
  end
176
182
 
183
+ def process_iso8601_date(date_field)
184
+ date_field = date_field.clone
185
+ date_field.content = begin
186
+ Date.iso8601(date_field.text).strftime(@config.full_date_format)
187
+ rescue
188
+ date_field.content
189
+ end
190
+ date_field
191
+ end
192
+
177
193
  def dedup_dates(date_fields)
178
194
  date_text = date_fields.map { |d| normalize_date(d.text) }
179
195
  if date_text != date_text.uniq
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ModsDisplay
4
+ module Helpers
5
+ module RecordHelper
6
+ def display_content_field(field)
7
+ return unless field.respond_to?(:label, :values) && field.values.any?(&:present?)
8
+
9
+ display_content_label(field.label) + display_content_values(field.values)
10
+ end
11
+
12
+ def display_content_label(label)
13
+ content_tag :dt, label
14
+ end
15
+
16
+ def display_content_values(values)
17
+ values.map do |value|
18
+ content_tag :dd, value
19
+ end.join('').html_safe
20
+ end
21
+
22
+ def mods_display_label(label)
23
+ content_tag(:dt, label.delete(':')) + "\n".html_safe
24
+ end
25
+
26
+ def mods_display_content(values, delimiter = nil)
27
+ if delimiter
28
+ content_tag(:dd, values.map do |value|
29
+ link_urls_and_email(value) if value.present?
30
+ end.compact.join(delimiter).html_safe)
31
+ else
32
+ Array[values].flatten.map do |value|
33
+ content_tag(:dd, link_urls_and_email(value.to_s).html_safe) if value.present?
34
+ end.join.html_safe
35
+ end
36
+ end
37
+
38
+ def mods_record_field(field, delimiter = nil)
39
+ return unless field.respond_to?(:label, :values) && field.values.any?(&:present?)
40
+
41
+ mods_display_label(field.label) + mods_display_content(field.values, delimiter)
42
+ end
43
+
44
+ def mods_name_field(field, &block)
45
+ return unless field.respond_to?(:label, :values) && field.values.any?(&:present?)
46
+
47
+ mods_display_label(field.label) + mods_display_name(field.values, &block)
48
+ end
49
+
50
+ def mods_display_name(names, &block)
51
+ names.map do |name|
52
+ content_tag(:dd) do
53
+ block_given? ? yield(name.name) : name.name
54
+ end
55
+ end.join.html_safe
56
+ end
57
+
58
+ # We need this to remove the ending ":" from the role labels only in data from
59
+ # mods_display
60
+ def sanitize_mods_name_label(label)
61
+ label.sub(/:$/, '')
62
+ end
63
+
64
+ def mods_subject_field(subject, &block)
65
+ return unless subject.values.any?(&:present?)
66
+
67
+ fields = subject.values.map do |subject_line|
68
+ content_tag :dd, safe_join(link_mods_subjects(subject_line, &block), ' > ')
69
+ end
70
+
71
+ (mods_display_label(subject.label) + safe_join(fields))
72
+ end
73
+
74
+ def mods_genre_field(genre, &block)
75
+ return unless genre.values.any?(&:present?)
76
+
77
+ fields = genre.values.map do |genre_line|
78
+ content_tag :dd, link_mods_genres(genre_line, &block)
79
+ end
80
+
81
+ mods_display_label(genre.label) + safe_join(fields)
82
+ end
83
+
84
+ def link_mods_genres(genre, &block)
85
+ link_buffer = []
86
+ link_to_mods_subject(genre, link_buffer, &block)
87
+ end
88
+
89
+ def link_mods_subjects(subjects, &block)
90
+ link_buffer = []
91
+ linked_subjects = []
92
+ subjects.each do |subject|
93
+ if subject.present?
94
+ linked_subjects << link_to_mods_subject(subject, link_buffer, &block)
95
+ end
96
+ end
97
+ linked_subjects
98
+ end
99
+
100
+ def link_to_mods_subject(subject, buffer, &block)
101
+ subject_text = subject.respond_to?(:name) ? subject.name : subject
102
+ link = block_given? ? yield(subject_text, buffer) : subject_text
103
+ buffer << subject_text.strip
104
+ link << " (#{subject.roles.join(', ')})" if subject.respond_to?(:roles) && subject.roles.present?
105
+ link
106
+ end
107
+
108
+ # rubocop:disable Layout/LineLength
109
+ def link_urls_and_email(val)
110
+ val = val.dup
111
+ # http://daringfireball.net/2010/07/improved_regex_for_matching_urls
112
+ url = %r{(?i)\b(?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\([^\s()<>]+|\([^\s()<>]+\)*\))+(?:\([^\s()<>]+|\([^\s()<>]+\)*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])}i
113
+ # http://www.regular-expressions.info/email.html
114
+ email = %r{[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[A-Z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|asia|jobs|museum)\b}i
115
+ matches = [val.scan(url), val.scan(email)].flatten.uniq
116
+ unless val =~ /<a/ # we'll assume that linking has alraedy occured and we don't want to double link
117
+ matches.each do |match|
118
+ if match =~ email
119
+ val.gsub!(match, "<a href='mailto:#{match}'>#{match}</a>")
120
+ else
121
+ val.gsub!(match, "<a href='#{match}'>#{match}</a>")
122
+ end
123
+ end
124
+ end
125
+ val
126
+ end
127
+ # rubocop:enable Layout/LineLength
128
+
129
+ end
130
+ end
131
+ end
@@ -41,7 +41,9 @@ module ModsDisplay
41
41
  if to_s.respond_to?(method_name)
42
42
  to_html.send(method_name, *args, &block)
43
43
  elsif method_name == :subTitle || mods_display_fields.include?(method_name)
44
- mods_field(@xml, method_name).fields
44
+ field = mods_field(@xml, method_name)
45
+ return field if (args.dig(0, :raw))
46
+ field.fields
45
47
  else
46
48
  super
47
49
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ModsDisplay
4
+ class Railtie < ::Rails::Railtie
5
+ ActiveSupport.on_load :action_view do
6
+ require 'mods_display/helpers/record_helper'
7
+ ::ActionView::Base.send :include, ModsDisplay::Helpers::RecordHelper
8
+ end
9
+ end
10
+ end
@@ -1,3 +1,3 @@
1
1
  module ModsDisplay
2
- VERSION = '0.6.0'
2
+ VERSION = '0.9.1'
3
3
  end
data/mods_display.gemspec CHANGED
@@ -22,7 +22,9 @@ Gem::Specification.new do |gem|
22
22
 
23
23
  gem.add_development_dependency 'rake'
24
24
  gem.add_development_dependency 'rspec', '~> 3.0'
25
+ gem.add_development_dependency 'rspec-rails'
25
26
  gem.add_development_dependency 'rubocop'
26
27
  gem.add_development_dependency 'capybara'
27
28
  gem.add_development_dependency 'byebug'
29
+ gem.add_development_dependency 'rails', '~> 6.0'
28
30
  end
data/spec/fake_app.rb ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'action_controller/railtie'
4
+ require 'action_view/railtie'
5
+
6
+ class ModsDisplayTestApp < Rails::Application
7
+ end
8
+
9
+ Rails.application.routes.draw do
10
+ resources 'searches', only: :index
11
+ end
12
+
13
+ class ApplicationController < ActionController::Base; end
14
+ class SearchesController < ApplicationController
15
+ def index; end
16
+ end
17
+
18
+ Object.const_set(:ApplicationHelper, Module.new)
@@ -8,14 +8,6 @@ def mods_display_access_condition(mods_record)
8
8
  )
9
9
  end
10
10
 
11
- def mods_display_versioned_access_condition(mods_record, version)
12
- ModsDisplay::AccessCondition.new(
13
- mods_record,
14
- ModsDisplay::Configuration::AccessCondition.new { cc_license_version version },
15
- double('controller')
16
- )
17
- end
18
-
19
11
  def mods_display_non_ignore_access_condition(mods_record)
20
12
  ModsDisplay::AccessCondition.new(
21
13
  mods_record,
@@ -33,6 +25,7 @@ describe ModsDisplay::AccessCondition do
33
25
  @cc_license_note = Stanford::Mods::Record.new.from_str(cc_license_fixture, false).accessCondition
34
26
  @odc_license_note = Stanford::Mods::Record.new.from_str(odc_license_fixture, false).accessCondition
35
27
  @no_link_license_note = Stanford::Mods::Record.new.from_str(no_license_fixture, false).accessCondition
28
+ @garbage_license_fixture = Stanford::Mods::Record.new.from_str(garbage_license_fixture, false).accessCondition
36
29
  end
37
30
  describe 'labels' do
38
31
  it 'should normalize types and assign proper labels' do
@@ -62,37 +55,25 @@ describe ModsDisplay::AccessCondition do
62
55
  expect(fields.first.values.length).to eq(1)
63
56
  expect(fields.first.values.first).to match(%r{^<div class='unknown-something'>.*</div>$})
64
57
  end
65
- it 'should itentify and link CreativeCommons licenses properly' do
58
+ it 'should identify and link CreativeCommons licenses properly' do
66
59
  fields = mods_display_access_condition(@cc_license_note).fields
67
60
  expect(fields.length).to eq(1)
68
61
  expect(fields.first.values.length).to eq(1)
69
62
  expect(fields.first.values.first).to include("<a href='http://creativecommons.org/licenses/by-sa/3.0/'>")
70
63
  expect(fields.first.values.first).to include(
71
- 'This work is licensed under a Creative Commons Attribution-Noncommercial 3.0 Unported License'
64
+ 'This work is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License'
72
65
  )
73
66
  end
74
- it 'should itentify and link OpenDataCommons licenses properly' do
67
+ it 'should identify and link OpenDataCommons licenses properly' do
75
68
  fields = mods_display_access_condition(@odc_license_note).fields
76
69
  expect(fields.length).to eq(1)
77
70
  expect(fields.first.values.length).to eq(1)
78
- expect(fields.first.values.first).to include("<a href='http://opendatacommons.org/licenses/pddl'>")
71
+ expect(fields.first.values.first).to include("<a href='http://opendatacommons.org/licenses/pddl/'>")
79
72
  expect(fields.first.values.first).to include(
80
73
  'This work is licensed under a Open Data Commons Public Domain Dedication and License (PDDL)'
81
74
  )
82
75
  end
83
- it 'should have a configurable version for CC licenses' do
84
- fields = mods_display_versioned_access_condition(@cc_license_note, '4.0').fields
85
- expect(fields.length).to eq(1)
86
- expect(fields.first.values.length).to eq(1)
87
- expect(fields.first.values.first).to include('http://creativecommons.org/licenses/by-sa/4.0/')
88
- expect(fields.first.values.first).not_to include('http://creativecommons.org/licenses/by-sa/3.0/')
89
- end
90
- it 'should not apply configured version to NON-CC licenses' do
91
- fields = mods_display_versioned_access_condition(@odc_license_note, '4.0').fields
92
- expect(fields.length).to eq(1)
93
- expect(fields.first.values.length).to eq(1)
94
- expect(fields.first.values.first).not_to include('/4.0/')
95
- end
76
+
96
77
  it 'should not attempt unknown license types' do
97
78
  fields = mods_display_access_condition(@no_link_license_note).fields
98
79
  expect(fields.length).to eq(1)
@@ -102,6 +83,16 @@ describe ModsDisplay::AccessCondition do
102
83
  )
103
84
  expect(fields.first.values.first).not_to include('<a.*>')
104
85
  end
86
+
87
+ it 'returns the license text if it does not look like our expected format' do
88
+ fields = mods_display_access_condition(@garbage_license_fixture).fields
89
+ expect(fields.length).to eq(1)
90
+ expect(fields.first.values.length).to eq(1)
91
+ expect(fields.first.values.first).to include(
92
+ 'Unknown garbage that does not look like a license'
93
+ )
94
+ expect(fields.first.values.first).not_to include('<a.*>')
95
+ end
105
96
  end
106
97
  end
107
98
  describe 'to_html' do
@@ -43,6 +43,7 @@ describe ModsDisplay::Imprint do
43
43
  @imprint_date_range = Stanford::Mods::Record.new.from_str(imprint_date_range, false).origin_info
44
44
  @encoded_place = Stanford::Mods::Record.new.from_str(encoded_place, false).origin_info
45
45
  @encoded_dates = Stanford::Mods::Record.new.from_str(encoded_dates, false).origin_info
46
+ @iso8601_encoded_dates = Stanford::Mods::Record.new.from_str(iso8601_encoded_dates, false).origin_info
46
47
  @bad_dates = Stanford::Mods::Record.new.from_str(bad_dates, false).origin_info
47
48
  @invalid_dates = Stanford::Mods::Record.new.from_str(invalid_dates, false).origin_info
48
49
  @punctuation_imprint = Stanford::Mods::Record.new.from_str(punctuation_imprint_fixture, false).origin_info
@@ -209,6 +210,23 @@ describe ModsDisplay::Imprint do
209
210
  end.values).to eq(['July (2013)'])
210
211
  end
211
212
  end
213
+
214
+ describe 'iso8601' do
215
+ it 'handles full dates properly' do
216
+ fields = mods_display_imprint(@iso8601_encoded_dates).fields
217
+ expect(fields.length).to eq(2)
218
+ expect(fields.find do |field|
219
+ field.label == 'Date created:'
220
+ end.values).to eq(['November 14, 2013'])
221
+ end
222
+ it "should not try to handle dates we can't parse" do
223
+ fields = mods_display_imprint(@iso8601_encoded_dates).fields
224
+ expect(fields.length).to eq(2)
225
+ expect(fields.find do |field|
226
+ field.label == 'Date modified:'
227
+ end.values).to eq(['Jul. 22, 2013'])
228
+ end
229
+ end
212
230
  end
213
231
  describe 'bad dates' do
214
232
  it 'should ignore date values' do
@@ -47,4 +47,12 @@ module AccessConditionFixtures
47
47
  </mods>
48
48
  XML
49
49
  end
50
+
51
+ def garbage_license_fixture
52
+ <<-XML
53
+ <mods>
54
+ <accessCondition type='license'>Unknown garbage that does not look like a license</accessCondition>
55
+ </mods>
56
+ XML
57
+ end
50
58
  end
@@ -280,6 +280,17 @@ module ImprintFixtures
280
280
  MODS
281
281
  end
282
282
 
283
+ def iso8601_encoded_dates
284
+ <<-MODS
285
+ <mods>
286
+ <originInfo>
287
+ <dateCreated encoding="iso8601">20131114161429</dateCreated>
288
+ <dateModified encoding="iso8601">Jul. 22, 2013</dateModified>
289
+ </originInfo>
290
+ </mods>
291
+ MODS
292
+ end
293
+
283
294
  def bad_dates
284
295
  <<-MODS
285
296
  <mods>
@@ -0,0 +1,241 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'byebug'
5
+
6
+ describe ModsDisplay::Helpers::RecordHelper, type: :helper do
7
+ let(:empty_field) { OpenStruct.new(label: 'test', values: ['']) }
8
+
9
+ describe 'display_content_field' do
10
+ let(:values) { ['guitar (1)', 'solo cowbell, trombone (2)'] }
11
+ let(:content) { OpenStruct.new(label: 'Instrumentation', values: values) }
12
+
13
+ it 'should return dt with label and dd with values' do
14
+ expect(helper.display_content_field(content)).to have_css('dt', text: 'Instrumentation')
15
+ expect(helper.display_content_field(content)).to have_css('dd', count: 2)
16
+ end
17
+ end
18
+
19
+ describe 'display_content_label' do
20
+ it 'should return correct dt' do
21
+ expect(helper.display_content_label('test')).to have_css('dt', text: 'test')
22
+ end
23
+ end
24
+
25
+ describe 'display_content_values' do
26
+ let(:values) { ['guitar (1)', 'solo cowbell, trombone (2)'] }
27
+
28
+ it 'should return dds of values' do
29
+ expect(helper.display_content_values(values)).to have_css('dd', count: 2)
30
+ expect(helper.display_content_values(values)).to have_css('dd', text: 'guitar (1)')
31
+ expect(helper.display_content_values(values)).to have_css('dd', text: 'solo cowbell, trombone (2)')
32
+ end
33
+ end
34
+
35
+ describe 'mods_display_label' do
36
+ it 'should return correct label' do
37
+ expect(helper.mods_display_label('test:')).not_to have_content ':'
38
+ expect(helper.mods_display_label('test:')).to have_css('dt', text: 'test')
39
+ end
40
+ end
41
+
42
+ describe 'mods_display_content' do
43
+ it 'should return correct content' do
44
+ expect(helper.mods_display_content('hello, there')).to have_css('dd', text: 'hello, there')
45
+ end
46
+ it 'should return multiple dd elements when a multi-element array is passed' do
47
+ expect(helper.mods_display_content(%w(hello there))).to have_css('dd', count: 2)
48
+ end
49
+ it 'should handle nil values correctly' do
50
+ expect(helper.mods_display_content(['something', nil])).to have_css('dd', count: 1)
51
+ end
52
+ end
53
+
54
+ describe 'mods_record_field' do
55
+ let(:mods_field) { OpenStruct.new(label: 'test', values: ['hello, there']) }
56
+ let(:url_field) { OpenStruct.new(label: 'test', values: ['https://library.stanford.edu']) }
57
+ let(:multi_values) { double(label: 'test', values: %w(123 321)) }
58
+
59
+ it 'should return correct content' do
60
+ expect(helper.mods_record_field(mods_field)).to have_css('dt', text: 'test')
61
+ expect(helper.mods_record_field(mods_field)).to have_css('dd', text: 'hello, there')
62
+ end
63
+ it 'should link fields with URLs' do
64
+ expect(mods_record_field(url_field)).to have_css("a[href='https://library.stanford.edu']", text: 'https://library.stanford.edu')
65
+ end
66
+ it 'should not print empty labels' do
67
+ expect(helper.mods_record_field(empty_field)).not_to be_present
68
+ end
69
+ it 'should join values with a <dd> by default' do
70
+ expect(helper.mods_record_field(multi_values)).to have_css('dd', count: 2)
71
+ end
72
+ it 'should join values with a supplied delimiter' do
73
+ expect(helper.mods_record_field(multi_values, 'DELIM')).to have_css('dd', count: 1)
74
+ expect(helper.mods_record_field(multi_values, 'DELIM')).to have_css('dd', text: '123DELIM321')
75
+ end
76
+ end
77
+
78
+ describe 'names' do
79
+ let(:name_field) do
80
+ OpenStruct.new(
81
+ label: 'Contributor',
82
+ values: [
83
+ OpenStruct.new(name: 'Winefrey, Oprah', roles: %w(Host Producer)),
84
+ OpenStruct.new(name: 'Kittenz, Emergency')
85
+ ]
86
+ )
87
+ end
88
+
89
+ describe '#mods_name_field' do
90
+ it 'should join the label and values' do
91
+ name = mods_name_field(name_field) do |name|
92
+ link_to(name, searches_path(q: "\"#{name}\"", search_field: 'search_author'))
93
+ end
94
+ expect(name).to match /<dt>Contributor<\/dt>/
95
+ expect(name).to match /<dd><a href.*<\/dd>/
96
+ end
97
+ it 'should not print empty labels' do
98
+ expect(mods_name_field(empty_field)).not_to be_present
99
+ end
100
+ end
101
+
102
+ describe '#mods_display_name' do
103
+ let(:name) do
104
+ mods_display_name(name_field.values) do |name|
105
+ link_to(name, searches_path(q: "\"#{name}\"", search_field: 'search_author'))
106
+ end
107
+ end
108
+
109
+ it 'should link to the name' do
110
+ expect(name).to match /<a href=.*%22Winefrey%2C\+Oprah%22.*>Winefrey, Oprah<\/a>/
111
+ expect(name).to match /<a href=.*%22Kittenz%2C\+Emergency%22.*>Kittenz, Emergency<\/a>/
112
+ end
113
+ it 'should link to an author search' do
114
+ expect(name).to match /<a href.*search_field=search_author.*>/
115
+ end
116
+ end
117
+
118
+ describe '#sanitize_mods_name_label' do
119
+ it 'removes a ":" at the end of label if present' do
120
+ expect(sanitize_mods_name_label('Test String:')).to eq 'Test String'
121
+ expect(sanitize_mods_name_label('Test String')).to eq 'Test String'
122
+ end
123
+ end
124
+ end
125
+
126
+ describe 'subjects' do
127
+ let(:subjects) { [OpenStruct.new(label: 'Subjects', values: [%w(Subject1a Subject1b), %w(Subject2a Subject2b Subject2c)])] }
128
+ let(:name_subjects) { [OpenStruct.new(label: 'Subjects', values: [OpenStruct.new(name: 'Person Name', roles: %w(Role1 Role2))])] }
129
+ let(:genres) { [OpenStruct.new(label: 'Genres', values: %w(Genre1 Genre2 Genre3))] }
130
+
131
+ describe '#mods_subject_field' do
132
+ let(:subject) do
133
+ mods_subject_field(subjects.first) do |subject_text|
134
+ link_to(
135
+ subject_text,
136
+ searches_path(
137
+ q: "\"#{[[], subject_text.strip].flatten.join(' ')}\"",
138
+ search_field: 'subject_terms'
139
+ )
140
+ )
141
+ end
142
+ end
143
+ it 'should join the subject fields in a dd' do
144
+ expect(subject).to match /<dd><a href=*.*\">Subject1a*.*Subject1b<\/a><\/dd><dd><a/
145
+ end
146
+ it "should join the individual subjects with a '>'" do
147
+ expect(subject).to match /Subject2b<\/a> &gt; <a href/
148
+ end
149
+ it 'should not print empty labels' do
150
+ expect(mods_subject_field(empty_field)).not_to be_present
151
+ end
152
+ end
153
+
154
+ describe '#mods_genre_field' do
155
+ it 'should join the genre fields with a dd' do
156
+ expect(mods_genre_field(genres.first) do |text|
157
+ link_to(text, searches_path(q: text))
158
+ end).to match /<dd><a href=*.*>Genre1*.*<\/a><\/dd><dd><a*.*Genre2<\/a><\/dd>/
159
+ end
160
+ it 'should not print empty labels' do
161
+ expect(mods_genre_field(empty_field)).not_to be_present
162
+ end
163
+ end
164
+
165
+ describe '#link_mods_subjects' do
166
+ let(:linked_subjects) do
167
+ link_mods_subjects(subjects.first.values.last) do |subject_text, buffer|
168
+ link_to(
169
+ subject_text,
170
+ searches_path(
171
+ q: "\"#{[buffer, subject_text.strip].flatten.join(' ')}\"",
172
+ search_field: 'subject_terms'
173
+ )
174
+ )
175
+ end
176
+ end
177
+
178
+ it 'should return all subjects' do
179
+ expect(linked_subjects.length).to eq 3
180
+ end
181
+ it 'should link to the subject hierarchically' do
182
+ expect(linked_subjects[0]).to match /^<a href=.*q=%22Subject2a%22.*>Subject2a<\/a>$/
183
+ expect(linked_subjects[1]).to match /^<a href=.*q=%22Subject2a\+Subject2b%22.*>Subject2b<\/a>$/
184
+ expect(linked_subjects[2]).to match /^<a href=.*q=%22Subject2a\+Subject2b\+Subject2c%22.*>Subject2c<\/a>$/
185
+ end
186
+ it 'should link to subject terms search field' do
187
+ linked_subjects.each do |subject|
188
+ expect(subject).to match /search_field=subject_terms/
189
+ end
190
+ end
191
+ end
192
+
193
+ describe '#link_mods_genres' do
194
+ let(:linked_genres) do
195
+ link_mods_genres(genres.first.values.last) do |text|
196
+ link_to(
197
+ text,
198
+ searches_path(
199
+ q: "\"#{[[], text.strip].flatten.join(' ')}\"",
200
+ search_field: 'subject_terms'
201
+ )
202
+ )
203
+ end
204
+ end
205
+
206
+ it 'should return correct link' do
207
+ expect(linked_genres).to match /<a href=*.*Genre3*.*<\/a>/
208
+ end
209
+ it 'should link to subject terms search field' do
210
+ expect(linked_genres).to match /search_field=subject_terms/
211
+ end
212
+ end
213
+
214
+ describe '#link_to_mods_subject' do
215
+ it 'should handle subjects that behave like names' do
216
+ name_subject = link_to_mods_subject(name_subjects.first.values.first, []) do |subject_text|
217
+ link_to(
218
+ subject_text,
219
+ searches_path(
220
+ q: "\"#{[[], subject_text.strip].flatten.join(' ')}\"",
221
+ search_field: 'subject_terms'
222
+ )
223
+ )
224
+ end
225
+ expect(name_subject).to match /<a href=.*%22Person\+Name%22.*>Person Name<\/a> \(Role1, Role2\)/
226
+ end
227
+ end
228
+ end
229
+
230
+ describe '#link_urls_and_email' do
231
+ let(:url) { 'This is a field that contains an https://library.stanford.edu URL' }
232
+ let(:email) { 'This is a field that contains an email@email.com address' }
233
+
234
+ it 'should link URLs' do
235
+ expect(link_urls_and_email(url)).to eq "This is a field that contains an <a href='https://library.stanford.edu'>https://library.stanford.edu</a> URL"
236
+ end
237
+ it 'should link email addresses' do
238
+ expect(link_urls_and_email(email)).to eq "This is a field that contains an <a href='mailto:email@email.com'>email@email.com</a> address"
239
+ end
240
+ end
241
+ end
@@ -79,4 +79,9 @@ describe 'HTML Output' do
79
79
  expect { @abstract.not_a_real_field }.to raise_error NoMethodError
80
80
  end
81
81
  end
82
+ describe 'individual fields' do
83
+ it 'should return ModsDispaly::Class when raw is specified' do
84
+ expect(@abstract.abstract(raw: true)).to be_a ModsDisplay::Abstract
85
+ end
86
+ end
82
87
  end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,11 @@
1
+ ENV['RAILS_ENV'] ||= 'test'
1
2
  require 'mods_display'
2
3
  require 'stanford-mods'
3
4
  require 'capybara'
5
+ require 'rails'
6
+ require 'fake_app'
7
+ require 'rspec/rails'
8
+ require 'mods_display/helpers/record_helper'
4
9
 
5
10
  Dir["#{File.expand_path('..', __FILE__)}/fixtures/*.rb"].each { |file| require file }
6
11
  # Load i18n test file.
@@ -24,6 +29,7 @@ RSpec.configure do |config|
24
29
  # the seed, which is printed after each run.
25
30
  # --seed 1234
26
31
  config.order = 'random'
32
+ config.include Rails.application.routes.url_helpers
27
33
  end
28
34
  class TestModel
29
35
  attr_accessor :modsxml
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mods_display
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jessie Keck
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-01 00:00:00.000000000 Z
11
+ date: 2021-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: stanford-mods
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rubocop
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +122,20 @@ dependencies:
108
122
  - - ">="
109
123
  - !ruby/object:Gem::Version
110
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rails
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '6.0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '6.0'
111
139
  description: MODS Display is a gem to centralize the display logic of MODS medadata.
112
140
  email:
113
141
  - jessie.keck@gmail.com
@@ -115,10 +143,10 @@ executables: []
115
143
  extensions: []
116
144
  extra_rdoc_files: []
117
145
  files:
146
+ - ".github/workflows/ruby.yml"
118
147
  - ".gitignore"
119
148
  - ".rubocop.yml"
120
149
  - ".rubocop_todo.yml"
121
- - ".travis.yml"
122
150
  - Gemfile
123
151
  - LICENSE.txt
124
152
  - README.md
@@ -163,14 +191,17 @@ files:
163
191
  - lib/mods_display/fields/subject.rb
164
192
  - lib/mods_display/fields/title.rb
165
193
  - lib/mods_display/fields/values.rb
194
+ - lib/mods_display/helpers/record_helper.rb
166
195
  - lib/mods_display/html.rb
167
196
  - lib/mods_display/model_extension.rb
197
+ - lib/mods_display/railtie.rb
168
198
  - lib/mods_display/related_item_concerns.rb
169
199
  - lib/mods_display/relator_codes.rb
170
200
  - lib/mods_display/version.rb
171
201
  - mods_display.gemspec
172
202
  - spec/configuration/access_condition_spec.rb
173
203
  - spec/configuration/base_spec.rb
204
+ - spec/fake_app.rb
174
205
  - spec/fields/abstract_spec.rb
175
206
  - spec/fields/access_condition_spec.rb
176
207
  - spec/fields/audience_spec.rb
@@ -203,6 +234,7 @@ files:
203
234
  - spec/fixtures/related_item_fixtures.rb
204
235
  - spec/fixtures/subjects_fixtures.rb
205
236
  - spec/fixtures/title_fixtures.rb
237
+ - spec/helpers/record_helper_spec.rb
206
238
  - spec/integration/configuration_spec.rb
207
239
  - spec/integration/html_spec.rb
208
240
  - spec/integration/installation_spec.rb
@@ -211,7 +243,7 @@ files:
211
243
  homepage: https://github.com/sul-dlss/mods_display
212
244
  licenses: []
213
245
  metadata: {}
214
- post_install_message:
246
+ post_install_message:
215
247
  rdoc_options: []
216
248
  require_paths:
217
249
  - lib
@@ -226,9 +258,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
226
258
  - !ruby/object:Gem::Version
227
259
  version: '0'
228
260
  requirements: []
229
- rubyforge_project:
230
- rubygems_version: 2.7.6
231
- signing_key:
261
+ rubygems_version: 3.2.3
262
+ signing_key:
232
263
  specification_version: 4
233
264
  summary: The MODS Display gem allows implementers to configure a customized display
234
265
  of MODS metadata. This display implements the specifications defined at Stanford
@@ -236,6 +267,7 @@ summary: The MODS Display gem allows implementers to configure a customized disp
236
267
  test_files:
237
268
  - spec/configuration/access_condition_spec.rb
238
269
  - spec/configuration/base_spec.rb
270
+ - spec/fake_app.rb
239
271
  - spec/fields/abstract_spec.rb
240
272
  - spec/fields/access_condition_spec.rb
241
273
  - spec/fields/audience_spec.rb
@@ -268,6 +300,7 @@ test_files:
268
300
  - spec/fixtures/related_item_fixtures.rb
269
301
  - spec/fixtures/subjects_fixtures.rb
270
302
  - spec/fixtures/title_fixtures.rb
303
+ - spec/helpers/record_helper_spec.rb
271
304
  - spec/integration/configuration_spec.rb
272
305
  - spec/integration/html_spec.rb
273
306
  - spec/integration/installation_spec.rb
data/.travis.yml DELETED
@@ -1,5 +0,0 @@
1
- notifications:
2
- email: false
3
- rvm:
4
- - 2.4.1
5
- - 2.3.4