mirror of
https://github.com/discourse/discourse.git
synced 2024-11-24 07:34:18 +08:00
c3b461f58d
This was giving an ugly border to avatars in the user card as the full size version loaded in Firefox.
312 lines
14 KiB
Ruby
312 lines
14 KiB
Ruby
require 'spec_helper'
|
|
require 'pretty_text'
|
|
|
|
describe PrettyText do
|
|
|
|
let(:wrapped_image) { "<div class=\"lightbox-wrapper\"><a href=\"//localhost:3000/uploads/default/4399/33691397e78b4d75.png\" class=\"lightbox\" title=\"Screen Shot 2014-04-14 at 9.47.10 PM.png\"><img src=\"//localhost:3000/uploads/default/_optimized/bd9/b20/bbbcd6a0c0_655x500.png\" width=\"655\" height=\"500\"><div class=\"meta\">\n<span class=\"filename\">Screen Shot 2014-04-14 at 9.47.10 PM.png</span><span class=\"informations\">966x737 1.47 MB</span><span class=\"expand\"></span>\n</div></a></div>" }
|
|
let(:wrapped_image_excerpt) { }
|
|
|
|
describe "Cooking" do
|
|
|
|
describe "with avatar" do
|
|
|
|
before(:each) do
|
|
eviltrout = User.new
|
|
eviltrout.stubs(:avatar_template).returns("//test.localhost/uploads/default/avatars/42d/57c/46ce7ee487/{size}.png")
|
|
User.expects(:find_by).with(username_lower: "eviltrout").returns(eviltrout)
|
|
end
|
|
|
|
it "produces a quote even with new lines in it" do
|
|
expect(PrettyText.cook("[quote=\"EvilTrout, post:123, topic:456, full:true\"]ddd\n[/quote]")).to match_html "<aside class=\"quote\" data-post=\"123\" data-topic=\"456\" data-full=\"true\"><div class=\"title\">\n<div class=\"quote-controls\"></div>\n<img alt='' width=\"20\" height=\"20\" src=\"//test.localhost/uploads/default/avatars/42d/57c/46ce7ee487/40.png\" class=\"avatar\">EvilTrout:</div>\n<blockquote><p>ddd</p></blockquote></aside>"
|
|
end
|
|
|
|
it "should produce a quote" do
|
|
expect(PrettyText.cook("[quote=\"EvilTrout, post:123, topic:456, full:true\"]ddd[/quote]")).to match_html "<aside class=\"quote\" data-post=\"123\" data-topic=\"456\" data-full=\"true\"><div class=\"title\">\n<div class=\"quote-controls\"></div>\n<img alt='' width=\"20\" height=\"20\" src=\"//test.localhost/uploads/default/avatars/42d/57c/46ce7ee487/40.png\" class=\"avatar\">EvilTrout:</div>\n<blockquote><p>ddd</p></blockquote></aside>"
|
|
end
|
|
|
|
it "trims spaces on quote params" do
|
|
expect(PrettyText.cook("[quote=\"EvilTrout, post:555, topic: 666\"]ddd[/quote]")).to match_html "<aside class=\"quote\" data-post=\"555\" data-topic=\"666\"><div class=\"title\">\n<div class=\"quote-controls\"></div>\n<img alt='' width=\"20\" height=\"20\" src=\"//test.localhost/uploads/default/avatars/42d/57c/46ce7ee487/40.png\" class=\"avatar\">EvilTrout:</div>\n<blockquote><p>ddd</p></blockquote></aside>"
|
|
end
|
|
|
|
end
|
|
|
|
it "should handle 3 mentions in a row" do
|
|
expect(PrettyText.cook('@hello @hello @hello')).to match_html "<p><span class=\"mention\">@hello</span> <span class=\"mention\">@hello</span> <span class=\"mention\">@hello</span></p>"
|
|
end
|
|
|
|
it "should sanitize the html" do
|
|
expect(PrettyText.cook("<script>alert(42)</script>")).to match_html "<p></p>"
|
|
end
|
|
|
|
it 'should allow for @mentions to have punctuation' do
|
|
expect(PrettyText.cook("hello @bob's @bob,@bob; @bob\"")).to match_html(
|
|
"<p>hello <span class=\"mention\">@bob</span>'s <span class=\"mention\">@bob</span>,<span class=\"mention\">@bob</span>; <span class=\"mention\">@bob</span>\"</p>"
|
|
)
|
|
end
|
|
|
|
# see: https://github.com/sparklemotion/nokogiri/issues/1173
|
|
skip 'allows html entities correctly' do
|
|
expect(PrettyText.cook("ℵ£¢")).to eq("<p>ℵ£¢</p>")
|
|
end
|
|
|
|
end
|
|
|
|
describe "rel nofollow" do
|
|
before do
|
|
SiteSetting.stubs(:add_rel_nofollow_to_user_content).returns(true)
|
|
SiteSetting.stubs(:exclude_rel_nofollow_domains).returns("foo.com|bar.com")
|
|
end
|
|
|
|
it "should inject nofollow in all user provided links" do
|
|
expect(PrettyText.cook('<a href="http://cnn.com">cnn</a>')).to match(/nofollow/)
|
|
end
|
|
|
|
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)
|
|
end
|
|
|
|
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)
|
|
end
|
|
|
|
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)
|
|
end
|
|
|
|
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)
|
|
end
|
|
|
|
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)
|
|
end
|
|
end
|
|
|
|
describe "Excerpt" do
|
|
|
|
it "sanitizes attempts to inject invalid attributes" do
|
|
spinner = "<a href=\"http://thedailywtf.com/\" data-bbcode=\"' class='fa fa-spin\">WTF</a>"
|
|
expect(PrettyText.excerpt(spinner, 20)).to match_html spinner
|
|
|
|
spinner = %q{<a href="http://thedailywtf.com/" title="' class="fa fa-spin"><img src='http://thedailywtf.com/Resources/Images/Primary/logo.gif"></a>}
|
|
expect(PrettyText.excerpt(spinner, 20)).to match_html spinner
|
|
end
|
|
|
|
context "images" do
|
|
|
|
it "should dump images" do
|
|
expect(PrettyText.excerpt("<img src='http://cnn.com/a.gif'>",100)).to eq("[image]")
|
|
end
|
|
|
|
it "should keep alt tags" do
|
|
expect(PrettyText.excerpt("<img src='http://cnn.com/a.gif' alt='car' title='my big car'>",100)).to eq("[car]")
|
|
end
|
|
|
|
it "should keep title tags" do
|
|
expect(PrettyText.excerpt("<img src='http://cnn.com/a.gif' title='car'>",100)).to eq("[car]")
|
|
end
|
|
|
|
it "should convert images to markdown if the option is set" do
|
|
expect(PrettyText.excerpt("<img src='http://cnn.com/a.gif' title='car'>", 100, markdown_images: true)).to eq("![car](http://cnn.com/a.gif)")
|
|
end
|
|
|
|
it "should keep spoilers" do
|
|
expect(PrettyText.excerpt("<div class='spoiler'><img src='http://cnn.com/a.gif'></div>", 100)).to match_html "<span class='spoiler'>[image]</span>"
|
|
expect(PrettyText.excerpt("<span class='spoiler'>spoiler</div>", 100)).to match_html "<span class='spoiler'>spoiler</span>"
|
|
end
|
|
|
|
it "should remove meta informations" do
|
|
expect(PrettyText.excerpt(wrapped_image, 100)).to match_html "<a href='//localhost:3000/uploads/default/4399/33691397e78b4d75.png' class='lightbox' title='Screen Shot 2014-04-14 at 9.47.10 PM.png'>[image]</a>"
|
|
end
|
|
end
|
|
|
|
it "should have an option to strip links" do
|
|
expect(PrettyText.excerpt("<a href='http://cnn.com'>cnn</a>",100, strip_links: true)).to eq("cnn")
|
|
end
|
|
|
|
it "should preserve links" do
|
|
expect(PrettyText.excerpt("<a href='http://cnn.com'>cnn</a>",100)).to match_html "<a href='http://cnn.com'>cnn</a>"
|
|
end
|
|
|
|
it "should deal with special keys properly" do
|
|
expect(PrettyText.excerpt("<pre><b></pre>",100)).to eq("")
|
|
end
|
|
|
|
it "should truncate stuff properly" do
|
|
expect(PrettyText.excerpt("hello world",5)).to eq("hello…")
|
|
expect(PrettyText.excerpt("<p>hello</p><p>world</p>",6)).to eq("hello w…")
|
|
end
|
|
|
|
it "should insert a space between to Ps" do
|
|
expect(PrettyText.excerpt("<p>a</p><p>b</p>",5)).to eq("a b")
|
|
end
|
|
|
|
it "should strip quotes" do
|
|
expect(PrettyText.excerpt("<aside class='quote'><p>a</p><p>b</p></aside>boom",5)).to eq("boom")
|
|
end
|
|
|
|
it "should not count the surrounds of a link" do
|
|
expect(PrettyText.excerpt("<a href='http://cnn.com'>cnn</a>",3)).to match_html "<a href='http://cnn.com'>cnn</a>"
|
|
end
|
|
|
|
it "uses an ellipsis instead of html entities if provided with the option" do
|
|
expect(PrettyText.excerpt("<a href='http://cnn.com'>cnn</a>", 2, text_entities: true)).to match_html "<a href='http://cnn.com'>cn...</a>"
|
|
end
|
|
|
|
it "should truncate links" do
|
|
expect(PrettyText.excerpt("<a href='http://cnn.com'>cnn</a>",2)).to match_html "<a href='http://cnn.com'>cn…</a>"
|
|
end
|
|
|
|
it "doesn't extract empty quotes as links" do
|
|
expect(PrettyText.extract_links("<aside class='quote'>not a linked quote</aside>\n").to_a).to be_empty
|
|
end
|
|
|
|
def extract_urls(text)
|
|
PrettyText.extract_links(text).map(&:url).to_a
|
|
end
|
|
|
|
it "should be able to extract links" do
|
|
expect(extract_urls("<a href='http://cnn.com'>http://bla.com</a>")).to eq(["http://cnn.com"])
|
|
end
|
|
|
|
it "should extract links to topics" do
|
|
expect(extract_urls("<aside class=\"quote\" data-topic=\"321\">aside</aside>")).to eq(["/t/topic/321"])
|
|
end
|
|
|
|
it "should extract links to posts" do
|
|
expect(extract_urls("<aside class=\"quote\" data-topic=\"1234\" data-post=\"4567\">aside</aside>")).to eq(["/t/topic/1234/4567"])
|
|
end
|
|
|
|
it "should not extract links inside quotes" do
|
|
links = PrettyText.extract_links("
|
|
<a href='http://body_only.com'>http://useless1.com</a>
|
|
<aside class=\"quote\" data-topic=\"1234\">
|
|
<a href='http://body_and_quote.com'>http://useless3.com</a>
|
|
<a href='http://quote_only.com'>http://useless4.com</a>
|
|
</aside>
|
|
<a href='http://body_and_quote.com'>http://useless2.com</a>
|
|
")
|
|
|
|
expect(links.map{|l| [l.url, l.is_quote]}.to_a.sort).to eq(
|
|
[["http://body_only.com",false],
|
|
["http://body_and_quote.com", false],
|
|
["/t/topic/1234",true]
|
|
].sort
|
|
)
|
|
end
|
|
|
|
it "should not preserve tags in code blocks" do
|
|
expect(PrettyText.excerpt("<pre><code class='handlebars'><h3>Hours</h3></code></pre>",100)).to eq("<h3>Hours</h3>")
|
|
end
|
|
|
|
it "should handle nil" do
|
|
expect(PrettyText.excerpt(nil,100)).to eq('')
|
|
end
|
|
|
|
it "handles span excerpt at the beginning of a post" do
|
|
expect(PrettyText.excerpt("<span class='excerpt'>hi</span> test",100)).to eq('hi')
|
|
post = Fabricate(:post, raw: "<span class='excerpt'>hi</span> test")
|
|
expect(post.excerpt).to eq("hi")
|
|
end
|
|
|
|
it "ignores max excerpt length if a span excerpt is specified" do
|
|
two_hundred = "123456789 " * 20 + "."
|
|
text = two_hundred + "<span class='excerpt'>#{two_hundred}</span>" + two_hundred
|
|
expect(PrettyText.excerpt(text, 100)).to eq(two_hundred)
|
|
post = Fabricate(:post, raw: text)
|
|
expect(post.excerpt).to eq(two_hundred)
|
|
end
|
|
|
|
it "unescapes html entities when we want text entities" do
|
|
expect(PrettyText.excerpt("'", 500, text_entities: true)).to eq("'")
|
|
end
|
|
|
|
end
|
|
|
|
describe "strip links" do
|
|
it "returns blank for blank input" do
|
|
expect(PrettyText.strip_links("")).to be_blank
|
|
end
|
|
|
|
it "does nothing to a string without links" do
|
|
expect(PrettyText.strip_links("I'm the <b>batman</b>")).to eq("I'm the <b>batman</b>")
|
|
end
|
|
|
|
it "strips links but leaves the text content" do
|
|
expect(PrettyText.strip_links("I'm the linked <a href='http://en.wikipedia.org/wiki/Batman'>batman</a>")).to eq("I'm the linked batman")
|
|
end
|
|
|
|
it "escapes the text content" do
|
|
expect(PrettyText.strip_links("I'm the linked <a href='http://en.wikipedia.org/wiki/Batman'><batman></a>")).to eq("I'm the linked <batman>")
|
|
end
|
|
end
|
|
|
|
describe "make_all_links_absolute" do
|
|
let(:base_url) { "http://baseurl.net" }
|
|
|
|
def make_abs_string(html)
|
|
doc = Nokogiri::HTML.fragment(html)
|
|
described_class.make_all_links_absolute(doc)
|
|
doc.to_html
|
|
end
|
|
|
|
before do
|
|
Discourse.stubs(:base_url).returns(base_url)
|
|
end
|
|
|
|
it "adds base url to relative links" do
|
|
html = "<p><a class=\"mention\" href=\"/users/wiseguy\">@wiseguy</a>, <a class=\"mention\" href=\"/users/trollol\">@trollol</a> what do you guys think? </p>"
|
|
output = make_abs_string(html)
|
|
expect(output).to eq("<p><a class=\"mention\" href=\"#{base_url}/users/wiseguy\">@wiseguy</a>, <a class=\"mention\" href=\"#{base_url}/users/trollol\">@trollol</a> what do you guys think? </p>")
|
|
end
|
|
|
|
it "doesn't change external absolute links" do
|
|
html = "<p>Check out <a href=\"http://mywebsite.com/users/boss\">this guy</a>.</p>"
|
|
expect(make_abs_string(html)).to eq(html)
|
|
end
|
|
|
|
it "doesn't change internal absolute links" do
|
|
html = "<p>Check out <a href=\"#{base_url}/users/boss\">this guy</a>.</p>"
|
|
expect(make_abs_string(html)).to eq(html)
|
|
end
|
|
|
|
it "can tolerate invalid URLs" do
|
|
html = "<p>Check out <a href=\"not a real url\">this guy</a>.</p>"
|
|
expect { make_abs_string(html) }.to_not raise_error
|
|
end
|
|
end
|
|
|
|
describe "strip_image_wrapping" do
|
|
def strip_image_wrapping(html)
|
|
doc = Nokogiri::HTML.fragment(html)
|
|
described_class.strip_image_wrapping(doc)
|
|
doc.to_html
|
|
end
|
|
|
|
it "doesn't change HTML when there's no wrapped image" do
|
|
html = "<img src=\"wat.png\">"
|
|
expect(strip_image_wrapping(html)).to eq(html)
|
|
end
|
|
|
|
it "strips the metadata" do
|
|
expect(strip_image_wrapping(wrapped_image)).to match_html "<div class=\"lightbox-wrapper\"><a href=\"//localhost:3000/uploads/default/4399/33691397e78b4d75.png\" class=\"lightbox\" title=\"Screen Shot 2014-04-14 at 9.47.10 PM.png\"><img src=\"//localhost:3000/uploads/default/_optimized/bd9/b20/bbbcd6a0c0_655x500.png\" width=\"655\" height=\"500\"></a></div>"
|
|
end
|
|
end
|
|
|
|
describe 'format_for_email' do
|
|
it 'does not crash' do
|
|
PrettyText.format_for_email('<a href="mailto:michael.brown@discourse.org?subject=Your%20post%20at%20http://try.discourse.org/t/discussion-happens-so-much/127/1000?u=supermathie">test</a>')
|
|
end
|
|
end
|
|
|
|
it 'can escape *' do
|
|
expect(PrettyText.cook("***a***a")).to match_html("<p><strong><em>a</em></strong>a</p>")
|
|
expect(PrettyText.cook("***\\****a")).to match_html("<p><strong><em>*</em></strong>a</p>")
|
|
end
|
|
|
|
it 'can include code class correctly' do
|
|
expect(PrettyText.cook("```cpp\ncpp\n```")).to match_html("<p></p><pre><code class='lang-cpp'>cpp</code></pre>")
|
|
end
|
|
|
|
end
|