module Twitter::Autolink
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.
Constants
- BOOLEAN_ATTRIBUTES
- DEFAULT_CASHTAG_CLASS
Default CSS class for auto-linked cashtags
- DEFAULT_CASHTAG_URL_BASE
Default URL base for auto-linked cashtags
- DEFAULT_HASHTAG_CLASS
Default CSS class for auto-linked hashtags
- DEFAULT_HASHTAG_URL_BASE
Default URL base for auto-linked hashtags
- DEFAULT_INVISIBLE_TAG_ATTRS
Default attributes for invisible span tag
- DEFAULT_LIST_CLASS
Default CSS class for auto-linked lists
- DEFAULT_LIST_URL_BASE
Default URL base for auto-linked lists
- DEFAULT_OPTIONS
- DEFAULT_USERNAME_CLASS
Default CSS class for auto-linked usernames
- DEFAULT_USERNAME_URL_BASE
Default URL base for auto-linked usernames
- HTML_ENTITIES
- OPTIONS_NOT_ATTRIBUTES
Options which should not be passed as HTML attributes
Public Instance Methods
Add <a></a>
tags around the usernames, lists,
hashtags and URLs in the provided text
. The
<a>
tags can be controlled with the following entries in
the options
hash: Also any elements in the
options
hash will be converted to HTML attributes and place in
the <a>
tag.
:url_class
-
class to add to url
<a>
tags :list_class
-
class to add to list
<a>
tags :username_class
-
class to add to username
<a>
tags :hashtag_class
-
class to add to hashtag
<a>
tags :cashtag_class
-
class to add to cashtag
<a>
tags :username_url_base
-
the value for
href
attribute on username links. The@username
(minus the@
) will be appended at the end of this. :list_url_base
-
the value for
href
attribute on list links. The@username/list
(minus the@
) will be appended at the end of this. :hashtag_url_base
-
the value for
href
attribute on hashtag links. The#hashtag
(minus the#
) will be appended at the end of this. :cashtag_url_base
-
the value for
href
attribute on cashtag links. The$cashtag
(minus the$
) will be appended at the end of this. :invisible_tag_attrs
-
HTML attribute to add to invisible span tags
:username_include_symbol
-
place the
@
symbol within username and list links :suppress_lists
-
disable auto-linking to lists
:suppress_no_follow
-
do not add
rel="nofollow"
to auto-linked items :symbol_tag
-
tag to apply around symbol (@, #, $) in username / hashtag / cashtag links
:text_with_symbol_tag
-
tag to apply around text part in username / hashtag / cashtag links
:url_target
-
the value for
target
attribute on URL links. :target_blank
-
adds
target="_blank"
to all auto_linked items username / hashtag / cashtag links / urls :link_attribute_block
-
function to modify the attributes of a link based on the entity. called with |entity, attributes| params, and should modify the attributes hash.
:link_text_block
-
function to modify the text of a link based on the entity. called with |entity, text| params, and should return a modified text.
# File lib/twitter-text/autolink.rb, line 106 def auto_link(text, options = {}, &block) auto_link_entities(text, Extractor.extract_entities_with_indices(text, :extract_url_without_protocol => false), options, &block) end
# File lib/twitter-text/autolink.rb, line 60 def auto_link_entities(text, entities, options = {}, &block) return text if entities.empty? # NOTE deprecate these attributes not options keys in options hash, then use html_attrs options = DEFAULT_OPTIONS.merge(options) options[:html_attrs] = extract_html_attrs_from_options!(options) options[:html_attrs][:rel] ||= "nofollow" unless options[:suppress_no_follow] options[:html_attrs][:target] = "_blank" if options[:target_blank] == true Twitter::Rewriter.rewrite_entities(text.dup, entities) do |entity, chars| if entity[:url] link_to_url(entity, chars, options, &block) elsif entity[:hashtag] link_to_hashtag(entity, chars, options, &block) elsif entity[:screen_name] link_to_screen_name(entity, chars, options, &block) elsif entity[:cashtag] link_to_cashtag(entity, chars, options, &block) end end end
Add <a></a>
tags around the URLs in the provided
text
. The <a>
tags can be controlled with
the following entries in the options
hash. Also any elements
in the options
hash will be converted to HTML attributes and
place in the <a>
tag.
:url_class
-
class to add to url
<a>
tags :invisible_tag_attrs
-
HTML attribute to add to invisible span tags
:suppress_no_follow
-
do not add
rel="nofollow"
to auto-linked items :symbol_tag
-
tag to apply around symbol (@, #, $) in username / hashtag / cashtag links
:text_with_symbol_tag
-
tag to apply around text part in username / hashtag / cashtag links
:url_target
-
the value for
target
attribute on URL links. :link_attribute_block
-
function to modify the attributes of a link based on the entity. called with |entity, attributes| params, and should modify the attributes hash.
:link_text_block
-
function to modify the text of a link based on the entity. called with |entity, text| params, and should return a modified text.
# File lib/twitter-text/autolink.rb, line 175 def auto_link_urls(text, options = {}, &block) auto_link_entities(text, Extractor.extract_urls_with_indices(text, :extract_url_without_protocol => false), options, &block) end
Deprecated: Please use #auto_link_urls instead.
Add <a></a>
tags around the URLs in the provided
text
. Any elements in the href_options
hash will
be converted to HTML attributes and place in the <a>
tag. Unless href_options
contains
:suppress_no_follow
the rel="nofollow"
attribute will be added.
Add <a></a>
tags around the usernames and lists in
the provided text
. The <a>
tags can be
controlled with the following entries in the options
hash.
Also any elements in the options
hash will be converted to
HTML attributes and place in the <a>
tag.
:list_class
-
class to add to list
<a>
tags :username_class
-
class to add to username
<a>
tags :username_url_base
-
the value for
href
attribute on username links. The@username
(minus the@
) will be appended at the end of this. :list_url_base
-
the value for
href
attribute on list links. The@username/list
(minus the@
) will be appended at the end of this. :username_include_symbol
-
place the
@
symbol within username and list links :suppress_lists
-
disable auto-linking to lists
:suppress_no_follow
-
do not add
rel="nofollow"
to auto-linked items :symbol_tag
-
tag to apply around symbol (@, #, $) in username / hashtag / cashtag links
:text_with_symbol_tag
-
tag to apply around text part in username / hashtag / cashtag links
:link_attribute_block
-
function to modify the attributes of a link based on the entity. called with |entity, attributes| params, and should modify the attributes hash.
:link_text_block
-
function to modify the text of a link based on the entity. called with |entity, text| params, and should return a modified text.
# File lib/twitter-text/autolink.rb, line 126 def auto_link_usernames_or_lists(text, options = {}, &block) # :yields: list_or_username auto_link_entities(text, Extractor.extract_mentions_or_lists_with_indices(text), options, &block) end
# File lib/twitter-text/autolink.rb, line 44 def auto_link_with_json(text, json, options = {}) # concatenate entities entities = json.values().flatten() # map JSON entity to twitter-text entity # be careful not to alter arguments received entities.map! do |entity| entity = HashHelper.symbolize_keys(entity) # hashtag entity[:hashtag] = entity[:text] if entity[:text] entity end auto_link_entities(text, entities, options) end
# File lib/twitter-text/autolink.rb, line 201 def html_escape(text) text && text.to_s.gsub(/[&"'><]/) do |character| HTML_ENTITIES[character] end end
Private Instance Methods
# File lib/twitter-text/autolink.rb, line 220 def extract_html_attrs_from_options!(options) html_attrs = {} options.reject! do |key, value| unless OPTIONS_NOT_ATTRIBUTES.include?(key) html_attrs[key] = value true end end html_attrs end
# File lib/twitter-text/autolink.rb, line 356 def link_to_cashtag(entity, chars, options = {}) dollar = chars[entity[:indices].first] cashtag = entity[:cashtag] cashtag = yield(cashtag) if block_given? href = if options[:cashtag_url_block] options[:cashtag_url_block].call(cashtag) else "#{options[:cashtag_url_base]}#{cashtag}" end html_attrs = { :class => "#{options[:cashtag_class]}", :title => "$#{cashtag}" }.merge(options[:html_attrs]) link_to_text_with_symbol(entity, dollar, cashtag, href, html_attrs, options) end
# File lib/twitter-text/autolink.rb, line 330 def link_to_hashtag(entity, chars, options = {}) hash = chars[entity[:indices].first] hashtag = entity[:hashtag] hashtag = yield(hashtag) if block_given? hashtag_class = options[:hashtag_class].to_s if hashtag.match Twitter::Regex::REGEXEN[:rtl_chars] hashtag_class += ' rtl' end href = if options[:hashtag_url_block] options[:hashtag_url_block].call(hashtag) else "#{options[:hashtag_url_base]}#{hashtag}" end html_attrs = { :class => hashtag_class, # FIXME As our conformance test, hash in title should be half-width, # this should be bug of conformance data. :title => "##{hashtag}" }.merge(options[:html_attrs]) link_to_text_with_symbol(entity, hash, hashtag, href, html_attrs, options) end
# File lib/twitter-text/autolink.rb, line 375 def link_to_screen_name(entity, chars, options = {}) name = "#{entity[:screen_name]}#{entity[:list_slug]}" chunk = name.dup chunk = yield(chunk) if block_given? at = chars[entity[:indices].first] html_attrs = options[:html_attrs].dup if entity[:list_slug] && !entity[:list_slug].empty? && !options[:suppress_lists] href = if options[:list_url_block] options[:list_url_block].call(name) else "#{options[:list_url_base]}#{name}" end html_attrs[:class] ||= "#{options[:list_class]}" else href = if options[:username_url_block] options[:username_url_block].call(chunk) else "#{options[:username_url_base]}#{name}" end html_attrs[:class] ||= "#{options[:username_class]}" end link_to_text_with_symbol(entity, at, chunk, href, html_attrs, options) end
# File lib/twitter-text/autolink.rb, line 415 def link_to_text(entity, text, href, attributes = {}, options = {}) attributes[:href] = href options[:link_attribute_block].call(entity, attributes) if options[:link_attribute_block] text = options[:link_text_block].call(entity, text) if options[:link_text_block] %Q(<a#{tag_attrs(attributes)}>#{text}</a>) end
# File lib/twitter-text/autolink.rb, line 404 def link_to_text_with_symbol(entity, symbol, text, href, attributes = {}, options = {}) tagged_symbol = options[:symbol_tag] ? "<#{options[:symbol_tag]}>#{symbol}</#{options[:symbol_tag]}>" : symbol text = html_escape(text) tagged_text = options[:text_with_symbol_tag] ? "<#{options[:text_with_symbol_tag]}>#{text}</#{options[:text_with_symbol_tag]}>" : text if options[:username_include_symbol] || symbol !~ Twitter::Regex::REGEXEN[:at_signs] "#{link_to_text(entity, tagged_symbol + tagged_text, href, attributes, options)}" else "#{tagged_symbol}#{link_to_text(entity, tagged_text, href, attributes, options)}" end end
# File lib/twitter-text/autolink.rb, line 240 def link_to_url(entity, chars, options = {}) url = entity[:url] href = if options[:link_url_block] options[:link_url_block].call(url) else url end # NOTE auto link to urls do not use any default values and options # like url_class but use suppress_no_follow. html_attrs = options[:html_attrs].dup html_attrs[:class] = options[:url_class] if options.key?(:url_class) # add target attribute only if :url_target is specified html_attrs[:target] = options[:url_target] if options.key?(:url_target) url_entities = url_entities_hash(options[:url_entities]) # use entity from urlEntities if available url_entity = url_entities[url] || entity link_text = if url_entity[:display_url] html_attrs[:title] ||= url_entity[:expanded_url] link_url_with_entity(url_entity, options) else html_escape(url) end link_to_text(entity, link_text, href, html_attrs, options) end
# File lib/twitter-text/autolink.rb, line 271 def link_url_with_entity(entity, options) display_url = entity[:display_url] expanded_url = entity[:expanded_url] invisible_tag_attrs = options[:invisible_tag_attrs] || DEFAULT_INVISIBLE_TAG_ATTRS # 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.gsub("…", "") if expanded_url.include?(display_url_sans_ellipses) before_display_url, after_display_url = expanded_url.split(display_url_sans_ellipses, 2) preceding_ellipsis = /\A…/.match(display_url).to_s following_ellipsis = /…\z/.match(display_url).to_s # 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 here so that the … doesn't bump up against the URL and ruin it. # The 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'> </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'> </span> # … # </span> %Q(<span class="tco-ellipsis">#{preceding_ellipsis}<span #{invisible_tag_attrs}> </span></span>) << %Q(<span #{invisible_tag_attrs}>#{html_escape(before_display_url)}</span>) << %Q(<span class="js-display-url">#{html_escape(display_url_sans_ellipses)}</span>) << %Q(<span #{invisible_tag_attrs}>#{html_escape(after_display_url)}</span>) << %Q(<span class="tco-ellipsis"><span #{invisible_tag_attrs}> </span>#{following_ellipsis}</span>) else html_escape(display_url) end end
# File lib/twitter-text/autolink.rb, line 424 def tag_attrs(attributes) attributes.keys.sort_by{|k| k.to_s}.inject("") do |attrs, key| value = attributes[key] if BOOLEAN_ATTRIBUTES.include?(key) value = value ? key : nil end unless value.nil? value = case value when Array value.compact.join(" ") else value end attrs << %Q( #{html_escape(key)}="#{html_escape(value)}") end attrs end end
# File lib/twitter-text/autolink.rb, line 231 def url_entities_hash(url_entities) (url_entities || {}).inject({}) do |entities, entity| # be careful not to alter arguments received _entity = HashHelper.symbolize_keys(entity) entities[_entity[:url]] = _entity entities end end