lib/autolink.rb in twitter-text-1.4.16 vs lib/autolink.rb in twitter-text-1.4.17

- old
+ new

@@ -1,5 +1,7 @@ +# encoding: UTF-8 + require 'set' module Twitter # A module for including Tweet auto-linking in a class. The primary use of this is for helpers/views so they can auto-link # usernames, lists, hashtags and URLs. @@ -146,18 +148,15 @@ options[:class] = options.delete(:url_class) url_entities = {} if options[:url_entities] options[:url_entities].each do |entity| - entity = entity.with_indifferent_access - url_entities[entity[:url]] = entity + url_entities[entity["url"]] = entity end options.delete(:url_entities) end - html_attrs = html_attrs_for_options(options) - Twitter::Rewriter.rewrite_urls(text) do |url| # In the case of t.co URLs, don't allow additional path characters after = "" if url =~ Twitter::Regex[:valid_tco_url] url = $& @@ -169,14 +168,70 @@ else html_escape(url) end display_url = url - if url_entities[url] && url_entities[url][:display_url] - display_url = url_entities[url][:display_url] + link_text = html_escape(display_url) + if url_entities[url] && url_entities[url]["display_url"] + display_url = url_entities[url]["display_url"] + expanded_url = url_entities[url]["expanded_url"] + if !options[:title] + options[:title] = expanded_url + end + + # Goal: If a user copies and pastes a tweet containing t.co'ed link, the resulting paste + # should contain the full original URL (expanded_url), not the display URL. + # + # Method: Whenever possible, we actually emit HTML that contains expanded_url, and use + # font-size:0 to hide those parts that should not be displayed (because they are not part of display_url). + # Elements with font-size:0 get copied even though they are not visible. + # Note that display:none doesn't work here. Elements with display:none don't get copied. + # + # Additionally, we want to *display* ellipses, but we don't want them copied. To make this happen we + # wrap the ellipses in a tco-ellipsis class and provide an onCopy handler that sets display:none on + # everything with the tco-ellipsis class. + # + # Exception: pic.twitter.com images, for which expandedUrl = "https://twitter.com/#!/username/status/1234/photo/1 + # For those URLs, display_url is not a substring of expanded_url, so we don't do anything special to render the elided parts. + # For a pic.twitter.com URL, the only elided part will be the "https://", so this is fine. + display_url_sans_ellipses = display_url.sub("…", "") + if expanded_url.include?(display_url_sans_ellipses) + display_url_index = expanded_url.index(display_url_sans_ellipses) + before_display_url = expanded_url.slice(0, display_url_index) + # Portion of expanded_url that comes after display_url + after_display_url = expanded_url.slice(display_url_index + display_url_sans_ellipses.length, 999999) + preceding_ellipsis = display_url.match(/^…/) ? "…" : "" + following_ellipsis = display_url.match(/…$/) ? "…" : "" + # As an example: The user tweets "hi http://longdomainname.com/foo" + # This gets shortened to "hi http://t.co/xyzabc", with display_url = "…nname.com/foo" + # This will get rendered as: + # <span class='tco-ellipsis'> <!-- This stuff should get displayed but not copied --> + # … + # <!-- There's a chance the onCopy event handler might not fire. In case that happens, + # we include an &nbsp; here so that the … doesn't bump up against the URL and ruin it. + # The &nbsp; is inside the tco-ellipsis span so that when the onCopy handler *does* + # fire, it doesn't get copied. Otherwise the copied text would have two spaces in a row, + # e.g. "hi http://longdomainname.com/foo". + # <span style='font-size:0'>&nbsp;</span> + # </span> + # <span style='font-size:0'> <!-- This stuff should get copied but not displayed --> + # http://longdomai + # </span> + # <span class='js-display-url'> <!-- This stuff should get displayed *and* copied --> + # nname.com/foo + # </span> + # <span class='tco-ellipsis'> <!-- This stuff should get displayed but not copied --> + # <span style='font-size:0'>&nbsp;</span> + # … + # </span> + invisible = "style='font-size:0; line-height:0'" + link_text = "<span class='tco-ellipsis'>#{preceding_ellipsis}<span #{invisible}>&nbsp;</span></span><span #{invisible}>#{html_escape before_display_url}</span><span class='js-display-url'>#{html_escape display_url_sans_ellipses}</span><span #{invisible}>#{after_display_url}</span><span class='tco-ellipsis'><span #{invisible}>&nbsp;</span>#{following_ellipsis}</span>" + end end - %(<a href="#{href}"#{html_attrs}>#{html_escape(display_url)}</a>#{after}) + html_attrs = html_attrs_for_options(options) + + %(<a href="#{href}"#{html_attrs}>#{link_text}</a>#{after}) end end private