Fix mention's inconsistent hyperlink (#4051)

* Upgrade mention parsing logic

* Avoid hardcoded link in spec
This commit is contained in:
Mac Siri 2019-09-18 17:15:06 -04:00 committed by Ben Halpern
parent 0a16bf934a
commit e6e57c8835
2 changed files with 30 additions and 16 deletions

View file

@ -203,23 +203,22 @@ class MarkdownParser
def wrap_mentions_with_links!(html)
html_doc = Nokogiri::HTML(html)
# looks for node that isn't <code>, <a>, and contains "@"
html_doc.xpath('//*[not (self::code) and not(self::a) and contains(text(), "@")]').each do |node|
# if the target node is a <p>, <ul>, or <li>, it will have more than 1 child
# otherwise inner_html can be use when there's only 1 child
if node.children.count > 1
# only focus on portion of text with "@"
node.xpath("text()[contains(.,'@')]").each do |el|
el.replace(el.text.gsub(/\B@[a-z0-9_-]+/i) do |text|
user_link_if_exists(text)
end)
end
else
# with only 1 child, inner_html can be used update the content
node.inner_html = node.inner_html.gsub(/\B@[a-z0-9_-]+/i) do |text|
user_link_if_exists(text)
end
# looks for nodes that isn't <code>, <a>, and contains "@"
targets = html_doc.xpath('//html/body/*[not (self::code) and not(self::a) and contains(., "@")]').to_a
# A Queue system to look for and replace possible usernames
until targets.empty?
node = targets.shift
# only focus on portion of text with "@"
node.xpath("text()[contains(.,'@')]").each do |el|
el.replace(el.text.gsub(/\B@[a-z0-9_-]+/i) { |text| user_link_if_exists(text) })
end
# enqueue children that has @ in it's text
children = node.xpath('*[not(self::code) and not(self::a) and contains(., "@")]').to_a
targets.concat(children)
end
if html_doc.at_css("body")

View file

@ -81,12 +81,27 @@ RSpec.describe MarkdownParser do
expect(result).to include "<a", "<em"
end
it "works in ul/li tag" do
mention = <<~DOC
`@#{user.username}` one two, @#{user.username} three four:
- `@#{user.username}`
DOC
result = generate_and_parse_markdown(mention)
expect(result).to eq("<p><code>@#{user.username}</code> one two, <a class=\"comment-mentioned-user\" href=\"#{ApplicationConfig['APP_PROTOCOL']}#{ApplicationConfig['APP_DOMAIN']}/#{user.username}\">@#{user.username}</a>\n three four:</p>\n\n<ul>\n<li><code>@#{user.username}</code></li>\n</ul>\n\n")
end
it "will not work in code tag" do
mention = "this is a chunk of text `@#{user.username}`"
result = generate_and_parse_markdown(mention)
expect(result).to include "<code"
expect(result).not_to include "<a"
end
it "works with markdown heavy contents" do
mention = "test **[link?](https://dev.to/ben/)** thread, @#{user.username} talks :"
result = generate_and_parse_markdown(mention)
expect(result).to include "<a class=\"comment-mentioned-user\""
end
end
it "renders a double backtick codespan with a word wrapped in single backticks properly" do