summaryrefslogtreecommitdiff
path: root/lib/gitlab
diff options
context:
space:
mode:
authorDouwe Maan <douwe@gitlab.com>2015-12-01 15:51:27 +0100
committerDouwe Maan <douwe@gitlab.com>2015-12-01 15:53:32 +0100
commitf3ea06eb7f8bef748be0882cb0b4fb58deed8eef (patch)
tree42e9620a2ec0234ce20778ae40d781c2504254e8 /lib/gitlab
parent62c14ba2edf9ac4b4bb1e8c46c0c60f1b6574909 (diff)
downloadgitlab-ce-f3ea06eb7f8bef748be0882cb0b4fb58deed8eef.tar.gz
Autolink first so we don't pick up numeric anchors as issue references.
Diffstat (limited to 'lib/gitlab')
-rw-r--r--lib/gitlab/closing_issue_extractor.rb2
-rw-r--r--lib/gitlab/markdown.rb5
-rw-r--r--lib/gitlab/markdown/abstract_reference_filter.rb20
-rw-r--r--lib/gitlab/markdown/commit_range_reference_filter.rb4
-rw-r--r--lib/gitlab/markdown/commit_reference_filter.rb4
-rw-r--r--lib/gitlab/markdown/external_link_filter.rb7
-rw-r--r--lib/gitlab/markdown/merge_request_reference_filter.rb2
-rw-r--r--lib/gitlab/markdown/redactor_filter.rb2
-rw-r--r--lib/gitlab/markdown/reference_filter.rb23
-rw-r--r--lib/gitlab/reference_extractor.rb14
10 files changed, 58 insertions, 25 deletions
diff --git a/lib/gitlab/closing_issue_extractor.rb b/lib/gitlab/closing_issue_extractor.rb
index 70b9943d7eb..0cf4c918736 100644
--- a/lib/gitlab/closing_issue_extractor.rb
+++ b/lib/gitlab/closing_issue_extractor.rb
@@ -2,7 +2,7 @@ module Gitlab
class ClosingIssueExtractor
ISSUE_CLOSING_REGEX = begin
pattern = Gitlab.config.gitlab.issue_closing_pattern
- pattern = pattern.sub('%{issue_ref}', "(?:#{Issue.reference_pattern})")
+ pattern = pattern.sub('%{issue_ref}', "(?:(?:#{Issue.link_reference_pattern})|(?:#{Issue.reference_pattern}))")
Regexp.new(pattern).freeze
end
diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb
index ee458eda025..b082bfc434b 100644
--- a/lib/gitlab/markdown.rb
+++ b/lib/gitlab/markdown.rb
@@ -181,6 +181,8 @@ module Gitlab
Gitlab::Markdown::RelativeLinkFilter,
Gitlab::Markdown::EmojiFilter,
Gitlab::Markdown::TableOfContentsFilter,
+ Gitlab::Markdown::AutolinkFilter,
+ Gitlab::Markdown::ExternalLinkFilter,
Gitlab::Markdown::UserReferenceFilter,
Gitlab::Markdown::IssueReferenceFilter,
@@ -191,9 +193,6 @@ module Gitlab
Gitlab::Markdown::CommitReferenceFilter,
Gitlab::Markdown::LabelReferenceFilter,
- Gitlab::Markdown::AutolinkFilter,
- Gitlab::Markdown::ExternalLinkFilter,
-
Gitlab::Markdown::TaskListFilter
]
end
diff --git a/lib/gitlab/markdown/abstract_reference_filter.rb b/lib/gitlab/markdown/abstract_reference_filter.rb
index f6df9518fc6..37ed423eeda 100644
--- a/lib/gitlab/markdown/abstract_reference_filter.rb
+++ b/lib/gitlab/markdown/abstract_reference_filter.rb
@@ -37,8 +37,8 @@ module Gitlab
# of the external project reference, and all of the matchdata.
#
# Returns a String replaced with the return of the block.
- def self.references_in(text)
- text.gsub(object_class.reference_pattern) do |match|
+ def self.references_in(text, pattern = object_class.reference_pattern)
+ text.gsub(pattern) do |match|
yield match, $~[object_sym].to_i, $~[:project], $~
end
end
@@ -61,7 +61,11 @@ module Gitlab
def call
replace_text_nodes_matching(object_class.reference_pattern) do |content|
- object_link_filter(content)
+ object_link_filter(content, object_class.reference_pattern)
+ end
+
+ replace_link_nodes_matching(object_class.link_reference_pattern) do |content|
+ object_link_filter(content, object_class.link_reference_pattern)
end
end
@@ -72,15 +76,17 @@ module Gitlab
#
# Returns a String with references replaced with links. All links
# have `gfm` and `gfm-OBJECT_NAME` class names attached for styling.
- def object_link_filter(text)
- references_in(text) do |match, id, project_ref, matches|
+ def object_link_filter(text, pattern)
+ references_in(text, pattern) do |match, id, project_ref, matches|
project = project_from_ref(project_ref)
if project && object = find_object(project, id)
title = escape_once(object_link_title(object))
klass = reference_class(object_sym)
data = data_attribute(project: project.id, object_sym => object.id, original: match)
- url = matches[:url] || url_for_object(object, project)
+
+ url = matches[:url] if matches.names.include?("url")
+ url ||= url_for_object(object, project)
text = object.reference_link_text(context[:project])
@@ -99,7 +105,7 @@ module Gitlab
def object_link_text_extras(object, matches)
extras = []
- if matches[:anchor] && matches[:anchor] =~ /\A\#note_(\d+)\z/
+ if matches.names.include?("anchor") && matches[:anchor] && matches[:anchor] =~ /\A\#note_(\d+)\z/
extras << "comment #{$1}"
end
diff --git a/lib/gitlab/markdown/commit_range_reference_filter.rb b/lib/gitlab/markdown/commit_range_reference_filter.rb
index f24bed76193..36b3258ef76 100644
--- a/lib/gitlab/markdown/commit_range_reference_filter.rb
+++ b/lib/gitlab/markdown/commit_range_reference_filter.rb
@@ -10,8 +10,8 @@ module Gitlab
CommitRange
end
- def self.references_in(text)
- text.gsub(CommitRange.reference_pattern) do |match|
+ def self.references_in(text, pattern = CommitRange.reference_pattern)
+ text.gsub(pattern) do |match|
yield match, $~[:commit_range], $~[:project], $~
end
end
diff --git a/lib/gitlab/markdown/commit_reference_filter.rb b/lib/gitlab/markdown/commit_reference_filter.rb
index cc7abc08c87..b4036578e60 100644
--- a/lib/gitlab/markdown/commit_reference_filter.rb
+++ b/lib/gitlab/markdown/commit_reference_filter.rb
@@ -10,8 +10,8 @@ module Gitlab
Commit
end
- def self.references_in(text)
- text.gsub(Commit.reference_pattern) do |match|
+ def self.references_in(text, pattern = Commit.reference_pattern)
+ text.gsub(pattern) do |match|
yield match, $~[:commit], $~[:project], $~
end
end
diff --git a/lib/gitlab/markdown/external_link_filter.rb b/lib/gitlab/markdown/external_link_filter.rb
index b6792932016..e09dfcb83c8 100644
--- a/lib/gitlab/markdown/external_link_filter.rb
+++ b/lib/gitlab/markdown/external_link_filter.rb
@@ -8,12 +8,9 @@ module Gitlab
class ExternalLinkFilter < HTML::Pipeline::Filter
def call
doc.search('a').each do |node|
- next unless node.has_attribute?('href')
+ link = node.attr('href')
- klass = node.attribute('class')
- next if klass && klass.include?('gfm')
-
- link = node.attribute('href').value
+ next unless link
# Skip non-HTTP(S) links
next unless link.start_with?('http')
diff --git a/lib/gitlab/markdown/merge_request_reference_filter.rb b/lib/gitlab/markdown/merge_request_reference_filter.rb
index 3780a14a130..de71fc76a9b 100644
--- a/lib/gitlab/markdown/merge_request_reference_filter.rb
+++ b/lib/gitlab/markdown/merge_request_reference_filter.rb
@@ -24,7 +24,7 @@ module Gitlab
def object_link_text_extras(object, matches)
extras = super
- if matches[:path] && matches[:path] == '/diffs'
+ if matches.names.include?("path") && matches[:path] && matches[:path] == '/diffs'
extras.unshift "diffs"
end
diff --git a/lib/gitlab/markdown/redactor_filter.rb b/lib/gitlab/markdown/redactor_filter.rb
index 2a58c798f9f..bea714a01e7 100644
--- a/lib/gitlab/markdown/redactor_filter.rb
+++ b/lib/gitlab/markdown/redactor_filter.rb
@@ -14,7 +14,7 @@ module Gitlab
unless user_can_reference?(node)
# The reference should be replaced by the original text,
# which is not always the same as the rendered text.
- text = node.attribute('data-original') || node.text
+ text = node.attr('data-original') || node.text
node.replace(text)
end
end
diff --git a/lib/gitlab/markdown/reference_filter.rb b/lib/gitlab/markdown/reference_filter.rb
index a4c560f578c..e52633ee74c 100644
--- a/lib/gitlab/markdown/reference_filter.rb
+++ b/lib/gitlab/markdown/reference_filter.rb
@@ -122,6 +122,29 @@ module Gitlab
doc
end
+ def replace_link_nodes_matching(pattern)
+ return doc if project.nil?
+
+ doc.search('a').each do |node|
+ klass = node.attr('class')
+ next if klass && klass.include?('gfm')
+
+ link = node.attr('href')
+ text = node.text
+
+ # Ignore ending punctionation like periods or commas
+ next unless link == text && text =~ /\A#{pattern}/
+
+ html = yield text
+
+ next if html == text
+
+ node.replace(html)
+ end
+
+ doc
+ end
+
# Ensure that a :project key exists in context
#
# Note that while the key might exist, its value could be nil!
diff --git a/lib/gitlab/reference_extractor.rb b/lib/gitlab/reference_extractor.rb
index da8df8a3025..3c3478a1271 100644
--- a/lib/gitlab/reference_extractor.rb
+++ b/lib/gitlab/reference_extractor.rb
@@ -41,14 +41,14 @@ module Gitlab
# Returns the results Array for the requested filter type
def pipeline_result(filter_type)
return [] if @text.blank?
-
+
klass = "#{filter_type.to_s.camelize}ReferenceFilter"
filter = Gitlab::Markdown.const_get(klass)
context = {
project: project,
current_user: current_user,
-
+
# We don't actually care about the links generated
only_path: true,
ignore_blockquotes: true,
@@ -58,7 +58,15 @@ module Gitlab
reference_filter: filter
}
- pipeline = HTML::Pipeline.new([filter, Gitlab::Markdown::ReferenceGathererFilter], context)
+ # We need to autolink first to finds links to referables, and to prevent
+ # numeric anchors to be parsed as issue references.
+ filters = [
+ Gitlab::Markdown::AutolinkFilter,
+ filter,
+ Gitlab::Markdown::ReferenceGathererFilter
+ ]
+
+ pipeline = HTML::Pipeline.new(filters, context)
result = pipeline.call(@text)
values = result[:references][filter_type].uniq