FIX: smarter newline handling for <img> tags on line alone
Run all of pretty text spec on new engine
This commit is contained in:
parent
890a99232d
commit
ba9898c5a9
|
@ -12,3 +12,4 @@
|
|||
//= require ./pretty-text/engines/markdown-it/table
|
||||
//= require ./pretty-text/engines/markdown-it/paragraph
|
||||
//= require ./pretty-text/engines/markdown-it/newline
|
||||
//= require ./pretty-text/engines/markdown-it/html_img
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
// special handling for IMG tags on a line by themeselves
|
||||
// we always have to handle it as so it is an inline
|
||||
// see: https://talk.commonmark.org/t/newline-and-img-tags/2511
|
||||
|
||||
const REGEX = /^<img.*\\?>\s*$/i;
|
||||
|
||||
function rule(state, startLine, endLine) {
|
||||
|
||||
var nextLine, token, lineText,
|
||||
pos = state.bMarks[startLine] + state.tShift[startLine],
|
||||
max = state.eMarks[startLine];
|
||||
|
||||
// if it's indented more than 3 spaces, it should be a code block
|
||||
if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
|
||||
|
||||
if (!state.md.options.html) { return false; }
|
||||
|
||||
if (state.src.charCodeAt(pos) !== 0x3C/* < */) { return false; }
|
||||
let pos1 = state.src.charCodeAt(pos+1);
|
||||
if (pos1 !== 73 /* I */ && pos1 !== 105 /* i */) { return false; }
|
||||
|
||||
lineText = state.src.slice(pos, max);
|
||||
|
||||
if (!REGEX.test(lineText)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let lines = [];
|
||||
lines.push(lineText);
|
||||
|
||||
nextLine = startLine + 1;
|
||||
for (; nextLine < endLine; nextLine++) {
|
||||
pos = state.bMarks[nextLine] + state.tShift[nextLine];
|
||||
max = state.eMarks[nextLine];
|
||||
lineText = state.src.slice(pos, max);
|
||||
|
||||
if (lineText.trim() === "") {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!REGEX.test(lineText)) {
|
||||
break;
|
||||
}
|
||||
|
||||
lines.push(lineText);
|
||||
}
|
||||
|
||||
state.line = nextLine;
|
||||
let oldParentType = state.parentType;
|
||||
state.parentType = 'paragraph';
|
||||
|
||||
token = state.push('paragraph_open', 'p', 0);
|
||||
token.map = [startLine, state.line];
|
||||
|
||||
token = state.push('inline', '', 0);
|
||||
token.content = lines.join('\n');
|
||||
token.map = [startLine, state.line];
|
||||
token.children = [];
|
||||
|
||||
token = state.push('paragraph_close', 'p', -1);
|
||||
state.parentType = oldParentType;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
export function setup(helper) {
|
||||
|
||||
if (!helper.markdownIt) { return; }
|
||||
|
||||
helper.registerPlugin(md=>{
|
||||
md.block.ruler.before('html_block', 'html_img', rule, {alt: ['fence']});
|
||||
});
|
||||
}
|
|
@ -4,6 +4,10 @@ require 'html_normalize'
|
|||
|
||||
describe PrettyText do
|
||||
|
||||
before do
|
||||
SiteSetting.enable_experimental_markdown_it = true
|
||||
end
|
||||
|
||||
def n(html)
|
||||
HtmlNormalize.normalize(html)
|
||||
end
|
||||
|
@ -12,23 +16,15 @@ describe PrettyText do
|
|||
n(PrettyText.cook(*args))
|
||||
end
|
||||
|
||||
# see: https://github.com/sparklemotion/nokogiri/issues/1173
|
||||
skip 'allows html entities correctly' do
|
||||
expect(PrettyText.cook("ℵ£¢")).to eq("<p>ℵ£¢</p>")
|
||||
end
|
||||
|
||||
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 "off topic quoting" do
|
||||
it "can correctly populate topic title" do
|
||||
topic = Fabricate(:topic, title: "this is a test topic :slight_smile:")
|
||||
expected = <<HTML
|
||||
<aside class="quote" data-post="2" data-topic="#{topic.id}"><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(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 "<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\">#{user.username}:</div>\n<blockquote><p>ddd</p></blockquote></aside>"
|
||||
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}\"]\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 "<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\">#{user.username}:</div>\n<blockquote><p>ddd</p></blockquote></aside>"
|
||||
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
|
||||
<aside class="quote" data-post="123" data-topic="456">
|
||||
<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 "trims spaces on quote params" do
|
||||
expect(PrettyText.cook("[quote=\"#{user.username}, 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\">#{user.username}:</div>\n<blockquote><p>ddd</p></blockquote></aside>"
|
||||
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)
|
||||
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 "<p><span class=\"mention\">@hello</span> <span class=\"mention\">@hello</span> <span class=\"mention\">@hello</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>"
|
||||
it "can handle mentions" do
|
||||
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>'
|
||||
expect(PrettyText.cook("hi\n@sam")).to eq("<p>hi<br>\n<a class=\"mention\" href=\"/u/sam\">@sam</a></p>")
|
||||
end
|
||||
|
||||
it "can handle mentions inside a hyperlink" do
|
||||
expect(PrettyText.cook("<a> @inner</a> ")).to match_html '<p><a> @inner</a></p>'
|
||||
end
|
||||
|
||||
|
||||
it "should sanitize the html" do
|
||||
expect(PrettyText.cook("<script>alert(42)</script>")).to match_html "<p></p>"
|
||||
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>"
|
||||
end
|
||||
|
||||
it 'should allow for @mentions to have punctuation' do
|
||||
|
@ -85,13 +175,52 @@ HTML
|
|||
)
|
||||
end
|
||||
|
||||
# see: https://github.com/sparklemotion/nokogiri/issues/1173
|
||||
skip 'allows html entities correctly' do
|
||||
expect(PrettyText.cook("ℵ£¢")).to eq("<p>ℵ£¢</p>")
|
||||
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
|
||||
expect(PrettyText.cook("```cpp\ncpp\n```")).to match_html("<pre><code class='lang-cpp'>cpp\n</code></pre>")
|
||||
expect(PrettyText.cook("```\ncpp\n```")).to match_html("<pre><code class='lang-auto'>cpp\n</code></pre>")
|
||||
expect(PrettyText.cook("```text\ncpp\n```")).to match_html("<pre><code class='lang-nohighlight'>cpp\n</code></pre>")
|
||||
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>")
|
||||
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("<p><strong><em>a</em></strong>a</p>")
|
||||
expect(PrettyText.cook("***\\****a")).to match_html("<p><strong><em>*</em></strong>a</p>")
|
||||
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>
|
||||
<p>
|
||||
<img><br>
|
||||
<img></p>
|
||||
<p>
|
||||
<img></p>
|
||||
<p>a</p>
|
||||
<p>
|
||||
<img></p>
|
||||
<ul>
|
||||
<li>li</li>
|
||||
</ul>
|
||||
<p>
|
||||
<img></p>
|
||||
<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)
|
||||
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
|
||||
|
||||
it 'indents code correctly' do
|
||||
code = "X\n```\n\n #\n x\n```"
|
||||
cooked = PrettyText.cook(code)
|
||||
expect(cooked).to match_html("<p>X<br></p>\n\n<p></p><pre><code class=\"lang-auto\"> #\n x</code></pre>")
|
||||
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 = <<HTML
|
||||
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
|
||||
|
||||
cooked = <<HTML
|
||||
<p> <img><br> <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 = <<~HTML
|
||||
<p>
|
||||
<img><br>
|
||||
<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 match_html(cooked)
|
||||
expect(PrettyText.cook(raw)).to eq(html.strip)
|
||||
end
|
||||
|
||||
describe "emoji" do
|
||||
|
@ -449,10 +615,6 @@ HTML
|
|||
expect(PrettyText.cook("`💣`")).not_to match(/\:bomb\:/)
|
||||
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 "replaces some glyphs that are not in the emoji range" do
|
||||
expect(PrettyText.cook("☺")).to match(/\:slight_smile\:/)
|
||||
end
|
||||
|
@ -470,22 +632,6 @@ HTML
|
|||
end
|
||||
end
|
||||
|
||||
describe "tag and category links" do
|
||||
it "produces tag links" do
|
||||
Fabricate(:topic, {tags: [Fabricate(:tag, name: 'known')]})
|
||||
|
||||
cooked = PrettyText.cook(" #unknown::tag #known::tag")
|
||||
|
||||
html = <<~HTML
|
||||
<p> <span class=\"hashtag\">#unknown::tag</span> <a class=\"hashtag\" href=\"http://test.localhost/tags/known\">#<span>known</span></a></p>
|
||||
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,12 +650,6 @@ 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("<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>")
|
||||
|
@ -583,24 +723,6 @@ HTML
|
|||
expect(PrettyText.cook("1\n2")).to match_html "<p>1<br>\n2</p>"
|
||||
end
|
||||
|
||||
it "can handle mentions" do
|
||||
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>'
|
||||
expect(PrettyText.cook("hi\n@sam")).to eq("<p>hi<br>\n<a class=\"mention\" href=\"/u/sam\">@sam</a></p>")
|
||||
end
|
||||
|
||||
it "can handle mentions inside a hyperlink" do
|
||||
expect(PrettyText.cook("<a> @inner</a> ")).to match_html '<p><a> @inner</a></p>'
|
||||
end
|
||||
|
||||
|
||||
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 "can handle emoji by name" do
|
||||
|
||||
|
@ -634,24 +756,10 @@ HTML
|
|||
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("<pre><code class='lang-cpp'>cpp\n</code></pre>")
|
||||
expect(PrettyText.cook("```\ncpp\n```")).to match_html("<pre><code class='lang-auto'>cpp\n</code></pre>")
|
||||
expect(PrettyText.cook("```text\ncpp\n```")).to match_html("<pre><code class='lang-nohighlight'>cpp\n</code></pre>")
|
||||
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>")
|
||||
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
|
||||
|
@ -685,27 +793,6 @@ HTML
|
|||
expect(PrettyText.cook("a[i]b[/i]c")).to eq('<p>a<span class="bbcode-i">b</span>c</p>')
|
||||
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)
|
||||
|
@ -749,23 +836,6 @@ HTML
|
|||
expect(PrettyText.cook(markdown)).to eq(expected.strip)
|
||||
end
|
||||
|
||||
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}\"]\nddd\n[/quote]", topic_id: 1)).to eq(n(expected))
|
||||
end
|
||||
|
||||
it "supports img bbcode" do
|
||||
cooked = PrettyText.cook "[img]http://www.image/test.png[/img]"
|
||||
|
@ -815,6 +885,10 @@ HTML
|
|||
expect(cooked).to eq(html)
|
||||
end
|
||||
|
||||
|
||||
it "should sanitize the html" do
|
||||
expect(PrettyText.cook("<script>alert(42)</script>")).to eq ""
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue