1#!/usr/bin/perl -w
2
3# t/xhtml01.t - check basic output from Pod::Simple::XHTML
4
5BEGIN {
6    chdir 't' if -d 't';
7}
8
9use strict;
10use warnings;
11use lib '../lib';
12use Test::More tests => 64;
13#use Test::More 'no_plan';
14
15use_ok('Pod::Simple::XHTML') or exit;
16
17my $parser = Pod::Simple::XHTML->new ();
18isa_ok ($parser, 'Pod::Simple::XHTML');
19
20my $results;
21
22my $PERLDOC = "https://metacpan.org/pod";
23my $MANURL = "http://man.he.net/man";
24
25initialize($parser, $results);
26$parser->parse_string_document( "=head1 Poit!" );
27is($results, qq{<h1 id="Poit">Poit!</h1>\n\n}, "head1 level output");
28
29initialize($parser, $results);
30$parser->parse_string_document( "=head2 Yada Yada Operator
31X<...> X<... operator> X<yada yada operator>" );
32is($results, qq{<h2 id="Yada-Yada-Operator">Yada Yada Operator   </h2>\n\n}, "head ID with X<>");
33
34initialize($parser, $results);
35$parser->parse_string_document( "=head2 Platforms with no supporting programmers:");
36is($results, qq{<h2 id="Platforms-with-no-supporting-programmers">Platforms with no supporting programmers:</h2>\n\n}, "head ID ending in colon");
37
38initialize($parser, $results);
39$parser->html_h_level(2);
40$parser->parse_string_document( "=head1 Poit!" );
41is($results, qq{<h2 id="Poit">Poit!</h2>\n\n}, "head1 level output h_level 2");
42
43initialize($parser, $results);
44$parser->parse_string_document( "=head2 I think so Brain." );
45is($results, qq{<h2 id="I-think-so-Brain">I think so Brain.</h2>\n\n}, "head2 level output");
46
47initialize($parser, $results);
48$parser->parse_string_document( "=head3 I say, Brain..." );
49is($results, qq{<h3 id="I-say-Brain">I say, Brain...</h3>\n\n}, "head3 level output");
50
51initialize($parser, $results);
52$parser->parse_string_document( "=head4 Zort & Zog!" );
53is($results, qq{<h4 id="Zort-Zog">Zort &amp; Zog!</h4>\n\n}, "head4 level output");
54
55initialize($parser, $results);
56$parser->parse_string_document( "=head5 I think so Brain, but..." );
57is($results, qq{<h5 id="I-think-so-Brain-but">I think so Brain, but...</h5>\n\n}, "head5 level output");
58
59initialize($parser, $results);
60$parser->parse_string_document( "=head6 Narf!" );
61is($results, qq{<h6 id="Narf">Narf!</h6>\n\n}, "head6 level output");
62
63sub x {
64  my $code = $_[1];
65  Pod::Simple::XHTML->_out(
66  sub { $code->($_[0]) if $code },
67  "=pod\n\n$_[0]",
68) }
69
70like(
71  x("=head1 Header\n\n=for html <div>RAW<span>!</span></div>\n\nDone."),
72  qr/.+<\/h1>\s+<div>RAW<span>!<\/span><\/div>\s+.*/sm,
73  "heading building"
74) or exit;
75
76initialize($parser, $results);
77$parser->parse_string_document(<<'EOPOD');
78=pod
79
80Gee, Brain, what do you want to do tonight?
81EOPOD
82
83is($results, <<'EOHTML', "simple paragraph");
84<p>Gee, Brain, what do you want to do tonight?</p>
85
86EOHTML
87
88
89initialize($parser, $results);
90$parser->parse_string_document(<<'EOPOD');
91=pod
92
93B: Now, Pinky, if by any chance you are captured during this mission,
94remember you are Gunther Heindriksen from Appenzell. You moved to
95Grindelwald to drive the cog train to Murren. Can you repeat that?
96
97P: Mmmm, no, Brain, dont think I can.
98EOPOD
99
100is($results, <<'EOHTML', "multiple paragraphs");
101<p>B: Now, Pinky, if by any chance you are captured during this mission, remember you are Gunther Heindriksen from Appenzell. You moved to Grindelwald to drive the cog train to Murren. Can you repeat that?</p>
102
103<p>P: Mmmm, no, Brain, dont think I can.</p>
104
105EOHTML
106
107initialize($parser, $results);
108$parser->parse_string_document(<<'EOPOD');
109=over
110
111=item *
112
113P: Gee, Brain, what do you want to do tonight?
114
115=item *
116
117B: The same thing we do every night, Pinky. Try to take over the world!
118
119=back
120
121EOPOD
122
123is($results, <<'EOHTML', "simple bulleted list");
124<ul>
125
126<li><p>P: Gee, Brain, what do you want to do tonight?</p>
127
128</li>
129<li><p>B: The same thing we do every night, Pinky. Try to take over the world!</p>
130
131</li>
132</ul>
133
134EOHTML
135
136
137initialize($parser, $results);
138$parser->parse_string_document(<<'EOPOD');
139=over
140
141=item *
142
143P: Gee, Brain, what do you want to do tonight?
144
145=item *
146
147B: The same thing we do every night, Pinky. Try to take over the world!
148
149=over
150
151=item *
152
153Take over world
154
155=item *
156
157Do laundry
158
159=back
160
161=back
162
163EOPOD
164
165is($results, <<'EOHTML', "nested bulleted list");
166<ul>
167
168<li><p>P: Gee, Brain, what do you want to do tonight?</p>
169
170</li>
171<li><p>B: The same thing we do every night, Pinky. Try to take over the world!</p>
172
173<ul>
174
175<li><p>Take over world</p>
176
177</li>
178<li><p>Do laundry</p>
179
180</li>
181</ul>
182
183</li>
184</ul>
185
186EOHTML
187
188
189
190initialize($parser, $results);
191$parser->parse_string_document(<<'EOPOD');
192=over
193
194=item 1
195
196P: Gee, Brain, what do you want to do tonight?
197
198=item 2
199
200B: The same thing we do every night, Pinky. Try to take over the world!
201
202=back
203
204EOPOD
205
206is($results, <<'EOHTML', "numbered list");
207<ol>
208
209<li><p>P: Gee, Brain, what do you want to do tonight?</p>
210
211</li>
212<li><p>B: The same thing we do every night, Pinky. Try to take over the world!</p>
213
214</li>
215</ol>
216
217EOHTML
218
219
220initialize($parser, $results);
221$parser->parse_string_document(<<'EOPOD');
222=over
223
224=item 1
225
226P: Gee, Brain, what do you want to do tonight?
227
228=item 2
229
230B: The same thing we do every night, Pinky. Try to take over the world!
231
232=over
233
234=item 1
235
236Take over world
237
238=item 2
239
240Do laundry
241
242=back
243
244=back
245
246EOPOD
247
248is($results, <<'EOHTML', "nested numbered list");
249<ol>
250
251<li><p>P: Gee, Brain, what do you want to do tonight?</p>
252
253</li>
254<li><p>B: The same thing we do every night, Pinky. Try to take over the world!</p>
255
256<ol>
257
258<li><p>Take over world</p>
259
260</li>
261<li><p>Do laundry</p>
262
263</li>
264</ol>
265
266</li>
267</ol>
268
269EOHTML
270
271
272initialize($parser, $results);
273$parser->parse_string_document(<<'EOPOD');
274=over
275
276=item Pinky
277
278Gee, Brain, what do you want to do tonight?
279
280=item Brain
281
282The same thing we do every night, Pinky. Try to take over the world!
283
284=back
285
286EOPOD
287
288is($results, <<'EOHTML', "list with text headings");
289<dl>
290
291<dt>Pinky</dt>
292<dd>
293
294<p>Gee, Brain, what do you want to do tonight?</p>
295
296</dd>
297<dt>Brain</dt>
298<dd>
299
300<p>The same thing we do every night, Pinky. Try to take over the world!</p>
301
302</dd>
303</dl>
304
305EOHTML
306
307initialize($parser, $results);
308$parser->parse_string_document(<<'EOPOD');
309=over
310
311=item * Pinky
312
313Gee, Brain, what do you want to do tonight?
314
315=item * Brain
316
317The same thing we do every night, Pinky. Try to take over the world!
318
319=back
320
321EOPOD
322
323is($results, <<'EOHTML', "list with bullet and text headings");
324<ul>
325
326<li><p>Pinky</p>
327
328<p>Gee, Brain, what do you want to do tonight?</p>
329
330</li>
331<li><p>Brain</p>
332
333<p>The same thing we do every night, Pinky. Try to take over the world!</p>
334
335</li>
336</ul>
337
338EOHTML
339
340initialize($parser, $results);
341$parser->parse_string_document(<<'EOPOD');
342=over
343
344=item * Brain <brain@binkyandthebrain.com>
345
346=item * Pinky <pinky@binkyandthebrain.com>
347
348=back
349
350EOPOD
351
352is($results, <<'EOHTML', "bulleted author list");
353<ul>
354
355<li><p>Brain &lt;brain@binkyandthebrain.com&gt;</p>
356
357</li>
358<li><p>Pinky &lt;pinky@binkyandthebrain.com&gt;</p>
359
360</li>
361</ul>
362
363EOHTML
364
365initialize($parser, $results);
366$parser->parse_string_document(<<'EOPOD');
367=over
368
369=item Pinky
370
371=over
372
373=item World Domination
374
375=back
376
377=item Brain
378
379=back
380
381EOPOD
382
383is($results, <<'EOHTML', 'nested lists');
384<dl>
385
386<dt>Pinky</dt>
387<dd>
388
389<dl>
390
391<dt>World Domination</dt>
392<dd>
393
394</dd>
395</dl>
396
397</dd>
398<dt>Brain</dt>
399<dd>
400
401</dd>
402</dl>
403
404EOHTML
405
406initialize($parser, $results);
407$parser->parse_string_document(<<'EOPOD');
408=over
409
410=item Pinky
411
412On the list:
413
414=over
415
416=item World Domination
417
418Fight the good fight
419
420=item Go to Europe
421
422(Steve Martin joke)
423
424=back
425
426=item Brain
427
428Not so much
429
430=back
431
432EOPOD
433
434is($results, <<'EOHTML', 'multiparagraph nested lists');
435<dl>
436
437<dt>Pinky</dt>
438<dd>
439
440<p>On the list:</p>
441
442<dl>
443
444<dt>World Domination</dt>
445<dd>
446
447<p>Fight the good fight</p>
448
449</dd>
450<dt>Go to Europe</dt>
451<dd>
452
453<p>(Steve Martin joke)</p>
454
455</dd>
456</dl>
457
458</dd>
459<dt>Brain</dt>
460<dd>
461
462<p>Not so much</p>
463
464</dd>
465</dl>
466
467EOHTML
468
469initialize($parser, $results);
470$parser->parse_string_document(<<'EOPOD');
471=pod
472
473  1 + 1 = 2;
474  2 + 2 = 4;
475
476EOPOD
477
478is($results, <<'EOHTML', "code block");
479<pre><code>  1 + 1 = 2;
480  2 + 2 = 4;</code></pre>
481
482EOHTML
483
484
485initialize($parser, $results);
486$parser->parse_string_document(<<'EOPOD');
487=pod
488
489A plain paragraph with a C<functionname>.
490
491C<< This code is B<important> to E<lt>me>! >>
492
493EOPOD
494is($results, <<"EOHTML", "code entity in a paragraph");
495<p>A plain paragraph with a <code>functionname</code>.</p>
496
497<p><code>This code is <b>important</b> to &lt;me&gt;!</code></p>
498
499EOHTML
500
501
502initialize($parser, $results);
503$parser->html_header("<html>\n<body>");
504$parser->html_footer("</body>\n</html>");
505$parser->parse_string_document(<<'EOPOD');
506=pod
507
508A plain paragraph with body tags turned on.
509EOPOD
510is($results, <<"EOHTML", "adding html body tags");
511<html>
512<body>
513
514<p>A plain paragraph with body tags turned on.</p>
515
516</body>
517</html>
518
519EOHTML
520
521
522initialize($parser, $results);
523$parser->html_css('style.css');
524$parser->html_header(undef);
525$parser->html_footer(undef);
526$parser->parse_string_document(<<'EOPOD');
527=pod
528
529A plain paragraph with body tags and css tags turned on.
530EOPOD
531like($results, qr/<link rel="stylesheet" href="style.css" type="text\/css" \/>/,
532"adding html body tags and css tags");
533
534
535initialize($parser, $results);
536$parser->parse_string_document(<<'EOPOD');
537=pod
538
539A plain paragraph with S<non breaking text>.
540EOPOD
541is($results, <<"EOHTML", "Non breaking text in a paragraph");
542<p>A plain paragraph with <span style="white-space: nowrap;">non breaking text</span>.</p>
543
544EOHTML
545
546initialize($parser, $results);
547$parser->parse_string_document(<<'EOPOD');
548=pod
549
550A plain paragraph with a L<Newlines>.
551EOPOD
552is($results, <<"EOHTML", "Link entity in a paragraph");
553<p>A plain paragraph with a <a href="$PERLDOC/Newlines">Newlines</a>.</p>
554
555EOHTML
556
557initialize($parser, $results);
558$parser->parse_string_document(<<'EOPOD');
559=pod
560
561A plain paragraph with a L<perlport/Newlines>.
562EOPOD
563is($results, <<"EOHTML", "Link entity in a paragraph");
564<p>A plain paragraph with a <a href="$PERLDOC/perlport#Newlines">&quot;Newlines&quot; in perlport</a>.</p>
565
566EOHTML
567
568initialize($parser, $results);
569$parser->parse_string_document(<<'EOPOD');
570=pod
571
572A plain paragraph with a L<Boo|http://link.included.here>.
573EOPOD
574is($results, <<"EOHTML", "A link in a paragraph");
575<p>A plain paragraph with a <a href="http://link.included.here">Boo</a>.</p>
576
577EOHTML
578
579initialize($parser, $results);
580$parser->parse_string_document(<<'EOPOD');
581=pod
582
583A plain paragraph with a L<http://link.included.here>.
584EOPOD
585is($results, <<"EOHTML", "A link in a paragraph");
586<p>A plain paragraph with a <a href="http://link.included.here">http://link.included.here</a>.</p>
587
588EOHTML
589
590initialize($parser, $results);
591$parser->parse_string_document(<<'EOPOD');
592=pod
593
594A plain paragraph with a L<http://link.included.here?o=1&p=2>.
595EOPOD
596is($results, <<"EOHTML", "A link in a paragraph");
597<p>A plain paragraph with a <a href="http://link.included.here?o=1&amp;p=2">http://link.included.here?o=1&amp;p=2</a>.</p>
598
599EOHTML
600
601initialize($parser, $results);
602$parser->parse_string_document(<<'EOPOD');
603=pod
604
605A plain paragraph with B<bold text>.
606EOPOD
607is($results, <<"EOHTML", "Bold text in a paragraph");
608<p>A plain paragraph with <b>bold text</b>.</p>
609
610EOHTML
611
612initialize($parser, $results);
613$parser->parse_string_document(<<'EOPOD');
614=pod
615
616A plain paragraph with I<italic text>.
617EOPOD
618is($results, <<"EOHTML", "Italic text in a paragraph");
619<p>A plain paragraph with <i>italic text</i>.</p>
620
621EOHTML
622
623initialize($parser, $results);
624$parser->parse_string_document(<<'EOPOD');
625=pod
626
627A plain paragraph with a F<filename>.
628EOPOD
629is($results, <<"EOHTML", "File name in a paragraph");
630<p>A plain paragraph with a <i>filename</i>.</p>
631
632EOHTML
633
634# It's not important that 's (apostrophes) be encoded for XHTML output.
635initialize($parser, $results);
636$parser->parse_string_document(<<'EOPOD');
637=pod
638
639  # this header is very important & dont you forget it
640  my $text = "File is: " . <FILE>;
641EOPOD
642is($results, <<"EOHTML", "Verbatim text with encodable entities");
643<pre><code>  # this header is very important &amp; dont you forget it
644  my \$text = &quot;File is: &quot; . &lt;FILE&gt;;</code></pre>
645
646EOHTML
647
648initialize($parser, $results);
649$parser->parse_string_document(<<'EOPOD');
650=pod
651
652A text paragraph using E<sol> and E<verbar> special POD entities.
653
654EOPOD
655is($results, <<"EOHTML", "Text with decodable entities");
656<p>A text paragraph using / and | special POD entities.</p>
657
658EOHTML
659
660initialize($parser, $results);
661$parser->parse_string_document(<<'EOPOD');
662=pod
663
664A text paragraph using numeric POD entities: E<60>, E<62>.
665
666EOPOD
667is($results, <<"EOHTML", "Text with numeric entities");
668<p>A text paragraph using numeric POD entities: &lt;, &gt;.</p>
669
670EOHTML
671
672my $html = q{<tt>
673<pre>
674#include &lt;stdio.h&gt;
675
676int main(int argc,char *argv[]) {
677
678        printf("Hellow World\n");
679        return 0;
680
681}
682</pre>
683</tt>};
684initialize($parser, $results);
685$parser->parse_string_document("=begin html\n\n$html\n\n=end html\n");
686is($results, "$html\n\n", "Text with =begin html");
687
688SKIP: for my $use_html_entities (0, 1) {
689  if ($use_html_entities and not $Pod::Simple::XHTML::HAS_HTML_ENTITIES) {
690    skip("HTML::Entities not installed", 3);
691  }
692  local $Pod::Simple::XHTML::HAS_HTML_ENTITIES = $use_html_entities;
693  initialize($parser, $results);
694  $parser->codes_in_verbatim(1);
695  $parser->parse_string_document(<<'EOPOD');
696=pod
697
698  # this header is very important & dont you forget it
699  B<my $file = <FILEE<gt> || Blank!;>
700  my $text = "File is: " . <FILE>;
701EOPOD
702is($results, <<"EOHTML", "Verbatim text with markup and embedded formatting");
703<pre><code>  # this header is very important &amp; dont you forget it
704  <b>my \$file = &lt;FILE&gt; || Blank!;</b>
705  my \$text = &quot;File is: &quot; . &lt;FILE&gt;;</code></pre>
706
707EOHTML
708
709  # Specify characters to encode.
710  initialize($parser, $results);
711  $parser->html_encode_chars('><"&T');
712  $parser->parse_string_document(<<'EOPOD');
713=pod
714
715This is Anna's "Answer" to the <q>Question</q>.
716
717=cut
718
719EOPOD
720my $T = $use_html_entities ? ord('T') : sprintf ("x%X", ord('T'));
721is($results, <<"EOHTML", 'HTML Entities should be only for specified characters');
722<p>&#$T;his is Anna's &quot;Answer&quot; to the &lt;q&gt;Question&lt;/q&gt;.</p>
723
724EOHTML
725
726  # Keep =encoding out of content.
727  initialize($parser, $results);
728  $parser->parse_string_document("=encoding ascii\n\n=head1 NAME\n");
729  is($results, <<"EOHTML", 'Encoding should not be in content')
730<h1 id="NAME">NAME</h1>
731
732EOHTML
733
734}
735
736
737ok $parser = Pod::Simple::XHTML->new, 'Construct a new parser';
738$results = '';
739$parser->output_string( \$results ); # Send the resulting output to a string
740ok $parser->parse_string_document( "=head1 Poit!" ), 'Parse with headers';
741like $results, qr{\Q<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />},
742    'Should have proper http-equiv meta tag';
743
744ok $parser = Pod::Simple::XHTML->new, 'Construct a new parser again';
745ok $parser->html_charset('UTF-8'), 'Set the html charset to UTF-8';
746$results = '';
747$parser->output_string( \$results ); # Send the resulting output to a string
748ok $parser->parse_string_document( "=head1 Poit!" ), 'Parse with headers';
749like $results, qr{\Q<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />},
750    'Should have http-equiv meta tag with UTF-8';
751
752# Test the link generation methods.
753is $parser->resolve_pod_page_link('Net::Ping', 'INSTALL'),
754    "$PERLDOC/Net::Ping#INSTALL",
755    'POD link with fragment';
756is $parser->resolve_pod_page_link('perlpodspec'),
757    "$PERLDOC/perlpodspec", 'Simple POD link';
758is $parser->resolve_pod_page_link(undef, 'SYNOPSIS'), '#SYNOPSIS',
759    'Simple fragment link';
760is $parser->resolve_pod_page_link(undef, 'this that'), '#this-that',
761    'Fragment link with space';
762is $parser->resolve_pod_page_link('perlpod', 'this that'),
763    "$PERLDOC/perlpod#this-that",
764    'POD link with fragment with space';
765
766is $parser->resolve_man_page_link('crontab(5)', 'EXAMPLE CRON FILE'),
767    "${MANURL}5/crontab", 'Man link with fragment';
768is $parser->resolve_man_page_link('crontab(5)'),
769    "${MANURL}5/crontab", 'Man link without fragment';
770is $parser->resolve_man_page_link('crontab'),
771    "${MANURL}1/crontab", 'Man link without section';
772
773# Make sure that batch_mode_page_object_init() works.
774ok $parser->batch_mode_page_object_init(0, 0, 0, 0, 6),
775    'Call batch_mode_page_object_init()';
776ok $parser->batch_mode, 'We should be in batch mode';
777is $parser->batch_mode_current_level, 6,
778    'The level should have been set';
779
780######################################
781
782sub initialize {
783	$_[0] = Pod::Simple::XHTML->new ();
784        $_[0]->html_header("");
785        $_[0]->html_footer("");
786	$_[0]->output_string( \$results ); # Send the resulting output to a string
787	$_[1] = '';
788	return;
789}
790