From f3ea06eb7f8bef748be0882cb0b4fb58deed8eef Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 1 Dec 2015 15:51:27 +0100 Subject: [PATCH] Autolink first so we don't pick up numeric anchors as issue references. --- app/models/commit.rb | 7 +--- app/models/commit_range.rb | 7 +--- app/models/issue.rb | 7 +--- app/models/merge_request.rb | 7 +--- app/models/snippet.rb | 7 +--- lib/gitlab/closing_issue_extractor.rb | 2 +- lib/gitlab/markdown.rb | 5 +-- .../markdown/abstract_reference_filter.rb | 20 ++++++---- .../markdown/commit_range_reference_filter.rb | 4 +- .../markdown/commit_reference_filter.rb | 4 +- lib/gitlab/markdown/external_link_filter.rb | 7 +--- .../merge_request_reference_filter.rb | 2 +- lib/gitlab/markdown/redactor_filter.rb | 2 +- lib/gitlab/markdown/reference_filter.rb | 23 +++++++++++ lib/gitlab/reference_extractor.rb | 14 +++++-- .../commit_range_reference_filter_spec.rb | 40 +++++++++---------- .../markdown/commit_reference_filter_spec.rb | 36 ++++++++--------- .../markdown/issue_reference_filter_spec.rb | 36 ++++++++--------- .../merge_request_reference_filter_spec.rb | 30 +++++++------- .../markdown/snippet_reference_filter_spec.rb | 32 +++++++-------- spec/support/filter_spec_helper.rb | 19 +++++++-- 21 files changed, 171 insertions(+), 140 deletions(-) diff --git a/app/models/commit.rb b/app/models/commit.rb index a5d041a49c8..c0998a45709 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -73,11 +73,8 @@ class Commit # This pattern supports cross-project references. def self.reference_pattern %r{ - #{link_reference_pattern} | - (?: - (?:#{Project.reference_pattern}#{reference_prefix})? - (?\h{6,40}) - ) + (?:#{Project.reference_pattern}#{reference_prefix})? + (?\h{6,40}) }x end diff --git a/app/models/commit_range.rb b/app/models/commit_range.rb index f786a749b8e..b8bf36b32ce 100644 --- a/app/models/commit_range.rb +++ b/app/models/commit_range.rb @@ -44,11 +44,8 @@ class CommitRange # This pattern supports cross-project references. def self.reference_pattern %r{ - #{link_reference_pattern} | - (?: - (?:#{Project.reference_pattern}#{reference_prefix})? - (?#{STRICT_PATTERN}) - ) + (?:#{Project.reference_pattern}#{reference_prefix})? + (?#{STRICT_PATTERN}) }x end diff --git a/app/models/issue.rb b/app/models/issue.rb index e62acfdfd91..187b6482b6c 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -64,11 +64,8 @@ class Issue < ActiveRecord::Base # This pattern supports cross-project references. def self.reference_pattern %r{ - #{link_reference_pattern} | - (?: - (#{Project.reference_pattern})? - #{Regexp.escape(reference_prefix)}(?\d+) - ) + (#{Project.reference_pattern})? + #{Regexp.escape(reference_prefix)}(?\d+) }x end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index c1d3874adee..2a4aee7e5d9 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -146,11 +146,8 @@ class MergeRequest < ActiveRecord::Base # This pattern supports cross-project references. def self.reference_pattern %r{ - #{link_reference_pattern} | - (?: - (#{Project.reference_pattern})? - #{Regexp.escape(reference_prefix)}(?\d+) - ) + (#{Project.reference_pattern})? + #{Regexp.escape(reference_prefix)}(?\d+) }x end diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 8ec12ddf6ef..f876be7a4c8 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -60,11 +60,8 @@ class Snippet < ActiveRecord::Base # This pattern supports cross-project references. def self.reference_pattern %r{ - #{link_reference_pattern} | - (?: - (#{Project.reference_pattern})? - #{Regexp.escape(reference_prefix)}(?\d+) - ) + (#{Project.reference_pattern})? + #{Regexp.escape(reference_prefix)}(?\d+) }x end 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 diff --git a/spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb b/spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb index f65a3e8a0bd..92158382790 100644 --- a/spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb +++ b/spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb @@ -18,7 +18,7 @@ module Gitlab::Markdown %w(pre code a style).each do |elem| it "ignores valid references contained inside '#{elem}' element" do exp = act = "<#{elem}>Commit Range #{range.to_reference}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp end end @@ -27,14 +27,14 @@ module Gitlab::Markdown let(:reference2) { range2.to_reference } it 'links to a valid two-dot reference' do - doc = filter("See #{reference2}") + doc = reference_filter("See #{reference2}") expect(doc.css('a').first.attr('href')). to eq urls.namespace_project_compare_url(project.namespace, project, range2.to_param) end it 'links to a valid three-dot reference' do - doc = filter("See #{reference}") + doc = reference_filter("See #{reference}") expect(doc.css('a').first.attr('href')). to eq urls.namespace_project_compare_url(project.namespace, project, range.to_param) @@ -46,12 +46,12 @@ module Gitlab::Markdown exp = commit1.short_id + '...' + commit2.short_id - expect(filter("See #{reference}").css('a').first.text).to eq exp - expect(filter("See #{reference2}").css('a').first.text).to eq exp + expect(reference_filter("See #{reference}").css('a').first.text).to eq exp + expect(reference_filter("See #{reference2}").css('a').first.text).to eq exp end it 'links with adjacent text' do - doc = filter("See (#{reference}.)") + doc = reference_filter("See (#{reference}.)") exp = Regexp.escape(range.reference_link_text) expect(doc.to_html).to match(/\(#{exp}<\/a>\.\)/) @@ -63,21 +63,21 @@ module Gitlab::Markdown expect(project).to receive(:valid_repo?).and_return(true) expect(project.repository).to receive(:commit).with(commit1.id.reverse) expect(project.repository).to receive(:commit).with(commit2.id) - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp end it 'includes a title attribute' do - doc = filter("See #{reference}") + doc = reference_filter("See #{reference}") expect(doc.css('a').first.attr('title')).to eq range.reference_title end it 'includes default classes' do - doc = filter("See #{reference}") + doc = reference_filter("See #{reference}") expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-commit_range' end it 'includes a data-project attribute' do - doc = filter("See #{reference}") + doc = reference_filter("See #{reference}") link = doc.css('a').first expect(link).to have_attribute('data-project') @@ -85,7 +85,7 @@ module Gitlab::Markdown end it 'includes a data-commit-range attribute' do - doc = filter("See #{reference}") + doc = reference_filter("See #{reference}") link = doc.css('a').first expect(link).to have_attribute('data-commit-range') @@ -93,7 +93,7 @@ module Gitlab::Markdown end it 'supports an :only_path option' do - doc = filter("See #{reference}", only_path: true) + doc = reference_filter("See #{reference}", only_path: true) link = doc.css('a').first.attr('href') expect(link).not_to match %r(https?://) @@ -116,14 +116,14 @@ module Gitlab::Markdown end it 'links to a valid reference' do - doc = filter("See #{reference}") + doc = reference_filter("See #{reference}") expect(doc.css('a').first.attr('href')). to eq urls.namespace_project_compare_url(project2.namespace, project2, range.to_param) end it 'links with adjacent text' do - doc = filter("Fixed (#{reference}.)") + doc = reference_filter("Fixed (#{reference}.)") exp = Regexp.escape("#{project2.to_reference}@#{range.reference_link_text}") expect(doc.to_html).to match(/\(#{exp}<\/a>\.\)/) @@ -131,10 +131,10 @@ module Gitlab::Markdown it 'ignores invalid commit IDs on the referenced project' do exp = act = "Fixed #{project2.to_reference}@#{commit1.id.reverse}...#{commit2.id}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp exp = act = "Fixed #{project2.to_reference}@#{commit1.id}...#{commit2.id.reverse}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp end it 'adds to the results hash' do @@ -154,14 +154,14 @@ module Gitlab::Markdown end it 'links to a valid reference' do - doc = filter("See #{reference}") + doc = reference_filter("See #{reference}") expect(doc.css('a').first.attr('href')). to eq reference end it 'links with adjacent text' do - doc = filter("Fixed (#{reference}.)") + doc = reference_filter("Fixed (#{reference}.)") exp = Regexp.escape(range.reference_link_text(project)) expect(doc.to_html).to match(/\(#{exp}<\/a>\.\)/) @@ -169,10 +169,10 @@ module Gitlab::Markdown it 'ignores invalid commit IDs on the referenced project' do exp = act = "Fixed #{project2.to_reference}@#{commit1.id.reverse}...#{commit2.id}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp exp = act = "Fixed #{project2.to_reference}@#{commit1.id}...#{commit2.id.reverse}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp end it 'adds to the results hash' do diff --git a/spec/lib/gitlab/markdown/commit_reference_filter_spec.rb b/spec/lib/gitlab/markdown/commit_reference_filter_spec.rb index 4cc6bbbfe94..6fe9b165ff5 100644 --- a/spec/lib/gitlab/markdown/commit_reference_filter_spec.rb +++ b/spec/lib/gitlab/markdown/commit_reference_filter_spec.rb @@ -14,7 +14,7 @@ module Gitlab::Markdown %w(pre code a style).each do |elem| it "ignores valid references contained inside '#{elem}' element" do exp = act = "<#{elem}>Commit #{commit.id}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp end end @@ -24,7 +24,7 @@ module Gitlab::Markdown # Let's test a variety of commit SHA sizes just to be paranoid [6, 8, 12, 18, 20, 32, 40].each do |size| it "links to a valid reference of #{size} characters" do - doc = filter("See #{reference[0...size]}") + doc = reference_filter("See #{reference[0...size]}") expect(doc.css('a').first.text).to eq commit.short_id expect(doc.css('a').first.attr('href')). @@ -33,15 +33,15 @@ module Gitlab::Markdown end it 'always uses the short ID as the link text' do - doc = filter("See #{commit.id}") + doc = reference_filter("See #{commit.id}") expect(doc.text).to eq "See #{commit.short_id}" - doc = filter("See #{commit.id[0...6]}") + doc = reference_filter("See #{commit.id[0...6]}") expect(doc.text).to eq "See #{commit.short_id}" end it 'links with adjacent text' do - doc = filter("See (#{reference}.)") + doc = reference_filter("See (#{reference}.)") expect(doc.to_html).to match(/\(#{commit.short_id}<\/a>\.\)/) end @@ -51,28 +51,28 @@ module Gitlab::Markdown expect(project).to receive(:valid_repo?).and_return(true) expect(project.repository).to receive(:commit).with(invalid) - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp end it 'includes a title attribute' do - doc = filter("See #{reference}") + doc = reference_filter("See #{reference}") expect(doc.css('a').first.attr('title')).to eq commit.link_title end it 'escapes the title attribute' do allow_any_instance_of(Commit).to receive(:title).and_return(%{">whatever#{exp}@#{commit.short_id}<\/a>\.\)/) @@ -123,7 +123,7 @@ module Gitlab::Markdown it 'ignores invalid commit IDs on the referenced project' do exp = act = "Committed #{invalidate_reference(reference)}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp end it 'adds to the results hash' do @@ -139,21 +139,21 @@ module Gitlab::Markdown let(:reference) { urls.namespace_project_commit_url(project2.namespace, project2, commit.id) } it 'links to a valid reference' do - doc = filter("See #{reference}") + doc = reference_filter("See #{reference}") expect(doc.css('a').first.attr('href')). to eq urls.namespace_project_commit_url(project2.namespace, project2, commit.id) end it 'links with adjacent text' do - doc = filter("Fixed (#{reference}.)") + doc = reference_filter("Fixed (#{reference}.)") expect(doc.to_html).to match(/\(#{commit.reference_link_text(project)}<\/a>\.\)/) end it 'ignores invalid commit IDs on the referenced project' do exp = act = "Committed #{invalidate_reference(reference)}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to match(/#{Regexp.escape(invalidate_reference(reference))}<\/a>/) end it 'adds to the results hash' do diff --git a/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb b/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb index 296e8868f46..0a741688b82 100644 --- a/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb +++ b/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb @@ -18,7 +18,7 @@ module Gitlab::Markdown %w(pre code a style).each do |elem| it "ignores valid references contained inside '#{elem}' element" do exp = act = "<#{elem}>Issue #{issue.to_reference}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp end end @@ -29,18 +29,18 @@ module Gitlab::Markdown expect(project).to receive(:get_issue).with(issue.iid).and_return(nil) exp = act = "Issue #{reference}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp end it 'links to a valid reference' do - doc = filter("Fixed #{reference}") + doc = reference_filter("Fixed #{reference}") expect(doc.css('a').first.attr('href')). to eq helper.url_for_issue(issue.iid, project) end it 'links with adjacent text' do - doc = filter("Fixed (#{reference}.)") + doc = reference_filter("Fixed (#{reference}.)") expect(doc.to_html).to match(/\(#{Regexp.escape(reference)}<\/a>\.\)/) end @@ -48,28 +48,28 @@ module Gitlab::Markdown invalid = invalidate_reference(reference) exp = act = "Fixed #{invalid}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp end it 'includes a title attribute' do - doc = filter("Issue #{reference}") + doc = reference_filter("Issue #{reference}") expect(doc.css('a').first.attr('title')).to eq "Issue: #{issue.title}" end it 'escapes the title attribute' do issue.update_attribute(:title, %{">whatever#{Regexp.escape(reference)}<\/a>\.\)/) end it 'ignores invalid issue IDs on the referenced project' do exp = act = "Fixed #{invalidate_reference(reference)}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp end it 'adds to the results hash' do @@ -147,18 +147,18 @@ module Gitlab::Markdown with(issue.iid).and_return(nil) exp = act = "Issue #{reference}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to match(/#{Regexp.escape(reference)}<\/a>/) end it 'links to a valid reference' do - doc = filter("See #{reference}") + doc = reference_filter("See #{reference}") expect(doc.css('a').first.attr('href')). to eq reference end it 'links with adjacent text' do - doc = filter("Fixed (#{reference}.)") + doc = reference_filter("Fixed (#{reference}.)") expect(doc.to_html).to match(/\(#{Regexp.escape(issue.to_reference(project))} \(comment 123\)<\/a>\.\)/) end diff --git a/spec/lib/gitlab/markdown/merge_request_reference_filter_spec.rb b/spec/lib/gitlab/markdown/merge_request_reference_filter_spec.rb index ca3e7151e02..cdb3390e793 100644 --- a/spec/lib/gitlab/markdown/merge_request_reference_filter_spec.rb +++ b/spec/lib/gitlab/markdown/merge_request_reference_filter_spec.rb @@ -14,7 +14,7 @@ module Gitlab::Markdown %w(pre code a style).each do |elem| it "ignores valid references contained inside '#{elem}' element" do exp = act = "<#{elem}>Merge #{merge.to_reference}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp end end @@ -22,42 +22,42 @@ module Gitlab::Markdown let(:reference) { merge.to_reference } it 'links to a valid reference' do - doc = filter("See #{reference}") + doc = reference_filter("See #{reference}") expect(doc.css('a').first.attr('href')).to eq urls. namespace_project_merge_request_url(project.namespace, project, merge) end it 'links with adjacent text' do - doc = filter("Merge (#{reference}.)") + doc = reference_filter("Merge (#{reference}.)") expect(doc.to_html).to match(/\(#{Regexp.escape(reference)}<\/a>\.\)/) end it 'ignores invalid merge IDs' do exp = act = "Merge #{invalidate_reference(reference)}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp end it 'includes a title attribute' do - doc = filter("Merge #{reference}") + doc = reference_filter("Merge #{reference}") expect(doc.css('a').first.attr('title')).to eq "Merge Request: #{merge.title}" end it 'escapes the title attribute' do merge.update_attribute(:title, %{">whatever#{Regexp.escape(reference)}<\/a>\.\)/) end it 'ignores invalid merge IDs on the referenced project' do exp = act = "Merge #{invalidate_reference(reference)}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp end it 'adds to the results hash' do @@ -124,14 +124,14 @@ module Gitlab::Markdown let(:reference) { urls.namespace_project_merge_request_url(project2.namespace, project2, merge) + '/diffs#note_123' } it 'links to a valid reference' do - doc = filter("See #{reference}") + doc = reference_filter("See #{reference}") expect(doc.css('a').first.attr('href')). to eq reference end it 'links with adjacent text' do - doc = filter("Merge (#{reference}.)") + doc = reference_filter("Merge (#{reference}.)") expect(doc.to_html).to match(/\(#{Regexp.escape(merge.to_reference(project))} \(diffs, comment 123\)<\/a>\.\)/) end diff --git a/spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb b/spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb index 3080a8a3608..73d20957a56 100644 --- a/spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb +++ b/spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb @@ -15,48 +15,48 @@ module Gitlab::Markdown %w(pre code a style).each do |elem| it "ignores valid references contained inside '#{elem}' element" do exp = act = "<#{elem}>Snippet #{reference}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp end end context 'internal reference' do it 'links to a valid reference' do - doc = filter("See #{reference}") + doc = reference_filter("See #{reference}") expect(doc.css('a').first.attr('href')).to eq urls. namespace_project_snippet_url(project.namespace, project, snippet) end it 'links with adjacent text' do - doc = filter("Snippet (#{reference}.)") + doc = reference_filter("Snippet (#{reference}.)") expect(doc.to_html).to match(/\(#{Regexp.escape(reference)}<\/a>\.\)/) end it 'ignores invalid snippet IDs' do exp = act = "Snippet #{invalidate_reference(reference)}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp end it 'includes a title attribute' do - doc = filter("Snippet #{reference}") + doc = reference_filter("Snippet #{reference}") expect(doc.css('a').first.attr('title')).to eq "Snippet: #{snippet.title}" end it 'escapes the title attribute' do snippet.update_attribute(:title, %{">whatever#{Regexp.escape(reference)}<\/a>\.\)/) end it 'ignores invalid snippet IDs on the referenced project' do exp = act = "See #{invalidate_reference(reference)}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to eq exp end it 'adds to the results hash' do @@ -122,21 +122,21 @@ module Gitlab::Markdown let(:reference) { urls.namespace_project_snippet_url(project2.namespace, project2, snippet) } it 'links to a valid reference' do - doc = filter("See #{reference}") + doc = reference_filter("See #{reference}") expect(doc.css('a').first.attr('href')). to eq urls.namespace_project_snippet_url(project2.namespace, project2, snippet) end it 'links with adjacent text' do - doc = filter("See (#{reference}.)") + doc = reference_filter("See (#{reference}.)") expect(doc.to_html).to match(/\(#{Regexp.escape(snippet.to_reference(project))}<\/a>\.\)/) end it 'ignores invalid snippet IDs on the referenced project' do exp = act = "See #{invalidate_reference(reference)}" - expect(filter(act).to_html).to eq exp + expect(reference_filter(act).to_html).to match(/#{Regexp.escape(invalidate_reference(reference))}<\/a>/) end it 'adds to the results hash' do diff --git a/spec/support/filter_spec_helper.rb b/spec/support/filter_spec_helper.rb index 97e5c270a59..91e3bee13c1 100644 --- a/spec/support/filter_spec_helper.rb +++ b/spec/support/filter_spec_helper.rb @@ -35,11 +35,24 @@ module FilterSpecHelper pipeline.call(body) end - def reference_pipeline_result(body, contexts = {}) + def reference_pipeline(contexts = {}) contexts.reverse_merge!(project: project) if defined?(project) - pipeline = HTML::Pipeline.new([described_class, Gitlab::Markdown::ReferenceGathererFilter], contexts) - pipeline.call(body) + filters = [ + Gitlab::Markdown::AutolinkFilter, + described_class, + Gitlab::Markdown::ReferenceGathererFilter + ] + + HTML::Pipeline.new(filters, contexts) + end + + def reference_pipeline_result(body, contexts = {}) + reference_pipeline(contexts).call(body) + end + + def reference_filter(html, contexts = {}) + reference_pipeline(contexts).to_document(html) end # Modify a String reference to make it invalid