'
);
});
QUnit.test("Line Breaks", (assert) => {
assert.cooked(
"[] first choice\n[] second choice",
"
[] first choice \n[] second choice
",
"it handles new lines correctly with [] options"
);
// note this is a change from previous engine but is correct
// we have an html block and behavior is defined per common mark
// spec
// ole engine would wrap trout in a
assert.cooked(
"
evil
\ntrout",
"
evil
\ntrout",
"it doesn't insert after blockquotes"
);
assert.cooked(
"leading
evil
\ntrout",
"
leading
evil
\ntrout",
"it doesn't insert after blockquotes with leading text"
);
});
QUnit.test("Paragraphs for HTML", (assert) => {
assert.cooked(
"
hello world
",
"
hello world
",
"it doesn't surround
with paragraphs"
);
assert.cooked(
"
hello world
",
"
hello world
",
"it doesn't surround
with paragraphs"
);
assert.cooked(
"hello world",
"
hello world
",
"it surrounds inline html tags with paragraphs"
);
assert.cooked(
"hello world",
"
hello world
",
"it surrounds inline html tags with paragraphs"
);
});
QUnit.test("Links", (assert) => {
assert.cooked(
"EvilTrout: http://eviltrout.com",
'
`,
"autolinks a URL with parentheses (like Wikipedia)"
);
assert.cooked(
"Here's a tweet:\nhttps://twitter.com/evil_trout/status/345954894420787200",
'
\n`,
"allows autolinking within a list without inserting a paragraph."
);
assert.cooked(
"[3]: http://eviltrout.com",
"",
"It doesn't autolink markdown link references"
);
assert.cooked(
"[]: http://eviltrout.com",
'
',
"It doesn't accept BBCode as link references"
);
assert.cooked(
"http://discourse.org and http://discourse.org/another_url and http://www.imdb.com/name/nm2225369",
'
',
"should not do mentions within a code block."
);
assert.cooked(
"> foo bar baz @eviltrout",
'
\n
foo bar baz @eviltrout
\n
',
"handles mentions in simple quotes"
);
assert.cooked(
"> foo bar baz @eviltrout ohmagerd\nlook at this",
'
\n
foo bar baz @eviltrout ohmagerd \nlook at this
\n
',
"does mentions properly with trailing text within a simple quote"
);
assert.cooked(
"`code` is okay before @mention",
'
code is okay before @mention
',
"Does not mention in an inline code block"
);
assert.cooked(
"@mention is okay before `code`",
'
@mention is okay before code
',
"Does not mention in an inline code block"
);
assert.cooked(
"don't `@mention`",
"
don't @mention
",
"Does not mention in an inline code block"
);
assert.cooked(
"Yes `@this` should be code @eviltrout",
'
Yes @this should be code @eviltrout
',
"Does not mention in an inline code block"
);
assert.cooked(
"@eviltrout and `@eviltrout`",
'
@eviltrout and @eviltrout
',
"you can have a mention in an inline code block following a real mention."
);
assert.cooked(
"1. this is a list\n\n2. this is an @eviltrout mention\n",
'\n
\n
this is a list
\n
\n
\n
this is an @eviltrout mention
\n
\n',
"it mentions properly in a list."
);
assert.cooked(
"Hello @foo/@bar",
'
Hello @foo/@bar
',
"handles mentions separated by a slash."
);
assert.cooked(
"a @sam c",
'
a @sam c
',
"it allows mentions within HTML tags"
);
assert.cooked(
"@_sam @1sam @ab-cd.123_ABC-xYz @sam1",
'
',
"it translates category hashtag into links"
);
assert.cooked(
"Check out #category-hashtag",
'
Check out #category-hashtag
',
"it does not translate category hashtag into links if it is not a valid category hashtag"
);
assert.cookedOptions(
"[#category-hashtag](http://www.test.com)",
alwaysTrue,
'
",
"allows escaping em"
);
});
QUnit.test("New Lines", (assert) => {
// historically we would not continue inline em or b across lines,
// however commonmark gives us no switch to do so and we would be very non compliant.
// turning softbreaks into a newline is just a renderer option, not a parser switch.
assert.cooked(
"_abc\ndef_",
"
abc \ndef
",
"it does allow inlines to span new lines"
);
assert.cooked(
"_abc\n\ndef_",
"
_abc
\n
def_
",
"it does not allow inlines to span new paragraphs"
);
});
QUnit.test("Oneboxing", (assert) => {
function matches(input, regexp) {
return new PrettyText(defaultOpts).cook(input).match(regexp);
}
assert.ok(
!matches(
"- http://www.textfiles.com/bbs/MINDVOX/FORUMS/ethics\n\n- http://drupal.org",
/class="onebox"/
),
"doesn't onebox a link within a list"
);
assert.ok(
matches("http://test.com", /class="onebox"/),
"adds a onebox class to a link on its own line"
);
assert.ok(
matches("http://test.com\nhttp://test2.com", /onebox[\s\S]+onebox/m),
"supports multiple links"
);
assert.ok(
!matches("http://test.com bob", /onebox/),
"doesn't onebox links that have trailing text"
);
assert.ok(
!matches("[Tom Cruise](http://www.tomcruise.com/)", "onebox"),
"Markdown links with labels are not oneboxed"
);
assert.ok(
!matches(
"[http://www.tomcruise.com/](http://www.tomcruise.com/)",
"onebox"
),
"Markdown links where the label is the same as the url but link is explicit"
);
assert.cooked(
"http://en.wikipedia.org/wiki/Homicide:_Life_on_the_Street",
'
',
"works with links that have underscores in them"
);
});
QUnit.test("links with full urls", (assert) => {
assert.cooked(
"[http://eviltrout.com][1] is a url\n\n[1]: http://eviltrout.com",
'
`,
"It returns the correct attachment link HTML when the URL is mapped with secure media"
);
});
QUnit.test("video", (assert) => {
assert.cooked(
"![baby shark|video](upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp4)",
`
`,
"It returns the correct video player HTML"
);
});
QUnit.test("video - mapped url - secure media enabled", (assert) => {
function lookupUploadUrls() {
let cache = {};
cache["upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp4"] = {
short_url: "upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp4",
url: "/secure-media-uploads/original/3X/c/b/test.mp4",
short_path: "/uploads/short-url/blah",
};
return cache;
}
assert.cookedOptions(
"![baby shark|video](upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp4)",
{
siteSettings: { secure_media: true },
lookupUploadUrls: lookupUploadUrls,
},
`
`,
"It returns the correct video HTML when the URL is mapped with secure media, removing data-orig-src"
);
});
QUnit.test("audio", (assert) => {
assert.cooked(
"![young americans|audio](upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp3)",
``,
"It returns the correct audio player HTML"
);
});
QUnit.test("audio - mapped url - secure media enabled", (assert) => {
function lookupUploadUrls() {
let cache = {};
cache["upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp3"] = {
short_url: "upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp3",
url: "/secure-media-uploads/original/3X/c/b/test.mp3",
short_path: "/uploads/short-url/blah",
};
return cache;
}
assert.cookedOptions(
"![baby shark|audio](upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp3)",
{
siteSettings: { secure_media: true },
lookupUploadUrls: lookupUploadUrls,
},
``,
"It returns the correct audio HTML when the URL is mapped with secure media, removing data-orig-src"
);
});
QUnit.test("censoring", (assert) => {
assert.cookedOptions(
"Pleased to meet you, but pleeeease call me later, xyz123",
{
censoredRegexp: "(xyz*|plee+ase)",
},
"
Pleased to meet you, but ■■■■■■■■■ call me later, ■■■123
",
"supports censoring"
);
// More tests in pretty_text_spec.rb
});
QUnit.test("code blocks/spans hoisting", (assert) => {
assert.cooked(
"```\n\n some code\n```",
'
\n some code\n
',
"it works when nesting standard markdown code blocks within a fenced code block"
);
assert.cooked(
"`$&`",
"
$&
",
"it works even when hoisting special replacement patterns"
);
});
QUnit.test("basic bbcode", (assert) => {
assert.cookedPara(
"[b]strong[/b]",
'strong',
"bolds text"
);
assert.cookedPara(
"[i]emphasis[/i]",
'emphasis',
"italics text"
);
assert.cookedPara(
"[u]underlined[/u]",
'underlined',
"underlines text"
);
assert.cookedPara(
"[s]strikethrough[/s]",
'strikethrough',
"strikes-through text"
);
assert.cookedPara(
"[img]http://eviltrout.com/eviltrout.png[/img]",
'',
"links images"
);
assert.cookedPara(
"[email]eviltrout@mailinator.com[/email]",
'eviltrout@mailinator.com',
"supports [email] without a title"
);
assert.cookedPara(
"[b]evil [i]trout[/i][/b]",
'evil trout',
"allows embedding of tags"
);
assert.cookedPara(
"[EMAIL]eviltrout@mailinator.com[/EMAIL]",
'eviltrout@mailinator.com',
"supports upper case bbcode"
);
assert.cookedPara(
"[b]strong [b]stronger[/b][/b]",
'strong stronger',
"accepts nested bbcode tags"
);
});
QUnit.test("urls", (assert) => {
assert.cookedPara(
"[url]not a url[/url]",
"not a url",
"supports [url] that isn't a url"
);
assert.cookedPara(
"[url]abc.com[/url]",
'abc.com',
"it magically links using linkify"
);
assert.cookedPara(
"[url]http://bettercallsaul.com[/url]",
'http://bettercallsaul.com',
"supports [url] without parameter"
);
assert.cookedPara(
"[url=http://example.com]example[/url]",
'example',
"supports [url] with given href"
);
assert.cookedPara(
"[url=http://www.example.com][img]http://example.com/logo.png[/img][/url]",
'',
"supports [url] with an embedded [img]"
);
});
QUnit.test("invalid bbcode", (assert) => {
assert.cooked(
"[code]I am not closed\n\nThis text exists.",
"
[code]I am not closed
\n
This text exists.
",
"does not raise an error with an open bbcode tag."
);
});
QUnit.test("code", (assert) => {
assert.cooked(
"[code]\nx++\n[/code]",
'
x++
',
"makes code into pre"
);
assert.cooked(
"[code]\nx++\ny++\nz++\n[/code]",
'
x++\ny++\nz++
',
"makes code into pre"
);
assert.cooked(
"[code]\nabc\n#def\n[/code]",
'
abc\n#def
',
"it handles headings in a [code] block"
);
assert.cooked(
"[code]\n s\n[/code]",
'
s
',
"it doesn't trim leading whitespace"
);
});
QUnit.test("tags with arguments", (assert) => {
assert.cookedPara(
"[url=http://bettercallsaul.com]better call![/url]",
'better call!',
"supports [url] with a title"
);
assert.cookedPara(
"[email=eviltrout@mailinator.com]evil trout[/email]",
'evil trout',
"supports [email] with a title"
);
assert.cookedPara(
"[u][i]abc[/i][/u]",
'abc',
"can nest tags"
);
assert.cookedPara(
"[b]first[/b] [b]second[/b]",
'firstsecond',
"can bold two things on the same line"
);
});
QUnit.test("quotes", (assert) => {
const post = Post.create({
cooked: "
lorem ipsum
",
username: "eviltrout",
post_number: 1,
topic_id: 2,
});
function formatQuote(val, expected, text, opts) {
assert.equal(buildQuote(post, val, opts), expected, text);
}
formatQuote(undefined, "", "empty string for undefined content");
formatQuote(null, "", "empty string for null content");
formatQuote("", "", "empty string for empty string content");
formatQuote(
"lorem",
'[quote="eviltrout, post:1, topic:2"]\nlorem\n[/quote]\n\n',
"correctly formats quotes"
);
formatQuote(
" lorem \t ",
'[quote="eviltrout, post:1, topic:2"]\nlorem\n[/quote]\n\n',
"trims white spaces before & after the quoted contents"
);
formatQuote(
"lorem ipsum",
'[quote="eviltrout, post:1, topic:2, full:true"]\nlorem ipsum\n[/quote]\n\n',
"marks quotes as full if the `full` option is passed",
{ full: true }
);
formatQuote(
"**lorem** ipsum",
'[quote="eviltrout, post:1, topic:2"]\n**lorem** ipsum\n[/quote]\n\n',
"keeps BBCode formatting"
);
assert.cooked(
"[quote]\ntest\n[/quote]",
'',
"it supports quotes without params"
);
assert.cooked(
"[quote]\n*test*\n[/quote]",
'',
"it doesn't insert a new line for italics"
);
assert.cooked(
"[quote=,script='a'>