]> git.openstreetmap.org Git - rails.git/blobdiff - app/helpers/browse_tags_helper.rb
Merge remote-tracking branch 'upstream/pull/4776'
[rails.git] / app / helpers / browse_tags_helper.rb
index aaf235369011de6b78c0e7f93d94517e7d9db2e6..6d3bf5e91245cb247b9ea71dc5786d5a699286d8 100644 (file)
@@ -1,4 +1,8 @@
 module BrowseTagsHelper
 module BrowseTagsHelper
+  # https://wiki.openstreetmap.org/wiki/Key:wikipedia#Secondary_Wikipedia_links
+  # https://wiki.openstreetmap.org/wiki/Key:wikidata#Secondary_Wikidata_links
+  SECONDARY_WIKI_PREFIXES = "architect|artist|brand|buried|flag|genus|manufacturer|model|name:etymology|network|operator|species|subject".freeze
+
   def format_key(key)
     if url = wiki_link("key", key)
       link_to h(key), url, :title => t("browse.tag_details.wiki_link.key", :key => key)
   def format_key(key)
     if url = wiki_link("key", key)
       link_to h(key), url, :title => t("browse.tag_details.wiki_link.key", :key => key)
@@ -17,8 +21,12 @@ module BrowseTagsHelper
         link_to(w[:title], w[:url], :title => t("browse.tag_details.wikidata_link", :page => w[:title].strip))
       end
       safe_join(wdt, ";")
         link_to(w[:title], w[:url], :title => t("browse.tag_details.wikidata_link", :page => w[:title].strip))
       end
       safe_join(wdt, ";")
+    elsif wmc = wikimedia_commons_link(key, value)
+      link_to h(wmc[:title]), wmc[:url], :title => t("browse.tag_details.wikimedia_commons_link", :page => wmc[:title])
     elsif url = wiki_link("tag", "#{key}=#{value}")
       link_to h(value), url, :title => t("browse.tag_details.wiki_link.tag", :key => key, :value => value)
     elsif url = wiki_link("tag", "#{key}=#{value}")
       link_to h(value), url, :title => t("browse.tag_details.wiki_link.tag", :key => key, :value => value)
+    elsif email = email_link(key, value)
+      mail_to(email, :title => t("browse.tag_details.email_link", :email => email))
     elsif phones = telephone_links(key, value)
       # similarly, telephone_links() returns an array of phone numbers
       phones = phones.map do |p|
     elsif phones = telephone_links(key, value)
       # similarly, telephone_links() returns an array of phone numbers
       phones = phones.map do |p|
@@ -26,9 +34,13 @@ module BrowseTagsHelper
       end
       safe_join(phones, "; ")
     elsif colour_value = colour_preview(key, value)
       end
       safe_join(phones, "; ")
     elsif colour_value = colour_preview(key, value)
-      content_tag(:span, "", :class => "colour-preview-box", :"data-colour" => colour_value, :title => t("browse.tag_details.colour_preview", :colour_value => colour_value)) + colour_value
+      svg = tag.svg :width => 14, :height => 14, :class => "float-end m-1" do
+        concat tag.title t("browse.tag_details.colour_preview", :colour_value => colour_value)
+        concat tag.rect :x => 0.5, :y => 0.5, :width => 13, :height => 13, :fill => colour_value, :stroke => "#2222"
+      end
+      svg + colour_value
     else
     else
-      linkify h(value)
+      safe_join(value.split(";", -1).map { |x| linkify(h(x)) }, ";")
     end
   end
 
     end
   end
 
@@ -43,20 +55,20 @@ module BrowseTagsHelper
     # the correct page.
     lookup_us = lookup.tr(" ", "_")
 
     # the correct page.
     lookup_us = lookup.tr(" ", "_")
 
-    if page = WIKI_PAGES.dig(locale, type, lookup_us)
-      url = "https://wiki.openstreetmap.org/wiki/#{page}?uselang=#{locale}"
-    elsif page = WIKI_PAGES.dig("en", type, lookup_us)
-      url = "https://wiki.openstreetmap.org/wiki/#{page}?uselang=#{locale}"
-    end
+    page = WIKI_PAGES.dig(locale, type, lookup_us) ||
+           WIKI_PAGES.dig("en", type, lookup_us)
+
+    url = "https://wiki.openstreetmap.org/wiki/#{page}?uselang=#{locale}" if page
 
     url
   end
 
   def wikipedia_link(key, value)
     # Some k/v's are wikipedia=http://en.wikipedia.org/wiki/Full%20URL
 
     url
   end
 
   def wikipedia_link(key, value)
     # Some k/v's are wikipedia=http://en.wikipedia.org/wiki/Full%20URL
-    return nil if value =~ %r{^https?://}
+    return nil if %r{^https?://}.match?(value)
 
 
-    if key == "wikipedia"
+    case key
+    when "wikipedia", /^(#{SECONDARY_WIKI_PREFIXES}):wikipedia/o
       # This regex should match Wikipedia language codes, everything
       # from de to zh-classical
       lang = if value =~ /^([a-z-]{2,12}):(.+)$/i
       # This regex should match Wikipedia language codes, everything
       # from de to zh-classical
       lang = if value =~ /^([a-z-]{2,12}):(.+)$/i
@@ -67,7 +79,7 @@ module BrowseTagsHelper
                # Value is <title> so default to English Wikipedia
                "en"
              end
                # Value is <title> so default to English Wikipedia
                "en"
              end
-    elsif key =~ /^wikipedia:(\S+)$/
+    when /^wikipedia:(\S+)$/
       # Language is in the key, so assume value is the title
       lang = Regexp.last_match(1)
     else
       # Language is in the key, so assume value is the title
       lang = Regexp.last_match(1)
     else
@@ -79,8 +91,8 @@ module BrowseTagsHelper
       # Contains a reference to a section of the wikipedia article
       # Must break it up to correctly build the url
       value = Regexp.last_match(1)
       # Contains a reference to a section of the wikipedia article
       # Must break it up to correctly build the url
       value = Regexp.last_match(1)
-      section = "#" + Regexp.last_match(2)
-      encoded_section = "#" + CGI.escape(Regexp.last_match(2).gsub(/ +/, "_")).tr("%", ".")
+      section = "##{Regexp.last_match(2)}"
+      encoded_section = "##{CGI.escape(Regexp.last_match(2).gsub(/ +/, '_'))}"
     else
       section = ""
       encoded_section = ""
     else
       section = ""
       encoded_section = ""
@@ -100,7 +112,7 @@ module BrowseTagsHelper
         :title => value
       }]
     # Key has to be one of the accepted wikidata-tags
         :title => value
       }]
     # Key has to be one of the accepted wikidata-tags
-    elsif key =~ /(architect|artist|brand|name:etymology|network|operator|subject):wikidata/ &&
+    elsif key =~ /(#{SECONDARY_WIKI_PREFIXES}):wikidata/o &&
           # Value has to be a semicolon-separated list of wikidata-IDs (whitespaces allowed before and after semicolons)
           value =~ /^[Qq][1-9][0-9]*(\s*;\s*[Qq][1-9][0-9]*)*$/
       # Splitting at every semicolon to get a separate hash for each wikidata-ID
           # Value has to be a semicolon-separated list of wikidata-IDs (whitespaces allowed before and after semicolons)
           value =~ /^[Qq][1-9][0-9]*(\s*;\s*[Qq][1-9][0-9]*)*$/
       # Splitting at every semicolon to get a separate hash for each wikidata-ID
@@ -111,6 +123,35 @@ module BrowseTagsHelper
     nil
   end
 
     nil
   end
 
+  def wikimedia_commons_link(key, value)
+    if key == "wikimedia_commons" && value =~ /^(?:file|category):/i
+      return {
+        :url => "//commons.wikimedia.org/wiki/#{value}?uselang=#{I18n.locale}",
+        :title => value
+      }
+    end
+    nil
+  end
+
+  def email_link(key, value)
+    # Avoid converting conditional tags into emails, since EMAIL_REGEXP is quite permissive
+    return nil unless %w[email contact:email].include? key
+
+    # Does the value look like an email? eg "someone@domain.tld"
+
+    #  Uses Ruby built-in regexp to validate email.
+    #  This will not catch certain valid emails containing comments, whitespace characters,
+    #  and quoted strings.
+    #    (see: https://github.com/ruby/ruby/blob/master/lib/uri/mailto.rb)
+
+    # remove any leading and trailing whitespace
+    email = value.strip
+
+    return email if email.match?(URI::MailTo::EMAIL_REGEXP)
+
+    nil
+  end
+
   def telephone_links(_key, value)
     # Does it look like a global phone number? eg "+1 (234) 567-8901 "
     # or a list of alternate numbers separated by ;
   def telephone_links(_key, value)
     # Does it look like a global phone number? eg "+1 (234) 567-8901 "
     # or a list of alternate numbers separated by ;
@@ -122,7 +163,7 @@ module BrowseTagsHelper
     #
     # Also accepting / as a visual separator although not given in RFC 3966,
     # because it is used as a visual separator in OSM data in some countries.
     #
     # Also accepting / as a visual separator although not given in RFC 3966,
     # because it is used as a visual separator in OSM data in some countries.
-    if value.match?(%r{^\s*\+[\d\s\(\)/\.-]{6,25}\s*(;\s*\+[\d\s\(\)/\.-]{6,25}\s*)*$})
+    if value.match?(%r{^\s*\+[\d\s()/.-]{6,25}\s*(;\s*\+[\d\s()/.-]{6,25}\s*)*$})
       return value.split(";").map do |phone_number|
         # for display, remove leading and trailing whitespace
         phone_number = phone_number.strip
       return value.split(";").map do |phone_number|
         # for display, remove leading and trailing whitespace
         phone_number = phone_number.strip
@@ -141,12 +182,19 @@ module BrowseTagsHelper
 
     # does value look like a colour? ( 3 or 6 digit hex code or w3c colour name)
     w3c_colors =
 
     # does value look like a colour? ( 3 or 6 digit hex code or w3c colour name)
     w3c_colors =
-      %w[aliceblue antiquewhite aqua aquamarine azure beige bisque black blanchedalmond blue blueviolet brown burlywood cadetblue chartreuse chocolate coral cornflowerblue cornsilk crimson cyan darkblue darkcyan darkgoldenrod darkgray darkgrey darkgreen darkkhaki darkmagenta darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen darkslateblue darkslategray
-         darkslategrey darkturquoise darkviolet deeppink deepskyblue dimgray dimgrey dodgerblue firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray grey green greenyellow honeydew hotpink indianred indigo ivory khaki lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan lightgoldenrodyellow lightgray lightgrey lightgreen
-         lightpink lightsalmon lightseagreen lightskyblue lightslategray lightslategrey lightsteelblue lightyellow lime limegreen linen magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen mediumslateblue mediumspringgreen mediumturquoise mediumvioletred midnightblue mintcream mistyrose moccasin navajowhite navy oldlace olive olivedrab orange
-         orangered orchid palegoldenrod palegreen paleturquoise palevioletred papayawhip peachpuff peru pink plum powderblue purple red rosybrown royalblue saddlebrown salmon sandybrown seagreen seashell sienna silver skyblue slateblue slategray slategrey snow springgreen steelblue tan teal thistle tomato turquoise violet wheat white whitesmoke yellow yellowgreen]
+      %w[aliceblue antiquewhite aqua aquamarine azure beige bisque black blanchedalmond blue blueviolet brown burlywood cadetblue chartreuse chocolate
+         coral cornflowerblue cornsilk crimson cyan darkblue darkcyan darkgoldenrod darkgray darkgrey darkgreen darkkhaki darkmagenta darkolivegreen
+         darkorange darkorchid darkred darksalmon darkseagreen darkslateblue darkslategray darkslategrey darkturquoise darkviolet deeppink deepskyblue
+         dimgray dimgrey dodgerblue firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray grey green greenyellow honeydew
+         hotpink indianred indigo ivory khaki lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan lightgoldenrodyellow lightgray
+         lightgrey lightgreen lightpink lightsalmon lightseagreen lightskyblue lightslategray lightslategrey lightsteelblue lightyellow lime limegreen
+         linen magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen mediumslateblue mediumspringgreen mediumturquoise
+         mediumvioletred midnightblue mintcream mistyrose moccasin navajowhite navy oldlace olive olivedrab orange orangered orchid palegoldenrod
+         palegreen paleturquoise palevioletred papayawhip peachpuff peru pink plum powderblue purple red rosybrown royalblue saddlebrown salmon
+         sandybrown seagreen seashell sienna silver skyblue slateblue slategray slategrey snow springgreen steelblue tan teal thistle tomato turquoise
+         violet wheat white whitesmoke yellow yellowgreen]
     return nil unless value =~ /^#([0-9a-fA-F]{3}){1,2}$/ || w3c_colors.include?(value.downcase)
     return nil unless value =~ /^#([0-9a-fA-F]{3}){1,2}$/ || w3c_colors.include?(value.downcase)
-    
+
     value
   end
 end
     value
   end
 end