mods_display 0.9.1 → 1.0.0.alpha2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -1
- data/.rubocop_todo.yml +433 -35
- data/README.md +0 -95
- data/app/components/mods_display/field_component.html.erb +13 -0
- data/app/components/mods_display/field_component.rb +27 -0
- data/app/components/mods_display/list_field_component.html.erb +11 -0
- data/app/components/mods_display/list_field_component.rb +10 -0
- data/app/components/mods_display/record_component.html.erb +5 -0
- data/app/components/mods_display/record_component.rb +39 -0
- data/app/helpers/mods_display/record_helper.rb +106 -0
- data/app/models/mods_display/record.rb +26 -0
- data/config/locales/en.yml +1 -1
- data/config.ru +9 -0
- data/lib/mods_display/engine.rb +13 -0
- data/lib/mods_display/fields/access_condition.rb +4 -0
- data/lib/mods_display/fields/contents.rb +14 -15
- data/lib/mods_display/fields/field.rb +13 -149
- data/lib/mods_display/fields/genre.rb +4 -0
- data/lib/mods_display/fields/imprint.rb +52 -3
- data/lib/mods_display/fields/location.rb +1 -1
- data/lib/mods_display/fields/name.rb +11 -20
- data/lib/mods_display/fields/nested_related_item.rb +7 -18
- data/lib/mods_display/fields/note.rb +4 -0
- data/lib/mods_display/fields/related_item.rb +4 -0
- data/lib/mods_display/fields/resource_type.rb +1 -1
- data/lib/mods_display/fields/sub_title.rb +3 -3
- data/lib/mods_display/fields/subject.rb +13 -39
- data/lib/mods_display/fields/title.rb +43 -32
- data/lib/mods_display/fields/values.rb +4 -4
- data/lib/mods_display/html.rb +55 -106
- data/lib/mods_display/version.rb +1 -1
- data/lib/mods_display.rb +2 -17
- data/mods_display.gemspec +15 -9
- metadata +45 -105
- data/.github/workflows/ruby.yml +0 -24
- data/.gitignore +0 -21
- data/lib/mods_display/configuration/access_condition.rb +0 -21
- data/lib/mods_display/configuration/base.rb +0 -34
- data/lib/mods_display/configuration/genre.rb +0 -9
- data/lib/mods_display/configuration/imprint.rb +0 -13
- data/lib/mods_display/configuration/name.rb +0 -9
- data/lib/mods_display/configuration/note.rb +0 -9
- data/lib/mods_display/configuration/related_item.rb +0 -9
- data/lib/mods_display/configuration/subject.rb +0 -13
- data/lib/mods_display/configuration/title.rb +0 -9
- data/lib/mods_display/configuration.rb +0 -93
- data/lib/mods_display/controller_extension.rb +0 -32
- data/lib/mods_display/helpers/record_helper.rb +0 -131
- data/lib/mods_display/model_extension.rb +0 -22
- data/lib/mods_display/railtie.rb +0 -10
- data/spec/configuration/access_condition_spec.rb +0 -10
- data/spec/configuration/base_spec.rb +0 -39
- data/spec/fake_app.rb +0 -18
- data/spec/fields/abstract_spec.rb +0 -39
- data/spec/fields/access_condition_spec.rb +0 -107
- data/spec/fields/audience_spec.rb +0 -24
- data/spec/fields/cartographics_spec.rb +0 -38
- data/spec/fields/collection_spec.rb +0 -77
- data/spec/fields/contact_spec.rb +0 -23
- data/spec/fields/contents_spec.rb +0 -39
- data/spec/fields/description_spec.rb +0 -55
- data/spec/fields/extent_spec.rb +0 -31
- data/spec/fields/form_spec.rb +0 -49
- data/spec/fields/genre_spec.rb +0 -34
- data/spec/fields/geo_spec.rb +0 -40
- data/spec/fields/identifier_spec.rb +0 -61
- data/spec/fields/imprint_spec.rb +0 -289
- data/spec/fields/language_spec.rb +0 -51
- data/spec/fields/location_spec.rb +0 -81
- data/spec/fields/name_spec.rb +0 -166
- data/spec/fields/nested_related_item_spec.rb +0 -89
- data/spec/fields/note_spec.rb +0 -72
- data/spec/fields/related_item_spec.rb +0 -72
- data/spec/fields/resource_type_spec.rb +0 -34
- data/spec/fields/sub_title_spec.rb +0 -20
- data/spec/fields/subject_spec.rb +0 -113
- data/spec/fields/title_spec.rb +0 -74
- data/spec/fixtures/access_condition_fixtures.rb +0 -58
- data/spec/fixtures/cartographics_fixtures.rb +0 -52
- data/spec/fixtures/imprint_fixtures.rb +0 -349
- data/spec/fixtures/name_fixtures.rb +0 -398
- data/spec/fixtures/nested_realted_items_fixtures.rb +0 -64
- data/spec/fixtures/related_item_fixtures.rb +0 -107
- data/spec/fixtures/subjects_fixtures.rb +0 -115
- data/spec/fixtures/title_fixtures.rb +0 -101
- data/spec/helpers/record_helper_spec.rb +0 -241
- data/spec/integration/configuration_spec.rb +0 -57
- data/spec/integration/html_spec.rb +0 -87
- data/spec/integration/installation_spec.rb +0 -26
- data/spec/spec_helper.rb +0 -46
- data/spec/test_fr.yml +0 -3
@@ -0,0 +1,27 @@
|
|
1
|
+
module ModsDisplay
|
2
|
+
class FieldComponent < ViewComponent::Base
|
3
|
+
with_collection_parameter :field
|
4
|
+
|
5
|
+
def initialize(field:, delimiter: nil, label_html_attributes: {}, value_html_attributes: {}, value_transformer: nil)
|
6
|
+
super
|
7
|
+
|
8
|
+
@field = field
|
9
|
+
@delimiter = delimiter
|
10
|
+
@value_transformer = value_transformer
|
11
|
+
@label_html_attributes = label_html_attributes
|
12
|
+
@value_html_attributes = value_html_attributes
|
13
|
+
end
|
14
|
+
|
15
|
+
def render?
|
16
|
+
@field.values.any?(&:present?)
|
17
|
+
end
|
18
|
+
|
19
|
+
def format_value(value)
|
20
|
+
if @value_transformer
|
21
|
+
@value_transformer.call(value)
|
22
|
+
else
|
23
|
+
helpers.link_urls_and_email(value)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<% if @field.label %>
|
2
|
+
<%= tag.dt @field.label.sub(/:$/, ''), **@label_html_attributes %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<%= tag.dd format_value(value), **@value_html_attributes %>
|
6
|
+
<% tag.ul **@list_html_attributes %>
|
7
|
+
<% @field.values.select(&:present?).each do |value| %>
|
8
|
+
<%= tag.li format_value(value), **@list_item_html_attributes %>
|
9
|
+
<% end %>
|
10
|
+
<% end %>
|
11
|
+
<% end %>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module ModsDisplay
|
2
|
+
class ListFieldComponent < ModsDisplay::FieldComponent
|
3
|
+
def initialize(list_html_attributes: {}, list_item_html_attributes: {}, **args)
|
4
|
+
super(**args)
|
5
|
+
|
6
|
+
@list_html_attributes = list_html_attributes
|
7
|
+
@list_item_html_attributes = list_item_html_attributes
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module ModsDisplay
|
2
|
+
class RecordComponent < ViewComponent::Base
|
3
|
+
DEFAULT_FIELDS = [
|
4
|
+
:subTitle,
|
5
|
+
:name,
|
6
|
+
:language,
|
7
|
+
:imprint,
|
8
|
+
:resourceType,
|
9
|
+
:genre,
|
10
|
+
:form,
|
11
|
+
:extent,
|
12
|
+
:geo,
|
13
|
+
:description,
|
14
|
+
:cartographics,
|
15
|
+
:abstract,
|
16
|
+
:contents,
|
17
|
+
:audience,
|
18
|
+
:note,
|
19
|
+
:contact,
|
20
|
+
:collection,
|
21
|
+
:nestedRelatedItem,
|
22
|
+
:relatedItem,
|
23
|
+
:subject,
|
24
|
+
:identifier,
|
25
|
+
:location
|
26
|
+
# :accessCondition
|
27
|
+
].freeze
|
28
|
+
|
29
|
+
with_collection_parameter :record
|
30
|
+
|
31
|
+
def initialize(record:, fields: DEFAULT_FIELDS, html_attributes: {})
|
32
|
+
super
|
33
|
+
|
34
|
+
@record = record
|
35
|
+
@fields = fields
|
36
|
+
@html_attributes = html_attributes
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ModsDisplay
|
4
|
+
module RecordHelper
|
5
|
+
def mods_display_label(label)
|
6
|
+
content_tag(:dt, label.delete(':')) + "\n".html_safe
|
7
|
+
end
|
8
|
+
|
9
|
+
# @private
|
10
|
+
def mods_display_content(values, delimiter = nil)
|
11
|
+
mods_record_field ModsDisplay::Values.new(values: Array(values)), delimiter
|
12
|
+
end
|
13
|
+
|
14
|
+
def mods_record_field(field, delimiter = nil, component: ModsDisplay::FieldComponent, &block)
|
15
|
+
render component.new(field: field, delimiter: delimiter, value_transformer: block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def mods_name_field(field, &block)
|
19
|
+
mods_record_field(field) do |name|
|
20
|
+
block_given? ? capture { yield(name.name) } : name.name
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def mods_display_name(values, &block)
|
25
|
+
mods_name_field(ModsDisplay::Values.new(values: Array(values)), &block)
|
26
|
+
end
|
27
|
+
|
28
|
+
# We need this to remove the ending ":" from the role labels only in data from
|
29
|
+
# mods_display
|
30
|
+
# @private (but currently used in searchworks)
|
31
|
+
def sanitize_mods_name_label(label)
|
32
|
+
label.sub(/:$/, '')
|
33
|
+
end
|
34
|
+
|
35
|
+
def mods_subject_field(field, &block)
|
36
|
+
mods_record_field(field) do |subject_line|
|
37
|
+
safe_join(link_mods_subjects(subject_line, &block), ' > ')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def mods_genre_field(field, &block)
|
42
|
+
mods_record_field(field) do |genre_line|
|
43
|
+
link_to_mods_subject(genre_line, &block)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# @private
|
48
|
+
def link_mods_genres(genre, &block)
|
49
|
+
link_buffer = []
|
50
|
+
link_to_mods_subject(genre, link_buffer, &block)
|
51
|
+
end
|
52
|
+
|
53
|
+
# @private
|
54
|
+
def link_mods_subjects(subjects, &block)
|
55
|
+
link_buffer = []
|
56
|
+
linked_subjects = []
|
57
|
+
subjects.each do |subject|
|
58
|
+
if subject.present?
|
59
|
+
linked_subjects << link_to_mods_subject(subject, link_buffer, &block)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
linked_subjects
|
63
|
+
end
|
64
|
+
|
65
|
+
# @private
|
66
|
+
def link_to_mods_subject(subject, buffer = [], &block)
|
67
|
+
subject_text = subject.respond_to?(:name) ? subject.name : subject
|
68
|
+
link = block_given? ? capture { yield(subject_text, buffer) } : subject_text
|
69
|
+
buffer << subject_text.strip
|
70
|
+
link << " (#{subject.roles.join(', ')})" if subject.respond_to?(:roles) && subject.roles.present?
|
71
|
+
link
|
72
|
+
end
|
73
|
+
|
74
|
+
# rubocop:disable Layout/LineLength
|
75
|
+
# @private, but used in PURL currently
|
76
|
+
def link_urls_and_email(val, tags: %w[a dl dd dt i b em strong])
|
77
|
+
val = val.gsub(%r{<[^/> ]+}) do |possible_tag|
|
78
|
+
# Allow potentially valid HTML tags through to the sanitizer step, and HTML escape the rest
|
79
|
+
if tags.include? possible_tag[1..]
|
80
|
+
possible_tag
|
81
|
+
else
|
82
|
+
"<#{possible_tag[1..]}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# http://daringfireball.net/2010/07/improved_regex_for_matching_urls
|
87
|
+
url = %r{(?i)\b(?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\([^\s()<>]+|\([^\s()<>]+\)*\))+(?:\([^\s()<>]+|\([^\s()<>]+\)*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])}i
|
88
|
+
# http://www.regular-expressions.info/email.html
|
89
|
+
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
|
90
|
+
matches = [val.scan(url), val.scan(email)].flatten.uniq
|
91
|
+
unless val =~ /<a/ # we'll assume that linking has alraedy occured and we don't want to double link
|
92
|
+
matches.each do |match|
|
93
|
+
if match =~ email
|
94
|
+
val.gsub!(match, "<a href='mailto:#{match}'>#{match}</a>")
|
95
|
+
else
|
96
|
+
val.gsub!(match, "<a href='#{match}'>#{match}</a>")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
sanitize val, tags: tags, attributes: %w[href]
|
102
|
+
end
|
103
|
+
# rubocop:enable Layout/LineLength
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stanford-mods'
|
4
|
+
|
5
|
+
##
|
6
|
+
# A convenience object for parsing and rendering MODS
|
7
|
+
module ModsDisplay
|
8
|
+
class Record
|
9
|
+
attr_reader :xml
|
10
|
+
|
11
|
+
def initialize(xml)
|
12
|
+
@xml = xml
|
13
|
+
end
|
14
|
+
|
15
|
+
def mods_record
|
16
|
+
return if xml.nil?
|
17
|
+
@mods_record ||= Stanford::Mods::Record.new.tap { |mods| mods.from_str(xml, false) }
|
18
|
+
end
|
19
|
+
|
20
|
+
def mods_display_html
|
21
|
+
return unless mods_record
|
22
|
+
|
23
|
+
ModsDisplay::HTML.new(mods_record)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/config/locales/en.yml
CHANGED
data/config.ru
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'view_component'
|
4
|
+
|
5
|
+
module ModsDisplay
|
6
|
+
class Engine < ::Rails::Engine
|
7
|
+
initializer 'mods_display.helpers' do
|
8
|
+
config.after_initialize do
|
9
|
+
ActionView::Base.include ModsDisplay::RecordHelper
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -1,21 +1,20 @@
|
|
1
1
|
module ModsDisplay
|
2
2
|
class Contents < Field
|
3
|
-
def to_html
|
4
|
-
|
5
|
-
|
6
|
-
fields.each do |field|
|
7
|
-
next unless field.values.any? { |f| f && !f.empty? }
|
8
|
-
output << "<dt#{label_class} #{sanitized_field_title(field.label)}>#{field.label}</dt>"
|
9
|
-
output << "<dd#{value_class}>"
|
10
|
-
output << '<ul><li>'
|
11
|
-
# compress all values into a "--"-delimited string then split them up
|
12
|
-
output << field.values.join('--').split('--').map(&:strip).map do |val|
|
13
|
-
@config.link ? link_to_value(val.to_s) : link_urls_and_email(val.to_s)
|
14
|
-
end.join('</li><li>')
|
15
|
-
output << '</li></ul>'
|
16
|
-
output << '</dd>'
|
3
|
+
def to_html(view_context = ApplicationController.renderer)
|
4
|
+
f = fields.map do |field|
|
5
|
+
ModsDisplay::Values.new(label: field.label, values: [field.values.join("\n\n")])
|
17
6
|
end
|
18
|
-
|
7
|
+
|
8
|
+
helpers = view_context.respond_to?(:simple_format) ? view_context : ApplicationController.new.view_context
|
9
|
+
|
10
|
+
value_transformer = lambda do |value|
|
11
|
+
text = ERB::Util.h(value.gsub(' ', "\n"))
|
12
|
+
helpers.simple_format(text, {}, sanitize: false)
|
13
|
+
end
|
14
|
+
|
15
|
+
component = ModsDisplay::FieldComponent.with_collection(f, value_transformer: value_transformer)
|
16
|
+
|
17
|
+
view_context.render component
|
19
18
|
end
|
20
19
|
|
21
20
|
private
|
@@ -1,10 +1,8 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module ModsDisplay
|
3
3
|
class Field
|
4
|
-
def initialize(values
|
4
|
+
def initialize(values)
|
5
5
|
@values = values
|
6
|
-
@config = config
|
7
|
-
@klass = klass
|
8
6
|
end
|
9
7
|
|
10
8
|
def fields
|
@@ -22,83 +20,18 @@ module ModsDisplay
|
|
22
20
|
displayLabel(@values.first)
|
23
21
|
end
|
24
22
|
|
25
|
-
def to_html
|
26
|
-
|
27
|
-
output = ''
|
28
|
-
fields.each do |field|
|
29
|
-
next unless field.values.any? { |f| f && !f.empty? }
|
30
|
-
output << "<dt#{label_class} #{sanitized_field_title(field.label)}>#{field.label}</dt>"
|
31
|
-
output << "<dd#{value_class}>"
|
32
|
-
output << field.values.map do |val|
|
33
|
-
@config.link ? link_to_value(val.to_s) : link_urls_and_email(val.to_s)
|
34
|
-
end.join(@config.delimiter)
|
35
|
-
output << '</dd>'
|
36
|
-
end
|
37
|
-
output
|
23
|
+
def to_html(view_context = ApplicationController.renderer)
|
24
|
+
view_context.render ModsDisplay::FieldComponent.with_collection(fields, delimiter: delimiter)
|
38
25
|
end
|
39
26
|
|
40
|
-
|
41
|
-
|
42
|
-
def compact_and_join_with_delimiter(values, delimiter)
|
43
|
-
compact_values = values.compact.reject { |v| v.strip.empty? }
|
44
|
-
return compact_values.join(delimiter) if compact_values.length == 1 ||
|
45
|
-
!ends_in_terminating_punctuation?(delimiter)
|
46
|
-
compact_values.each_with_index.map do |value, i|
|
47
|
-
if (compact_values.length - 1) == i || # last item?
|
48
|
-
ends_in_terminating_punctuation?(value)
|
49
|
-
value << ' '
|
50
|
-
else
|
51
|
-
value << delimiter
|
52
|
-
end
|
53
|
-
end.join.strip
|
27
|
+
def render_in(view_context)
|
28
|
+
to_html(view_context)
|
54
29
|
end
|
55
30
|
|
56
|
-
|
57
|
-
date_fields.map do |date_field|
|
58
|
-
case
|
59
|
-
when date_is_bc_edtf?(date_field)
|
60
|
-
year = date_field.text.strip.gsub(/^-0*/, '').to_i + 1
|
61
|
-
date_field.content = "#{year} B.C."
|
62
|
-
when date_is_ad?(date_field)
|
63
|
-
date_field.content = "#{date_field.text.strip.gsub(/^0*/, '')} A.D."
|
64
|
-
end
|
65
|
-
date_field
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def date_is_bc_edtf?(date_field)
|
70
|
-
date_field.text.strip.start_with?('-') && date_is_edtf?(date_field)
|
71
|
-
end
|
72
|
-
|
73
|
-
def date_is_ad?(date_field)
|
74
|
-
date_field.text.strip.gsub(/^0*/, '').length < 4
|
75
|
-
end
|
76
|
-
|
77
|
-
def date_is_edtf?(date_field)
|
78
|
-
field_is_encoded?(date_field, 'edtf')
|
79
|
-
end
|
80
|
-
|
81
|
-
def field_is_encoded?(field, encoding)
|
82
|
-
field.attributes['encoding'] &&
|
83
|
-
field.attributes['encoding'].respond_to?(:value) &&
|
84
|
-
field.attributes['encoding'].value.downcase == encoding
|
85
|
-
end
|
86
|
-
|
87
|
-
def ends_in_terminating_punctuation?(value)
|
88
|
-
value.strip.end_with?('.', ',', ':', ';')
|
89
|
-
end
|
90
|
-
|
91
|
-
def label_class
|
92
|
-
" class='#{@config.label_class}'" unless @config.label_class == ''
|
93
|
-
end
|
94
|
-
|
95
|
-
def value_class
|
96
|
-
" class='#{@config.value_class}'" unless @config.value_class == ''
|
97
|
-
end
|
31
|
+
private
|
98
32
|
|
99
|
-
def
|
100
|
-
|
101
|
-
"<a href='#{@klass.send(@config.link[0], replace_tokens(@config.link[1], href_or_text))}'>#{link_text}</a>"
|
33
|
+
def delimiter
|
34
|
+
nil
|
102
35
|
end
|
103
36
|
|
104
37
|
def displayForm(element)
|
@@ -113,83 +46,14 @@ module ModsDisplay
|
|
113
46
|
"#{element.attributes['displayLabel'].value}:"
|
114
47
|
end
|
115
48
|
|
116
|
-
def
|
117
|
-
|
118
|
-
end
|
119
|
-
|
120
|
-
def replace_tokens(object, value)
|
121
|
-
object = object.dup
|
122
|
-
if object.is_a?(Hash)
|
123
|
-
object.each do |k, v|
|
124
|
-
object[k] = replace_token(v, value)
|
125
|
-
end
|
126
|
-
elsif object.is_a?(String)
|
127
|
-
object = replace_token(object, value)
|
128
|
-
end
|
129
|
-
object
|
130
|
-
end
|
131
|
-
|
132
|
-
def replace_token(string, value)
|
133
|
-
string = string.dup
|
134
|
-
tokens.each do |token|
|
135
|
-
string.gsub!(token, value)
|
136
|
-
end
|
137
|
-
string
|
138
|
-
end
|
139
|
-
|
140
|
-
def tokens
|
141
|
-
['%value%']
|
142
|
-
end
|
49
|
+
def collapse_fields(display_fields)
|
50
|
+
return display_fields if display_fields.length == 1
|
143
51
|
|
144
|
-
|
145
|
-
|
146
|
-
def link_urls_and_email(val)
|
147
|
-
val = val.dup
|
148
|
-
# http://daringfireball.net/2010/07/improved_regex_for_matching_urls
|
149
|
-
url = %r{(?i)\b(?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\([^\s()<>]+|\([^\s()<>]+\)*\))+(?:\([^\s()<>]+|\([^\s()<>]+\)*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])}i
|
150
|
-
# http://www.regular-expressions.info/email.html
|
151
|
-
email = /[A-Z0-9_\.%\+\-\']+@(?:[A-Z0-9\-]+\.)+(?:[A-Z]{2,4}|museum|travel)/i
|
152
|
-
matches = [val.scan(url), val.scan(email)].flatten
|
153
|
-
unless val =~ /<a/ # we'll assume that linking has alraedy occured and we don't want to double link
|
154
|
-
matches.each do |match|
|
155
|
-
if match =~ email
|
156
|
-
val = val.gsub(match, "<a href='mailto:#{match}'>#{match}</a>")
|
157
|
-
else
|
158
|
-
val = val.gsub(match, "<a href='#{match}'>#{match}</a>")
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
val
|
163
|
-
end
|
164
|
-
# rubocop:enable Metrics/LineLength
|
52
|
+
display_fields.slice_when { |before, after| before.label != after.label }.map do |group|
|
53
|
+
next group.first if group.length == 1
|
165
54
|
|
166
|
-
|
167
|
-
return_values = []
|
168
|
-
current_label = nil
|
169
|
-
prev_label = nil
|
170
|
-
buffer = []
|
171
|
-
display_fields.each_with_index do |field, index|
|
172
|
-
current_label = field.label
|
173
|
-
current_values = field.values
|
174
|
-
if display_fields.length == 1
|
175
|
-
return_values << ModsDisplay::Values.new(label: current_label, values: current_values)
|
176
|
-
elsif index == (display_fields.length - 1)
|
177
|
-
# need to deal w/ when we have a last element but we have separate labels in the buffer.
|
178
|
-
if current_label != prev_label
|
179
|
-
return_values << ModsDisplay::Values.new(label: prev_label, values: buffer.flatten)
|
180
|
-
return_values << ModsDisplay::Values.new(label: current_label, values: current_values)
|
181
|
-
else
|
182
|
-
buffer.concat(current_values)
|
183
|
-
return_values << ModsDisplay::Values.new(label: current_label, values: buffer.flatten)
|
184
|
-
end
|
185
|
-
elsif prev_label && (current_label != prev_label)
|
186
|
-
return_values << ModsDisplay::Values.new(label: prev_label, values: buffer.flatten)
|
187
|
-
buffer = []
|
188
|
-
end
|
189
|
-
buffer.concat(current_values)
|
190
|
-
prev_label = current_label
|
55
|
+
ModsDisplay::Values.new(label: group.first.label, values: group.map(&:values).flatten)
|
191
56
|
end
|
192
|
-
return_values
|
193
57
|
end
|
194
58
|
end
|
195
59
|
end
|
@@ -168,9 +168,9 @@ module ModsDisplay
|
|
168
168
|
date_field = date_field.clone
|
169
169
|
date_field.content = begin
|
170
170
|
if date_field.text.strip =~ /^\d{4}-\d{2}-\d{2}$/
|
171
|
-
Date.parse(date_field.text).strftime(
|
171
|
+
Date.parse(date_field.text).strftime('%B %d, %Y')
|
172
172
|
elsif date_field.text.strip =~ /^\d{4}-\d{2}$/
|
173
|
-
Date.parse("#{date_field.text}-01").strftime(
|
173
|
+
Date.parse("#{date_field.text}-01").strftime('%B %Y')
|
174
174
|
else
|
175
175
|
date_field.content
|
176
176
|
end
|
@@ -183,7 +183,7 @@ module ModsDisplay
|
|
183
183
|
def process_iso8601_date(date_field)
|
184
184
|
date_field = date_field.clone
|
185
185
|
date_field.content = begin
|
186
|
-
Date.iso8601(date_field.text).strftime(
|
186
|
+
Date.iso8601(date_field.text).strftime('%B %d, %Y')
|
187
187
|
rescue
|
188
188
|
date_field.content
|
189
189
|
end
|
@@ -256,6 +256,55 @@ module ModsDisplay
|
|
256
256
|
|
257
257
|
private
|
258
258
|
|
259
|
+
def compact_and_join_with_delimiter(values, delimiter)
|
260
|
+
compact_values = values.compact.reject { |v| v.strip.empty? }
|
261
|
+
return compact_values.join(delimiter) if compact_values.length == 1 ||
|
262
|
+
!ends_in_terminating_punctuation?(delimiter)
|
263
|
+
compact_values.each_with_index.map do |value, i|
|
264
|
+
if (compact_values.length - 1) == i || # last item?
|
265
|
+
ends_in_terminating_punctuation?(value)
|
266
|
+
value << ' '
|
267
|
+
else
|
268
|
+
value << delimiter
|
269
|
+
end
|
270
|
+
end.join.strip
|
271
|
+
end
|
272
|
+
|
273
|
+
def process_bc_ad_dates(date_fields)
|
274
|
+
date_fields.map do |date_field|
|
275
|
+
case
|
276
|
+
when date_is_bc_edtf?(date_field)
|
277
|
+
year = date_field.text.strip.gsub(/^-0*/, '').to_i + 1
|
278
|
+
date_field.content = "#{year} B.C."
|
279
|
+
when date_is_ad?(date_field)
|
280
|
+
date_field.content = "#{date_field.text.strip.gsub(/^0*/, '')} A.D."
|
281
|
+
end
|
282
|
+
date_field
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
def date_is_bc_edtf?(date_field)
|
287
|
+
date_field.text.strip.start_with?('-') && date_is_edtf?(date_field)
|
288
|
+
end
|
289
|
+
|
290
|
+
def date_is_ad?(date_field)
|
291
|
+
date_field.text.strip.gsub(/^0*/, '').length < 4
|
292
|
+
end
|
293
|
+
|
294
|
+
def date_is_edtf?(date_field)
|
295
|
+
field_is_encoded?(date_field, 'edtf')
|
296
|
+
end
|
297
|
+
|
298
|
+
def field_is_encoded?(field, encoding)
|
299
|
+
field.attributes['encoding'] &&
|
300
|
+
field.attributes['encoding'].respond_to?(:value) &&
|
301
|
+
field.attributes['encoding'].value.downcase == encoding
|
302
|
+
end
|
303
|
+
|
304
|
+
def ends_in_terminating_punctuation?(value)
|
305
|
+
value.strip.end_with?('.', ',', ':', ';')
|
306
|
+
end
|
307
|
+
|
259
308
|
def edition_element(value)
|
260
309
|
value.edition.reject do |e|
|
261
310
|
e.text.strip.empty?
|
@@ -16,26 +16,18 @@ module ModsDisplay
|
|
16
16
|
collapse_roles(collapse_fields(return_fields))
|
17
17
|
end
|
18
18
|
|
19
|
-
def to_html
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
output << "<dt#{label_class} #{sanitized_field_title(field.label)}>#{field.label}</dt>"
|
24
|
-
output << "<dd#{value_class}>"
|
25
|
-
output << field.values.map do |val|
|
26
|
-
if @config.link
|
27
|
-
link_to_value(val.name)
|
28
|
-
else
|
29
|
-
val.to_s
|
30
|
-
end
|
31
|
-
end.join(@config.delimiter)
|
32
|
-
output << '</dd>'
|
33
|
-
end
|
34
|
-
output
|
19
|
+
def to_html(view_context = ApplicationController.renderer)
|
20
|
+
component = ModsDisplay::FieldComponent.with_collection(fields, value_transformer: ->(value) { value.to_s })
|
21
|
+
|
22
|
+
view_context.render component
|
35
23
|
end
|
36
24
|
|
37
25
|
private
|
38
26
|
|
27
|
+
def delimiter
|
28
|
+
'<br />'
|
29
|
+
end
|
30
|
+
|
39
31
|
def collapse_roles(fields)
|
40
32
|
return [] if fields.blank?
|
41
33
|
|
@@ -150,12 +142,11 @@ module ModsDisplay
|
|
150
142
|
def rebuild_fields_with_new_labels(label_keys, results)
|
151
143
|
# Build the new fields data, stripping out the roles within the Person classes
|
152
144
|
label_keys.uniq.map do |k|
|
153
|
-
|
154
|
-
mdv.label = k
|
155
|
-
mdv.values = results[k].map do |person|
|
145
|
+
values = results[k].map do |person|
|
156
146
|
ModsDisplay::Name::Person.new(name: person.name)
|
157
147
|
end
|
158
|
-
|
148
|
+
|
149
|
+
ModsDisplay::Values.new(label: k, values: values)
|
159
150
|
end
|
160
151
|
end
|
161
152
|
|