diff options
-rw-r--r-- | app/models/milestone.rb | 42 | ||||
-rw-r--r-- | lib/banzai/filter/milestone_reference_filter.rb | 26 | ||||
-rw-r--r-- | spec/fixtures/markdown.md.erb | 9 | ||||
-rw-r--r-- | spec/support/markdown_feature.rb | 6 | ||||
-rw-r--r-- | spec/support/matchers/markdown_matchers.rb | 2 |
5 files changed, 71 insertions, 14 deletions
diff --git a/app/models/milestone.rb b/app/models/milestone.rb index 986184dd301..39dc8d89614 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -74,8 +74,22 @@ class Milestone < ActiveRecord::Base end end + def self.reference_prefix + '%' + end + def self.reference_pattern - nil + %r{ + (#{Project.reference_pattern})? + #{Regexp.escape(reference_prefix)} + (?: + (?<milestone_id>\d+) | # Integer-based milestone ID, or + (?<milestone_name> + [A-Za-z0-9_-]+ | # String-based single-word milestone title, or + "[^"]+" # String-based multi-word milestone surrounded in quotes + ) + ) + }x end def self.link_reference_pattern @@ -86,13 +100,15 @@ class Milestone < ActiveRecord::Base self.where('due_date > ?', Time.now).reorder(due_date: :asc).first end - def to_reference(from_project = nil) - escaped_title = self.title.gsub("]", "\\]") + def to_reference(from_project = nil, format: :id) + format_reference = milestone_format_reference(format) + reference = "#{self.class.reference_prefix}#{format_reference}" - h = Gitlab::Routing.url_helpers - url = h.namespace_project_milestone_url(self.project.namespace, self.project, self) - - "[#{escaped_title}](#{url})" + if cross_project_reference?(from_project) + project.to_reference + reference + else + reference + end end def reference_link_text(from_project = nil) @@ -160,4 +176,16 @@ class Milestone < ActiveRecord::Base issues.where(id: ids). update_all(["position = CASE #{conditions} ELSE position END", *pairs]) end + + private + + def milestone_format_reference(format = :id) + raise StandardError, 'Unknown format' unless [:id, :name].include?(format) + + if format == :name && !name.include?('"') + %("#{name}") + else + id + end + end end diff --git a/lib/banzai/filter/milestone_reference_filter.rb b/lib/banzai/filter/milestone_reference_filter.rb index 4cb82178024..2c90fd4d385 100644 --- a/lib/banzai/filter/milestone_reference_filter.rb +++ b/lib/banzai/filter/milestone_reference_filter.rb @@ -7,14 +7,36 @@ module Banzai end def find_object(project, id) - project.milestones.find_by(iid: id) + project.milestones.find(id) end - def url_for_object(issue, project) + def references_in(text, pattern = Milestone.reference_pattern) + text.gsub(pattern) do |match| + project = project_from_ref($~[:project]) + params = milestone_params($~[:milestone_id].to_i, $~[:milestone_name]) + milestone = project.milestones.find_by(params) + + if milestone + yield match, milestone.id, $~[:project], $~ + else + match + end + end + end + + def url_for_object(milestone, project) h = Gitlab::Routing.url_helpers h.namespace_project_milestone_url(project.namespace, project, milestone, only_path: context[:only_path]) end + + def milestone_params(id, name) + if name + { name: name.tr('"', '') } + else + { id: id } + end + end end end end diff --git a/spec/fixtures/markdown.md.erb b/spec/fixtures/markdown.md.erb index 1772cc3f6a4..6d3bf810c2c 100644 --- a/spec/fixtures/markdown.md.erb +++ b/spec/fixtures/markdown.md.erb @@ -216,10 +216,13 @@ References should be parseable even inside _<%= merge_request.to_reference %>_ e #### MilestoneReferenceFilter -- Milestone: <%= milestone.to_reference %> +- Milestone by ID: <%= simple_milestone.to_reference %> +- Milestone by name: <%= Milestone.reference_prefix %><%= simple_milestone.name %> +- Milestone by name in quotes: <%= milestone.to_reference(format: :name) %> - Milestone in another project: <%= xmilestone.to_reference(project) %> -- Ignored in code: `<%= milestone.to_reference %>` -- Link to milestone by URL: [Milestone](<%= urls.namespace_project_milestone_url(milestone.project.namespace, milestone.project, milestone) %>) +- Ignored in code: `<%= simple_milestone.to_reference %>` +- Ignored in links: [Link to <%= simple_milestone.to_reference %>](#milestone-link) +- Link to milestone by URL: [Milestone](<%= milestone.to_reference %>) ### Task Lists diff --git a/spec/support/markdown_feature.rb b/spec/support/markdown_feature.rb index b87cd6bbca2..7fc6d6fcc5e 100644 --- a/spec/support/markdown_feature.rb +++ b/spec/support/markdown_feature.rb @@ -63,8 +63,12 @@ class MarkdownFeature @label ||= create(:label, name: 'awaiting feedback', project: project) end + def simple_milestone + @simple_milestone ||= create(:milestone, name: 'gfm-milestone', project: project) + end + def milestone - @milestone ||= create(:milestone, project: project) + @milestone ||= create(:milestone, name: 'next goal', project: project) end # Cross-references ----------------------------------------------------------- diff --git a/spec/support/matchers/markdown_matchers.rb b/spec/support/matchers/markdown_matchers.rb index 43cb6ef43f2..492138716af 100644 --- a/spec/support/matchers/markdown_matchers.rb +++ b/spec/support/matchers/markdown_matchers.rb @@ -154,7 +154,7 @@ module MarkdownMatchers set_default_markdown_messages match do |actual| - expect(actual).to have_selector('a.gfm.gfm-milestone', count: 3) + expect(actual).to have_selector('a.gfm.gfm-milestone', count: 5) end end |