Allow reference format as link href
This commit is contained in:
parent
6dad2bc6e6
commit
1d6d757dbd
7 changed files with 80 additions and 25 deletions
|
@ -178,7 +178,6 @@ module Gitlab
|
||||||
Gitlab::Markdown::SanitizationFilter,
|
Gitlab::Markdown::SanitizationFilter,
|
||||||
|
|
||||||
Gitlab::Markdown::UploadLinkFilter,
|
Gitlab::Markdown::UploadLinkFilter,
|
||||||
Gitlab::Markdown::RelativeLinkFilter,
|
|
||||||
Gitlab::Markdown::EmojiFilter,
|
Gitlab::Markdown::EmojiFilter,
|
||||||
Gitlab::Markdown::TableOfContentsFilter,
|
Gitlab::Markdown::TableOfContentsFilter,
|
||||||
Gitlab::Markdown::AutolinkFilter,
|
Gitlab::Markdown::AutolinkFilter,
|
||||||
|
@ -193,6 +192,8 @@ module Gitlab
|
||||||
Gitlab::Markdown::CommitReferenceFilter,
|
Gitlab::Markdown::CommitReferenceFilter,
|
||||||
Gitlab::Markdown::LabelReferenceFilter,
|
Gitlab::Markdown::LabelReferenceFilter,
|
||||||
|
|
||||||
|
Gitlab::Markdown::RelativeLinkFilter,
|
||||||
|
|
||||||
Gitlab::Markdown::TaskListFilter
|
Gitlab::Markdown::TaskListFilter
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,7 @@ require 'gitlab/markdown'
|
||||||
|
|
||||||
module Gitlab
|
module Gitlab
|
||||||
module Markdown
|
module Markdown
|
||||||
# Issues, Snippets, Merge Requests, Commits and Commit Ranges share
|
# Issues, Merge Requests, Snippets, Commits and Commit Ranges share
|
||||||
# similar functionality in refernce filtering.
|
# similar functionality in refernce filtering.
|
||||||
class AbstractReferenceFilter < ReferenceFilter
|
class AbstractReferenceFilter < ReferenceFilter
|
||||||
include CrossProjectReference
|
include CrossProjectReference
|
||||||
|
@ -64,8 +64,13 @@ module Gitlab
|
||||||
object_link_filter(content, object_class.reference_pattern)
|
object_link_filter(content, object_class.reference_pattern)
|
||||||
end
|
end
|
||||||
|
|
||||||
replace_link_nodes_matching(object_class.link_reference_pattern) do |content|
|
replace_link_nodes_with_href(object_class.reference_pattern) do |link, text|
|
||||||
object_link_filter(content, object_class.link_reference_pattern)
|
object_link_filter(link, object_class.reference_pattern, link_text: text)
|
||||||
|
end
|
||||||
|
|
||||||
|
replace_link_nodes_with_text(object_class.link_reference_pattern) do |text|
|
||||||
|
object_link_filter(text, object_class.link_reference_pattern)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -76,7 +81,7 @@ module Gitlab
|
||||||
#
|
#
|
||||||
# Returns a String with references replaced with links. All links
|
# Returns a String with references replaced with links. All links
|
||||||
# have `gfm` and `gfm-OBJECT_NAME` class names attached for styling.
|
# have `gfm` and `gfm-OBJECT_NAME` class names attached for styling.
|
||||||
def object_link_filter(text, pattern)
|
def object_link_filter(text, pattern, link_text: nil)
|
||||||
references_in(text, pattern) do |match, id, project_ref, matches|
|
references_in(text, pattern) do |match, id, project_ref, matches|
|
||||||
project = project_from_ref(project_ref)
|
project = project_from_ref(project_ref)
|
||||||
|
|
||||||
|
@ -88,10 +93,13 @@ module Gitlab
|
||||||
url = matches[:url] if matches.names.include?("url")
|
url = matches[:url] if matches.names.include?("url")
|
||||||
url ||= url_for_object(object, project)
|
url ||= url_for_object(object, project)
|
||||||
|
|
||||||
text = object.reference_link_text(context[:project])
|
text = link_text
|
||||||
|
unless text
|
||||||
|
text = object.reference_link_text(context[:project])
|
||||||
|
|
||||||
extras = object_link_text_extras(object, matches)
|
extras = object_link_text_extras(object, matches)
|
||||||
text += " (#{extras.join(", ")})" if extras.any?
|
text += " (#{extras.join(", ")})" if extras.any?
|
||||||
|
end
|
||||||
|
|
||||||
%(<a href="#{url}" #{data}
|
%(<a href="#{url}" #{data}
|
||||||
title="#{title}"
|
title="#{title}"
|
||||||
|
|
|
@ -30,6 +30,10 @@ module Gitlab
|
||||||
replace_text_nodes_matching(ExternalIssue.reference_pattern) do |content|
|
replace_text_nodes_matching(ExternalIssue.reference_pattern) do |content|
|
||||||
issue_link_filter(content)
|
issue_link_filter(content)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
replace_link_nodes_with_href(ExternalIssue.reference_pattern) do |link, text|
|
||||||
|
issue_link_filter(link, link_text: text)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Replace `JIRA-123` issue references in text with links to the referenced
|
# Replace `JIRA-123` issue references in text with links to the referenced
|
||||||
|
@ -39,7 +43,7 @@ module Gitlab
|
||||||
#
|
#
|
||||||
# Returns a String with `JIRA-123` references replaced with links. All
|
# Returns a String with `JIRA-123` references replaced with links. All
|
||||||
# links have `gfm` and `gfm-issue` class names attached for styling.
|
# links have `gfm` and `gfm-issue` class names attached for styling.
|
||||||
def issue_link_filter(text)
|
def issue_link_filter(text, link_text: nil)
|
||||||
project = context[:project]
|
project = context[:project]
|
||||||
|
|
||||||
self.class.references_in(text) do |match, issue|
|
self.class.references_in(text) do |match, issue|
|
||||||
|
@ -49,9 +53,11 @@ module Gitlab
|
||||||
klass = reference_class(:issue)
|
klass = reference_class(:issue)
|
||||||
data = data_attribute(project: project.id)
|
data = data_attribute(project: project.id)
|
||||||
|
|
||||||
|
text = link_text || match
|
||||||
|
|
||||||
%(<a href="#{url}" #{data}
|
%(<a href="#{url}" #{data}
|
||||||
title="#{title}"
|
title="#{title}"
|
||||||
class="#{klass}">#{match}</a>)
|
class="#{klass}">#{text}</a>)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,10 @@ module Gitlab
|
||||||
replace_text_nodes_matching(Label.reference_pattern) do |content|
|
replace_text_nodes_matching(Label.reference_pattern) do |content|
|
||||||
label_link_filter(content)
|
label_link_filter(content)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
replace_link_nodes_with_href(Label.reference_pattern) do |link, text|
|
||||||
|
label_link_filter(link, link_text: text)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Replace label references in text with links to the label specified.
|
# Replace label references in text with links to the label specified.
|
||||||
|
@ -38,7 +42,7 @@ module Gitlab
|
||||||
#
|
#
|
||||||
# Returns a String with label references replaced with links. All links
|
# Returns a String with label references replaced with links. All links
|
||||||
# have `gfm` and `gfm-label` class names attached for styling.
|
# have `gfm` and `gfm-label` class names attached for styling.
|
||||||
def label_link_filter(text)
|
def label_link_filter(text, link_text: nil)
|
||||||
project = context[:project]
|
project = context[:project]
|
||||||
|
|
||||||
self.class.references_in(text) do |match, id, name|
|
self.class.references_in(text) do |match, id, name|
|
||||||
|
@ -49,8 +53,10 @@ module Gitlab
|
||||||
klass = reference_class(:label)
|
klass = reference_class(:label)
|
||||||
data = data_attribute(project: project.id, label: label.id)
|
data = data_attribute(project: project.id, label: label.id)
|
||||||
|
|
||||||
|
text = link_text || render_colored_label(label)
|
||||||
|
|
||||||
%(<a href="#{url}" #{data}
|
%(<a href="#{url}" #{data}
|
||||||
class="#{klass}">#{render_colored_label(label)}</a>)
|
class="#{klass}">#{text}</a>)
|
||||||
else
|
else
|
||||||
match
|
match
|
||||||
end
|
end
|
||||||
|
|
|
@ -122,7 +122,7 @@ module Gitlab
|
||||||
doc
|
doc
|
||||||
end
|
end
|
||||||
|
|
||||||
def replace_link_nodes_matching(pattern)
|
def replace_link_nodes_with_text(pattern)
|
||||||
return doc if project.nil?
|
return doc if project.nil?
|
||||||
|
|
||||||
doc.search('a').each do |node|
|
doc.search('a').each do |node|
|
||||||
|
@ -132,6 +132,9 @@ module Gitlab
|
||||||
link = node.attr('href')
|
link = node.attr('href')
|
||||||
text = node.text
|
text = node.text
|
||||||
|
|
||||||
|
next unless link && text
|
||||||
|
|
||||||
|
link = URI.decode(link)
|
||||||
# Ignore ending punctionation like periods or commas
|
# Ignore ending punctionation like periods or commas
|
||||||
next unless link == text && text =~ /\A#{pattern}/
|
next unless link == text && text =~ /\A#{pattern}/
|
||||||
|
|
||||||
|
@ -145,6 +148,30 @@ module Gitlab
|
||||||
doc
|
doc
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def replace_link_nodes_with_href(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
|
||||||
|
|
||||||
|
next unless link && text
|
||||||
|
link = URI.decode(link)
|
||||||
|
next unless link && link =~ /\A#{pattern}\z/
|
||||||
|
|
||||||
|
html = yield link, text
|
||||||
|
|
||||||
|
next if html == link
|
||||||
|
|
||||||
|
node.replace(html)
|
||||||
|
end
|
||||||
|
|
||||||
|
doc
|
||||||
|
end
|
||||||
|
|
||||||
# Ensure that a :project key exists in context
|
# Ensure that a :project key exists in context
|
||||||
#
|
#
|
||||||
# Note that while the key might exist, its value could be nil!
|
# Note that while the key might exist, its value could be nil!
|
||||||
|
|
|
@ -17,6 +17,9 @@ module Gitlab
|
||||||
return doc unless linkable_files?
|
return doc unless linkable_files?
|
||||||
|
|
||||||
doc.search('a').each do |el|
|
doc.search('a').each do |el|
|
||||||
|
klass = el.attr('class')
|
||||||
|
next if klass && klass.include?('gfm')
|
||||||
|
|
||||||
process_link_attr el.attribute('href')
|
process_link_attr el.attribute('href')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,10 @@ module Gitlab
|
||||||
replace_text_nodes_matching(User.reference_pattern) do |content|
|
replace_text_nodes_matching(User.reference_pattern) do |content|
|
||||||
user_link_filter(content)
|
user_link_filter(content)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
replace_link_nodes_with_href(User.reference_pattern) do |link, text|
|
||||||
|
user_link_filter(link, link_text: text)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Replace `@user` user references in text with links to the referenced
|
# Replace `@user` user references in text with links to the referenced
|
||||||
|
@ -61,12 +65,12 @@ module Gitlab
|
||||||
#
|
#
|
||||||
# Returns a String with `@user` references replaced with links. All links
|
# Returns a String with `@user` references replaced with links. All links
|
||||||
# have `gfm` and `gfm-project_member` class names attached for styling.
|
# have `gfm` and `gfm-project_member` class names attached for styling.
|
||||||
def user_link_filter(text)
|
def user_link_filter(text, link_text: nil)
|
||||||
self.class.references_in(text) do |match, username|
|
self.class.references_in(text) do |match, username|
|
||||||
if username == 'all'
|
if username == 'all'
|
||||||
link_to_all
|
link_to_all(link_text: link_text)
|
||||||
elsif namespace = Namespace.find_by(path: username)
|
elsif namespace = Namespace.find_by(path: username)
|
||||||
link_to_namespace(namespace) || match
|
link_to_namespace(namespace, link_text: link_text) || match
|
||||||
else
|
else
|
||||||
match
|
match
|
||||||
end
|
end
|
||||||
|
@ -83,36 +87,36 @@ module Gitlab
|
||||||
reference_class(:project_member)
|
reference_class(:project_member)
|
||||||
end
|
end
|
||||||
|
|
||||||
def link_to_all
|
def link_to_all(link_text: nil)
|
||||||
project = context[:project]
|
project = context[:project]
|
||||||
url = urls.namespace_project_url(project.namespace, project,
|
url = urls.namespace_project_url(project.namespace, project,
|
||||||
only_path: context[:only_path])
|
only_path: context[:only_path])
|
||||||
data = data_attribute(project: project.id)
|
data = data_attribute(project: project.id)
|
||||||
text = User.reference_prefix + 'all'
|
text = link_text || User.reference_prefix + 'all'
|
||||||
|
|
||||||
link_tag(url, data, text)
|
link_tag(url, data, text)
|
||||||
end
|
end
|
||||||
|
|
||||||
def link_to_namespace(namespace)
|
def link_to_namespace(namespace, link_text: nil)
|
||||||
if namespace.is_a?(Group)
|
if namespace.is_a?(Group)
|
||||||
link_to_group(namespace.path, namespace)
|
link_to_group(namespace.path, namespace, link_text: link_text)
|
||||||
else
|
else
|
||||||
link_to_user(namespace.path, namespace)
|
link_to_user(namespace.path, namespace, link_text: link_text)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def link_to_group(group, namespace)
|
def link_to_group(group, namespace, link_text: nil)
|
||||||
url = urls.group_url(group, only_path: context[:only_path])
|
url = urls.group_url(group, only_path: context[:only_path])
|
||||||
data = data_attribute(group: namespace.id)
|
data = data_attribute(group: namespace.id)
|
||||||
text = Group.reference_prefix + group
|
text = link_text || Group.reference_prefix + group
|
||||||
|
|
||||||
link_tag(url, data, text)
|
link_tag(url, data, text)
|
||||||
end
|
end
|
||||||
|
|
||||||
def link_to_user(user, namespace)
|
def link_to_user(user, namespace, link_text: nil)
|
||||||
url = urls.user_url(user, only_path: context[:only_path])
|
url = urls.user_url(user, only_path: context[:only_path])
|
||||||
data = data_attribute(user: namespace.owner_id)
|
data = data_attribute(user: namespace.owner_id)
|
||||||
text = User.reference_prefix + user
|
text = link_text || User.reference_prefix + user
|
||||||
|
|
||||||
link_tag(url, data, text)
|
link_tag(url, data, text)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue