mirror of
https://github.com/redmine/redmine.git
synced 2025-11-06 21:35:46 +01:00
Link to user in wiki syntax (#4179).
Patch by Marius BALTEANU. git-svn-id: http://svn.redmine.org/redmine/trunk@16636 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
@@ -810,6 +810,9 @@ module ApplicationHelper
|
|||||||
# Projects:
|
# Projects:
|
||||||
# project:someproject -> Link to project named "someproject"
|
# project:someproject -> Link to project named "someproject"
|
||||||
# project#3 -> Link to project with id 3
|
# project#3 -> Link to project with id 3
|
||||||
|
# Users:
|
||||||
|
# user:jsmith -> Link to user with login jsmith
|
||||||
|
# @jsmith -> Link to user with login jsmith
|
||||||
#
|
#
|
||||||
# Links can refer other objects from other projects, using project identifier:
|
# Links can refer other objects from other projects, using project identifier:
|
||||||
# identifier:r52
|
# identifier:r52
|
||||||
@@ -826,8 +829,8 @@ module ApplicationHelper
|
|||||||
prefix = $~[:prefix]
|
prefix = $~[:prefix]
|
||||||
repo_prefix = $~[:repo_prefix]
|
repo_prefix = $~[:repo_prefix]
|
||||||
repo_identifier = $~[:repo_identifier]
|
repo_identifier = $~[:repo_identifier]
|
||||||
sep = $~[:sep1] || $~[:sep2] || $~[:sep3]
|
sep = $~[:sep1] || $~[:sep2] || $~[:sep3] || $~[:sep4]
|
||||||
identifier = $~[:identifier1] || $~[:identifier2]
|
identifier = $~[:identifier1] || $~[:identifier2] || $~[:identifier3]
|
||||||
comment_suffix = $~[:comment_suffix]
|
comment_suffix = $~[:comment_suffix]
|
||||||
comment_id = $~[:comment_id]
|
comment_id = $~[:comment_id]
|
||||||
|
|
||||||
@@ -899,9 +902,7 @@ module ApplicationHelper
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
elsif sep == ':'
|
elsif sep == ':'
|
||||||
# removes the double quotes if any
|
name = remove_double_quotes(identifier)
|
||||||
name = identifier.gsub(%r{^"(.*)"$}, "\\1")
|
|
||||||
name = CGI.unescapeHTML(name)
|
|
||||||
case prefix
|
case prefix
|
||||||
when 'document'
|
when 'document'
|
||||||
if project && document = project.documents.visible.find_by_title(name)
|
if project && document = project.documents.visible.find_by_title(name)
|
||||||
@@ -957,7 +958,14 @@ module ApplicationHelper
|
|||||||
if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first
|
if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first
|
||||||
link = link_to_project(p, {:only_path => only_path}, :class => 'project')
|
link = link_to_project(p, {:only_path => only_path}, :class => 'project')
|
||||||
end
|
end
|
||||||
|
when 'user'
|
||||||
|
u = User.visible.where(:login => name, :type => 'User').first
|
||||||
|
link = link_to_user(u) if u
|
||||||
end
|
end
|
||||||
|
elsif "@"
|
||||||
|
name = remove_double_quotes(identifier)
|
||||||
|
u = User.visible.where(:login => name, :type => 'User').first
|
||||||
|
link = link_to_user(u) if u
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
(leading + (link || "#{project_prefix}#{prefix}#{repo_prefix}#{sep}#{identifier}#{comment_suffix}"))
|
(leading + (link || "#{project_prefix}#{prefix}#{repo_prefix}#{sep}#{identifier}#{comment_suffix}"))
|
||||||
@@ -971,7 +979,7 @@ module ApplicationHelper
|
|||||||
(?<leading>[\s\(,\-\[\>]|^)
|
(?<leading>[\s\(,\-\[\>]|^)
|
||||||
(?<esc>!)?
|
(?<esc>!)?
|
||||||
(?<project_prefix>(?<project_identifier>[a-z0-9\-_]+):)?
|
(?<project_prefix>(?<project_identifier>[a-z0-9\-_]+):)?
|
||||||
(?<prefix>attachment|document|version|forum|news|message|project|commit|source|export)?
|
(?<prefix>attachment|document|version|forum|news|message|project|commit|source|export|user)?
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
(?<sep1>\#)|
|
(?<sep1>\#)|
|
||||||
@@ -987,8 +995,14 @@ module ApplicationHelper
|
|||||||
-(?<comment_id>\d+)
|
-(?<comment_id>\d+)
|
||||||
)?
|
)?
|
||||||
)|
|
)|
|
||||||
|
(
|
||||||
(?<sep3>:)
|
(?<sep3>:)
|
||||||
(?<identifier2>[^"\s<>][^\s<>]*?|"[^"]+?")
|
(?<identifier2>[^"\s<>][^\s<>]*?|"[^"]+?")
|
||||||
|
)|
|
||||||
|
(
|
||||||
|
(?<sep4>@)
|
||||||
|
(?<identifier3>[a-z0-9_\-@\.]*)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
(?=
|
(?=
|
||||||
(?=[[:punct:]][^A-Za-z0-9_/])|
|
(?=[[:punct:]][^A-Za-z0-9_/])|
|
||||||
@@ -1465,4 +1479,10 @@ module ApplicationHelper
|
|||||||
extend helper
|
extend helper
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# remove double quotes if any
|
||||||
|
def remove_double_quotes(identifier)
|
||||||
|
name = identifier.gsub(%r{^"(.*)"$}, "\\1")
|
||||||
|
return CGI.unescapeHTML(name)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ module Redmine
|
|||||||
|
|
||||||
# Destructively replaces email addresses into clickable links
|
# Destructively replaces email addresses into clickable links
|
||||||
def auto_mailto!(text)
|
def auto_mailto!(text)
|
||||||
text.gsub!(/([\w\.!#\$%\-+.\/]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do
|
text.gsub!(/((?<!@)\b[\w\.!#\$%\-+.\/]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do
|
||||||
mail = $1
|
mail = $1
|
||||||
if text.match(/<a\b[^>]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/)
|
if text.match(/<a\b[^>]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/)
|
||||||
mail
|
mail
|
||||||
|
|||||||
@@ -66,6 +66,10 @@ module Redmine
|
|||||||
html.gsub!(/(\w):"(.+?)"/) do
|
html.gsub!(/(\w):"(.+?)"/) do
|
||||||
"#{$1}:\"#{$2}\""
|
"#{$1}:\"#{$2}\""
|
||||||
end
|
end
|
||||||
|
# restore user links with @ in login name eg. [@jsmith@somenet.foo]
|
||||||
|
html.gsub!(%r{[@\A]<a href="mailto:(.*?)">(.*?)</a>}) do
|
||||||
|
"@#{$2}"
|
||||||
|
end
|
||||||
html
|
html
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -384,11 +384,24 @@ RAW
|
|||||||
'source:' => 'source:',
|
'source:' => 'source:',
|
||||||
# url hash
|
# url hash
|
||||||
"http://foo.bar/FAQ#3" => '<a class="external" href="http://foo.bar/FAQ#3">http://foo.bar/FAQ#3</a>',
|
"http://foo.bar/FAQ#3" => '<a class="external" href="http://foo.bar/FAQ#3">http://foo.bar/FAQ#3</a>',
|
||||||
|
# user
|
||||||
|
'user:jsmith' => link_to_user(User.find_by_id(2)),
|
||||||
|
'@jsmith' => link_to_user(User.find_by_id(2)),
|
||||||
|
# invalid user
|
||||||
|
'user:foobar' => 'user:foobar',
|
||||||
}
|
}
|
||||||
@project = Project.find(1)
|
@project = Project.find(1)
|
||||||
to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
|
to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_user_links_with_email_as_login_name_should_not_be_parsed
|
||||||
|
u = User.generate!(:login => 'jsmith@somenet.foo')
|
||||||
|
raw = "@jsmith@somenet.foo should not be parsed in jsmith@somenet.foo"
|
||||||
|
|
||||||
|
assert_match %r{<p><a class="user active".*>#{u.name}</a> should not be parsed in <a class="email" href="mailto:jsmith@somenet.foo">jsmith@somenet.foo</a></p>},
|
||||||
|
textilizable(raw, :project => Project.find(1))
|
||||||
|
end
|
||||||
|
|
||||||
def test_should_not_parse_redmine_links_inside_link
|
def test_should_not_parse_redmine_links_inside_link
|
||||||
raw = "r1 should not be parsed in http://example.com/url-r1/"
|
raw = "r1 should not be parsed in http://example.com/url-r1/"
|
||||||
assert_match %r{<p><a class="changeset".*>r1</a> should not be parsed in <a class="external" href="http://example.com/url-r1/">http://example.com/url-r1/</a></p>},
|
assert_match %r{<p><a class="changeset".*>r1</a> should not be parsed in <a class="external" href="http://example.com/url-r1/">http://example.com/url-r1/</a></p>},
|
||||||
|
|||||||
Reference in New Issue
Block a user