From ba9898c5a9b9fdaa61abeb1c051aa28705a2bb2e Mon Sep 17 00:00:00 2001
From: Sam ℵ£¢ ddd @hello @hello @hello @hello @hello-hello hi @sam! hi hi @a,@b @hello @hello-hello ℵ£¢ X X aa *a a
+
+ a
+
+ X
+
-HTML
- expect(PrettyText.cook("[quote=\"EvilTrout, post:2, topic:#{topic.id}\"]ddd\n[/quote]", topic_id: 1)).to match_html expected
- end
- end
+ describe "Quoting" do
describe "with avatar" do
let(:default_avatar) { "//test.localhost/uploads/default/avatars/42d/57c/46ce7ee487/{size}.png" }
@@ -38,19 +34,91 @@ HTML
User.stubs(:default_template).returns(default_avatar)
end
- it "produces a quote even with new lines in it" do
- expect(PrettyText.cook("[quote=\"#{user.username}, post:123, topic:456, full:true\"]ddd\n[/quote]")).to match_html ""
+ it "do off topic quoting with emoji unescape" do
+
+ topic = Fabricate(:topic, title: "this is a test topic :slight_smile:")
+ expected = <<~HTML
+
+ HTML
+
+ expect(cook("[quote=\"EvilTrout, post:2, topic:#{topic.id}\"]\nddd\n[/quote]", topic_id: 1)).to eq(n(expected))
end
- it "should produce a quote" do
- expect(PrettyText.cook("[quote=\"#{user.username}, post:123, topic:456, full:true\"]ddd[/quote]")).to match_html ""
+ it "produces a quote even with new lines in it" do
+ md = <<~MD
+ [quote="#{user.username}, post:123, topic:456, full:true"]
+
+ ddd
+
+ [/quote]
+ MD
+ html = <<~HTML
+
+ HTML
+
+ expect(PrettyText.cook(md)).to eq(html.strip)
end
+
it "trims spaces on quote params" do
- expect(PrettyText.cook("[quote=\"#{user.username}, post:555, topic: 666\"]ddd[/quote]")).to match_html ""
+ md = <<~MD
+ [quote="#{user.username}, post:555, topic: 666"]
+ ddd
+ [/quote]
+ MD
+
+ html = <<~HTML
+
+ HTML
+
+ expect(PrettyText.cook(md)).to eq(html.strip)
end
end
+ it "can handle quote edge cases" do
+ expect(PrettyText.cook("a\n[quote]\ntest\n[/quote]\n\n\na")).to include('aside')
+ expect(PrettyText.cook("- a\n[quote]\ntest\n[/quote]\n\n\na")).to include('aside')
+ expect(PrettyText.cook("[quote]\ntest")).not_to include('aside')
+ expect(PrettyText.cook("[quote]abc\ntest\n[/quote]")).not_to include('aside')
+ expect(PrettyText.cook("[quote]\ntest\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
+
describe "with letter avatar" do
let(:user) { Fabricate(:user) }
@@ -61,22 +129,44 @@ HTML
end
it "should have correct avatar url" do
- expect(PrettyText.cook("[quote=\"#{user.username}, post:123, topic:456, full:true\"]ddd[/quote]")).to include("/forum/letter_avatar_proxy")
+ md = <<~MD
+ [quote="#{user.username}, post:123, topic:456, full:true"]
+ ddd
+ [/quote]
+ MD
+ expect(PrettyText.cook(md)).to include("/forum/letter_avatar_proxy")
end
end
end
+ end
+
+ describe "Mentions" do
it "should handle 3 mentions in a row" do
expect(PrettyText.cook('@hello @hello @hello')).to match_html "
\n@sam
+ 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
+ expect(PrettyText.cook("```cpp\ncpp\n```")).to match_html(" #
+ x
+
")
+ expect(PrettyText.cook("```\ncpp\n```")).to match_html("cpp\n
")
+ expect(PrettyText.cook("```text\ncpp\n```")).to match_html("cpp\n
")
+ end
+
+ it 'indents code correctly' do
+ code = "X\n```\n\n #\n x\n```"
+ cooked = PrettyText.cook(code)
+ expect(cooked).to match_html("cpp\n
")
+ end
+
+ it 'does censor code fences' do
+ SiteSetting.censored_words = 'apple|banana'
+ expect(PrettyText.cook("# banana")).not_to include('banana')
+ end
end
+
describe "rel nofollow" do
before do
SiteSetting.add_rel_nofollow_to_user_content = true
@@ -330,7 +459,6 @@ HTML
)).to eq("boom")
end
end
-
end
describe "strip links" do
@@ -402,20 +530,55 @@ HTML
end
end
- it 'can escape *' do
- expect(PrettyText.cook("***a***a")).to match_html("\n #\n x\n
+
+
+
+
+ test
+
+ HTML
+
+ expect(PrettyText.cook(raw)).to eq(html.strip)
end
- it 'can include code class correctly' do
- expect(PrettyText.cook("```cpp\ncpp\n```")).to match_html("test
+
")
- end
-
- it 'indents code correctly' do
- code = "X\n```\n\n #\n x\n```"
- cooked = PrettyText.cook(code)
- expect(cooked).to match_html("cpp
")
- end
it 'can substitute s3 cdn correctly' do
SiteSetting.enable_s3_uploads = true
@@ -425,19 +588,22 @@ HTML
SiteSetting.s3_cdn_url = "https://awesome.cdn"
# add extra img tag to ensure it does not blow up
- raw = <
-
-
-
+ raw = <<~HTML
+
+
+
+
+ HTML
-HTML
+ html = <<~HTML
+ #\n x
+
+
+
#unknown::tag #known
- HTML - - expect(cooked).to match_html(html) - end - - # TODO does it make sense to generate hashtags for tags that are missing in action? - end - describe "custom emoji" do it "replaces the custom emoji" do CustomEmoji.create!(name: 'trout', upload: Fabricate(:upload)) @@ -504,317 +650,245 @@ HTML end end - context "markdown it" do - - before do - SiteSetting.enable_experimental_markdown_it = true - end - - it "replaces skin toned emoji" do - expect(PrettyText.cook("hello š±šæāāļø")).to eq("hello
") - expect(PrettyText.cook("hello š©āš¤")).to eq("hello
") - expect(PrettyText.cook("hello š©š¾āš")).to eq("hello
") - expect(PrettyText.cook("hello š¤·āāļø")).to eq("hello
") - end + it "replaces skin toned emoji" do + expect(PrettyText.cook("hello š±šæāāļø")).to eq("hello
") + expect(PrettyText.cook("hello š©āš¤")).to eq("hello
") + expect(PrettyText.cook("hello š©š¾āš")).to eq("hello
") + expect(PrettyText.cook("hello š¤·āāļø")).to eq("hello
") + end - it "supports href schemes" do - SiteSetting.allowed_href_schemes = "macappstore|steam" - cooked = cook("[Steam URL Scheme](steam://store/452530)") - expected = '' - expect(cooked).to eq(n expected) - end + it "supports href schemes" do + SiteSetting.allowed_href_schemes = "macappstore|steam" + cooked = cook("[Steam URL Scheme](steam://store/452530)") + expected = '' + expect(cooked).to eq(n expected) + end - it "supports forbidden schemes" do - SiteSetting.allowed_href_schemes = "macappstore|itunes" - cooked = cook("[Steam URL Scheme](steam://store/452530)") - expected = '' - expect(cooked).to eq(n expected) - end + it "supports forbidden schemes" do + SiteSetting.allowed_href_schemes = "macappstore|itunes" + cooked = cook("[Steam URL Scheme](steam://store/452530)") + expected = '' + expect(cooked).to eq(n expected) + end - it "produces tag links" do - Fabricate(:topic, {tags: [Fabricate(:tag, name: 'known')]}) + it "produces tag links" do + Fabricate(:topic, {tags: [Fabricate(:tag, name: 'known')]}) - cooked = PrettyText.cook(" #unknown::tag #known::tag") + cooked = PrettyText.cook(" #unknown::tag #known::tag") - html = <<~HTML -#unknown::tag #known
- HTML + html = <<~HTML +#unknown::tag #known
+ HTML - expect(cooked).to eq(html.strip) + expect(cooked).to eq(html.strip) - cooked = PrettyText.cook("[`a` #known::tag here](http://somesite.com)") + cooked = PrettyText.cook("[`a` #known::tag here](http://somesite.com)") - html = <<~HTML - - HTML + html = <<~HTML + + HTML - expect(cooked).to eq(html.strip) + expect(cooked).to eq(html.strip) - cooked = PrettyText.cook("`a` #known::tag here") + cooked = PrettyText.cook("`a` #known::tag here") - expect(cooked).to eq(html.strip) + expect(cooked).to eq(html.strip) - cooked = PrettyText.cook("test #known::tag") - html = <<~HTML - - HTML + cooked = PrettyText.cook("test #known::tag") + html = <<~HTML + + HTML - expect(cooked).to eq(html.strip) + expect(cooked).to eq(html.strip) - # 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') - - end - - it "can handle mixed lists" do - # known bug in old md engine - cooked = PrettyText.cook("* a\n\n1. b") - expect(cooked).to match_html("1 2
" - - SiteSetting.traditional_markdown_linebreaks = false - expect(PrettyText.cook("1\n2")).to match_html "1
\n2
hi @sam! hi
' - expect(PrettyText.cook("hi\n@sam")).to eq("hi
\n@sam
@a,@b
') - end - - it "can handle emoji by name" do - - expected = < -HTML - expect(PrettyText.cook(":smile::sunny:")).to eq(expected.strip) - end - - it "handles emoji boundaries correctly" do - cooked = PrettyText.cook("a,:man:t2:,b") - expected = 'a,,b
' - expect(cooked).to match(expected.strip) - end - - it "can handle emoji by translation" do - expected = '' - expect(PrettyText.cook(";)")).to eq(expected) - end - - it "can handle multiple emojis by translation" do - cooked = PrettyText.cook(":) ;) :)") - expect(cooked.split("img").length-1).to eq(3) - end - - 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 - - - it 'can include code class correctly' do - expect(PrettyText.cook("```cpp\ncpp\n```")).to match_html("cpp\n
")
- expect(PrettyText.cook("```\ncpp\n```")).to match_html("cpp\n
")
- expect(PrettyText.cook("```text\ncpp\n```")).to match_html("cpp\n
")
- end
-
- it 'indents code correctly' do
- code = "X\n```\n\n #\n x\n```"
- cooked = PrettyText.cook(code)
- expect(cooked).to match_html("X
\n\n #\n x\n
")
- end
-
- it 'can censor words correctly' do
- SiteSetting.censored_words = 'apple|banana'
- expect(PrettyText.cook('yay banana yay')).not_to include('banana')
- expect(PrettyText.cook('yay `banana` yay')).not_to include('banana')
- expect(PrettyText.cook("yay \n\n```\nbanana\n````\n yay")).not_to include('banana')
- expect(PrettyText.cook("# banana")).not_to include('banana')
- expect(PrettyText.cook("# banana")).to include("\u25a0\u25a0")
- end
-
- it 'supports typographer' do
- SiteSetting.enable_markdown_typographer = true
- expect(PrettyText.cook('(tm)')).to eq('ā¢
') - - SiteSetting.enable_markdown_typographer = false - expect(PrettyText.cook('(tm)')).to eq('(tm)
') - end - - it 'handles onebox correctly' do - expect(PrettyText.cook("http://a.com\nhttp://b.com").split("onebox").length).to eq(3) - expect(PrettyText.cook("http://a.com\n\nhttp://b.com").split("onebox").length).to eq(3) - expect(PrettyText.cook("a\nhttp://a.com")).to include('onebox') - expect(PrettyText.cook("> http://a.com")).not_to include('onebox') - expect(PrettyText.cook("a\nhttp://a.com a")).not_to include('onebox') - expect(PrettyText.cook("a\nhttp://a.com\na")).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("abc
') - expect(PrettyText.cook("a[i]b[/i]c")).to eq('abc
') - end - - it "can handle quote edge cases" do - expect(PrettyText.cook("a\n[quote]\ntest\n[/quote]\n\n\na")).to include('aside') - expect(PrettyText.cook("- a\n[quote]\ntest\n[/quote]\n\n\na")).to include('aside') - expect(PrettyText.cook("[quote]\ntest")).not_to include('aside') - expect(PrettyText.cook("[quote]abc\ntest\n[/quote]")).not_to include('aside') - expect(PrettyText.cook("[quote]\ntest\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 - - it "can onebox local topics" do - op = Fabricate(:post) - reply = Fabricate(:post, topic_id: op.topic_id) - - - 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 - - expect(quote.cooked).not_to include('[quote') - end - - it "supports tables" do - - markdown = <<~MD - | Tables | Are | Cool | - | ------------- |:-------------:| -----:| - | col 3 is | right-aligned | $1600 | - MD - - expected = <<~HTML -Tables | -Are | -Cool | -
---|---|---|
col 3 is | -right-aligned | -$1600 | -
Testing codified **stuff** and `more` stuff
codified\n\n\n **stuff** and `more` stuff
"
- expect(cooked).to eq(html)
- end
-
- it "support special handling for space in urls" do
- cooked = PrettyText.cook "http://testing.com?a%20b"
- html = ''
- expect(cooked).to eq(html)
- end
-
- it "supports onebox for decoded urls" do
- cooked = PrettyText.cook "http://testing.com?a%50b"
- html = ''
- expect(cooked).to eq(html)
- end
+ # 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')
end
+ it "can handle mixed lists" do
+ # known bug in old md engine
+ cooked = PrettyText.cook("* a\n\n1. b")
+ expect(cooked).to match_html("1 2
" + + SiteSetting.traditional_markdown_linebreaks = false + expect(PrettyText.cook("1\n2")).to match_html "1
\n2
a,,b
' + expect(cooked).to match(expected.strip) + end + + it "can handle emoji by translation" do + expected = '' + expect(PrettyText.cook(";)")).to eq(expected) + end + + it "can handle multiple emojis by translation" do + cooked = PrettyText.cook(":) ;) :)") + expect(cooked.split("img").length-1).to eq(3) + end + + 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 + + it 'can censor words correctly' do + SiteSetting.censored_words = 'apple|banana' + 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") + end + + it 'supports typographer' do + SiteSetting.enable_markdown_typographer = true + expect(PrettyText.cook('(tm)')).to eq('ā¢
') + + SiteSetting.enable_markdown_typographer = false + expect(PrettyText.cook('(tm)')).to eq('(tm)
') + end + + it 'handles onebox correctly' do + expect(PrettyText.cook("http://a.com\nhttp://b.com").split("onebox").length).to eq(3) + expect(PrettyText.cook("http://a.com\n\nhttp://b.com").split("onebox").length).to eq(3) + expect(PrettyText.cook("a\nhttp://a.com")).to include('onebox') + expect(PrettyText.cook("> http://a.com")).not_to include('onebox') + expect(PrettyText.cook("a\nhttp://a.com a")).not_to include('onebox') + expect(PrettyText.cook("a\nhttp://a.com\na")).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("abc
') + expect(PrettyText.cook("a[i]b[/i]c")).to eq('abc
') + end + + + it "can onebox local topics" do + op = Fabricate(:post) + reply = Fabricate(:post, topic_id: op.topic_id) + + + 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 + + expect(quote.cooked).not_to include('[quote') + end + + it "supports tables" do + + markdown = <<~MD + | Tables | Are | Cool | + | ------------- |:-------------:| -----:| + | col 3 is | right-aligned | $1600 | + MD + + expected = <<~HTML +Tables | +Are | +Cool | +
---|---|---|
col 3 is | +right-aligned | +$1600 | +
Testing codified **stuff** and `more` stuff
codified\n\n\n **stuff** and `more` stuff
"
+ expect(cooked).to eq(html)
+ end
+
+ it "support special handling for space in urls" do
+ cooked = PrettyText.cook "http://testing.com?a%20b"
+ html = ''
+ expect(cooked).to eq(html)
+ end
+
+ it "supports onebox for decoded urls" do
+ cooked = PrettyText.cook "http://testing.com?a%50b"
+ html = ''
+ expect(cooked).to eq(html)
+ end
+
+
+ it "should sanitize the html" do
+ expect(PrettyText.cook("")).to eq ""
+ end
+
+
end