2015-10-11 05:41:23 -04:00
require 'rails_helper'
2013-02-05 14:16:51 -05:00
require 'pretty_text'
2017-06-08 18:02:30 -04:00
require 'html_normalize'
2013-02-05 14:16:51 -05:00
describe PrettyText do
2017-07-10 12:20:50 -04:00
before do
2017-07-14 08:27:28 -04:00
SiteSetting . enable_markdown_typographer = false
2017-07-10 12:20:50 -04:00
end
2017-06-08 18:02:30 -04:00
def n ( html )
HtmlNormalize . normalize ( html )
end
def cook ( * args )
n ( PrettyText . cook ( * args ) )
end
2014-11-05 14:37:00 -05:00
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> " }
2017-07-27 21:20:09 -04:00
let ( :wrapped_image_excerpt ) { }
2014-11-05 14:37:00 -05:00
2017-07-10 12:20:50 -04:00
describe " Quoting " do
2015-09-24 23:35:14 -04:00
2013-08-13 16:08:29 -04:00
describe " with avatar " do
2015-06-26 13:37:50 -04:00
let ( :default_avatar ) { " //test.localhost/uploads/default/avatars/42d/57c/46ce7ee487/{size}.png " }
2017-01-05 19:53:30 -05:00
let ( :user ) { Fabricate ( :user ) }
2013-02-05 14:16:51 -05:00
2015-09-24 23:35:14 -04:00
before do
2015-06-26 13:37:50 -04:00
User . stubs ( :default_template ) . returns ( default_avatar )
2013-08-13 16:08:29 -04:00
end
2013-02-05 14:16:51 -05:00
2017-07-10 12:20:50 -04:00
it " do off topic quoting with emoji unescape " do
topic = Fabricate ( :topic , title : " this is a test topic :slight_smile: " )
expected = << ~ HTML
< aside class = " quote " data - topic = " #{ topic . id } " data - post = " 2 " >
< div class = " title " >
< div class = " quote-controls " > < / div>
< a href = " http://test.localhost/t/this-is-a-test-topic-slight-smile/ #{ topic . id } /2 " > This is a test topic < img src = " /images/emoji/twitter/slight_smile.png?v=5 " title = " slight_smile " alt = " slight_smile " class = " emoji " > < / a>
< / div>
< blockquote >
< p > ddd < / p>
< / blockquote>
< / aside>
HTML
expect ( cook ( " [quote= \" EvilTrout, post:2, topic: #{ topic . id } \" ] \n ddd \n [/quote] " , topic_id : 1 ) ) . to eq ( n ( expected ) )
2013-08-13 16:08:29 -04:00
end
2013-02-05 14:16:51 -05:00
2017-07-24 18:36:17 -04:00
it " indifferent about missing quotations " do
md = << ~ MD
[ quote = #{user.username}, post:123, topic:456, full:true]
ddd
[ / quote]
MD
html = << ~ HTML
< aside class = " quote " data - post = " 123 " data - topic = " 456 " data - full = " true " >
< div class = " title " >
< div class = " quote-controls " > < / div>
< img alt width = " 20 " height = " 20 " src = " //test.localhost/uploads/default/avatars/42d/57c/46ce7ee487/40.png " class = " avatar " > #{user.username}:</div>
< blockquote >
< p > ddd < / p>
< / blockquote>
< / aside>
HTML
expect ( PrettyText . cook ( md ) ) . to eq ( html . strip )
end
it " indifferent about curlies and no curlies " do
2017-07-10 12:20:50 -04:00
md = << ~ MD
2017-07-24 12:21:49 -04:00
[ quote = “ #{user.username}, post:123, topic:456, full:true”]
2017-07-10 12:20:50 -04:00
ddd
[ / quote]
MD
html = << ~ HTML
2017-07-14 08:27:28 -04:00
< aside class = " quote " data - post = " 123 " data - topic = " 456 " data - full = " true " >
2017-07-10 12:20:50 -04:00
< div class = " title " >
< div class = " quote-controls " > < / div>
< img alt width = " 20 " height = " 20 " src = " //test.localhost/uploads/default/avatars/42d/57c/46ce7ee487/40.png " class = " avatar " > #{user.username}:</div>
< blockquote >
< p > ddd < / p>
< / blockquote>
< / aside>
HTML
expect ( PrettyText . cook ( md ) ) . to eq ( html . strip )
2013-08-13 16:08:29 -04:00
end
it " trims spaces on quote params " do
2017-07-10 12:20:50 -04:00
md = << ~ MD
[ quote = " #{ user . username } , post:555, topic: 666 " ]
ddd
[ / quote]
MD
html = << ~ HTML
< aside class = " quote " data - post = " 555 " data - topic = " 666 " >
< div class = " title " >
< div class = " quote-controls " > < / div>
< img alt width = " 20 " height = " 20 " src = " //test.localhost/uploads/default/avatars/42d/57c/46ce7ee487/40.png " class = " avatar " > #{user.username}:</div>
< blockquote >
< p > ddd < / p>
< / blockquote>
< / aside>
HTML
expect ( PrettyText . cook ( md ) ) . to eq ( html . strip )
2013-08-13 16:08:29 -04:00
end
2017-06-23 17:12:06 -04:00
end
2017-07-27 17:55:04 -04:00
it " can handle inline block bbcode " do
cooked = PrettyText . cook ( " [quote]te **s** t[/quote] " )
html = << ~ HTML
< aside class = " quote " >
< blockquote >
< p > te < strong > s < / strong> t< / p >
< / blockquote>
< / aside>
HTML
expect ( cooked ) . to eq ( html . strip )
end
2017-07-10 12:20:50 -04:00
it " can handle quote edge cases " do
2017-07-27 17:55:04 -04:00
expect ( PrettyText . cook ( " [quote]abc \n test \n [/quote] " ) ) . not_to include ( 'aside' )
expect ( PrettyText . cook ( " [quote] \n test \n [/quote] " ) ) . to include ( 'aside' )
2017-07-10 12:20:50 -04:00
expect ( PrettyText . cook ( " a \n [quote] \n test \n [/quote] \n \n \n a " ) ) . to include ( 'aside' )
expect ( PrettyText . cook ( " - a \n [quote] \n test \n [/quote] \n \n \n a " ) ) . to include ( 'aside' )
expect ( PrettyText . cook ( " [quote] \n test " ) ) . not_to include ( 'aside' )
expect ( PrettyText . cook ( " [quote] \n test \n [/quote]z " ) ) . not_to include ( 'aside' )
nested = << ~ QUOTE
[ quote ]
a
[ quote ]
b
[ / quote]
c
[ / quote]
QUOTE
cooked = PrettyText . cook ( nested )
expect ( cooked . scan ( 'aside' ) . length ) . to eq ( 4 )
expect ( cooked . scan ( 'quote]' ) . length ) . to eq ( 0 )
end
2017-06-23 17:12:06 -04:00
describe " with letter avatar " do
let ( :user ) { Fabricate ( :user ) }
2013-08-13 16:08:29 -04:00
2017-06-23 17:12:06 -04:00
context " subfolder " do
before do
GlobalSetting . stubs ( :relative_url_root ) . returns ( " /forum " )
Discourse . stubs ( :base_uri ) . returns ( " /forum " )
end
it " should have correct avatar url " do
2017-07-10 12:20:50 -04:00
md = << ~ MD
[ quote = " #{ user . username } , post:123, topic:456, full:true " ]
ddd
[ / quote]
MD
expect ( PrettyText . cook ( md ) ) . to include ( " /forum/letter_avatar_proxy " )
2017-06-23 17:12:06 -04:00
end
end
2013-08-13 16:08:29 -04:00
end
2017-07-10 12:20:50 -04:00
end
describe " Mentions " do
2013-02-05 14:16:51 -05:00
2013-02-25 11:42:20 -05:00
it " should handle 3 mentions in a row " do
2015-01-09 11:34:37 -05:00
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> "
2013-02-05 14:16:51 -05:00
end
2017-07-20 11:52:29 -04:00
it " can handle mention edge cases " do
expect ( PrettyText . cook ( " hi \n @s " ) ) . to eq ( " <p>hi<br> \n <span class= \" mention \" >@s</span></p> " )
expect ( PrettyText . cook ( " hi \n @ss " ) ) . to eq ( " <p>hi<br> \n <span class= \" mention \" >@ss</span></p> " )
expect ( PrettyText . cook ( " hi \n @s. " ) ) . to eq ( " <p>hi<br> \n <span class= \" mention \" >@s</span>.</p> " )
expect ( PrettyText . cook ( " hi \n @s.s " ) ) . to eq ( " <p>hi<br> \n <span class= \" mention \" >@s.s</span></p> " )
expect ( PrettyText . cook ( " hi \n @.s.s " ) ) . to eq ( " <p>hi<br> \n @.s.s</p> " )
end
it " can handle mention with hyperlinks " do
2017-07-10 12:20:50 -04:00
Fabricate ( :user , username : " sam " )
expect ( PrettyText . cook ( " hi @sam! hi " ) ) . to match_html '<p>hi <a class="mention" href="/u/sam">@sam</a>! hi</p>'
2017-07-20 11:52:29 -04:00
expect ( PrettyText . cook ( " hi \n @sam. " ) ) . to eq ( " <p>hi<br> \n <a class= \" mention \" href= \" /u/sam \" >@sam</a>.</p> " )
2017-07-10 12:20:50 -04:00
end
it " can handle mentions inside a hyperlink " do
expect ( PrettyText . cook ( " <a> @inner</a> " ) ) . to match_html '<p><a> @inner</a></p>'
2016-02-23 14:57:54 -05:00
end
2017-07-10 12:20:50 -04:00
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>'
end
it " can handle a list of mentions " do
expect ( PrettyText . cook ( " @a,@b " ) ) . to match_html ( '<p><span class="mention">@a</span>,<span class="mention">@b</span></p>' )
end
it " should handle group mentions with a hyphen and without " do
expect ( PrettyText . cook ( '@hello @hello-hello' ) ) . to match_html " <p><span class= \" mention \" >@hello</span> <span class= \" mention \" >@hello-hello</span></p> "
2013-02-05 14:16:51 -05:00
end
it 'should allow for @mentions to have punctuation' do
2015-01-09 11:34:37 -05:00
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> "
)
2013-02-05 14:16:51 -05:00
end
2017-07-17 16:21:47 -04:00
it 'should not treat a medium link as a mention' do
expect ( PrettyText . cook ( " . http://test/@sam " ) ) . not_to include ( 'mention' )
end
2013-02-05 14:16:51 -05:00
2017-07-10 12:20:50 -04:00
end
describe " code fences " do
it 'indents code correctly' do
code = << ~ MD
X
` ` `
#
x
` ` `
MD
cooked = PrettyText . cook ( code )
html = << ~ HTML
< p > X < / p>
< pre > < code class = " lang-auto " > #
x
< / code>< / pre >
HTML
expect ( cooked ) . to eq ( html . strip )
end
it " doesn't replace emoji in code blocks with our emoji sets if emoji is enabled " do
expect ( PrettyText . cook ( " ``` \n 💣` \n ``` \n " ) ) . not_to match ( / \ :bomb \ : / )
end
it 'can include code class correctly' do
2017-07-21 13:20:45 -04:00
# keep in mind spaces should be trimmed per spec
expect ( PrettyText . cook ( " ``` ruby the mooby \n ````` " ) ) . to eq ( '<pre><code class="lang-ruby"></code></pre>' )
2017-07-10 12:20:50 -04:00
expect ( PrettyText . cook ( " ```cpp \n cpp \n ``` " ) ) . to match_html ( " <pre><code class='lang-cpp'>cpp \n </code></pre> " )
expect ( PrettyText . cook ( " ``` \n cpp \n ``` " ) ) . to match_html ( " <pre><code class='lang-auto'>cpp \n </code></pre> " )
expect ( PrettyText . cook ( " ```text \n cpp \n ``` " ) ) . to match_html ( " <pre><code class='lang-nohighlight'>cpp \n </code></pre> " )
2017-07-21 13:20:45 -04:00
2017-07-10 12:20:50 -04:00
end
it 'indents code correctly' do
code = " X \n ``` \n \n # \n x \n ``` "
cooked = PrettyText . cook ( code )
expect ( cooked ) . to match_html ( " <p>X</p> \n <pre><code class= \" lang-auto \" > \n # \n x \n </code></pre> " )
2014-10-02 22:37:07 -04:00
end
2017-07-10 12:20:50 -04:00
it 'does censor code fences' do
2017-07-27 12:26:55 -04:00
begin
[ 'apple' , 'banana' ] . each { | w | Fabricate ( :watched_word , word : w , action : WatchedWord . actions [ :censor ] ) }
expect ( PrettyText . cook ( " # banana " ) ) . not_to include ( 'banana' )
ensure
$redis . flushall
end
2017-07-10 12:20:50 -04:00
end
2013-02-05 14:16:51 -05:00
end
2013-02-25 11:42:20 -05:00
2013-02-10 19:43:07 -05:00
describe " rel nofollow " do
2013-02-25 11:42:20 -05:00
before do
2017-07-07 02:09:14 -04:00
SiteSetting . add_rel_nofollow_to_user_content = true
SiteSetting . exclude_rel_nofollow_domains = " foo.com|bar.com "
2013-02-10 19:43:07 -05:00
end
2013-02-25 11:42:20 -05:00
it " should inject nofollow in all user provided links " do
2016-11-20 07:49:14 -05:00
expect ( PrettyText . cook ( '<a href="http://cnn.com">cnn</a>' ) ) . to match ( / nofollow noopener / )
2013-02-10 19:43:07 -05:00
end
2013-02-25 11:42:20 -05:00
it " should not inject nofollow in all local links " do
2015-01-09 11:34:37 -05:00
expect ( PrettyText . cook ( " <a href=' #{ Discourse . base_url } /test.html'>cnn</a> " ) !~ / nofollow / ) . to eq ( true )
2013-02-10 19:43:07 -05:00
end
2013-02-25 11:42:20 -05:00
it " should not inject nofollow in all subdomain links " do
2015-01-09 11:34:37 -05:00
expect ( PrettyText . cook ( " <a href=' #{ Discourse . base_url . sub ( 'http://' , 'http://bla.' ) } /test.html'>cnn</a> " ) !~ / nofollow / ) . to eq ( true )
2013-02-10 19:43:07 -05:00
end
2013-02-11 02:58:19 -05:00
2015-05-27 00:31:01 -04:00
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 / )
end
2013-02-11 02:58:19 -05:00
it " should not inject nofollow for foo.com " do
2015-01-09 11:34:37 -05:00
expect ( PrettyText . cook ( " <a href='http://foo.com/test.html'>cnn</a> " ) !~ / nofollow / ) . to eq ( true )
2013-02-11 02:58:19 -05:00
end
2015-05-27 00:31:01 -04:00
it " should inject nofollow for afoo.com " do
expect ( PrettyText . cook ( " <a href='http://afoo.com/test.html'>cnn</a> " ) ) . to match ( / nofollow / )
end
2013-02-25 11:42:20 -05:00
2013-02-11 02:58:19 -05:00
it " should not inject nofollow for bar.foo.com " do
2015-01-09 11:34:37 -05:00
expect ( PrettyText . cook ( " <a href='http://bar.foo.com/test.html'>cnn</a> " ) !~ / nofollow / ) . to eq ( true )
2013-02-11 02:58:19 -05:00
end
2014-01-15 11:34:17 -05:00
it " should not inject nofollow if omit_nofollow option is given " do
2015-01-09 11:34:37 -05:00
expect ( PrettyText . cook ( '<a href="http://cnn.com">cnn</a>' , omit_nofollow : true ) !~ / nofollow / ) . to eq ( true )
2014-01-15 11:34:17 -05:00
end
2013-02-10 19:43:07 -05:00
end
2013-02-05 14:16:51 -05:00
2013-02-25 11:42:20 -05:00
describe " Excerpt " do
2013-04-29 23:25:55 -04:00
2014-07-24 22:15:43 -04:00
it " sanitizes attempts to inject invalid attributes " do
spinner = " <a href= \" http://thedailywtf.com/ \" data-bbcode= \" ' class='fa fa-spin \" >WTF</a> "
2015-01-09 11:34:37 -05:00
expect ( PrettyText . excerpt ( spinner , 20 ) ) . to match_html spinner
2014-07-24 22:15:43 -04:00
spinner = %q{ <a href="http://thedailywtf.com/" title="' class="fa fa-spin"><img src='http://thedailywtf.com/Resources/Images/Primary/logo.gif"></a> }
2015-01-09 11:34:37 -05:00
expect ( PrettyText . excerpt ( spinner , 20 ) ) . to match_html spinner
2014-07-24 22:15:43 -04:00
end
2013-06-05 18:54:46 -04:00
context " images " do
2014-07-17 01:40:19 -04:00
2013-06-05 18:54:46 -04:00
it " should dump images " do
2017-07-27 21:20:09 -04:00
expect ( PrettyText . excerpt ( " <img src='http://cnn.com/a.gif'> " , 100 ) ) . to eq ( " [image] " )
2013-06-05 18:54:46 -04:00
end
2013-04-29 23:25:55 -04:00
2017-04-11 00:12:51 -04:00
context 'alt tags' do
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
describe 'when alt tag is empty' do
it " should not keep alt tags " do
expect ( PrettyText . excerpt ( " <img src='http://cnn.com/a.gif' alt> " , 100 ) ) . to eq ( " [ #{ I18n . t ( 'excerpt_image' ) } ] " )
end
end
2013-06-05 18:54:46 -04:00
end
2017-04-11 00:12:51 -04:00
context 'title tags' do
it " should keep title tags " do
expect ( PrettyText . excerpt ( " <img src='http://cnn.com/a.gif' title='car'> " , 100 ) ) . to eq ( " [car] " )
end
describe 'when title tag is empty' do
it " should not keep title tags " do
expect ( PrettyText . excerpt ( " <img src='http://cnn.com/a.gif' title> " , 100 ) ) . to eq ( " [ #{ I18n . t ( 'excerpt_image' ) } ] " )
end
end
2013-06-05 18:54:46 -04:00
end
it " should convert images to markdown if the option is set " do
2015-01-09 11:34:37 -05:00
expect ( PrettyText . excerpt ( " <img src='http://cnn.com/a.gif' title='car'> " , 100 , markdown_images : true ) ) . to eq ( " ![car](http://cnn.com/a.gif) " )
2013-06-05 18:54:46 -04:00
end
2013-02-05 14:16:51 -05:00
2014-02-20 03:48:30 -05:00
it " should keep spoilers " do
2015-01-09 11:34:37 -05:00
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> "
2014-02-20 03:48:30 -05:00
end
2014-11-05 14:37:00 -05:00
it " should remove meta informations " do
2015-01-09 11:34:37 -05:00
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> "
2014-11-05 14:37:00 -05:00
end
2013-02-05 14:16:51 -05:00
end
2013-02-25 11:42:20 -05:00
2013-06-05 18:54:46 -04:00
it " should have an option to strip links " do
2017-07-27 21:20:09 -04:00
expect ( PrettyText . excerpt ( " <a href='http://cnn.com'>cnn</a> " , 100 , strip_links : true ) ) . to eq ( " cnn " )
2013-02-05 14:16:51 -05:00
end
2013-02-25 11:42:20 -05:00
2013-06-05 18:54:46 -04:00
it " should preserve links " do
2017-07-27 21:20:09 -04:00
expect ( PrettyText . excerpt ( " <a href='http://cnn.com'>cnn</a> " , 100 ) ) . to match_html " <a href='http://cnn.com'>cnn</a> "
2013-02-05 14:16:51 -05:00
end
2013-02-25 11:42:20 -05:00
it " should deal with special keys properly " do
2017-07-27 21:20:09 -04:00
expect ( PrettyText . excerpt ( " <pre><b></pre> " , 100 ) ) . to eq ( " " )
2013-02-05 14:16:51 -05:00
end
2013-02-25 11:42:20 -05:00
it " should truncate stuff properly " do
2017-07-27 21:20:09 -04:00
expect ( PrettyText . excerpt ( " hello world " , 5 ) ) . to eq ( " hello… " )
expect ( PrettyText . excerpt ( " <p>hello</p><p>world</p> " , 6 ) ) . to eq ( " hello w… " )
2013-02-05 14:16:51 -05:00
end
2013-02-25 11:42:20 -05:00
it " should insert a space between to Ps " do
2017-07-27 21:20:09 -04:00
expect ( PrettyText . excerpt ( " <p>a</p><p>b</p> " , 5 ) ) . to eq ( " a b " )
2013-02-05 14:16:51 -05:00
end
2013-02-25 11:42:20 -05:00
it " should strip quotes " do
2017-07-27 21:20:09 -04:00
expect ( PrettyText . excerpt ( " <aside class='quote'><p>a</p><p>b</p></aside>boom " , 5 ) ) . to eq ( " boom " )
2013-02-05 14:16:51 -05:00
end
2013-02-25 11:42:20 -05:00
it " should not count the surrounds of a link " do
2017-07-27 21:20:09 -04:00
expect ( PrettyText . excerpt ( " <a href='http://cnn.com'>cnn</a> " , 3 ) ) . to match_html " <a href='http://cnn.com'>cnn</a> "
2013-02-05 14:16:51 -05:00
end
2013-06-03 16:12:24 -04:00
it " uses an ellipsis instead of html entities if provided with the option " do
2015-01-09 11:34:37 -05:00
expect ( PrettyText . excerpt ( " <a href='http://cnn.com'>cnn</a> " , 2 , text_entities : true ) ) . to match_html " <a href='http://cnn.com'>cn...</a> "
2013-06-03 16:12:24 -04:00
end
2013-02-25 11:42:20 -05:00
it " should truncate links " do
2017-07-27 21:20:09 -04:00
expect ( PrettyText . excerpt ( " <a href='http://cnn.com'>cnn</a> " , 2 ) ) . to match_html " <a href='http://cnn.com'>cn…</a> "
2013-02-05 14:16:51 -05:00
end
2014-05-20 17:20:52 -04:00
it " doesn't extract empty quotes as links " do
2015-01-09 11:34:37 -05:00
expect ( PrettyText . extract_links ( " <aside class='quote'>not a linked quote</aside> \n " ) . to_a ) . to be_empty
2014-05-20 17:20:52 -04:00
end
2016-03-16 17:35:08 -04:00
it " doesn't extract links from elided parts " do
expect ( PrettyText . extract_links ( " <details class='elided'><a href='http://cnn.com'>cnn</a></details> \n " ) . to_a ) . to be_empty
end
2014-07-11 00:17:01 -04:00
def extract_urls ( text )
PrettyText . extract_links ( text ) . map ( & :url ) . to_a
end
2013-02-25 11:42:20 -05:00
it " should be able to extract links " do
2015-01-09 11:34:37 -05:00
expect ( extract_urls ( " <a href='http://cnn.com'>http://bla.com</a> " ) ) . to eq ( [ " http://cnn.com " ] )
2013-02-05 14:16:51 -05:00
end
2013-02-13 15:22:04 -05:00
it " should extract links to topics " do
2015-01-09 11:34:37 -05:00
expect ( extract_urls ( " <aside class= \" quote \" data-topic= \" 321 \" >aside</aside> " ) ) . to eq ( [ " /t/topic/321 " ] )
2013-02-13 15:22:04 -05:00
end
2016-09-22 16:50:05 -04:00
it " should lazyYT videos " do
expect ( extract_urls ( " <div class= \" lazyYT \" data-youtube-id= \" yXEuEUQIP3Q \" data-youtube-title= \" Mister Rogers defending PBS to the US Senate \" data-width= \" 480 \" data-height= \" 270 \" data-parameters= \" feature=oembed&wmode=opaque \" ></div> " ) ) . to eq ( [ " https://www.youtube.com/watch?v=yXEuEUQIP3Q " ] )
end
2013-02-13 15:22:04 -05:00
it " should extract links to posts " do
2015-01-09 11:34:37 -05:00
expect ( extract_urls ( " <aside class= \" quote \" data-topic= \" 1234 \" data-post= \" 4567 \" >aside</aside> " ) ) . to eq ( [ " /t/topic/1234/4567 " ] )
2013-02-13 15:22:04 -05:00
end
2016-04-15 14:02:18 -04:00
it " should not extract links to anchors " do
expect ( extract_urls ( " <a href=' # tos'>TOS</a> " ) ) . to eq ( [ ] )
end
2013-06-05 14:53:07 -04:00
it " should not extract links inside quotes " do
2014-07-11 00:17:01 -04:00
links = PrettyText . extract_links ( "
2013-06-05 14:53:07 -04:00
< a href = 'http://body_only.com' > http : / /use less1 . com < / a>
< aside class = \ " quote \" data-topic= \" 1234 \" >
< a href = 'http://body_and_quote.com' > http : / /use less3 . com < / a>
< a href = 'http://quote_only.com' > http : / /use less4 . com < / a>
< / aside>
< a href = 'http://body_and_quote.com' > http : / /use less2 . com < / a>
2014-07-11 00:17:01 -04:00
" )
2017-02-06 08:45:04 -05:00
expect ( links . map { | l | [ l . url , l . is_quote ] } . sort ) . to eq ( [
[ " http://body_only.com " , false ] ,
[ " http://body_and_quote.com " , false ] ,
[ " /t/topic/1234 " , true ] ,
] . sort )
2013-06-05 14:53:07 -04:00
end
2013-02-25 11:42:20 -05:00
it " should not preserve tags in code blocks " do
2017-07-27 21:20:09 -04:00
expect ( PrettyText . excerpt ( " <pre><code class='handlebars'><h3>Hours</h3></code></pre> " , 100 ) ) . to eq ( " <h3>Hours</h3> " )
2013-02-05 14:16:51 -05:00
end
it " should handle nil " do
2017-07-27 21:20:09 -04:00
expect ( PrettyText . excerpt ( nil , 100 ) ) . to eq ( '' )
2013-02-05 14:16:51 -05:00
end
2013-05-10 06:28:17 -04:00
2014-09-03 03:12:56 -04:00
it " handles span excerpt at the beginning of a post " do
2017-07-27 21:20:09 -04:00
expect ( PrettyText . excerpt ( " <span class='excerpt'>hi</span> test " , 100 ) ) . to eq ( 'hi' )
2014-07-17 07:32:17 -04:00
post = Fabricate ( :post , raw : " <span class='excerpt'>hi</span> test " )
2015-01-09 11:34:37 -05:00
expect ( post . excerpt ) . to eq ( " hi " )
2014-07-17 07:32:17 -04:00
end
2014-09-04 01:03:12 -04:00
it " ignores max excerpt length if a span excerpt is specified " do
two_hundred = " 123456789 " * 20 + " . "
2017-07-27 21:20:09 -04:00
text = two_hundred + " <span class='excerpt'> #{ two_hundred } </span> " + two_hundred
2015-01-09 11:34:37 -05:00
expect ( PrettyText . excerpt ( text , 100 ) ) . to eq ( two_hundred )
2014-09-03 03:12:56 -04:00
post = Fabricate ( :post , raw : text )
2015-01-09 11:34:37 -05:00
expect ( post . excerpt ) . to eq ( two_hundred )
2014-09-03 03:12:56 -04:00
end
2014-12-10 06:52:51 -05:00
it " unescapes html entities when we want text entities " do
2015-01-09 11:34:37 -05:00
expect ( PrettyText . excerpt ( " & # 39; " , 500 , text_entities : true ) ) . to eq ( " ' " )
2014-12-10 06:52:51 -05:00
end
2015-12-14 08:46:15 -05:00
it " should have an option to preserve emoji images " do
2017-06-26 16:50:46 -04:00
emoji_image = " <img src='/images/emoji/twitter/heart.png?v=1' title=':heart:' class='emoji' alt='heart'> "
2017-07-27 21:20:09 -04:00
expect ( PrettyText . excerpt ( emoji_image , 100 , keep_emoji_images : true ) ) . to match_html ( emoji_image )
2015-12-14 08:46:15 -05:00
end
2016-10-10 22:03:21 -04:00
it " should have an option to remap emoji to code points " do
2017-06-26 16:50:46 -04:00
emoji_image = " I <img src='/images/emoji/twitter/heart.png?v=1' title=':heart:' class='emoji' alt=':heart:'> you <img src='/images/emoji/twitter/heart.png?v=1' title=':unknown:' class='emoji' alt=':unknown:'> "
2017-07-27 21:20:09 -04:00
expect ( PrettyText . excerpt ( emoji_image , 100 , remap_emoji : true ) ) . to match_html ( " I ❤ you :unknown: " )
2016-10-10 22:03:21 -04:00
end
2015-12-14 08:46:15 -05:00
it " should have an option to preserve emoji codes " do
2017-06-26 16:50:46 -04:00
emoji_code = " <img src='/images/emoji/twitter/heart.png?v=1' title=':heart:' class='emoji' alt=':heart:'> "
2016-06-01 22:29:25 -04:00
expect ( PrettyText . excerpt ( emoji_code , 100 ) ) . to eq ( " :heart: " )
2015-07-23 11:02:03 -04:00
end
2017-06-27 15:34:16 -04:00
context 'option to preserve onebox source' do
2017-04-11 03:13:21 -04:00
it " should return the right excerpt " do
onebox = " <aside class= \" onebox whitelistedgeneric \" > \n <header class= \" source \" > \n <a href= \" https://meta.discourse.org/t/infrequent-translation-updates-in-stable-branch/31213/9 \" >meta.discourse.org</a> \n </header> \n <article class= \" onebox-body \" > \n <img src= \" https://cdn-enterprise.discourse.org/meta/user_avatar/meta.discourse.org/gerhard/200/70381_1.png \" width= \" \" height= \" \" class= \" thumbnail \" > \n \n <h3><a href= \" https://meta.discourse.org/t/infrequent-translation-updates-in-stable-branch/31213/9 \" >Infrequent translation updates in stable branch</a></h3> \n \n <p>Well, there's an Italian translation for \" New Topic \" in beta, it's been there since November 2014 and it works here on meta. Do you have any plugins installed? Try disabling them. I'm quite confident that it's either a plugin or a site...</p> \n \n </article> \n <div class= \" onebox-metadata \" > \n \n \n </div> \n <div style= \" clear: both \" ></div> \n </aside> \n \n \n "
expected = " <a href= \" https://meta.discourse.org/t/infrequent-translation-updates-in-stable-branch/31213/9 \" >meta.discourse.org</a> "
2017-04-10 04:11:58 -04:00
2017-04-11 03:13:21 -04:00
expect ( PrettyText . excerpt ( onebox , 100 , keep_onebox_source : true ) )
. to eq ( expected )
2017-04-10 04:11:58 -04:00
2017-04-11 03:13:21 -04:00
expect ( PrettyText . excerpt ( " #{ onebox } \n \n \n \n \n \n #{ onebox } " , 100 , keep_onebox_source : true ) )
. to eq ( " #{ expected } \n \n #{ expected } " )
end
it 'should continue to strip quotes' do
expect ( PrettyText . excerpt (
" <aside class='quote'><p>a</p><p>b</p></aside>boom " , 100 , keep_onebox_source : true
) ) . to eq ( " boom " )
end
2017-04-10 04:11:58 -04:00
end
2013-02-05 14:16:51 -05:00
end
2013-06-05 15:28:10 -04:00
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
2014-09-17 12:08:00 -04:00
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
2013-06-05 15:28:10 -04:00
end
2013-02-10 19:43:07 -05:00
2016-05-21 09:17:54 -04:00
describe " strip_image_wrapping " do
def strip_image_wrapping ( html )
2014-04-17 12:32:51 -04:00
doc = Nokogiri :: HTML . fragment ( html )
2016-05-21 09:17:54 -04:00
described_class . strip_image_wrapping ( doc )
2014-04-17 12:32:51 -04:00
doc . to_html
end
2016-05-21 09:17:54 -04:00
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
let ( :base_url ) { " http://baseurl.net " }
let ( :post ) { Fabricate ( :post ) }
2013-11-28 15:57:21 -05:00
before do
Discourse . stubs ( :base_url ) . returns ( base_url )
end
2016-05-21 09:17:54 -04:00
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>' , post )
end
2013-11-28 15:57:21 -05:00
it " adds base url to relative links " do
2017-03-28 14:27:54 -04:00
html = " <p><a class= \" mention \" href= \" /u/wiseguy \" >@wiseguy</a>, <a class= \" mention \" href= \" /u/trollol \" >@trollol</a> what do you guys think? </p> "
2016-05-21 09:17:54 -04:00
output = described_class . format_for_email ( html , post )
2017-03-28 14:27:54 -04:00
expect ( output ) . to eq ( " <p><a class= \" mention \" href= \" #{ base_url } /u/wiseguy \" >@wiseguy</a>, <a class= \" mention \" href= \" #{ base_url } /u/trollol \" >@trollol</a> what do you guys think? </p> " )
2013-11-28 15:57:21 -05:00
end
it " doesn't change external absolute links " do
html = " <p>Check out <a href= \" http://mywebsite.com/users/boss \" >this guy</a>.</p> "
2016-05-21 09:17:54 -04:00
expect ( described_class . format_for_email ( html , post ) ) . to eq ( html )
2013-11-28 15:57:21 -05:00
end
it " doesn't change internal absolute links " do
html = " <p>Check out <a href= \" #{ base_url } /users/boss \" >this guy</a>.</p> "
2016-05-21 09:17:54 -04:00
expect ( described_class . format_for_email ( html , post ) ) . to eq ( html )
2013-11-28 15:57:21 -05:00
end
it " can tolerate invalid URLs " do
html = " <p>Check out <a href= \" not a real url \" >this guy</a>.</p> "
2016-05-21 09:17:54 -04:00
expect { described_class . format_for_email ( html , post ) } . to_not raise_error
2014-07-30 03:09:55 -04:00
end
end
2017-07-10 12:20:50 -04:00
it 'Is smart about linebreaks and IMG tags' do
raw = << ~ MD
a < img >
< img >
< img >
< img >
< img >
a
< img >
- li
< img >
` ` `
test
` ` `
` ` `
test
` ` `
MD
html = << ~ HTML
< p > a < img > < br >
< img > < / p>
2017-07-17 17:25:40 -04:00
< p > < img > < br >
2017-07-10 12:20:50 -04:00
< img > < / p>
2017-07-17 17:25:40 -04:00
< p > < img > < / p>
2017-07-10 12:20:50 -04:00
< p > a < / p>
2017-07-17 17:25:40 -04:00
< p > < img > < / p>
2017-07-10 12:20:50 -04:00
< ul >
< li > li < / li>
< / ul>
2017-07-17 17:25:40 -04:00
< p > < img > < / p>
2017-07-10 12:20:50 -04:00
< pre > < code class = " lang-auto " > test
< / code>< / pre >
< pre > < code class = " lang-auto " > test
< / code>< / pre >
HTML
expect ( PrettyText . cook ( raw ) ) . to eq ( html . strip )
2015-03-13 01:15:13 -04:00
end
2015-05-25 21:13:12 -04:00
it 'can substitute s3 cdn correctly' do
SiteSetting . enable_s3_uploads = true
SiteSetting . s3_access_key_id = " XXX "
SiteSetting . s3_secret_access_key = " XXX "
SiteSetting . s3_upload_bucket = " test "
SiteSetting . s3_cdn_url = " https://awesome.cdn "
2015-06-10 04:56:44 -04:00
# add extra img tag to ensure it does not blow up
2017-07-10 12:20:50 -04:00
raw = << ~ HTML
< img >
< img src = 'https:#{Discourse.store.absolute_base_url}/original/9/9/99c9384b8b6d87f8509f8395571bc7512ca3cad1.jpg' >
< img src = 'http:#{Discourse.store.absolute_base_url}/original/9/9/99c9384b8b6d87f8509f8395571bc7512ca3cad1.jpg' >
< img src = '#{Discourse.store.absolute_base_url}/original/9/9/99c9384b8b6d87f8509f8395571bc7512ca3cad1.jpg' >
HTML
html = << ~ HTML
2017-07-17 17:25:40 -04:00
< p > < img > < br >
2017-07-10 12:20:50 -04:00
< img src = " https://awesome.cdn/original/9/9/99c9384b8b6d87f8509f8395571bc7512ca3cad1.jpg " > < br >
< img src = " https://awesome.cdn/original/9/9/99c9384b8b6d87f8509f8395571bc7512ca3cad1.jpg " > < br >
< img src = " https://awesome.cdn/original/9/9/99c9384b8b6d87f8509f8395571bc7512ca3cad1.jpg " > < / p>
HTML
expect ( PrettyText . cook ( raw ) ) . to eq ( html . strip )
2015-05-25 21:13:12 -04:00
end
2015-12-29 16:27:56 -05:00
describe " emoji " do
it " replaces unicode emoji with our emoji sets if emoji is enabled " do
expect ( PrettyText . cook ( " 💣 " ) ) . to match ( / \ :bomb \ : / )
end
2015-07-20 02:56:32 -04:00
2016-03-02 14:31:32 -05:00
it " doesn't replace emoji in inline code blocks with our emoji sets if emoji is enabled " do
expect ( PrettyText . cook ( " `💣` " ) ) . not_to match ( / \ :bomb \ : / )
end
2015-12-30 14:46:52 -05:00
it " replaces some glyphs that are not in the emoji range " do
2016-03-04 14:20:44 -05:00
expect ( PrettyText . cook ( " ☺ " ) ) . to match ( / \ :slight_smile \ : / )
2015-12-30 14:46:52 -05:00
end
2015-12-29 16:27:56 -05:00
it " doesn't replace unicode emoji if emoji is disabled " do
2015-12-14 08:46:15 -05:00
SiteSetting . enable_emoji = false
2015-12-29 16:27:56 -05:00
expect ( PrettyText . cook ( " 💣 " ) ) . not_to match ( / \ :bomb \ : / )
end
2017-06-14 09:35:37 -04:00
it " replaces skin toned emoji " do
2017-06-26 16:50:46 -04:00
expect ( PrettyText . cook ( " hello 👱🏿♀️ " ) ) . to eq ( " <p>hello <img src= \" /images/emoji/twitter/blonde_woman/6.png?v=5 \" title= \" :blonde_woman:t6: \" class= \" emoji \" alt= \" :blonde_woman:t6: \" ></p> " )
expect ( PrettyText . cook ( " hello 👩🎤 " ) ) . to eq ( " <p>hello <img src= \" /images/emoji/twitter/woman_singer.png?v=5 \" title= \" :woman_singer: \" class= \" emoji \" alt= \" :woman_singer: \" ></p> " )
expect ( PrettyText . cook ( " hello 👩🏾🎓 " ) ) . to eq ( " <p>hello <img src= \" /images/emoji/twitter/woman_student/5.png?v=5 \" title= \" :woman_student:t5: \" class= \" emoji \" alt= \" :woman_student:t5: \" ></p> " )
expect ( PrettyText . cook ( " hello 🤷♀️ " ) ) . to eq ( " <p>hello <img src= \" /images/emoji/twitter/woman_shrugging.png?v=5 \" title= \" :woman_shrugging: \" class= \" emoji \" alt= \" :woman_shrugging: \" ></p> " )
2017-06-14 09:35:37 -04:00
end
2015-07-20 02:56:32 -04:00
end
2016-06-14 14:31:51 -04:00
describe " custom emoji " do
it " replaces the custom emoji " do
2017-02-02 04:41:57 -05:00
CustomEmoji . create! ( name : 'trout' , upload : Fabricate ( :upload ) )
2017-03-14 02:58:22 -04:00
Emoji . clear_cache
2017-04-10 04:11:58 -04:00
2016-06-14 14:31:51 -04:00
expect ( PrettyText . cook ( " hello :trout: " ) ) . to match ( / <img src[^>]+trout[^>]+> / )
end
2016-05-01 21:36:09 -04:00
end
2016-11-08 16:36:34 -05:00
describe " censored_pattern site setting " do
it " can be cleared if it causes cooking to timeout " do
SiteSetting . censored_pattern = " evilregex "
described_class . stubs ( :markdown ) . raises ( MiniRacer :: ScriptTerminatedError )
PrettyText . cook ( " Protect against it plz. " ) rescue nil
expect ( SiteSetting . censored_pattern ) . to be_blank
end
end
2017-07-10 12:20:50 -04:00
it " replaces skin toned emoji " do
expect ( PrettyText . cook ( " hello 👱🏿♀️ " ) ) . to eq ( " <p>hello <img src= \" /images/emoji/twitter/blonde_woman/6.png?v=5 \" title= \" :blonde_woman:t6: \" class= \" emoji \" alt= \" :blonde_woman:t6: \" ></p> " )
expect ( PrettyText . cook ( " hello 👩🎤 " ) ) . to eq ( " <p>hello <img src= \" /images/emoji/twitter/woman_singer.png?v=5 \" title= \" :woman_singer: \" class= \" emoji \" alt= \" :woman_singer: \" ></p> " )
expect ( PrettyText . cook ( " hello 👩🏾🎓 " ) ) . to eq ( " <p>hello <img src= \" /images/emoji/twitter/woman_student/5.png?v=5 \" title= \" :woman_student:t5: \" class= \" emoji \" alt= \" :woman_student:t5: \" ></p> " )
expect ( PrettyText . cook ( " hello 🤷♀️ " ) ) . to eq ( " <p>hello <img src= \" /images/emoji/twitter/woman_shrugging.png?v=5 \" title= \" :woman_shrugging: \" class= \" emoji \" alt= \" :woman_shrugging: \" ></p> " )
end
2017-06-29 12:48:04 -04:00
2017-07-17 17:25:40 -04:00
it " should not treat a non emoji as an emoji " do
expect ( PrettyText . cook ( ':email,class_name:' ) ) . not_to include ( 'emoji' )
end
2017-06-29 12:48:04 -04:00
2017-07-10 12:20:50 -04:00
it " supports href schemes " do
SiteSetting . allowed_href_schemes = " macappstore|steam "
cooked = cook ( " [Steam URL Scheme](steam://store/452530) " )
expected = '<p><a href="steam://store/452530" rel="nofollow noopener">Steam URL Scheme</a></p>'
expect ( cooked ) . to eq ( n expected )
end
2017-06-29 12:48:04 -04:00
2017-07-10 12:20:50 -04:00
it " supports forbidden schemes " do
SiteSetting . allowed_href_schemes = " macappstore|itunes "
cooked = cook ( " [Steam URL Scheme](steam://store/452530) " )
expected = '<p><a>Steam URL Scheme</a></p>'
expect ( cooked ) . to eq ( n expected )
end
2017-06-29 12:48:04 -04:00
2017-07-10 12:20:50 -04:00
it " produces tag links " do
2017-07-27 21:20:09 -04:00
Fabricate ( :topic , tags : [ Fabricate ( :tag , name : 'known' ) ] )
2017-06-29 12:48:04 -04:00
2017-07-10 12:20:50 -04:00
cooked = PrettyText . cook ( " # unknown::tag # known::tag " )
2017-06-29 12:48:04 -04:00
2017-07-10 12:20:50 -04:00
html = << ~ HTML
< p > < span class = \ " hashtag \" > # unknown::tag</span> <a class= \" hashtag \" href= \" http://test.localhost/tags/known \" > # <span>known</span></a></p>
HTML
2017-06-29 12:48:04 -04:00
2017-07-10 12:20:50 -04:00
expect ( cooked ) . to eq ( html . strip )
2017-06-29 12:48:04 -04:00
2017-07-10 12:20:50 -04:00
cooked = PrettyText . cook ( " [`a` # known::tag here](http://somesite.com) " )
2017-06-29 12:48:04 -04:00
2017-07-10 12:20:50 -04:00
html = << ~ HTML
< p > < a href = " http://somesite.com " rel = " nofollow noopener " > < code > a < / code> # known::tag here< / a > < / p>
HTML
2017-06-29 12:48:04 -04:00
2017-07-10 12:20:50 -04:00
expect ( cooked ) . to eq ( html . strip )
2017-07-07 13:03:36 -04:00
2017-07-10 12:20:50 -04:00
cooked = PrettyText . cook ( " <a href='http://somesite.com'>`a` # known::tag here</a> " )
2017-07-07 13:03:36 -04:00
2017-07-10 12:20:50 -04:00
expect ( cooked ) . to eq ( html . strip )
2017-06-08 18:02:30 -04:00
2017-07-10 12:20:50 -04:00
cooked = PrettyText . cook ( " <A href='/a'>test</A> # known::tag " )
html = << ~ HTML
< p > < a href = " /a " > test < / a> <a class="hashtag" href="http: / / test . localhost / tags / known " > # <span>known</span></a></p>
HTML
2017-06-08 18:02:30 -04:00
2017-07-10 12:20:50 -04:00
expect ( cooked ) . to eq ( html . strip )
2017-06-08 18:02:30 -04:00
2017-07-10 12:20:50 -04:00
# ensure it does not fight with the autolinker
expect ( PrettyText . cook ( ' http://somewhere.com/#known' ) ) . not_to include ( 'hashtag' )
expect ( PrettyText . cook ( ' http://somewhere.com/?#known' ) ) . not_to include ( 'hashtag' )
expect ( PrettyText . cook ( ' http://somewhere.com/?abc#known' ) ) . not_to include ( 'hashtag' )
2017-06-08 18:02:30 -04:00
2017-07-10 12:20:50 -04:00
end
2017-06-08 18:02:30 -04:00
2017-07-10 12:20:50 -04:00
it " can handle mixed lists " do
# known bug in old md engine
cooked = PrettyText . cook ( " * a \n \n 1. b " )
expect ( cooked ) . to match_html ( " <ul> \n <li>a</li> \n </ul><ol> \n <li>b</li> \n </ol> " )
end
2017-06-08 18:02:30 -04:00
2017-07-10 12:20:50 -04:00
it " can handle traditional vs non traditional newlines " do
SiteSetting . traditional_markdown_linebreaks = true
expect ( PrettyText . cook ( " 1 \n 2 " ) ) . to match_html " <p>1 2</p> "
2017-07-07 11:06:50 -04:00
2017-07-10 12:20:50 -04:00
SiteSetting . traditional_markdown_linebreaks = false
expect ( PrettyText . cook ( " 1 \n 2 " ) ) . to match_html " <p>1<br> \n 2</p> "
end
2017-06-08 18:02:30 -04:00
2017-07-10 12:20:50 -04:00
it " can handle emoji by name " do
2017-06-08 18:02:30 -04:00
2017-07-10 12:20:50 -04:00
expected = <<HTML
2017-06-26 16:50:46 -04:00
< p > < img src = " /images/emoji/twitter/smile.png?v=5 \" title= " :smile :" class= " emoji " alt= " :smile :" ><img src= " / images / emoji / twitter / sunny . png? v = 5 " title= " :sunny :" class= " emoji " alt= " :sunny :" ></p>
2017-06-08 18:02:30 -04:00
HTML
2017-07-10 12:20:50 -04:00
expect ( PrettyText . cook ( " :smile::sunny: " ) ) . to eq ( expected . strip )
end
2017-07-07 11:06:50 -04:00
2017-07-10 12:20:50 -04:00
it " handles emoji boundaries correctly " do
cooked = PrettyText . cook ( " a,:man:t2:,b " )
expected = '<p>a,<img src="/images/emoji/twitter/man/2.png?v=5" title=":man:t2:" class="emoji" alt=":man:t2:">,b</p>'
expect ( cooked ) . to match ( expected . strip )
end
2017-06-27 16:50:13 -04:00
2017-07-10 12:20:50 -04:00
it " can handle emoji by translation " do
expected = '<p><img src="/images/emoji/twitter/wink.png?v=5" title=":wink:" class="emoji" alt=":wink:"></p>'
expect ( PrettyText . cook ( " ;) " ) ) . to eq ( expected )
end
2017-06-08 18:02:30 -04:00
2017-07-10 12:20:50 -04:00
it " can handle multiple emojis by translation " do
cooked = PrettyText . cook ( " :) ;) :) " )
2017-07-27 21:20:09 -04:00
expect ( cooked . split ( " img " ) . length - 1 ) . to eq ( 3 )
2017-07-10 12:20:50 -04:00
end
2017-06-08 18:02:30 -04:00
2017-07-10 12:20:50 -04:00
it " handles emoji boundries correctly " do
expect ( PrettyText . cook ( " ,:) " ) ) . to include ( " emoji " )
expect ( PrettyText . cook ( " :-) \n " ) ) . to include ( " emoji " )
expect ( PrettyText . cook ( " a :) " ) ) . to include ( " emoji " )
expect ( PrettyText . cook ( " :), " ) ) . not_to include ( " emoji " )
expect ( PrettyText . cook ( " abcde ^:;-P " ) ) . to include ( " emoji " )
end
2017-06-27 10:06:55 -04:00
2017-07-10 12:20:50 -04:00
it 'can censor words correctly' do
2017-07-27 12:26:55 -04:00
begin
[ 'apple' , 'banana' ] . each { | w | Fabricate ( :watched_word , word : w , action : WatchedWord . actions [ :censor ] ) }
expect ( PrettyText . cook ( 'yay banana yay' ) ) . not_to include ( 'banana' )
expect ( PrettyText . cook ( 'yay `banana` yay' ) ) . not_to include ( 'banana' )
expect ( PrettyText . cook ( " # banana " ) ) . not_to include ( 'banana' )
expect ( PrettyText . cook ( " # banana " ) ) . to include ( " \ u25a0 \ u25a0 " )
ensure
$redis . flushall
end
2017-07-10 12:20:50 -04:00
end
2017-06-27 10:06:55 -04:00
2017-07-10 12:20:50 -04:00
it 'supports typographer' do
SiteSetting . enable_markdown_typographer = true
expect ( PrettyText . cook ( '(tm)' ) ) . to eq ( '<p>™</p>' )
2017-06-26 16:50:46 -04:00
2017-07-10 12:20:50 -04:00
SiteSetting . enable_markdown_typographer = false
expect ( PrettyText . cook ( '(tm)' ) ) . to eq ( '<p>(tm)</p>' )
end
2017-06-27 10:57:29 -04:00
2017-07-10 12:20:50 -04:00
it 'handles onebox correctly' do
expect ( PrettyText . cook ( " http://a.com \n http://b.com " ) . split ( " onebox " ) . length ) . to eq ( 3 )
expect ( PrettyText . cook ( " http://a.com \n \n http://b.com " ) . split ( " onebox " ) . length ) . to eq ( 3 )
expect ( PrettyText . cook ( " a \n http://a.com " ) ) . to include ( 'onebox' )
expect ( PrettyText . cook ( " > http://a.com " ) ) . not_to include ( 'onebox' )
expect ( PrettyText . cook ( " a \n http://a.com a " ) ) . not_to include ( 'onebox' )
expect ( PrettyText . cook ( " a \n http://a.com \n a " ) ) . to include ( 'onebox' )
expect ( PrettyText . cook ( " http://a.com " ) ) . to include ( 'onebox' )
expect ( PrettyText . cook ( " http://a.com " ) ) . to include ( 'onebox' )
expect ( PrettyText . cook ( " http://a.com a " ) ) . not_to include ( 'onebox' )
expect ( PrettyText . cook ( " - http://a.com " ) ) . not_to include ( 'onebox' )
expect ( PrettyText . cook ( " <http://a.com> " ) ) . not_to include ( 'onebox' )
expect ( PrettyText . cook ( " http://a.com " ) ) . not_to include ( 'onebox' )
expect ( PrettyText . cook ( " a \n http://a.com " ) ) . not_to include ( 'onebox' )
2017-07-14 08:27:28 -04:00
expect ( PrettyText . cook ( " sam@sam.com " ) ) . not_to include ( 'onebox' )
2017-07-17 17:25:40 -04:00
expect ( PrettyText . cook ( " <img src='a'> \n http://a.com " ) ) . to include ( 'onebox' )
2017-07-10 12:20:50 -04:00
end
2017-06-27 10:57:29 -04:00
2017-08-02 16:10:08 -04:00
it 'handles mini onebox' do
SiteSetting . enable_inline_onebox_on_all_domains = true
2017-08-02 17:27:41 -04:00
InlineOneboxer . purge ( " http://cnn.com/a " )
2017-08-02 16:10:08 -04:00
2017-08-02 17:27:41 -04:00
stub_request ( :head , " http://cnn.com/a " ) . to_return ( status : 200 )
2017-08-02 16:10:08 -04:00
2017-08-02 17:27:41 -04:00
stub_request ( :get , " http://cnn.com/a " ) .
2017-08-02 16:10:08 -04:00
to_return ( status : 200 , body : " <html><head><title>news</title></head></html> " , headers : { } )
2017-08-02 17:27:41 -04:00
expect ( PrettyText . cook ( " - http://cnn.com/a \n - a http://cnn.com/a " ) . split ( " news " ) . length ) . to eq ( 3 )
expect ( PrettyText . cook ( " - http://cnn.com/a \n - a http://cnn.com/a " ) . split ( " news " ) . length ) . to eq ( 3 )
end
it 'handles mini onebox with query param' do
SiteSetting . enable_inline_onebox_on_all_domains = true
InlineOneboxer . purge ( " http://cnn.com?a " )
stub_request ( :head , " http://cnn.com?a " ) . to_return ( status : 200 )
stub_request ( :get , " http://cnn.com?a " ) .
to_return ( status : 200 , body : " <html><head><title>news</title></head></html> " , headers : { } )
expect ( PrettyText . cook ( " - http://cnn.com?a \n - a http://cnn.com?a " ) . split ( " news " ) . length ) . to eq ( 3 )
expect ( PrettyText . cook ( " - http://cnn.com?a \n - a http://cnn.com?a " ) . split ( " news " ) . length ) . to eq ( 3 )
end
it 'skips mini onebox for primary domain' do
# we only include mini onebox if there is something in path or query params
SiteSetting . enable_inline_onebox_on_all_domains = true
InlineOneboxer . purge ( " http://cnn.com/ " )
stub_request ( :head , " http://cnn.com/ " ) . to_return ( status : 200 )
stub_request ( :get , " http://cnn.com/ " ) .
to_return ( status : 200 , body : " <html><head><title>news</title></head></html> " , headers : { } )
expect ( PrettyText . cook ( " - http://cnn.com/ \n - a http://cnn.com/ " ) . split ( " news " ) . length ) . to eq ( 1 )
expect ( PrettyText . cook ( " - cnn.com \n - a http://cnn.com/ " ) . split ( " news " ) . length ) . to eq ( 1 )
2017-08-02 16:10:08 -04:00
end
2017-07-10 12:20:50 -04:00
it " can handle bbcode " do
expect ( PrettyText . cook ( " a[b]b[/b]c " ) ) . to eq ( '<p>a<span class="bbcode-b">b</span>c</p>' )
expect ( PrettyText . cook ( " a[i]b[/i]c " ) ) . to eq ( '<p>a<span class="bbcode-i">b</span>c</p>' )
end
2017-06-27 10:57:29 -04:00
2017-07-10 12:20:50 -04:00
it " can onebox local topics " do
op = Fabricate ( :post )
reply = Fabricate ( :post , topic_id : op . topic_id )
2017-06-29 12:48:04 -04:00
2017-07-10 12:20:50 -04:00
url = Discourse . base_url + reply . url
quote = create_post ( topic_id : op . topic . id , raw : " This is a sample reply with a quote \n \n #{ url } " )
quote . reload
2017-06-28 16:08:20 -04:00
2017-07-10 12:20:50 -04:00
expect ( quote . cooked ) . not_to include ( '[quote' )
end
2017-06-28 16:08:20 -04:00
2017-07-10 12:20:50 -04:00
it " supports tables " do
markdown = << ~ MD
| Tables | Are | Cool |
| - - - - - - - - - - - - - | :- - - - - - - - - - - - - :| - - - - - :|
| col 3 is | right - aligned | $1600 |
MD
expected = << ~ HTML
< table >
< thead >
< tr >
< th > Tables < / th>
< th style = " text-align:center " > Are < / th>
< th style = " text-align:right " > Cool < / th>
< / tr>
< / thead>
< tbody >
< tr >
< td > col 3 is < / td>
< td style = " text-align:center " > right - aligned < / td>
< td style = " text-align:right " > $1600 < / td>
< / tr>
< / tbody>
< / table>
HTML
expect ( PrettyText . cook ( markdown ) ) . to eq ( expected . strip )
end
2017-06-08 18:02:30 -04:00
2017-07-10 12:20:50 -04:00
it " supports img bbcode " do
cooked = PrettyText . cook " [img]http://www.image/test.png[/img] "
html = " <p><img src= \" http://www.image/test.png \" alt></p> "
expect ( cooked ) . to eq ( html )
end
2017-06-29 13:59:40 -04:00
2017-07-10 12:20:50 -04:00
it " provides safety for img bbcode " do
cooked = PrettyText . cook " [img]http://aaa.com<script>alert(1);</script>[/img] "
html = '<p><img src="http://aaa.com<script>alert(1);</script>" alt></p>'
expect ( cooked ) . to eq ( html )
end
2017-06-29 13:59:40 -04:00
2017-07-10 12:20:50 -04:00
it " supports email bbcode " do
cooked = PrettyText . cook " [email]sam@sam.com[/email] "
html = '<p><a href="mailto:sam@sam.com" data-bbcode="true">sam@sam.com</a></p>'
expect ( cooked ) . to eq ( html )
end
2017-06-29 13:59:40 -04:00
2017-07-10 12:20:50 -04:00
it " supports url bbcode " do
cooked = PrettyText . cook " [url]http://sam.com[/url] "
2017-07-14 08:27:28 -04:00
html = '<p><a href="http://sam.com" data-bbcode="true" rel="nofollow noopener">http://sam.com</a></p>' ;
expect ( cooked ) . to eq ( html )
end
it " supports nesting tags in url " do
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>' ;
2017-07-10 12:20:50 -04:00
expect ( cooked ) . to eq ( html )
end
2017-06-29 13:59:40 -04:00
2017-07-20 13:02:31 -04:00
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] " )
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>'
expect ( cooked ) . to eq ( html )
end
2017-07-10 12:20:50 -04:00
it " supports inline code bbcode " do
cooked = PrettyText . cook " Testing [code]codified **stuff** and `more` stuff[/code] "
html = " <p>Testing <code>codified **stuff** and `more` stuff</code></p> "
expect ( cooked ) . to eq ( html )
end
2017-06-29 13:59:40 -04:00
2017-07-10 12:20:50 -04:00
it " supports block code bbcode " do
cooked = PrettyText . cook " [code] \n codified \n \n \n **stuff** and `more` stuff \n [/code] "
html = " <pre><code class= \" lang-auto \" >codified \n \n \n **stuff** and `more` stuff</code></pre> "
expect ( cooked ) . to eq ( html )
end
2017-06-29 16:04:10 -04:00
2017-07-10 12:20:50 -04:00
it " support special handling for space in urls " do
cooked = PrettyText . cook " http://testing.com?a%20b "
2017-07-14 08:27:28 -04:00
html = '<p><a href="http://testing.com?a%20b" class="onebox" target="_blank" rel="nofollow noopener">http://testing.com?a%20b</a></p>'
2017-07-10 12:20:50 -04:00
expect ( cooked ) . to eq ( html )
end
2017-06-29 16:04:10 -04:00
2017-07-10 12:20:50 -04:00
it " supports onebox for decoded urls " do
cooked = PrettyText . cook " http://testing.com?a%50b "
2017-07-14 08:27:28 -04:00
html = '<p><a href="http://testing.com?a%50b" class="onebox" target="_blank" rel="nofollow noopener">http://testing.com?aPb</a></p>'
2017-07-10 12:20:50 -04:00
expect ( cooked ) . to eq ( html )
end
2017-07-03 16:32:53 -04:00
2017-07-14 08:27:28 -04:00
it " should sanitize the html " do
expect ( PrettyText . cook ( " <test>alert(42)</test> " ) ) . to eq " <p>alert(42)</p> "
end
it " should not onebox magically linked urls " do
expect ( PrettyText . cook ( '[url]site.com[/url]' ) ) . not_to include ( 'onebox' )
end
2017-07-03 16:32:53 -04:00
2017-07-10 12:20:50 -04:00
it " should sanitize the html " do
2017-07-14 08:27:28 -04:00
expect ( PrettyText . cook ( " <p class='hi'>hi</p> " ) ) . to eq " <p>hi</p> "
end
it " should strip SCRIPT " do
2017-07-10 12:20:50 -04:00
expect ( PrettyText . cook ( " <script>alert(42)</script> " ) ) . to eq " "
2017-06-08 18:02:30 -04:00
end
2017-07-14 08:27:28 -04:00
it " should allow sanitize bypass " do
expect ( PrettyText . cook ( " <test>alert(42)</test> " , sanitize : false ) ) . to eq " <p><test>alert(42)</test></p> "
end
2017-07-11 12:13:03 -04:00
# custom rule used to specify image dimensions via alt tags
describe " image dimensions " do
it " allows title plus dimensions " do
cooked = PrettyText . cook << ~ MD
! [ title with | title | 220 x100 ] ( http : / / png . com / my . png )
! [ ] ( http : / / png . com / my . png )
! [ | 220 x100 ] ( http : / / png . com / my . png )
! [ stuff ] ( http : / / png . com / my . png )
! [ | 220 x100 , 50 % ] ( http : / / png . com / my . png )
MD
html = << ~ HTML
< p > < img src = " http://png.com/my.png " alt = " title with | title " width = " 220 " height = " 100 " > < br >
< img src = " http://png.com/my.png " alt > < br >
< img src = " http://png.com/my.png " alt width = " 220 " height = " 100 " > < br >
< img src = " http://png.com/my.png " alt = " stuff " > < br >
< img src = " http://png.com/my.png " alt width = " 110 " height = " 50 " > < / p>
HTML
expect ( cooked ) . to eq ( html . strip )
end
2017-07-26 10:54:20 -04:00
it " allows whitespace before the percent scaler " do
cooked = PrettyText . cook << ~ MD
! [ | 220 x100 , 50 % ] ( http : / / png . com / my . png )
! [ | 220 x100 , 50 % ] ( http : / / png . com / my . png )
! [ | 220 x100 , 50 % ] ( http : / / png . com / my . png )
MD
html = << ~ HTML
2017-07-27 17:55:04 -04:00
< p > < img src = " http://png.com/my.png " alt width = " 110 " height = " 50 " > < br >
< img src = " http://png.com/my.png " alt width = " 110 " height = " 50 " > < br >
2017-07-26 10:54:20 -04:00
< img src = " http://png.com/my.png " alt width = " 110 " height = " 50 " > < / p>
HTML
2017-07-27 17:55:04 -04:00
expect ( cooked ) . to eq ( html . strip )
2017-07-26 10:54:20 -04:00
end
2017-07-11 12:13:03 -04:00
end
2017-07-19 15:08:54 -04:00
describe " inline onebox " do
it " includes the topic title " do
topic = Fabricate ( :topic )
raw = " Hello #{ topic . url } "
cooked = << ~ HTML
< p > Hello < a href = " #{ topic . url } " > #{topic.title}</a></p>
HTML
expect ( PrettyText . cook ( raw ) ) . to eq ( cooked . strip )
end
end
2017-08-22 11:46:15 -04:00
describe " image decoding " do
it " can decode upload:// for default setup " do
upload = Fabricate ( :upload )
raw = << ~ RAW
! [ upload ] ( #{upload.short_url})
- ! [ upload ] ( #{upload.short_url})
- test
- ! [ upload ] ( #{upload.short_url})
RAW
cooked = << ~ HTML
< p > < img src = " #{ upload . url } " alt = " upload " > < / p>
< ul >
< li >
< p > < img src = " #{ upload . url } " alt = " upload " > < / p>
< / li>
< li >
< p > test < / p>
< ul >
< li > < img src = " #{ upload . url } " alt = " upload " > < / li>
< / ul>
< / li>
< / ul>
HTML
expect ( PrettyText . cook ( raw ) ) . to eq ( cooked . strip )
end
it " can place a blank image if we can not find the upload " do
raw = " ![upload](upload://abcABC.png) "
cooked = << ~ HTML
< p > < img src = " /images/transparent.png " alt = " upload " data - orig - src = " upload://abcABC.png " > < / p>
HTML
expect ( PrettyText . cook ( raw ) ) . to eq ( cooked . strip )
end
end
2013-02-05 14:16:51 -05:00
end