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.

Constant Summary collapse

MentionPattern =

Pattern used to extract @mentions from text.

/
  (?:^|\W)                   # beginning of string or non-word char
  @((?>[a-z0-9][a-z0-9-]*))  # @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
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
)
IGNORE_PARENTS =

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

%w(pre code a).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, #can_access_repo?, #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) ⇒ Object

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

MentionFilter.mentioned_logins_in(text) do |match, , is_mentioned|
  "<a href=...>#{}</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.



30
31
32
33
34
35
# File 'lib/html/pipeline/@mention_filter.rb', line 30

def self.mentioned_logins_in(text)
  text.gsub MentionPattern do |match|
     = $1
    yield match, , MentionLogins.include?(.downcase)
  end
end

Instance Method Details

#callObject



62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/html/pipeline/@mention_filter.rb', line 62

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

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

#info_urlObject

The URL to provide when someone @mentions a “mention” name, such as



78
79
80
# File 'lib/html/pipeline/@mention_filter.rb', line 78

def info_url
  context[:info_url] || nil
end


105
106
107
108
109
110
# File 'lib/html/pipeline/@mention_filter.rb', line 105

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


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

def link_to_mentioned_user()
  result[:mentioned_usernames] |= []
  url = File.join(base_url, )
  "<a href='#{url}' class='user-mention'>" +
  "@#{}" +
  "</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.

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



92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/html/pipeline/@mention_filter.rb', line 92

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

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