Commit 9c046fea676b65c4883707fad22ceb8dd0e7525e
Committed by
GitLab
1 parent
ef933ae6
Exists in
spb-stable
and in
2 other branches
links to issues on main dashboard
Showing
6 changed files
with
110 additions
and
78 deletions
Show diff stats
app/helpers/gitlab_markdown_helper.rb
... | ... | @@ -19,7 +19,7 @@ module GitlabMarkdownHelper |
19 | 19 | escape_once(body) |
20 | 20 | end |
21 | 21 | |
22 | - gfm_body = gfm(escaped_body, html_options) | |
22 | + gfm_body = gfm(escaped_body, @project, html_options) | |
23 | 23 | |
24 | 24 | gfm_body.gsub!(%r{<a.*?>.*?</a>}m) do |match| |
25 | 25 | "</a>#{match}#{link_to("", url, html_options)[0..-5]}" # "</a>".length +1 | ... | ... |
app/helpers/issues_helper.rb
... | ... | @@ -13,76 +13,80 @@ module IssuesHelper |
13 | 13 | OpenStruct.new(id: 0, title: 'None (backlog)', name: 'Unassigned') |
14 | 14 | end |
15 | 15 | |
16 | - def url_for_project_issues | |
17 | - return "" if @project.nil? | |
16 | + def url_for_project_issues(project = @project) | |
17 | + return '' if project.nil? | |
18 | 18 | |
19 | - if @project.used_default_issues_tracker? || !external_issues_tracker_enabled? | |
20 | - project_issues_path(@project) | |
19 | + if project.used_default_issues_tracker? || !external_issues_tracker_enabled? | |
20 | + project_issues_path(project) | |
21 | 21 | else |
22 | - url = Gitlab.config.issues_tracker[@project.issues_tracker]["project_url"] | |
23 | - url.gsub(':project_id', @project.id.to_s) | |
24 | - .gsub(':issues_tracker_id', @project.issues_tracker_id.to_s) | |
22 | + url = Gitlab.config.issues_tracker[project.issues_tracker]['project_url'] | |
23 | + url.gsub(':project_id', project.id.to_s). | |
24 | + gsub(':issues_tracker_id', project.issues_tracker_id.to_s) | |
25 | 25 | end |
26 | 26 | end |
27 | 27 | |
28 | - def url_for_new_issue | |
29 | - return "" if @project.nil? | |
28 | + def url_for_new_issue(project = @project) | |
29 | + return '' if project.nil? | |
30 | 30 | |
31 | - if @project.used_default_issues_tracker? || !external_issues_tracker_enabled? | |
32 | - url = new_project_issue_path project_id: @project | |
31 | + if project.used_default_issues_tracker? || !external_issues_tracker_enabled? | |
32 | + url = new_project_issue_path project_id: project | |
33 | 33 | else |
34 | - url = Gitlab.config.issues_tracker[@project.issues_tracker]["new_issue_url"] | |
35 | - url.gsub(':project_id', @project.id.to_s) | |
36 | - .gsub(':issues_tracker_id', @project.issues_tracker_id.to_s) | |
34 | + issues_tracker = Gitlab.config.issues_tracker[project.issues_tracker] | |
35 | + url = issues_tracker['new_issue_url'] | |
36 | + url.gsub(':project_id', project.id.to_s). | |
37 | + gsub(':issues_tracker_id', project.issues_tracker_id.to_s) | |
37 | 38 | end |
38 | 39 | end |
39 | 40 | |
40 | - def url_for_issue(issue_iid) | |
41 | - return "" if @project.nil? | |
41 | + def url_for_issue(issue_iid, project = @project) | |
42 | + return '' if project.nil? | |
42 | 43 | |
43 | - if @project.used_default_issues_tracker? || !external_issues_tracker_enabled? | |
44 | - url = project_issue_url project_id: @project, id: issue_iid | |
44 | + if project.used_default_issues_tracker? || !external_issues_tracker_enabled? | |
45 | + url = project_issue_url project_id: project, id: issue_iid | |
45 | 46 | else |
46 | - url = Gitlab.config.issues_tracker[@project.issues_tracker]["issues_url"] | |
47 | - url.gsub(':id', issue_iid.to_s) | |
48 | - .gsub(':project_id', @project.id.to_s) | |
49 | - .gsub(':issues_tracker_id', @project.issues_tracker_id.to_s) | |
47 | + url = Gitlab.config.issues_tracker[project.issues_tracker]['issues_url'] | |
48 | + url.gsub(':id', issue_iid.to_s). | |
49 | + gsub(':project_id', project.id.to_s). | |
50 | + gsub(':issues_tracker_id', project.issues_tracker_id.to_s) | |
50 | 51 | end |
51 | 52 | end |
52 | 53 | |
53 | - def title_for_issue(issue_iid) | |
54 | - return "" if @project.nil? | |
54 | + def title_for_issue(issue_iid, project = @project) | |
55 | + return '' if project.nil? | |
55 | 56 | |
56 | - if @project.used_default_issues_tracker? && issue = @project.issues.where(iid: issue_iid).first | |
57 | - issue.title | |
58 | - else | |
59 | - "" | |
57 | + if project.used_default_issues_tracker? | |
58 | + issue = project.issues.where(iid: issue_iid).first | |
59 | + return issue.title if issue | |
60 | 60 | end |
61 | + | |
62 | + '' | |
61 | 63 | end |
62 | 64 | |
63 | 65 | # Checks if issues_tracker setting exists in gitlab.yml |
64 | 66 | def external_issues_tracker_enabled? |
65 | - if Gitlab.config.issues_tracker && Gitlab.config.issues_tracker.values.any? | |
66 | - true | |
67 | - else | |
68 | - false | |
69 | - end | |
67 | + Gitlab.config.issues_tracker && Gitlab.config.issues_tracker.values.any? | |
70 | 68 | end |
71 | 69 | |
72 | 70 | def bulk_update_milestone_options |
73 | - options_for_select(["None (backlog)"]) + options_from_collection_for_select(project_active_milestones, "id", "title", params[:milestone_id]) | |
71 | + options_for_select(['None (backlog)']) + | |
72 | + options_from_collection_for_select(project_active_milestones, 'id', | |
73 | + 'title', params[:milestone_id]) | |
74 | 74 | end |
75 | 75 | |
76 | - def bulk_update_assignee_options | |
77 | - options_for_select(["None (unassigned)"]) + options_from_collection_for_select(@project.team.members, "id", "name", params[:assignee_id]) | |
76 | + def bulk_update_assignee_options(project = @project) | |
77 | + options_for_select(['None (unassigned)']) + | |
78 | + options_from_collection_for_select(project.team.members, 'id', | |
79 | + 'name', params[:assignee_id]) | |
78 | 80 | end |
79 | 81 | |
80 | - def assignee_options object | |
81 | - options_from_collection_for_select(@project.team.members.sort_by(&:name), 'id', 'name', object.assignee_id) | |
82 | + def assignee_options(object, project = @project) | |
83 | + options_from_collection_for_select(project.team.members.sort_by(&:name), | |
84 | + 'id', 'name', object.assignee_id) | |
82 | 85 | end |
83 | 86 | |
84 | 87 | def milestone_options object |
85 | - options_from_collection_for_select(object.project.milestones.active, 'id', 'title', object.milestone_id) | |
88 | + options_from_collection_for_select(object.project.milestones.active, | |
89 | + 'id', 'title', object.milestone_id) | |
86 | 90 | end |
87 | 91 | |
88 | 92 | def issue_box_class(item) | ... | ... |
app/views/events/_commit.html.haml
lib/gitlab/markdown.rb
... | ... | @@ -33,10 +33,9 @@ module Gitlab |
33 | 33 | # Public: Parse the provided text with GitLab-Flavored Markdown |
34 | 34 | # |
35 | 35 | # text - the source text |
36 | + # project - extra options for the reference links as given to link_to | |
36 | 37 | # html_options - extra options for the reference links as given to link_to |
37 | - # | |
38 | - # Note: reference links will only be generated if @project is set | |
39 | - def gfm(text, html_options = {}) | |
38 | + def gfm(text, project = @project, html_options = {}) | |
40 | 39 | return text if text.nil? |
41 | 40 | |
42 | 41 | # Duplicate the string so we don't alter the original, then call to_str |
... | ... | @@ -56,14 +55,19 @@ module Gitlab |
56 | 55 | |
57 | 56 | # TODO: add popups with additional information |
58 | 57 | |
59 | - text = parse(text) | |
58 | + text = parse(text, project) | |
60 | 59 | |
61 | 60 | # Insert pre block extractions |
62 | 61 | text.gsub!(/\{gfm-extraction-(\h{32})\}/) do |
63 | 62 | insert_piece($1) |
64 | 63 | end |
65 | 64 | |
66 | - sanitize text.html_safe, attributes: ActionView::Base.sanitized_allowed_attributes + %w(id class), tags: ActionView::Base.sanitized_allowed_tags + %w(table tr td th) | |
65 | + allowed_attributes = ActionView::Base.sanitized_allowed_attributes | |
66 | + allowed_tags = ActionView::Base.sanitized_allowed_tags | |
67 | + | |
68 | + sanitize text.html_safe, | |
69 | + attributes: allowed_attributes + %w(id class), | |
70 | + tags: allowed_tags + %w(table tr td th) | |
67 | 71 | end |
68 | 72 | |
69 | 73 | private |
... | ... | @@ -84,11 +88,9 @@ module Gitlab |
84 | 88 | # |
85 | 89 | # text - Text to parse |
86 | 90 | # |
87 | - # Note: reference links will only be generated if @project is set | |
88 | - # | |
89 | 91 | # Returns parsed text |
90 | - def parse(text) | |
91 | - parse_references(text) if @project | |
92 | + def parse(text, project = @project) | |
93 | + parse_references(text, project) if project | |
92 | 94 | parse_emoji(text) |
93 | 95 | |
94 | 96 | text |
... | ... | @@ -110,7 +112,7 @@ module Gitlab |
110 | 112 | |
111 | 113 | TYPES = [:user, :issue, :merge_request, :snippet, :commit].freeze |
112 | 114 | |
113 | - def parse_references(text) | |
115 | + def parse_references(text, project = @project) | |
114 | 116 | # parse reference links |
115 | 117 | text.gsub!(REFERENCE_PATTERN) do |match| |
116 | 118 | prefix = $~[:prefix] |
... | ... | @@ -123,7 +125,7 @@ module Gitlab |
123 | 125 | # Avoid HTML entities |
124 | 126 | if prefix && suffix && prefix[0] == '&' && suffix[-1] == ';' |
125 | 127 | match |
126 | - elsif ref_link = reference_link(type, identifier) | |
128 | + elsif ref_link = reference_link(type, identifier, project) | |
127 | 129 | "#{prefix}#{ref_link}#{suffix}" |
128 | 130 | else |
129 | 131 | match |
... | ... | @@ -153,7 +155,7 @@ module Gitlab |
153 | 155 | # |
154 | 156 | # Returns boolean |
155 | 157 | def valid_emoji?(emoji) |
156 | - Emoji.find_by_name emoji | |
158 | + Emoji.find_by_name(emoji) | |
157 | 159 | end |
158 | 160 | |
159 | 161 | # Private: Dispatches to a dedicated processing method based on reference |
... | ... | @@ -162,52 +164,77 @@ module Gitlab |
162 | 164 | # identifier - Object identifier (Issue ID, SHA hash, etc.) |
163 | 165 | # |
164 | 166 | # Returns string rendered by the processing method |
165 | - def reference_link(type, identifier) | |
166 | - send("reference_#{type}", identifier) | |
167 | + def reference_link(type, identifier, project = @project) | |
168 | + send("reference_#{type}", identifier, project) | |
167 | 169 | end |
168 | 170 | |
169 | - def reference_user(identifier) | |
170 | - if user = User.find_by_username(identifier) | |
171 | - link_to("@#{identifier}", user_url(identifier), html_options.merge(class: "gfm gfm-team_member #{html_options[:class]}")) | |
171 | + def reference_user(identifier, project = @project) | |
172 | + if user = User.find_by(username: identifier) | |
173 | + options = html_options.merge( | |
174 | + class: "gfm gfm-team_member #{html_options[:class]}" | |
175 | + ) | |
176 | + link_to("@#{identifier}", user_url(identifier), options) | |
172 | 177 | end |
173 | 178 | end |
174 | 179 | |
175 | - def reference_issue(identifier) | |
176 | - if @project.used_default_issues_tracker? || !external_issues_tracker_enabled? | |
177 | - if @project.issue_exists? identifier | |
178 | - url = url_for_issue(identifier) | |
180 | + def reference_issue(identifier, project = @project) | |
181 | + if project.used_default_issues_tracker? || !external_issues_tracker_enabled? | |
182 | + if project.issue_exists? identifier | |
183 | + url = url_for_issue(identifier, project) | |
179 | 184 | title = title_for_issue(identifier) |
185 | + options = html_options.merge( | |
186 | + title: "Issue: #{title}", | |
187 | + class: "gfm gfm-issue #{html_options[:class]}" | |
188 | + ) | |
180 | 189 | |
181 | - link_to("##{identifier}", url, html_options.merge(title: "Issue: #{title}", class: "gfm gfm-issue #{html_options[:class]}")) | |
190 | + link_to("##{identifier}", url, options) | |
182 | 191 | end |
183 | - else | |
184 | - reference_jira_issue(identifier) if @project.issues_tracker == "jira" | |
192 | + elsif project.issues_tracker == 'jira' | |
193 | + reference_jira_issue(identifier, project) | |
185 | 194 | end |
186 | 195 | end |
187 | 196 | |
188 | - def reference_merge_request(identifier) | |
189 | - if merge_request = @project.merge_requests.where(iid: identifier).first | |
190 | - link_to("!#{identifier}", project_merge_request_url(@project, merge_request), html_options.merge(title: "Merge Request: #{merge_request.title}", class: "gfm gfm-merge_request #{html_options[:class]}")) | |
197 | + def reference_merge_request(identifier, project = @project) | |
198 | + if merge_request = project.merge_requests.find_by(iid: identifier) | |
199 | + options = html_options.merge( | |
200 | + title: "Merge Request: #{merge_request.title}", | |
201 | + class: "gfm gfm-merge_request #{html_options[:class]}" | |
202 | + ) | |
203 | + url = project_merge_request_url(project, merge_request) | |
204 | + link_to("!#{identifier}", url, options) | |
191 | 205 | end |
192 | 206 | end |
193 | 207 | |
194 | - def reference_snippet(identifier) | |
195 | - if snippet = @project.snippets.where(id: identifier).first | |
196 | - link_to("$#{identifier}", project_snippet_url(@project, snippet), html_options.merge(title: "Snippet: #{snippet.title}", class: "gfm gfm-snippet #{html_options[:class]}")) | |
208 | + def reference_snippet(identifier, project = @project) | |
209 | + if snippet = project.snippets.find_by(id: identifier) | |
210 | + options = html_options.merge( | |
211 | + title: "Snippet: #{snippet.title}", | |
212 | + class: "gfm gfm-snippet #{html_options[:class]}" | |
213 | + ) | |
214 | + link_to("$#{identifier}", project_snippet_url(project, snippet), | |
215 | + options) | |
197 | 216 | end |
198 | 217 | end |
199 | 218 | |
200 | - def reference_commit(identifier) | |
201 | - if @project.valid_repo? && commit = @project.repository.commit(identifier) | |
202 | - link_to(identifier, project_commit_url(@project, commit), html_options.merge(title: commit.link_title, class: "gfm gfm-commit #{html_options[:class]}")) | |
219 | + def reference_commit(identifier, project = @project) | |
220 | + if project.valid_repo? && commit = project.repository.commit(identifier) | |
221 | + options = html_options.merge( | |
222 | + title: commit.link_title, | |
223 | + class: "gfm gfm-commit #{html_options[:class]}" | |
224 | + ) | |
225 | + link_to(identifier, project_commit_url(project, commit), options) | |
203 | 226 | end |
204 | 227 | end |
205 | 228 | |
206 | - def reference_jira_issue(identifier) | |
229 | + def reference_jira_issue(identifier, project = @project) | |
207 | 230 | url = url_for_issue(identifier) |
208 | 231 | title = Gitlab.config.issues_tracker[@project.issues_tracker]["title"] |
209 | 232 | |
210 | - link_to("#{identifier}", url, html_options.merge(title: "Issue in #{title}", class: "gfm gfm-issue #{html_options[:class]}")) | |
233 | + options = html_options.merge( | |
234 | + title: "Issue in #{title}", | |
235 | + class: "gfm gfm-issue #{html_options[:class]}" | |
236 | + ) | |
237 | + link_to("#{identifier}", url, options) | |
211 | 238 | end |
212 | 239 | end |
213 | 240 | end | ... | ... |
lib/gitlab/reference_extractor.rb
spec/helpers/gitlab_markdown_helper_spec.rb
... | ... | @@ -41,7 +41,8 @@ describe GitlabMarkdownHelper do |
41 | 41 | end |
42 | 42 | |
43 | 43 | it "should forward HTML options to links" do |
44 | - gfm("Fixed in #{commit.id}", class: "foo").should have_selector("a.gfm.foo") | |
44 | + gfm("Fixed in #{commit.id}", @project, class: 'foo'). | |
45 | + should have_selector('a.gfm.foo') | |
45 | 46 | end |
46 | 47 | |
47 | 48 | describe "referencing a commit" do | ... | ... |