summaryrefslogtreecommitdiff
path: root/lib/banzai/filter
diff options
context:
space:
mode:
Diffstat (limited to 'lib/banzai/filter')
-rw-r--r--lib/banzai/filter/abstract_reference_filter.rb52
-rw-r--r--lib/banzai/filter/external_link_filter.rb13
-rw-r--r--lib/banzai/filter/issue_reference_filter.rb31
-rw-r--r--lib/banzai/filter/upload_link_filter.rb11
-rw-r--r--lib/banzai/filter/wiki_link_filter.rb2
5 files changed, 86 insertions, 23 deletions
diff --git a/lib/banzai/filter/abstract_reference_filter.rb b/lib/banzai/filter/abstract_reference_filter.rb
index db95d7c908b..81d66271136 100644
--- a/lib/banzai/filter/abstract_reference_filter.rb
+++ b/lib/banzai/filter/abstract_reference_filter.rb
@@ -103,7 +103,7 @@ module Banzai
ref_pattern = object_class.reference_pattern
link_pattern = object_class.link_reference_pattern
- each_node do |node|
+ nodes.each do |node|
if text_node?(node) && ref_pattern
replace_text_when_pattern_matches(node, ref_pattern) do |content|
object_link_filter(content, ref_pattern)
@@ -206,6 +206,56 @@ module Banzai
text
end
+ # Returns a Hash containing all object references (e.g. issue IDs) per the
+ # project they belong to.
+ def references_per_project
+ @references_per_project ||= begin
+ refs = Hash.new { |hash, key| hash[key] = Set.new }
+
+ regex = Regexp.union(object_class.reference_pattern,
+ object_class.link_reference_pattern)
+
+ nodes.each do |node|
+ node.to_html.scan(regex) do
+ project = $~[:project] || current_project_path
+ symbol = $~[object_sym]
+
+ refs[project] << symbol if object_class.reference_valid?(symbol)
+ end
+ end
+
+ refs
+ end
+ end
+
+ # Returns a Hash containing referenced projects grouped per their full
+ # path.
+ def projects_per_reference
+ @projects_per_reference ||= begin
+ hash = {}
+ refs = Set.new
+
+ references_per_project.each do |project_ref, _|
+ refs << project_ref
+ end
+
+ find_projects_for_paths(refs.to_a).each do |project|
+ hash[project.path_with_namespace] = project
+ end
+
+ hash
+ end
+ end
+
+ # Returns the projects for the given paths.
+ def find_projects_for_paths(paths)
+ Project.where_paths_in(paths).includes(:namespace)
+ end
+
+ def current_project_path
+ @current_project_path ||= project.path_with_namespace
+ end
+
private
def project_refs_cache
diff --git a/lib/banzai/filter/external_link_filter.rb b/lib/banzai/filter/external_link_filter.rb
index f73ecfc9418..0a29c547a4d 100644
--- a/lib/banzai/filter/external_link_filter.rb
+++ b/lib/banzai/filter/external_link_filter.rb
@@ -3,17 +3,8 @@ module Banzai
# HTML Filter to modify the attributes of external links
class ExternalLinkFilter < HTML::Pipeline::Filter
def call
- doc.search('a').each do |node|
- link = node.attr('href')
-
- next unless link
-
- # Skip non-HTTP(S) links
- next unless link.start_with?('http')
-
- # Skip internal links
- next if link.start_with?(internal_url)
-
+ # Skip non-HTTP(S) links and internal links
+ doc.xpath("descendant-or-self::a[starts-with(@href, 'http') and not(starts-with(@href, '#{internal_url}'))]").each do |node|
node.set_attribute('rel', 'nofollow noreferrer')
node.set_attribute('target', '_blank')
end
diff --git a/lib/banzai/filter/issue_reference_filter.rb b/lib/banzai/filter/issue_reference_filter.rb
index 2496e704002..2614261f9eb 100644
--- a/lib/banzai/filter/issue_reference_filter.rb
+++ b/lib/banzai/filter/issue_reference_filter.rb
@@ -11,13 +11,40 @@ module Banzai
Issue
end
- def find_object(project, id)
- project.get_issue(id)
+ def find_object(project, iid)
+ issues_per_project[project][iid]
end
def url_for_object(issue, project)
IssuesHelper.url_for_issue(issue.iid, project, only_path: context[:only_path])
end
+
+ def project_from_ref(ref)
+ projects_per_reference[ref || current_project_path]
+ end
+
+ # Returns a Hash containing the issues per Project instance.
+ def issues_per_project
+ @issues_per_project ||= begin
+ hash = Hash.new { |h, k| h[k] = {} }
+
+ projects_per_reference.each do |path, project|
+ issue_ids = references_per_project[path]
+
+ next unless project.default_issues_tracker?
+
+ project.issues.where(iid: issue_ids.to_a).each do |issue|
+ hash[project][issue.iid] = issue
+ end
+ end
+
+ hash
+ end
+ end
+
+ def find_projects_for_paths(paths)
+ super(paths).includes(:gitlab_issue_tracker_service)
+ end
end
end
end
diff --git a/lib/banzai/filter/upload_link_filter.rb b/lib/banzai/filter/upload_link_filter.rb
index c0f503c9af3..45bb66dc99f 100644
--- a/lib/banzai/filter/upload_link_filter.rb
+++ b/lib/banzai/filter/upload_link_filter.rb
@@ -10,11 +10,11 @@ module Banzai
def call
return doc unless project
- doc.search('a').each do |el|
+ doc.xpath('descendant-or-self::a[starts-with(@href, "/uploads/")]').each do |el|
process_link_attr el.attribute('href')
end
- doc.search('img').each do |el|
+ doc.xpath('descendant-or-self::img[starts-with(@src, "/uploads/")]').each do |el|
process_link_attr el.attribute('src')
end
@@ -24,12 +24,7 @@ module Banzai
protected
def process_link_attr(html_attr)
- return if html_attr.blank?
-
- uri = html_attr.value
- if uri.starts_with?("/uploads/")
- html_attr.value = build_url(uri).to_s
- end
+ html_attr.value = build_url(html_attr.value).to_s
end
def build_url(uri)
diff --git a/lib/banzai/filter/wiki_link_filter.rb b/lib/banzai/filter/wiki_link_filter.rb
index 37a2779d453..1bb6d6bba87 100644
--- a/lib/banzai/filter/wiki_link_filter.rb
+++ b/lib/banzai/filter/wiki_link_filter.rb
@@ -29,7 +29,7 @@ module Banzai
return if html_attr.blank?
html_attr.value = apply_rewrite_rules(html_attr.value)
- rescue URI::Error
+ rescue URI::Error, Addressable::URI::InvalidURIError
# noop
end