#!/usr/bin/env perl
# Comprehensive/chained test of formatters, with the main formatter set to MultiMarkdown
use strict;
use warnings;
use Test::More tests => 27;
use HTTP::Request::Common;
use Test::Differences;
my $original_formatter; # used to save/restore the existing formatter set up in mojomojo.db
my $c; # the Catalyst object of this live server
my $test; # test description
my $content; # the markup content that is being rendered
my $got; # the rendered result
my $expected; # the expected rendered result
BEGIN {
$ENV{CATALYST_CONFIG} = 't/var/mojomojo.yml';
use_ok 'MojoMojo::Formatter::Markdown';
use_ok 'Catalyst::Test', 'MojoMojo';
}
END {
ok( $c->pref( main_formatter => $original_formatter ),
'restore original formatter' );
done_testing;
}
( undef, $c ) = ctx_request('/');
ok( $original_formatter = $c->pref('main_formatter'),
'save original formatter' );
ok( $c->pref( main_formatter => 'MojoMojo::Formatter::Markdown' ),
'set preferred formatter to Markdown' );
#-------------------------------------------------------------------------------
$test = "empty body";
$content = '';
$got = get( POST '/.jsrpc/render', [ content => $content ] );
is( $got, 'Please type something', $test );
#-------------------------------------------------------------------------------
$test = 'headings';
$content = <<'MARKDOWN';
# Heading 1
paragraph
## Heading 2
MARKDOWN
$got = get( POST '/.jsrpc/render', [ content => $content ] );
eq_or_diff( $got, <<'HTML', $test );
<h1>Heading 1</h1>
<p>paragraph</p>
<h2>Heading 2</h2>
HTML
#-------------------------------------------------------------------------------
$test = 'direct <http://url.com> hyperlinks';
$content = <<'MARKDOWN';
This should be linked: <http://mojomojo.org>.
MARKDOWN
$got = get( POST '/.jsrpc/render', [ content => $content ] );
eq_or_diff( $got, <<'HTML', $test );
<p>This should be linked: <a href="http://mojomojo.org">http://mojomojo.org</a>.</p>
HTML
#-------------------------------------------------------------------------------
$test = '<span>s need to be kept because they are the only way to specify text attributes';
$content = <<'MARKDOWN';
Print media uses <span style="font-family: Times New Roman">Times New Roman</span> fonts.
MARKDOWN
$got = get( POST '/.jsrpc/render', [ content => $content ] );
is( $got, <<HTML, $test );
<p>Print media uses <span style="font-family: Times New Roman">Times New Roman</span> fonts.</p>
HTML
#-------------------------------------------------------------------------------
$test = 'HTML entities must be preserved in code sections';
$content = <<'MARKDOWN';
Here's some code:
1 < 2 && '4' > "3" ™
The 5 predefined XML entities must be escaped accordingly.
MARKDOWN
$got = get( POST '/.jsrpc/render', [ content => $content ] );
eq_or_diff( $got, <<'HTML', $test );
<p>Here's some code:</p>
<pre><code>1 < 2 && '4' > "3" &trade;
</code></pre>
<p>The 5 predefined XML entities must be escaped accordingly.</p>
HTML
#-------------------------------------------------------------------------------
$test = 'apparent HTML tags in Markdown code sections must be rendered verbatim';
$content = <<'MARKDOWN';
This is a Config::General example:
<foo>
<script>yes, even scripts must be left alone</script>
</foo>
Ensure no angle brackets were stripped.
MARKDOWN
$got = get( POST '/.jsrpc/render', [ content => $content ] );
eq_or_diff( $got, <<'HTML', $test );
<p>This is a Config::General example:</p>
<pre><code><foo>
<script>yes, even scripts must be left alone</script>
</foo>
</code></pre>
<p>Ensure no angle brackets were stripped.</p>
HTML
#-------------------------------------------------------------------------------
$test = "don't escape the HTML of syntax highlighting";
$content = <<'MARKDOWN';
This is how you highlight HTML:
<pre lang="HTML">
HTML <b>text</b> here with some <div>tags</div>.
</pre>
HTML formatting generated by the SyntaxHighlight formatter must not be escaped by Markdown
MARKDOWN
if (MojoMojo::Formatter::SyntaxHighlight->module_loaded) {
$expected = <<'HTML';
<p>This is how you highlight HTML:</p>
<pre>
HTML <b><b></b>text<b></b></b> here with some <b><div></b>tags<b></div></b>.
</pre>
<p>HTML formatting generated by the SyntaxHighlight formatter must not be escaped by Markdown</p>
HTML
} else {
# if Syntax::Highlight::Engine::Kate (or whatever syntax highlight module is used) isn't loaded,
# expect an unadulterated <pre>. Currently, this fails because Defang steps in.
$expected = <<'HTML';
<p>This is how you highlight HTML:</p>
<pre lang="HTML">
HTML <b>text</b> here with some <div>tags</div>.
</pre>
<p>HTML formatting generated by the SyntaxHighlight formatter must not be escaped by Markdown</p>
HTML
}
$got = get( POST '/.jsrpc/render', [ content => $content ] );
eq_or_diff( $got, $expected, $test );
#-------------------------------------------------------------------------------
TODO: {
local $TODO = "priority of wiki link interpretation must be tweaked with regards to <pre>, and Defang must not mess up <pre lang=''>";
$test = "no wiki link hyperlinking in multi-line <pre> sections";
$content = <<'MARKDOWN';
<pre lang="Perl">
# A comment, not a heading
[this isn't](a link)
[[this isn't a wikilink]]
|| this is not | a table ||
|| this is | a <pre> element ||
</pre>
MARKDOWN
if (MojoMojo::Formatter::SyntaxHighlight->module_loaded) {
$expected = <<'HTML';
<pre><span class="kateComment"><i># A comment, not a heading</i></span><span class="kateComment"><i>
</i></span>[this isn<span class="kateOperator">'</span><span class="kateString">t](a link)</span><span class="kateString">
</span><span class="kateString">[[this isn</span><span class="kateOperator">'</span>t a wikilink]]
|| this is <span class="kateOperator">not</span> | a table ||
|| this is | a <pre> element ||
</pre>
HTML
} else {
# if Syntax::Highlight::Engine::Kate (or whatever syntax highlight module is used) isn't loaded,
# expect an unadulterated <pre>. Currently, this fails because Defang steps in.
$expected = <<'HTML';
<pre lang="Perl">
# A comment, not a heading
[this isn't](a link)
[[this isn't a wikilink]]
|| this is not | a table ||
|| this is | a <pre> element ||
</pre>
HTML
}
$got = get( POST '/.jsrpc/render', [ content => $content ] );
eq_or_diff( $got, $expected, $test );
}
#----------------------------------------------------------------------------
$test = '<div> with HTML attribute in a code span';
$content = <<'MARKDOWN';
This is the code: `<div class="content">`.
MARKDOWN
$got = get( POST '/.jsrpc/render', [ content => $content ] );
eq_or_diff( $got, <<'HTML', $test );
<p>This is the code: <code><div class="content"></code>.</p>
HTML
$test = '<div> with non-standard HTML attribute> in a code span - the HTML scrubber should leave this alone';
$content = <<'MARKDOWN';
This quoted div has an ARIA role attribute: `<div role="content">`.
MARKDOWN
$got = get( POST '/.jsrpc/render', [ content => $content ] );
eq_or_diff( $got, <<'HTML', $test );
<p>This quoted div has an ARIA role attribute: <code><div role="content"></code>.</p>
HTML
$test = '<br/>s need to be preserved';
$content = <<'MARKDOWN';
Roses are red<br/>
Violets are blue
MARKDOWN
$got = get( POST '/.jsrpc/render', [ content => $content ] );
eq_or_diff( $got, <<'HTML', $test );
<p>Roses are red<br/>
Violets are blue</p>
HTML
#-------------------------------------------------------------------------------
$test = 'blockquotes';
$content = <<'MARKDOWN';
Below is a blockquote:
> quoted text
A quote is above.
MARKDOWN
$got = get( POST '/.jsrpc/render', [ content => $content ] );
eq_or_diff( $got, <<'HTML', $test );
<p>Below is a blockquote:</p>
<blockquote>
<p>quoted text</p>
</blockquote>
<p>A quote is above.</p>
HTML
#-------------------------------------------------------------------------------
$test = 'wikilink to ../new_sibling';
$content = <<'MARKDOWN';
This is a child page with a link to a [[../new_sibling]].
MARKDOWN
$got = get( POST '/parent/child.jsrpc/render', [ content => $content ] );
is( $got, <<'HTML', $test );
<p>This is a child page with a link to a <span class="newWikiWord"><a title="Not found. Click to create this page." href="/parent/new_sibling.edit">new sibling?</a></span>.</p>
HTML
#-------------------------------------------------------------------------------
$test = '<div> with markdown="1"';
$content = <<'MARKDOWN';
We want to be able to have Markdown interpreted in `<div markdown="1">` sections
so that we can build sidebars, photo divs etc.
<div class="navbar" markdown="1">
* [[Home]]
* [[Products]]
* [[About]]
![alt text](/.static/catalyst.png "Image title")
<span style="color: green">This is an image caption</span>
</div>
The above should render as a list of items with an image and caption below.
MARKDOWN
$got = get( POST '/.jsrpc/render', [ content => $content ] );
eq_or_diff( $got, <<'HTML', $test );
<p>We want to be able to have Markdown interpreted in <code><div markdown="1"></code> sections
so that we can build sidebars, photo divs etc.</p>
<div class="navbar">
<ul>
<li><span class="newWikiWord"><a title="Not found. Click to create this page." href="/Home.edit">Home?</a></span></li>
<li><span class="newWikiWord"><a title="Not found. Click to create this page." href="/Products.edit">Products?</a></span></li>
<li><span class="newWikiWord"><a title="Not found. Click to create this page." href="/About.edit">About?</a></span></li>
</ul>
<p><img src="/.static/catalyst.png" alt="alt text" title="Image title" />
<span style="color: green">This is an image caption</span></p>
</div>
<p>The above should render as a list of items with an image and caption below.</p>
HTML
#-------------------------------------------------------------------------------
$test = 'Markdown should not parse block-level markdown in <pre> tags';
$content = <<'MARKDOWN';
<pre lang="Perl">
# A comment, not a heading
</pre>
MARKDOWN
if (MojoMojo::Formatter::SyntaxHighlight->module_loaded) {
$expected = <<'HTML_HIGHLIGHTED';
<pre>
<span class="kateComment"><i># A comment, not a heading</i></span><span class="kateComment"><i>
</i></span></pre>
HTML_HIGHLIGHTED
} else {
$expected = <<'HTML_UNPROCESSED';
<pre lang="Perl">
# A comment, not a heading
</pre>
HTML_UNPROCESSED
}
$got = get( POST '/.jsrpc/render', [ content => $content ] );
# note the newline enclosed in a kateComment. That's just the way Kate outputs it, even if perhaps not the most fortunate.
eq_or_diff( $got, $expected, $test );
#-------------------------------------------------------------------------------
$test = 'in <pre>, 4 leading spaces should not be interpreted as another <pre>';
$content = <<'MARKDOWN';
<pre>
if (...) {
foo();
}
</pre>
MARKDOWN
$got = get( POST '/.jsrpc/render', [ content => $content ] );
eq_or_diff( $got, <<'HTML', $test );
<pre>
if (...) {
foo();
}
</pre>
HTML
#-------------------------------------------------------------------------------
$test = 'in <pre lang=...>, 4 leading spaces should not be interpreted as another <pre>';
$content = <<'MARKDOWN';
<pre lang="Perl">
if (...) {
foo();
}
</pre>
MARKDOWN
if (MojoMojo::Formatter::SyntaxHighlight->module_loaded) {
$expected = <<'HTML_HIGHLIGHTED';
<pre>
<b>if</b> (...) {
foo();
}
</pre>
HTML_HIGHLIGHTED
} else {
$expected = <<'HTML_UNPROCESSED';
<pre lang="Perl">
if (...) {
foo();
}
</pre>
HTML_UNPROCESSED
}
$got = get( POST '/.jsrpc/render', [ content => $content ] );
# Kate has another bug here, that the 'if' should be in a <span class="kateOperator">,
# not simply in <b>if</b>
eq_or_diff( $got, $expected, $test );
#-------------------------------------------------------------------------------
$test = 'POD while Markdown is the main formatter';
$content = <<'MARKDOWN';
{{pod}}
=head1 NAME
Some POD here
{{end}}
MARKDOWN
$got = get( POST '/.jsrpc/render', [ content => $content ] );
like($got, qr'<h1><a.*NAME.*/h1>'s, "POD: there is an h1 NAME");
#-------------------------------------------------------------------------------
# Formerly: Text::MultiMarkdown bug, see http://github.com/bobtfish/text-multimarkdown/commit/6600cef8e22a988b9a87750f1a144c7706784548";
$test = 'Underscore in code in footnotes becomes 128-bit hash';
$content = <<'MARKDOWN';
This is buggy[^bug].
[^bug]: Use `MYAPP_CONFIG_LOCAL_SUFFIX`.
MARKDOWN
$got = get( POST '/.jsrpc/render', [ content => $content ] );
like($got, qr/MYAPP_CONFIG_LOCAL_SUFFIX/s, "'MYAPP_CONFIG_LOCAL_SUFFIX' in footnote");
#-------------------------------------------------------------------------------
$test = '"<code>" and "<tt>" strings in <pre lang="Perl"> run through the JSRPC renderer';
$content = <<MARKDOWN;
<pre lang="Perl">
"Monotype: use <tt>.";
"Source code: <code>.";
</pre>
MARKDOWN
if (MojoMojo::Formatter::SyntaxHighlight->module_loaded) {
$expected = <<'HTML_HIGHLIGHTED';
<pre>
<span class="kateOperator">"</span><span class="kateString">Monotype: use <tt>.</span><span class="kateOperator">"</span>;
<span class="kateOperator">"</span><span class="kateString">Source code: <code>.</span><span class="kateOperator">"</span>;
</pre>
HTML_HIGHLIGHTED
} else {
$expected = <<'HTML_UNPROCESSED';
<pre lang="Perl">
"Monotype: use <tt>.";
"Source code: <code>.";
</pre>
HTML_UNPROCESSED
}
$got = get( POST '/.jsrpc/render', [ content => $content ] );
eq_or_diff( $got, $expected, $test );
#-------------------------------------------------------------------------------
$test = "newline present before EOF";
$content = 'Markdown ensures the output ends with a newline';
$expected = "<p>Markdown ensures the output ends with a newline</p>\n";
$got = get( POST '/.jsrpc/render', [ content => $content ] );
is $got, $expected, $test;
$test = "multiple newlines at EOF collapsed into one";
$content = "Markdown ensures the output ends with *one* newline\n\n\n";
$expected = "<p>Markdown ensures the output ends with <em>one</em> newline</p>\n";
$got = get( POST '/.jsrpc/render', [ content => $content ] );
is $got, $expected, $test;