# 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