Class: HTML::Pipeline::MentionFilter

Inherits:
Filter
  • Object
show all
Defined in:
lib/html/pipeline/@mention_filter.rb

Overview

HTML filter that replaces @user mentions with links. Mentions within <pre>, <code>, and <a> elements are ignored. Mentions that reference users that do not exist are ignored.

Context options:

:base_url - Used to construct links to user profile pages for each
            mention.
:info_url - Used to link to "more info" when someone mentions @mention
            or @mentioned.
:username_pattern - Used to provide a custom regular expression to
                    identify usernames

Constant Summary collapse

MentionPatterns =

Hash that contains all of the mention patterns used by the pipeline

Hash.new do |hash, key|
  hash[key] = /
    (?:^|\W)                    # beginning of string or non-word char
    @((?>#{key}))  # @username
    (?!\/)                      # without a trailing slash
    (?=
      \.+[ \t\W]|               # dots followed by space or non-word character
      \.+$|                     # dots at end of line
      [^0-9a-zA-Z_.]|           # non-word character except dot
      $                         # end of line
    )
  /ix
end
UsernamePattern =

Default pattern used to extract usernames from text. The value can be overriden by providing the username_pattern variable in the context.

/[a-z0-9][a-z0-9-]*/
MentionLogins =

List of username logins that, when mentioned, link to the blog post about @mentions instead of triggering a real mention.

%w[
  mention
  mentions
  mentioned
  mentioning
].freeze
IGNORE_PARENTS =

Don't look for mentions in text nodes that are children of these elements

%w(pre code a style script).to_set

Instance Attribute Summary

Attributes inherited from Filter

#context, #result

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Filter

#base_url, call, #current_user, #doc, #has_ancestor?, #html, #initialize, #needs, #parse_html, #repository, to_document, to_html, #validate

Constructor Details

This class inherits a constructor from HTML::Pipeline::Filter

Class Method Details

.mentioned_logins_in(text, username_pattern = UsernamePattern) ⇒ Object

Public: Find user @mentions in text. See MentionFilter#mention_link_filter.

MentionFilter.mentioned_logins_in(text) do |match, , is_mentioned|
  "<a href=...>#{login}</a>"
end

text - String text to search.

Yields the String match, the String login name, and a Boolean determining if the match = “@mention”. The yield's return replaces the match in the original text.

Returns a String replaced with the return of the block.


34
35
36
37
38
39
# File 'lib/html/pipeline/@mention_filter.rb', line 34

def self.mentioned_logins_in(text, username_pattern = UsernamePattern)
  text.gsub MentionPatterns[username_pattern] do |match|
     = Regexp.last_match(1)
    yield match, , MentionLogins.include?(.downcase)
  end
end

Instance Method Details

#callObject


72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/html/pipeline/@mention_filter.rb', line 72

def call
  result[:mentioned_usernames] ||= []

  doc.search('.//text()').each do |node|
    content = node.to_html
    next unless content.include?('@')
    next if has_ancestor?(node, IGNORE_PARENTS)
    html = mention_link_filter(content, base_url, info_url, username_pattern)
    next if html == content
    node.replace(html)
  end
  doc
end

#info_urlObject

The URL to provide when someone @mentions a “mention” name, such as @mention or @mentioned, that will give them more info on mentions.


88
89
90
# File 'lib/html/pipeline/@mention_filter.rb', line 88

def info_url
  context[:info_url] || nil
end

121
122
123
124
125
126
# File 'lib/html/pipeline/@mention_filter.rb', line 121

def link_to_mention_info(text, info_url = nil)
  return "@#{text}" if info_url.nil?
  "<a href='#{info_url}' class='user-mention'>" \
    "@#{text}" \
    '</a>'
end

128
129
130
131
132
133
134
135
136
137
# File 'lib/html/pipeline/@mention_filter.rb', line 128

def link_to_mentioned_user()
  result[:mentioned_usernames] |= []

  url = base_url.dup
  url << '/' unless url =~ /[\/~]\z/

  "<a href='#{url << login}' class='user-mention'>" \
    "@#{login}" \
    '</a>'
end

Replace user @mentions in text with links to the mentioned user's profile page.

text - String text to replace @mention usernames in. base_url - The base URL used to construct user profile URLs. info_url - The “more info” URL used to link to more info on @mentions.

If nil we don't link @mention or @mentioned.

username_pattern - Regular expression used to identify usernames in

text

Returns a string with @mentions replaced with links. All links have a 'user-mention' class name attached for styling.


108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/html/pipeline/@mention_filter.rb', line 108

def mention_link_filter(text, _base_url = '/', info_url = nil, username_pattern = UsernamePattern)
  self.class.mentioned_logins_in(text, username_pattern) do |match, , is_mentioned|
    link =
      if is_mentioned
        link_to_mention_info(, info_url)
      else
        link_to_mentioned_user()
      end

    link ? match.sub("@#{login}", link) : match
  end
end

#username_patternObject


92
93
94
# File 'lib/html/pipeline/@mention_filter.rb', line 92

def username_pattern
  context[:username_pattern] || UsernamePattern
end