# encoding: utf-8
module ModsDisplay
class Field
def initialize(values, config, klass)
@values = values
@config = config
@klass = klass
end
def fields
return_fields = @values.map do |value|
ModsDisplay::Values.new(
label: displayLabel(value) || label,
values: [displayForm(@values) || value.text].flatten
)
end
collapse_fields(return_fields)
end
def label
return nil if @values.nil?
displayLabel(@values.first)
end
def to_html
return nil if fields.empty? || @config.ignore?
output = ''
fields.each do |field|
next unless field.values.any? { |f| f && !f.empty? }
output << "
#{field.label}"
output << ""
output << field.values.map do |val|
@config.link ? link_to_value(val.to_s) : link_urls_and_email(val.to_s)
end.join(@config.delimiter)
output << ''
end
output
end
private
def compact_and_join_with_delimiter(values, delimiter)
compact_values = values.compact.reject { |v| v.strip.empty? }
return compact_values.join(delimiter) if compact_values.length == 1 ||
!ends_in_terminating_punctuation?(delimiter)
compact_values.each_with_index.map do |value, i|
if (compact_values.length - 1) == i || # last item?
ends_in_terminating_punctuation?(value)
value << ' '
else
value << delimiter
end
end.join.strip
end
def process_bc_ad_dates(date_fields)
date_fields.map do |date_field|
case
when date_is_bc_edtf?(date_field)
year = date_field.text.strip.gsub(/^-0*/, '').to_i + 1
date_field.content = "#{year} B.C."
when date_is_ad?(date_field)
date_field.content = "#{date_field.text.strip.gsub(/^0*/, '')} A.D."
end
date_field
end
end
def date_is_bc_edtf?(date_field)
date_field.text.strip.start_with?('-') && date_is_edtf?(date_field)
end
def date_is_ad?(date_field)
date_field.text.strip.gsub(/^0*/, '').length < 4
end
def date_is_edtf?(date_field)
field_is_encoded?(date_field, 'edtf')
end
def field_is_encoded?(field, encoding)
field.attributes['encoding'] &&
field.attributes['encoding'].respond_to?(:value) &&
field.attributes['encoding'].value.downcase == encoding
end
def ends_in_terminating_punctuation?(value)
value.strip.end_with?('.', ',', ':', ';')
end
def label_class
" class='#{@config.label_class}'" unless @config.label_class == ''
end
def value_class
" class='#{@config.value_class}'" unless @config.value_class == ''
end
def link_to_value(link_text, link_href = nil)
href_or_text = link_href || link_text
"#{link_text}"
end
def displayForm(element)
return element unless element # basically return nil
display = element.children.find { |c| c.name == 'displayForm' }
return display.text if display
end
def displayLabel(element)
return unless element.respond_to?(:attributes) &&
element.attributes['displayLabel'].respond_to?(:value)
"#{element.attributes['displayLabel'].value}:"
end
def sanitized_field_title(label)
"title='#{label.gsub(/:$/, '').strip}'"
end
def replace_tokens(object, value)
object = object.dup
if object.is_a?(Hash)
object.each do |k, v|
object[k] = replace_token(v, value)
end
elsif object.is_a?(String)
object = replace_token(object, value)
end
object
end
def replace_token(string, value)
string = string.dup
tokens.each do |token|
string.gsub!(token, value)
end
string
end
def tokens
['%value%']
end
# rubocop:disable Metrics/LineLength
# Disabling line length due to necessarily long regular expressions
def link_urls_and_email(val)
val = val.dup
# http://daringfireball.net/2010/07/improved_regex_for_matching_urls
url = %r{(?i)\b(?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\([^\s()<>]+|\([^\s()<>]+\)*\))+(?:\([^\s()<>]+|\([^\s()<>]+\)*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])}i
# http://www.regular-expressions.info/email.html
email = /[A-Z0-9_\.%\+\-\']+@(?:[A-Z0-9\-]+\.)+(?:[A-Z]{2,4}|museum|travel)/i
matches = [val.scan(url), val.scan(email)].flatten
unless val =~ /#{match}")
else
val = val.gsub(match, "#{match}")
end
end
end
val
end
# rubocop:enable Metrics/LineLength
def collapse_fields(display_fields)
return_values = []
current_label = nil
prev_label = nil
buffer = []
display_fields.each_with_index do |field, index|
current_label = field.label
current_values = field.values
if display_fields.length == 1
return_values << ModsDisplay::Values.new(label: current_label, values: current_values)
elsif index == (display_fields.length - 1)
# need to deal w/ when we have a last element but we have separate labels in the buffer.
if current_label != prev_label
return_values << ModsDisplay::Values.new(label: prev_label, values: buffer.flatten)
return_values << ModsDisplay::Values.new(label: current_label, values: current_values)
else
buffer.concat(current_values)
return_values << ModsDisplay::Values.new(label: current_label, values: buffer.flatten)
end
elsif prev_label && (current_label != prev_label)
return_values << ModsDisplay::Values.new(label: prev_label, values: buffer.flatten)
buffer = []
end
buffer.concat(current_values)
prev_label = current_label
end
return_values
end
end
end