FIX: Make sure rel attributes are correctly set. (#10645)
We must guarantee that "rel=noopener" was set if "target=_blank" is present, which is not always the case for trusted users. Also, if the link contains the "nofollow" attribute, it has to have the "ugc" attribute as well.
This commit is contained in:
parent
dee451605b
commit
efb9fd6ac0
|
@ -656,9 +656,8 @@ class CookedPostProcessor
|
||||||
end
|
end
|
||||||
|
|
||||||
def enforce_nofollow
|
def enforce_nofollow
|
||||||
if !@omit_nofollow && SiteSetting.add_rel_nofollow_to_user_content
|
add_nofollow = !@omit_nofollow && SiteSetting.add_rel_nofollow_to_user_content
|
||||||
PrettyText.add_rel_nofollow_to_user_content(@doc)
|
PrettyText.add_rel_attributes_to_user_content(@doc, add_nofollow)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def pull_hotlinked_images
|
def pull_hotlinked_images
|
||||||
|
|
|
@ -269,9 +269,8 @@ module PrettyText
|
||||||
|
|
||||||
doc = Nokogiri::HTML5.fragment(sanitized)
|
doc = Nokogiri::HTML5.fragment(sanitized)
|
||||||
|
|
||||||
if !options[:omit_nofollow] && SiteSetting.add_rel_nofollow_to_user_content
|
add_nofollow = !options[:omit_nofollow] && SiteSetting.add_rel_nofollow_to_user_content
|
||||||
add_rel_nofollow_to_user_content(doc)
|
add_rel_attributes_to_user_content(doc, add_nofollow)
|
||||||
end
|
|
||||||
|
|
||||||
if SiteSetting.enable_mentions
|
if SiteSetting.enable_mentions
|
||||||
add_mentions(doc, user_id: opts[:user_id])
|
add_mentions(doc, user_id: opts[:user_id])
|
||||||
|
@ -284,7 +283,7 @@ module PrettyText
|
||||||
loofah_fragment.scrub!(scrubber).to_html
|
loofah_fragment.scrub!(scrubber).to_html
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.add_rel_nofollow_to_user_content(doc)
|
def self.add_rel_attributes_to_user_content(doc, add_nofollow)
|
||||||
allowlist = []
|
allowlist = []
|
||||||
|
|
||||||
domains = SiteSetting.exclude_rel_nofollow_domains
|
domains = SiteSetting.exclude_rel_nofollow_domains
|
||||||
|
@ -293,22 +292,21 @@ module PrettyText
|
||||||
site_uri = nil
|
site_uri = nil
|
||||||
doc.css("a").each do |l|
|
doc.css("a").each do |l|
|
||||||
href = l["href"].to_s
|
href = l["href"].to_s
|
||||||
|
l["rel"] = "noopener" if l["target"] == "_blank"
|
||||||
|
|
||||||
begin
|
begin
|
||||||
uri = URI(UrlHelper.encode_component(href))
|
uri = URI(UrlHelper.encode_component(href))
|
||||||
site_uri ||= URI(Discourse.base_url)
|
site_uri ||= URI(Discourse.base_url)
|
||||||
|
|
||||||
if !uri.host.present? ||
|
same_domain = !uri.host.present? ||
|
||||||
uri.host == site_uri.host ||
|
uri.host == site_uri.host ||
|
||||||
uri.host.ends_with?(".#{site_uri.host}") ||
|
uri.host.ends_with?(".#{site_uri.host}") ||
|
||||||
allowlist.any? { |u| uri.host == u || uri.host.ends_with?(".#{u}") }
|
allowlist.any? { |u| uri.host == u || uri.host.ends_with?(".#{u}") }
|
||||||
# we are good no need for nofollow
|
|
||||||
l.remove_attribute("rel")
|
l["rel"] = "noopener nofollow ugc" if add_nofollow && !same_domain
|
||||||
else
|
|
||||||
l["rel"] = "nofollow noopener"
|
|
||||||
end
|
|
||||||
rescue URI::Error
|
rescue URI::Error
|
||||||
# add a nofollow anyway
|
# add a nofollow anyway
|
||||||
l["rel"] = "nofollow noopener"
|
l["rel"] = "noopener nofollow ugc"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -237,13 +237,13 @@ describe CookedPostProcessor do
|
||||||
count: 1
|
count: 1
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(html).to have_tag("a[rel='nofollow noopener']")
|
expect(html).to have_tag("a[rel='noopener nofollow ugc']")
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'removes nofollow if user is staff/tl3' do
|
it 'removes nofollow if user is staff/tl3' do
|
||||||
cpp = CookedPostProcessor.new(staff_post, invalidate_oneboxes: true)
|
cpp = CookedPostProcessor.new(staff_post, invalidate_oneboxes: true)
|
||||||
cpp.post_process
|
cpp.post_process
|
||||||
expect(cpp.html).to_not have_tag("a[rel='nofollow noopener']")
|
expect(cpp.html).to_not have_tag("a[rel='noopener nofollow ugc']")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1102,7 +1102,7 @@ describe CookedPostProcessor do
|
||||||
SiteSetting.add_rel_nofollow_to_user_content = false
|
SiteSetting.add_rel_nofollow_to_user_content = false
|
||||||
Oneboxer.expects(:onebox)
|
Oneboxer.expects(:onebox)
|
||||||
.with("http://www.youtube.com/watch?v=9bZkp7q19f0", invalidate_oneboxes: true, user_id: nil, category_id: post.topic.category_id)
|
.with("http://www.youtube.com/watch?v=9bZkp7q19f0", invalidate_oneboxes: true, user_id: nil, category_id: post.topic.category_id)
|
||||||
.returns('<aside class="onebox"><a href="https://www.youtube.com/watch?v=9bZkp7q19f0" rel="nofollow noopener ugc">GANGNAM STYLE</a></aside>')
|
.returns('<aside class="onebox"><a href="https://www.youtube.com/watch?v=9bZkp7q19f0" rel="noopener nofollow ugc">GANGNAM STYLE</a></aside>')
|
||||||
cpp.post_process_oneboxes
|
cpp.post_process_oneboxes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1123,7 +1123,7 @@ describe CookedPostProcessor do
|
||||||
SiteSetting.tl3_links_no_follow = false
|
SiteSetting.tl3_links_no_follow = false
|
||||||
Oneboxer.expects(:onebox)
|
Oneboxer.expects(:onebox)
|
||||||
.with("http://www.youtube.com/watch?v=9bZkp7q19f0", invalidate_oneboxes: true, user_id: nil, category_id: post.topic.category_id)
|
.with("http://www.youtube.com/watch?v=9bZkp7q19f0", invalidate_oneboxes: true, user_id: nil, category_id: post.topic.category_id)
|
||||||
.returns('<aside class="onebox"><a href="https://www.youtube.com/watch?v=9bZkp7q19f0" rel="nofollow ugc noopener">GANGNAM STYLE</a></aside>')
|
.returns('<aside class="onebox"><a href="https://www.youtube.com/watch?v=9bZkp7q19f0" rel="noopener nofollow ugc">GANGNAM STYLE</a></aside>')
|
||||||
cpp.post_process_oneboxes
|
cpp.post_process_oneboxes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1204,7 +1204,7 @@ describe CookedPostProcessor do
|
||||||
expect(cpp.html).to match_html <<~HTML.rstrip
|
expect(cpp.html).to match_html <<~HTML.rstrip
|
||||||
<p><a href="//test.localhost/#{upload_path}/original/2X/2345678901234567.jpg">Link</a><br>
|
<p><a href="//test.localhost/#{upload_path}/original/2X/2345678901234567.jpg">Link</a><br>
|
||||||
<img src="//test.localhost/#{upload_path}/original/1X/1234567890123456.jpg"><br>
|
<img src="//test.localhost/#{upload_path}/original/1X/1234567890123456.jpg"><br>
|
||||||
<a href="http://www.google.com" rel="nofollow noopener">Google</a><br>
|
<a href="http://www.google.com" rel="noopener nofollow ugc">Google</a><br>
|
||||||
<img src="http://foo.bar/image.png"><br>
|
<img src="http://foo.bar/image.png"><br>
|
||||||
<a class="attachment" href="//test.localhost/#{upload_path}/original/1X/af2c2618032c679333bebf745e75f9088748d737.txt">text.txt</a> (20 Bytes)<br>
|
<a class="attachment" href="//test.localhost/#{upload_path}/original/1X/af2c2618032c679333bebf745e75f9088748d737.txt">text.txt</a> (20 Bytes)<br>
|
||||||
<img src="//test.localhost/images/emoji/twitter/smile.png?v=#{Emoji::EMOJI_VERSION}" title=":smile:" class="emoji only-emoji" alt=":smile:"></p>
|
<img src="//test.localhost/images/emoji/twitter/smile.png?v=#{Emoji::EMOJI_VERSION}" title=":smile:" class="emoji only-emoji" alt=":smile:"></p>
|
||||||
|
@ -1219,7 +1219,7 @@ describe CookedPostProcessor do
|
||||||
expect(cpp.html).to match_html <<~HTML.rstrip
|
expect(cpp.html).to match_html <<~HTML.rstrip
|
||||||
<p><a href="//my.cdn.com/#{upload_path}/original/2X/2345678901234567.jpg">Link</a><br>
|
<p><a href="//my.cdn.com/#{upload_path}/original/2X/2345678901234567.jpg">Link</a><br>
|
||||||
<img src="//my.cdn.com/#{upload_path}/original/1X/1234567890123456.jpg"><br>
|
<img src="//my.cdn.com/#{upload_path}/original/1X/1234567890123456.jpg"><br>
|
||||||
<a href="http://www.google.com" rel="nofollow noopener">Google</a><br>
|
<a href="http://www.google.com" rel="noopener nofollow ugc">Google</a><br>
|
||||||
<img src="http://foo.bar/image.png"><br>
|
<img src="http://foo.bar/image.png"><br>
|
||||||
<a class="attachment" href="//my.cdn.com/#{upload_path}/original/1X/af2c2618032c679333bebf745e75f9088748d737.txt">text.txt</a> (20 Bytes)<br>
|
<a class="attachment" href="//my.cdn.com/#{upload_path}/original/1X/af2c2618032c679333bebf745e75f9088748d737.txt">text.txt</a> (20 Bytes)<br>
|
||||||
<img src="//my.cdn.com/images/emoji/twitter/smile.png?v=#{Emoji::EMOJI_VERSION}" title=":smile:" class="emoji only-emoji" alt=":smile:"></p>
|
<img src="//my.cdn.com/images/emoji/twitter/smile.png?v=#{Emoji::EMOJI_VERSION}" title=":smile:" class="emoji only-emoji" alt=":smile:"></p>
|
||||||
|
@ -1232,7 +1232,7 @@ describe CookedPostProcessor do
|
||||||
expect(cpp.html).to match_html <<~HTML.rstrip
|
expect(cpp.html).to match_html <<~HTML.rstrip
|
||||||
<p><a href="https://my.cdn.com/#{upload_path}/original/2X/2345678901234567.jpg">Link</a><br>
|
<p><a href="https://my.cdn.com/#{upload_path}/original/2X/2345678901234567.jpg">Link</a><br>
|
||||||
<img src="https://my.cdn.com/#{upload_path}/original/1X/1234567890123456.jpg"><br>
|
<img src="https://my.cdn.com/#{upload_path}/original/1X/1234567890123456.jpg"><br>
|
||||||
<a href="http://www.google.com" rel="nofollow noopener">Google</a><br>
|
<a href="http://www.google.com" rel="noopener nofollow ugc">Google</a><br>
|
||||||
<img src="http://foo.bar/image.png"><br>
|
<img src="http://foo.bar/image.png"><br>
|
||||||
<a class="attachment" href="https://my.cdn.com/#{upload_path}/original/1X/af2c2618032c679333bebf745e75f9088748d737.txt">text.txt</a> (20 Bytes)<br>
|
<a class="attachment" href="https://my.cdn.com/#{upload_path}/original/1X/af2c2618032c679333bebf745e75f9088748d737.txt">text.txt</a> (20 Bytes)<br>
|
||||||
<img src="https://my.cdn.com/images/emoji/twitter/smile.png?v=#{Emoji::EMOJI_VERSION}" title=":smile:" class="emoji only-emoji" alt=":smile:"></p>
|
<img src="https://my.cdn.com/images/emoji/twitter/smile.png?v=#{Emoji::EMOJI_VERSION}" title=":smile:" class="emoji only-emoji" alt=":smile:"></p>
|
||||||
|
@ -1246,7 +1246,7 @@ describe CookedPostProcessor do
|
||||||
expect(cpp.html).to match_html <<~HTML.rstrip
|
expect(cpp.html).to match_html <<~HTML.rstrip
|
||||||
<p><a href="//my.cdn.com/#{upload_path}/original/2X/2345678901234567.jpg">Link</a><br>
|
<p><a href="//my.cdn.com/#{upload_path}/original/2X/2345678901234567.jpg">Link</a><br>
|
||||||
<img src="//my.cdn.com/#{upload_path}/original/1X/1234567890123456.jpg"><br>
|
<img src="//my.cdn.com/#{upload_path}/original/1X/1234567890123456.jpg"><br>
|
||||||
<a href="http://www.google.com" rel="nofollow noopener">Google</a><br>
|
<a href="http://www.google.com" rel="noopener nofollow ugc">Google</a><br>
|
||||||
<img src="http://foo.bar/image.png"><br>
|
<img src="http://foo.bar/image.png"><br>
|
||||||
<a class="attachment" href="//test.localhost/#{upload_path}/original/1X/af2c2618032c679333bebf745e75f9088748d737.txt">text.txt</a> (20 Bytes)<br>
|
<a class="attachment" href="//test.localhost/#{upload_path}/original/1X/af2c2618032c679333bebf745e75f9088748d737.txt">text.txt</a> (20 Bytes)<br>
|
||||||
<img src="//my.cdn.com/images/emoji/twitter/smile.png?v=#{Emoji::EMOJI_VERSION}" title=":smile:" class="emoji only-emoji" alt=":smile:"></p>
|
<img src="//my.cdn.com/images/emoji/twitter/smile.png?v=#{Emoji::EMOJI_VERSION}" title=":smile:" class="emoji only-emoji" alt=":smile:"></p>
|
||||||
|
@ -1260,7 +1260,7 @@ describe CookedPostProcessor do
|
||||||
expect(cpp.html).to match_html <<~HTML.rstrip
|
expect(cpp.html).to match_html <<~HTML.rstrip
|
||||||
<p><a href="//my.cdn.com/#{upload_path}/original/2X/2345678901234567.jpg">Link</a><br>
|
<p><a href="//my.cdn.com/#{upload_path}/original/2X/2345678901234567.jpg">Link</a><br>
|
||||||
<img src="//my.cdn.com/#{upload_path}/original/1X/1234567890123456.jpg"><br>
|
<img src="//my.cdn.com/#{upload_path}/original/1X/1234567890123456.jpg"><br>
|
||||||
<a href="http://www.google.com" rel="nofollow noopener">Google</a><br>
|
<a href="http://www.google.com" rel="noopener nofollow ugc">Google</a><br>
|
||||||
<img src="http://foo.bar/image.png"><br>
|
<img src="http://foo.bar/image.png"><br>
|
||||||
<a class="attachment" href="//test.localhost/#{upload_path}/original/1X/af2c2618032c679333bebf745e75f9088748d737.txt">text.txt</a> (20 Bytes)<br>
|
<a class="attachment" href="//test.localhost/#{upload_path}/original/1X/af2c2618032c679333bebf745e75f9088748d737.txt">text.txt</a> (20 Bytes)<br>
|
||||||
<img src="//my.cdn.com/images/emoji/twitter/smile.png?v=#{Emoji::EMOJI_VERSION}" title=":smile:" class="emoji only-emoji" alt=":smile:"></p>
|
<img src="//my.cdn.com/images/emoji/twitter/smile.png?v=#{Emoji::EMOJI_VERSION}" title=":smile:" class="emoji only-emoji" alt=":smile:"></p>
|
||||||
|
|
|
@ -425,7 +425,7 @@ describe PrettyText do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "can handle mentions inside a hyperlink" do
|
it "can handle mentions inside a hyperlink" do
|
||||||
expect(PrettyText.cook("[link @inner](http://site.com)")).to match_html '<p><a href="http://site.com" rel="nofollow noopener">link @inner</a></p>'
|
expect(PrettyText.cook("[link @inner](http://site.com)")).to match_html '<p><a href="http://site.com" rel="noopener nofollow ugc">link @inner</a></p>'
|
||||||
end
|
end
|
||||||
|
|
||||||
it "can handle a list of mentions" do
|
it "can handle a list of mentions" do
|
||||||
|
@ -513,42 +513,56 @@ describe PrettyText do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "rel nofollow" do
|
describe "rel attributes" do
|
||||||
before do
|
before do
|
||||||
SiteSetting.add_rel_nofollow_to_user_content = true
|
SiteSetting.add_rel_nofollow_to_user_content = true
|
||||||
SiteSetting.exclude_rel_nofollow_domains = "foo.com|bar.com"
|
SiteSetting.exclude_rel_nofollow_domains = "foo.com|bar.com"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should inject nofollow in all user provided links" do
|
it "should inject nofollow in all user provided links" do
|
||||||
expect(PrettyText.cook('<a href="http://cnn.com">cnn</a>')).to match(/nofollow noopener/)
|
expect(PrettyText.cook('<a href="http://cnn.com">cnn</a>')).to match(/noopener nofollow ugc/)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not inject nofollow in all local links" do
|
it "should not inject nofollow in all local links" do
|
||||||
expect(PrettyText.cook("<a href='#{Discourse.base_url}/test.html'>cnn</a>") !~ /nofollow/).to eq(true)
|
expect(PrettyText.cook("<a href='#{Discourse.base_url}/test.html'>cnn</a>") !~ /nofollow ugc/).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not inject nofollow in all subdomain links" do
|
it "should not inject nofollow in all subdomain links" do
|
||||||
expect(PrettyText.cook("<a href='#{Discourse.base_url.sub('http://', 'http://bla.')}/test.html'>cnn</a>") !~ /nofollow/).to eq(true)
|
expect(PrettyText.cook("<a href='#{Discourse.base_url.sub('http://', 'http://bla.')}/test.html'>cnn</a>") !~ /nofollow ugc/).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should inject nofollow in all non subdomain links" do
|
it "should inject nofollow in all non subdomain links" do
|
||||||
expect(PrettyText.cook("<a href='#{Discourse.base_url.sub('http://', 'http://bla')}/test.html'>cnn</a>")).to match(/nofollow/)
|
expect(PrettyText.cook("<a href='#{Discourse.base_url.sub('http://', 'http://bla')}/test.html'>cnn</a>")).to match(/nofollow ugc/)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not inject nofollow for foo.com" do
|
it "should not inject nofollow for foo.com" do
|
||||||
expect(PrettyText.cook("<a href='http://foo.com/test.html'>cnn</a>") !~ /nofollow/).to eq(true)
|
expect(PrettyText.cook("<a href='http://foo.com/test.html'>cnn</a>") !~ /nofollow ugc/).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should inject nofollow for afoo.com" do
|
it "should inject nofollow for afoo.com" do
|
||||||
expect(PrettyText.cook("<a href='http://afoo.com/test.html'>cnn</a>")).to match(/nofollow/)
|
expect(PrettyText.cook("<a href='http://afoo.com/test.html'>cnn</a>")).to match(/nofollow ugc/)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not inject nofollow for bar.foo.com" do
|
it "should not inject nofollow for bar.foo.com" do
|
||||||
expect(PrettyText.cook("<a href='http://bar.foo.com/test.html'>cnn</a>") !~ /nofollow/).to eq(true)
|
expect(PrettyText.cook("<a href='http://bar.foo.com/test.html'>cnn</a>") !~ /nofollow ugc/).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not inject nofollow if omit_nofollow option is given" do
|
it "should not inject nofollow if omit_nofollow option is given" do
|
||||||
expect(PrettyText.cook('<a href="http://cnn.com">cnn</a>', omit_nofollow: true) !~ /nofollow/).to eq(true)
|
expect(PrettyText.cook('<a href="http://cnn.com">cnn</a>', omit_nofollow: true) !~ /nofollow ugc/).to eq(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'adds the noopener attribute even if omit_nofollow option is given' do
|
||||||
|
raw_html = '<a href="https://www.mysite.com/" target="_blank">Check out my site!</a>'
|
||||||
|
expect(
|
||||||
|
PrettyText.cook(raw_html, omit_nofollow: true)
|
||||||
|
).to match(/noopener/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'adds the noopener attribute even if omit_nofollow option is given' do
|
||||||
|
raw_html = '<a href="https://www.mysite.com/" target="_blank">Check out my site!</a>'
|
||||||
|
expect(
|
||||||
|
PrettyText.cook(raw_html, omit_nofollow: false)
|
||||||
|
).to match(/noopener nofollow ugc/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -724,7 +738,7 @@ describe PrettyText do
|
||||||
more stuff
|
more stuff
|
||||||
RAW
|
RAW
|
||||||
post = Fabricate(:post, raw: raw)
|
post = Fabricate(:post, raw: raw)
|
||||||
expect(post.excerpt).to eq("hello <a href=\"https://site.com\" rel=\"nofollow noopener\">site</a>")
|
expect(post.excerpt).to eq("hello <a href=\"https://site.com\" rel=\"noopener nofollow ugc\">site</a>")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "handles span excerpt at the beginning of a post" do
|
it "handles span excerpt at the beginning of a post" do
|
||||||
|
@ -1109,7 +1123,7 @@ describe PrettyText do
|
||||||
it "supports href schemes" do
|
it "supports href schemes" do
|
||||||
SiteSetting.allowed_href_schemes = "macappstore|steam"
|
SiteSetting.allowed_href_schemes = "macappstore|steam"
|
||||||
cooked = cook("[Steam URL Scheme](steam://store/452530)")
|
cooked = cook("[Steam URL Scheme](steam://store/452530)")
|
||||||
expected = '<p><a href="steam://store/452530" rel="nofollow noopener">Steam URL Scheme</a></p>'
|
expected = '<p><a href="steam://store/452530" rel="noopener nofollow ugc">Steam URL Scheme</a></p>'
|
||||||
expect(cooked).to eq(n expected)
|
expect(cooked).to eq(n expected)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1123,7 +1137,7 @@ describe PrettyText do
|
||||||
it 'allows only tel URL scheme to start with a plus character' do
|
it 'allows only tel URL scheme to start with a plus character' do
|
||||||
SiteSetting.allowed_href_schemes = "tel|steam"
|
SiteSetting.allowed_href_schemes = "tel|steam"
|
||||||
cooked = cook("[Tel URL Scheme](tel://+452530579785)")
|
cooked = cook("[Tel URL Scheme](tel://+452530579785)")
|
||||||
expected = '<p><a href="tel://+452530579785" rel="nofollow noopener">Tel URL Scheme</a></p>'
|
expected = '<p><a href="tel://+452530579785" rel="noopener nofollow ugc">Tel URL Scheme</a></p>'
|
||||||
expect(cooked).to eq(n expected)
|
expect(cooked).to eq(n expected)
|
||||||
|
|
||||||
cooked2 = cook("[Steam URL Scheme](steam://+store/452530)")
|
cooked2 = cook("[Steam URL Scheme](steam://+store/452530)")
|
||||||
|
@ -1151,7 +1165,7 @@ describe PrettyText do
|
||||||
cooked = PrettyText.cook("[`a` #known::tag here](http://example.com)")
|
cooked = PrettyText.cook("[`a` #known::tag here](http://example.com)")
|
||||||
|
|
||||||
html = <<~HTML
|
html = <<~HTML
|
||||||
<p><a href="http://example.com" rel="nofollow noopener"><code>a</code> #known::tag here</a></p>
|
<p><a href="http://example.com" rel="noopener nofollow ugc"><code>a</code> #known::tag here</a></p>
|
||||||
HTML
|
HTML
|
||||||
|
|
||||||
expect(cooked).to eq(html.strip)
|
expect(cooked).to eq(html.strip)
|
||||||
|
@ -1251,7 +1265,7 @@ HTML
|
||||||
|
|
||||||
it "won't break links by censoring them." do
|
it "won't break links by censoring them." do
|
||||||
expect_cooked_match("The link still works. [whiz](http://www.whiz.com)",
|
expect_cooked_match("The link still works. [whiz](http://www.whiz.com)",
|
||||||
'<p>The link still works. <a href="http://www.whiz.com" rel="nofollow noopener">■■■■</a></p>')
|
'<p>The link still works. <a href="http://www.whiz.com" rel="noopener nofollow ugc">■■■■</a></p>')
|
||||||
end
|
end
|
||||||
|
|
||||||
it "escapes regexp characters" do
|
it "escapes regexp characters" do
|
||||||
|
@ -1415,19 +1429,19 @@ HTML
|
||||||
|
|
||||||
it "supports url bbcode" do
|
it "supports url bbcode" do
|
||||||
cooked = PrettyText.cook "[url]http://sam.com[/url]"
|
cooked = PrettyText.cook "[url]http://sam.com[/url]"
|
||||||
html = '<p><a href="http://sam.com" data-bbcode="true" rel="nofollow noopener">http://sam.com</a></p>'
|
html = '<p><a href="http://sam.com" data-bbcode="true" rel="noopener nofollow ugc">http://sam.com</a></p>'
|
||||||
expect(cooked).to eq(html)
|
expect(cooked).to eq(html)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "supports nesting tags in url" do
|
it "supports nesting tags in url" do
|
||||||
cooked = PrettyText.cook("[url=http://sam.com][b]I am sam[/b][/url]")
|
cooked = PrettyText.cook("[url=http://sam.com][b]I am sam[/b][/url]")
|
||||||
html = '<p><a href="http://sam.com" data-bbcode="true" rel="nofollow noopener"><span class="bbcode-b">I am sam</span></a></p>'
|
html = '<p><a href="http://sam.com" data-bbcode="true" rel="noopener nofollow ugc"><span class="bbcode-b">I am sam</span></a></p>'
|
||||||
expect(cooked).to eq(html)
|
expect(cooked).to eq(html)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "supports query params in bbcode url" do
|
it "supports query params in bbcode url" do
|
||||||
cooked = PrettyText.cook("[url=https://www.amazon.com/Camcorder-Hausbell-302S-Control-Infrared/dp/B01KLOA1PI/?tag=discourse]BBcode link[/url]")
|
cooked = PrettyText.cook("[url=https://www.amazon.com/Camcorder-Hausbell-302S-Control-Infrared/dp/B01KLOA1PI/?tag=discourse]BBcode link[/url]")
|
||||||
html = '<p><a href="https://www.amazon.com/Camcorder-Hausbell-302S-Control-Infrared/dp/B01KLOA1PI/?tag=discourse" data-bbcode="true" rel="nofollow noopener">BBcode link</a></p>'
|
html = '<p><a href="https://www.amazon.com/Camcorder-Hausbell-302S-Control-Infrared/dp/B01KLOA1PI/?tag=discourse" data-bbcode="true" rel="noopener nofollow ugc">BBcode link</a></p>'
|
||||||
expect(cooked).to eq(html)
|
expect(cooked).to eq(html)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1445,13 +1459,13 @@ HTML
|
||||||
|
|
||||||
it "support special handling for space in urls" do
|
it "support special handling for space in urls" do
|
||||||
cooked = PrettyText.cook "http://testing.com?a%20b"
|
cooked = PrettyText.cook "http://testing.com?a%20b"
|
||||||
html = '<p><a href="http://testing.com?a%20b" class="onebox" target="_blank" rel="nofollow noopener">http://testing.com?a%20b</a></p>'
|
html = '<p><a href="http://testing.com?a%20b" class="onebox" target="_blank" rel="noopener nofollow ugc">http://testing.com?a%20b</a></p>'
|
||||||
expect(cooked).to eq(html)
|
expect(cooked).to eq(html)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "supports onebox for decoded urls" do
|
it "supports onebox for decoded urls" do
|
||||||
cooked = PrettyText.cook "http://testing.com?a%50b"
|
cooked = PrettyText.cook "http://testing.com?a%50b"
|
||||||
html = '<p><a href="http://testing.com?a%50b" class="onebox" target="_blank" rel="nofollow noopener">http://testing.com?aPb</a></p>'
|
html = '<p><a href="http://testing.com?a%50b" class="onebox" target="_blank" rel="noopener nofollow ugc">http://testing.com?aPb</a></p>'
|
||||||
expect(cooked).to eq(html)
|
expect(cooked).to eq(html)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1613,7 +1627,7 @@ HTML
|
||||||
cooked = PrettyText.cook(md)
|
cooked = PrettyText.cook(md)
|
||||||
|
|
||||||
html = <<~HTML
|
html = <<~HTML
|
||||||
<p><a href="http://www.cnn.com" rel="nofollow noopener">www.cnn.com</a> test.it <a href="http://test.com" rel="nofollow noopener">http://test.com</a> <a href="https://test.ab" rel="nofollow noopener">https://test.ab</a> <a href="https://a" rel="nofollow noopener">https://a</a></p>
|
<p><a href="http://www.cnn.com" rel="noopener nofollow ugc">www.cnn.com</a> test.it <a href="http://test.com" rel="noopener nofollow ugc">http://test.com</a> <a href="https://test.ab" rel="noopener nofollow ugc">https://test.ab</a> <a href="https://a" rel="noopener nofollow ugc">https://a</a></p>
|
||||||
HTML
|
HTML
|
||||||
|
|
||||||
expect(cooked).to eq(html.strip)
|
expect(cooked).to eq(html.strip)
|
||||||
|
@ -1623,7 +1637,7 @@ HTML
|
||||||
|
|
||||||
cooked = PrettyText.cook(md)
|
cooked = PrettyText.cook(md)
|
||||||
html = <<~HTML
|
html = <<~HTML
|
||||||
<p>www.cnn.com <a href="http://test.it" rel="nofollow noopener">test.it</a> <a href="http://test.com" rel="nofollow noopener">http://test.com</a> <a href="https://test.ab" rel="nofollow noopener">https://test.ab</a> <a href="https://a" rel="nofollow noopener">https://a</a></p>
|
<p>www.cnn.com <a href="http://test.it" rel="noopener nofollow ugc">test.it</a> <a href="http://test.com" rel="noopener nofollow ugc">http://test.com</a> <a href="https://test.ab" rel="noopener nofollow ugc">https://test.ab</a> <a href="https://a" rel="noopener nofollow ugc">https://a</a></p>
|
||||||
HTML
|
HTML
|
||||||
|
|
||||||
expect(cooked).to eq(html.strip)
|
expect(cooked).to eq(html.strip)
|
||||||
|
@ -1633,7 +1647,7 @@ HTML
|
||||||
|
|
||||||
cooked = PrettyText.cook(md)
|
cooked = PrettyText.cook(md)
|
||||||
html = <<~HTML
|
html = <<~HTML
|
||||||
<p>www.cnn.com test.it <a href="http://test.com" rel="nofollow noopener">http://test.com</a> <a href="https://test.ab" rel="nofollow noopener">https://test.ab</a> <a href="https://a" rel="nofollow noopener">https://a</a></p>
|
<p>www.cnn.com test.it <a href="http://test.com" rel="noopener nofollow ugc">http://test.com</a> <a href="https://test.ab" rel="noopener nofollow ugc">https://test.ab</a> <a href="https://a" rel="noopener nofollow ugc">https://a</a></p>
|
||||||
HTML
|
HTML
|
||||||
|
|
||||||
expect(cooked).to eq(html.strip)
|
expect(cooked).to eq(html.strip)
|
||||||
|
|
|
@ -1025,7 +1025,7 @@ describe Post do
|
||||||
it "should add nofollow to links in the post for trust levels below 3" do
|
it "should add nofollow to links in the post for trust levels below 3" do
|
||||||
post.user.trust_level = 2
|
post.user.trust_level = 2
|
||||||
post.save
|
post.save
|
||||||
expect(post.cooked).to match(/nofollow noopener/)
|
expect(post.cooked).to match(/noopener nofollow ugc/)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "when tl3_links_no_follow is false, should not add nofollow for trust level 3 and higher" do
|
it "when tl3_links_no_follow is false, should not add nofollow for trust level 3 and higher" do
|
||||||
|
@ -1039,7 +1039,7 @@ describe Post do
|
||||||
SiteSetting.tl3_links_no_follow = true
|
SiteSetting.tl3_links_no_follow = true
|
||||||
post.user.trust_level = 3
|
post.user.trust_level = 3
|
||||||
post.save
|
post.save
|
||||||
expect(post.cooked).to match(/nofollow noopener/)
|
expect(post.cooked).to match(/noopener nofollow ugc/)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'mentions' do
|
describe 'mentions' do
|
||||||
|
|
|
@ -138,8 +138,8 @@ describe UserProfile do
|
||||||
|
|
||||||
it 'includes the link as nofollow if the user is not new' do
|
it 'includes the link as nofollow if the user is not new' do
|
||||||
user.user_profile.send(:cook)
|
user.user_profile.send(:cook)
|
||||||
expect(user_profile.bio_excerpt).to match_html("I love <a href='http://discourse.org' rel='nofollow noopener'>http://discourse.org</a>")
|
expect(user_profile.bio_excerpt).to match_html("I love <a href='http://discourse.org' rel='noopener nofollow ugc'>http://discourse.org</a>")
|
||||||
expect(user_profile.bio_processed).to match_html("<p>I love <a href=\"http://discourse.org\" rel=\"nofollow noopener\">http://discourse.org</a></p>")
|
expect(user_profile.bio_processed).to match_html("<p>I love <a href=\"http://discourse.org\" rel=\"noopener nofollow ugc\">http://discourse.org</a></p>")
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'removes the link if the user is new' do
|
it 'removes the link if the user is new' do
|
||||||
|
@ -177,8 +177,8 @@ describe UserProfile do
|
||||||
created_user.save
|
created_user.save
|
||||||
created_user.reload
|
created_user.reload
|
||||||
created_user.change_trust_level!(TrustLevel[2])
|
created_user.change_trust_level!(TrustLevel[2])
|
||||||
expect(created_user.user_profile.bio_excerpt).to match_html("I love <a href='http://discourse.org' rel='nofollow noopener'>http://discourse.org</a>")
|
expect(created_user.user_profile.bio_excerpt).to match_html("I love <a href='http://discourse.org' rel='noopener nofollow ugc'>http://discourse.org</a>")
|
||||||
expect(created_user.user_profile.bio_processed).to match_html("<p>I love <a href=\"http://discourse.org\" rel=\"nofollow noopener\">http://discourse.org</a></p>")
|
expect(created_user.user_profile.bio_processed).to match_html("<p>I love <a href=\"http://discourse.org\" rel=\"noopener nofollow ugc\">http://discourse.org</a></p>")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -188,8 +188,8 @@ describe UserProfile do
|
||||||
it 'includes the link with nofollow if the user is trust level 3 or higher' do
|
it 'includes the link with nofollow if the user is trust level 3 or higher' do
|
||||||
user.trust_level = TrustLevel[3]
|
user.trust_level = TrustLevel[3]
|
||||||
user_profile.send(:cook)
|
user_profile.send(:cook)
|
||||||
expect(user_profile.bio_excerpt).to match_html("I love <a href='http://discourse.org' rel='nofollow noopener'>http://discourse.org</a>")
|
expect(user_profile.bio_excerpt).to match_html("I love <a href='http://discourse.org' rel='noopener nofollow ugc'>http://discourse.org</a>")
|
||||||
expect(user_profile.bio_processed).to match_html("<p>I love <a href=\"http://discourse.org\" rel=\"nofollow noopener\">http://discourse.org</a></p>")
|
expect(user_profile.bio_processed).to match_html("<p>I love <a href=\"http://discourse.org\" rel=\"noopener nofollow ugc\">http://discourse.org</a></p>")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue