summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSean McGivern <sean@gitlab.com>2018-02-22 12:09:27 +0000
committerSean McGivern <sean@gitlab.com>2018-03-02 13:42:57 +0000
commitcb55bc3c0770adf7122d7cf49b12cb45c43de7ec (patch)
tree6ec14a9b8b407ac7986b9e940254d63288266379 /lib
parent1a09d5cda8e9f6b90b85351a16fcddea351b869f (diff)
downloadgitlab-ce-cb55bc3c0770adf7122d7cf49b12cb45c43de7ec.tar.gz
Match Rinku's behaviour for closing punctuation in links41719-mr-title-fix
Rinku 2.0.0 (the version we use) will remove the last character of a link if it's a closing part of a punctuation pair (different types of parentheses and quotes), unless both of the below are true: 1. The matching pair has different start and end characters. 2. There are equal numbers of both in the matched string (they don't have to be balanced).
Diffstat (limited to 'lib')
-rw-r--r--lib/banzai/filter/autolink_filter.rb50
1 files changed, 35 insertions, 15 deletions
diff --git a/lib/banzai/filter/autolink_filter.rb b/lib/banzai/filter/autolink_filter.rb
index c4990637971..75b64ae9af2 100644
--- a/lib/banzai/filter/autolink_filter.rb
+++ b/lib/banzai/filter/autolink_filter.rb
@@ -25,7 +25,7 @@ module Banzai
# period or comma for punctuation without those characters being included
# in the generated link.
#
- # Rubular: http://rubular.com/r/cxjPyZc7Sb
+ # Rubular: http://rubular.com/r/JzPhi6DCZp
LINK_PATTERN = %r{([a-z][a-z0-9\+\.-]+://[^\s>]+)(?<!,|\.)}
# Text matching LINK_PATTERN inside these elements will not be linked
@@ -37,23 +37,17 @@ module Banzai
and contains(., '://')
]).freeze
+ PUNCTUATION_PAIRS = {
+ "'" => "'",
+ '"' => '"',
+ ')' => '(',
+ ']' => '[',
+ '}' => '{'
+ }.freeze
+
def call
return doc if context[:autolink] == false
- text_parse
- end
-
- private
-
- # Return true if any of the UNSAFE_PROTOCOLS strings are included in the URI scheme
- def contains_unsafe?(scheme)
- return false unless scheme
-
- scheme = scheme.strip.downcase
- Banzai::Filter::SanitizationFilter::UNSAFE_PROTOCOLS.any? { |protocol| scheme.include?(protocol) }
- end
-
- def text_parse
doc.xpath(TEXT_QUERY).each do |node|
content = node.to_html
@@ -69,6 +63,16 @@ module Banzai
doc
end
+ private
+
+ # Return true if any of the UNSAFE_PROTOCOLS strings are included in the URI scheme
+ def contains_unsafe?(scheme)
+ return false unless scheme
+
+ scheme = scheme.strip.downcase
+ Banzai::Filter::SanitizationFilter::UNSAFE_PROTOCOLS.any? { |protocol| scheme.include?(protocol) }
+ end
+
def autolink_match(match)
# start by stripping out dangerous links
begin
@@ -84,6 +88,22 @@ module Banzai
match.gsub!(/((?:&[\w#]+;)+)\z/, '')
dropped = ($1 || '').html_safe
+ # To match the behaviour of Rinku, if the matched link ends with a
+ # closing part of a matched pair of punctuation, we remove that trailing
+ # character unless there are an equal number of closing and opening
+ # characters in the link.
+ if match.end_with?(*PUNCTUATION_PAIRS.keys)
+ close_character = match[-1]
+ close_count = match.count(close_character)
+ open_character = PUNCTUATION_PAIRS[close_character]
+ open_count = match.count(open_character)
+
+ if open_count != close_count || open_character == close_character
+ dropped += close_character
+ match = match[0..-2]
+ end
+ end
+
options = link_options.merge(href: match)
content_tag(:a, match.html_safe, options) + dropped
end