PageRenderTime 48ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/banzai/filter/user_reference_filter.rb

https://gitlab.com/luishgo/gitlab-ce
Ruby | 151 lines | 101 code | 23 blank | 27 comment | 12 complexity | 6c90182a284b0e686f9a415175d4be50 MD5 | raw file
  1. module Banzai
  2. module Filter
  3. # HTML filter that replaces user or group references with links.
  4. #
  5. # A special `@all` reference is also supported.
  6. class UserReferenceFilter < ReferenceFilter
  7. self.reference_type = :user
  8. # Public: Find `@user` user references in text
  9. #
  10. # UserReferenceFilter.references_in(text) do |match, username|
  11. # "<a href=...>@#{user}</a>"
  12. # end
  13. #
  14. # text - String text to search.
  15. #
  16. # Yields the String match, and the String user name.
  17. #
  18. # Returns a String replaced with the return of the block.
  19. def self.references_in(text)
  20. text.gsub(User.reference_pattern) do |match|
  21. yield match, $~[:user]
  22. end
  23. end
  24. def call
  25. return doc if project.nil?
  26. ref_pattern = User.reference_pattern
  27. ref_pattern_start = /\A#{ref_pattern}\z/
  28. nodes.each do |node|
  29. if text_node?(node)
  30. replace_text_when_pattern_matches(node, ref_pattern) do |content|
  31. user_link_filter(content)
  32. end
  33. elsif element_node?(node)
  34. yield_valid_link(node) do |link, text|
  35. if link =~ ref_pattern_start
  36. replace_link_node_with_href(node, link) do
  37. user_link_filter(link, link_text: text)
  38. end
  39. end
  40. end
  41. end
  42. end
  43. doc
  44. end
  45. # Replace `@user` user references in text with links to the referenced
  46. # user's profile page.
  47. #
  48. # text - String text to replace references in.
  49. #
  50. # Returns a String with `@user` references replaced with links. All links
  51. # have `gfm` and `gfm-project_member` class names attached for styling.
  52. def user_link_filter(text, link_text: nil)
  53. self.class.references_in(text) do |match, username|
  54. if username == 'all'
  55. link_to_all(link_text: link_text)
  56. elsif namespace = namespaces[username]
  57. link_to_namespace(namespace, link_text: link_text) || match
  58. else
  59. match
  60. end
  61. end
  62. end
  63. # Returns a Hash containing all Namespace objects for the username
  64. # references in the current document.
  65. #
  66. # The keys of this Hash are the namespace paths, the values the
  67. # corresponding Namespace objects.
  68. def namespaces
  69. @namespaces ||=
  70. Namespace.where(path: usernames).each_with_object({}) do |row, hash|
  71. hash[row.path] = row
  72. end
  73. end
  74. # Returns all usernames referenced in the current document.
  75. def usernames
  76. refs = Set.new
  77. nodes.each do |node|
  78. node.to_html.scan(User.reference_pattern) do
  79. refs << $~[:user]
  80. end
  81. end
  82. refs.to_a
  83. end
  84. private
  85. def urls
  86. Gitlab::Routing.url_helpers
  87. end
  88. def link_class
  89. reference_class(:project_member)
  90. end
  91. def link_to_all(link_text: nil)
  92. project = context[:project]
  93. author = context[:author]
  94. if author && !project.team.member?(author)
  95. link_text
  96. else
  97. url = urls.namespace_project_url(project.namespace, project,
  98. only_path: context[:only_path])
  99. data = data_attribute(project: project.id, author: author.try(:id))
  100. text = link_text || User.reference_prefix + 'all'
  101. link_tag(url, data, text, 'All Project and Group Members')
  102. end
  103. end
  104. def link_to_namespace(namespace, link_text: nil)
  105. if namespace.is_a?(Group)
  106. link_to_group(namespace.path, namespace, link_text: link_text)
  107. else
  108. link_to_user(namespace.path, namespace, link_text: link_text)
  109. end
  110. end
  111. def link_to_group(group, namespace, link_text: nil)
  112. url = urls.group_url(group, only_path: context[:only_path])
  113. data = data_attribute(group: namespace.id)
  114. text = link_text || Group.reference_prefix + group
  115. link_tag(url, data, text, namespace.name)
  116. end
  117. def link_to_user(user, namespace, link_text: nil)
  118. url = urls.user_url(user, only_path: context[:only_path])
  119. data = data_attribute(user: namespace.owner_id)
  120. text = link_text || User.reference_prefix + user
  121. link_tag(url, data, text, namespace.owner_name)
  122. end
  123. def link_tag(url, data, text, title)
  124. %(<a href="#{url}" #{data} class="#{link_class}" title="#{escape_once(title)}">#{escape_once(text)}</a>)
  125. end
  126. end
  127. end
  128. end