Info.pm 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. # Info.pm: output tree as Info.
  2. #
  3. # Copyright 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
  4. # Free Software Foundation, Inc.
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 3 of the License,
  9. # or (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. #
  19. # Original author: Patrice Dumas <pertusus@free.fr>
  20. package Texinfo::Convert::Info;
  21. use 5.00405;
  22. use strict;
  23. use Texinfo::Convert::Plaintext;
  24. use Texinfo::Convert::Text;
  25. use Texinfo::Convert::Paragraph;
  26. require Exporter;
  27. use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  28. @ISA = qw(Texinfo::Convert::Plaintext);
  29. # Items to export into callers namespace by default. Note: do not export
  30. # names by default without a very good reason. Use EXPORT_OK instead.
  31. # Do not simply export all your public functions/methods/constants.
  32. # This allows declaration use Texinfo::Convert::Info ':all';
  33. # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
  34. # will save memory.
  35. %EXPORT_TAGS = ( 'all' => [ qw(
  36. convert
  37. ) ] );
  38. @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
  39. @EXPORT = qw(
  40. );
  41. $VERSION = '6.3.90';
  42. my $STDIN_DOCU_NAME = 'stdin';
  43. my %defaults = Texinfo::Convert::Plaintext::converter_defaults(undef, undef);
  44. $defaults{'SHOW_MENU'} = 1;
  45. $defaults{'EXTENSION'} = 'info';
  46. $defaults{'USE_SETFILENAME_EXTENSION'} = 1;
  47. $defaults{'OUTFILE'} = undef;
  48. sub converter_defaults($$)
  49. {
  50. return %defaults;
  51. }
  52. sub output($)
  53. {
  54. my $self = shift;
  55. my $root = shift;
  56. my $result;
  57. $self->_set_outfile();
  58. $self->{'input_basename'} = $STDIN_DOCU_NAME if ($self->{'input_basename'} eq '-');
  59. # no splitting when writing to the null device or to stdout
  60. if ($Texinfo::Common::null_device_file{$self->{'output_file'}}
  61. or $self->{'output_file'} eq '-') {
  62. $self->force_conf('SPLIT_SIZE', undef);
  63. }
  64. push @{$self->{'count_context'}}, {'lines' => 0, 'bytes' => 0,
  65. 'locations' => []};
  66. my $header = $self->_info_header();
  67. # header + text between setfilename and first node
  68. my $complete_header = $header;
  69. pop @{$self->{'count_context'}};
  70. return undef unless $self->_create_destination_directory();
  71. my $header_bytes = Texinfo::Convert::Plaintext::count_bytes($self, $header);
  72. my $complete_header_bytes = $header_bytes;
  73. my $elements = Texinfo::Structuring::split_by_node($root);
  74. my $fh;
  75. if (! $self->{'output_file'} eq '') {
  76. if ($self->get_conf('VERBOSE')) {
  77. print STDERR "Output file $self->{'output_file'}\n";
  78. }
  79. $fh = _open_info_file($self, $self->{'output_file'});
  80. if (!$fh) {
  81. return undef;
  82. }
  83. }
  84. print STDERR "DOCUMENT\n" if ($self->get_conf('DEBUG'));
  85. my $out_file_nr = 0;
  86. my @indirect_files;
  87. if (!defined($elements) or $elements->[0]->{'extra'}->{'no_node'}) {
  88. $self->file_line_warn($self->__("document without nodes"),
  89. $self->{'info'}->{'input_file_name'});
  90. my $output = $header.$self->_convert($root);
  91. $self->_count_context_bug_message('no element ');
  92. my $footnotes = $self->_footnotes();
  93. $self->_count_context_bug_message('no element footnotes ');
  94. $output .= $footnotes;
  95. if ($fh) {
  96. print $fh $output;
  97. } else {
  98. $result = $output;
  99. }
  100. } else {
  101. unless ($self->{'structuring'} and $self->{'structuring'}->{'top_node'}
  102. and $self->{'structuring'}->{'top_node'}->{'extra'}->{'normalized'} eq 'Top') {
  103. $self->file_line_warn($self->__("document without Top node"),
  104. $self->{'info'}->{'input_file_name'});
  105. }
  106. $out_file_nr = 1;
  107. my $first_node = 0;
  108. $self->{'count_context'}->[-1]->{'bytes'} += $header_bytes;
  109. my @nodes = @$elements;
  110. while (@nodes) {
  111. my $node = shift @nodes;
  112. my $node_text = $self->_convert_element($node);
  113. if (!$first_node) {
  114. $first_node = 1;
  115. if (defined($self->{'text_before_first_node'})) {
  116. $complete_header .= $self->{'text_before_first_node'};
  117. $complete_header_bytes += Texinfo::Convert::Plaintext::count_bytes($self, $self->{'text_before_first_node'});
  118. }
  119. # for the first node, header is prepended, not complete_header
  120. # as 'text_before_first_node' is already part of the node
  121. # text
  122. $node_text = $header . $node_text;
  123. }
  124. if ($fh) {
  125. print $fh $node_text;
  126. } else {
  127. $result .= $node_text;
  128. }
  129. $self->_update_count_context();
  130. if (defined($self->get_conf('SPLIT_SIZE'))
  131. and $self->{'count_context'}->[-1]->{'bytes'} >
  132. $out_file_nr * $self->get_conf('SPLIT_SIZE')
  133. and @nodes and $fh) {
  134. my $close_error;
  135. if (!close ($fh)) {
  136. $close_error = $!;
  137. }
  138. if ($out_file_nr == 1) {
  139. $self->register_close_file($self->{'output_file'});
  140. if (defined($close_error)) {
  141. $self->document_error(sprintf($self->__("error on closing %s: %s"),
  142. $self->{'output_file'}, $close_error));
  143. return undef;
  144. }
  145. if ($self->get_conf('VERBOSE')) {
  146. print STDERR "Renaming first output file as ".
  147. $self->{'output_file'}.'-'.$out_file_nr."\n";
  148. }
  149. unless (rename($self->{'output_file'},
  150. $self->{'output_file'}.'-'.$out_file_nr)) {
  151. $self->document_error(sprintf($self->__("rename %s failed: %s"),
  152. $self->{'output_file'}, $!));
  153. return undef;
  154. }
  155. # remove the main file from opened files since it was renamed
  156. # and add the file with a number.
  157. @{$self->{'opened_files'}} = grep {$_ ne $self->{'output_file'}}
  158. @{$self->{'opened_files'}};
  159. push @{$self->{'opened_files'}},
  160. $self->{'output_file'}.'-'.$out_file_nr;
  161. push @indirect_files, [$self->{'output_filename'}.'-'.$out_file_nr,
  162. $complete_header_bytes];
  163. #print STDERR join(' --> ', @{$indirect_files[-1]}) ."\n";
  164. } else {
  165. $self->register_close_file($self->{'output_file'}.'-'.$out_file_nr);
  166. if (defined($close_error)) {
  167. $self->document_error(sprintf($self->__("error on closing %s: %s"),
  168. $self->{'output_file'}.'-'.$out_file_nr,
  169. $close_error));
  170. return undef;
  171. }
  172. }
  173. $out_file_nr++;
  174. if ($self->get_conf('VERBOSE')) {
  175. print STDERR "New output file ".
  176. $self->{'output_file'}.'-'.$out_file_nr."\n";
  177. }
  178. $fh = _open_info_file($self, $self->{'output_file'}.'-'.$out_file_nr);
  179. if (!$fh) {
  180. return undef;
  181. }
  182. print $fh $complete_header;
  183. $self->_update_count_context();
  184. $self->{'count_context'}->[-1]->{'bytes'} += $complete_header_bytes;
  185. push @indirect_files, [$self->{'output_filename'}.'-'.$out_file_nr,
  186. $self->{'count_context'}->[-1]->{'bytes'}];
  187. #print STDERR join(' --> ', @{$indirect_files[-1]}) ."\n";
  188. }
  189. }
  190. }
  191. my $tag_text = '';
  192. if ($out_file_nr > 1) {
  193. $self->register_close_file($self->{'output_file'}.'-'.$out_file_nr);
  194. if (!close ($fh)) {
  195. $self->document_error(sprintf($self->__("error on closing %s: %s"),
  196. $self->{'output_file'}.'-'.$out_file_nr, $!));
  197. return undef;
  198. }
  199. if ($self->get_conf('VERBOSE')) {
  200. print STDERR "Outputing the split manual file $self->{'output_file'}\n";
  201. }
  202. $fh = _open_info_file($self, $self->{'output_file'});
  203. if (!$fh) {
  204. return undef;
  205. }
  206. $tag_text = $complete_header;
  207. $tag_text .= "\x{1F}\nIndirect:";
  208. foreach my $indirect (@indirect_files) {
  209. $tag_text .= "\n$indirect->[0]: $indirect->[1]";
  210. }
  211. }
  212. $tag_text .= "\n\x{1F}\nTag Table:\n";
  213. if ($out_file_nr > 1) {
  214. $tag_text .= "(Indirect)\n";
  215. }
  216. # This may happen for anchors in @insertcopying
  217. my %seen_anchors;
  218. foreach my $label (@{$self->{'count_context'}->[-1]->{'locations'}}) {
  219. next unless ($label->{'root'} and $label->{'root'}->{'extra'}
  220. and defined($label->{'root'}->{'extra'}->{'node_content'}));
  221. my $prefix;
  222. if ($label->{'root'}->{'cmdname'} eq 'node') {
  223. $prefix = 'Node';
  224. } else {
  225. $prefix = 'Ref';
  226. }
  227. my ($label_text, $byte_count) = $self->_node_line($label->{'root'});
  228. if ($seen_anchors{$label_text}) {
  229. $self->line_error(sprintf($self->__("\@%s output more than once: %s"),
  230. $label->{'root'}->{'cmdname'},
  231. Texinfo::Convert::Texinfo::convert({'contents' =>
  232. $label->{'root'}->{'extra'}->{'node_content'}})),
  233. $label->{'root'}->{'line_nr'});
  234. next;
  235. } else {
  236. $seen_anchors{$label_text} = 1;
  237. }
  238. $tag_text .= "$prefix: $label_text\x{7F}$label->{'bytes'}\n";
  239. }
  240. $tag_text .= "\x{1F}\nEnd Tag Table\n";
  241. my $coding = $self->get_conf('OUTPUT_ENCODING_NAME');
  242. if ($coding) {
  243. $tag_text .= "\n\x{1F}\nLocal Variables:\ncoding: $coding\nEnd:\n";
  244. }
  245. if ($fh) {
  246. print $fh $tag_text;
  247. # NOTE it should be possible to close STDOUT. However this leads to
  248. # 'Filehandle STDOUT reopened as FH only for input' if there are files
  249. # reopened after closing STDOUT. So closing STDOUT is handled by the
  250. # caller.
  251. unless ($self->{'output_file'} eq '-') {
  252. $self->register_close_file($self->{'output_file'});
  253. if (!close ($fh)) {
  254. $self->document_error(sprintf($self->__("error on closing %s: %s"),
  255. $self->{'output_file'}, $!));
  256. }
  257. }
  258. } else {
  259. $result .= $tag_text;
  260. }
  261. return $result;
  262. }
  263. # Wrapper around Texinfo::Common::open_out. Open the file with any CR-LF
  264. # conversion disabled. We need this for tag tables to be correct under
  265. # MS-Windows. Return filehandle or undef on failure.
  266. sub _open_info_file($$)
  267. {
  268. my $self = shift;
  269. my $filename = shift;
  270. my $fh = $self->Texinfo::Common::open_out($filename, undef, 'use_binmode');
  271. if (!$fh) {
  272. $self->document_error(sprintf(
  273. $self->__("could not open %s for writing: %s"),
  274. $filename, $!));
  275. return undef;
  276. }
  277. return $fh;
  278. }
  279. sub _info_header($)
  280. {
  281. my $self = shift;
  282. $self->_set_global_multiple_commands();
  283. my $paragraph = Texinfo::Convert::Paragraph->new();
  284. my $result = add_text($paragraph, "This is ");
  285. # This ensures that spaces in file are kept.
  286. $result .= add_next($paragraph, $self->{'output_filename'});
  287. my $program = $self->get_conf('PROGRAM');
  288. my $version = $self->get_conf('PACKAGE_VERSION');
  289. if (defined($program) and $program ne '') {
  290. $result .= add_text($paragraph, ", produced by $program version $version from ");
  291. } else {
  292. $result .= add_text($paragraph, ", produced from ");
  293. }
  294. $result .= add_next($paragraph, $self->{'input_basename'});
  295. $result .= add_text($paragraph, '.');
  296. $result .= Texinfo::Convert::Paragraph::end($paragraph);
  297. $result .= "\n";
  298. $self->{'empty_lines_count'} = 1;
  299. if ($self->{'extra'} and $self->{'extra'}->{'copying'}) {
  300. print STDERR "COPYING HEADER\n" if ($self->get_conf('DEBUG'));
  301. $self->{'in_copying_header'} = 1;
  302. my $copying = $self->_convert({'contents' =>
  303. $self->{'extra'}->{'copying'}->{'contents'}});
  304. $result .= $copying;
  305. $result .= $self->_footnotes();
  306. delete $self->{'in_copying_header'};
  307. }
  308. if ($self->{'info'}->{'dircategory_direntry'}) {
  309. $self->{'ignored_commands'}->{'direntry'} = 0;
  310. foreach my $command (@{$self->{'info'}->{'dircategory_direntry'}}) {
  311. if ($command->{'cmdname'} eq 'dircategory') {
  312. if ($command->{'extra'}
  313. and defined($command->{'extra'}->{'misc_content'})) {
  314. my $dircategory = "INFO-DIR-SECTION ".$self->convert_line(
  315. {'contents' => $command->{'extra'}->{'misc_content'}});
  316. $result .= $self->ensure_end_of_line($dircategory);
  317. }
  318. $self->{'empty_lines_count'} = 0;
  319. } elsif ($command->{'cmdname'} eq 'direntry') {
  320. $result .= "START-INFO-DIR-ENTRY\n";
  321. my $direntry = $self->_convert($command);
  322. $result .= $direntry;
  323. $result .= "END-INFO-DIR-ENTRY\n\n";
  324. $self->{'empty_lines_count'} = 1;
  325. }
  326. }
  327. $self->{'ignored_commands'}->{'direntry'} = 1;
  328. }
  329. $self->_unset_global_multiple_commands();
  330. return $result;
  331. }
  332. sub _contents($$$)
  333. {
  334. my $self = shift;
  335. my $section_root = shift;
  336. my $contents_or_shortcontents = shift;
  337. return ('', 0);
  338. }
  339. sub _printindex($$)
  340. {
  341. my $self = shift;
  342. my $printindex = shift;
  343. return $self->_printindex_formatted($printindex, 1);
  344. }
  345. sub _error_outside_of_any_node($$)
  346. {
  347. my $self = shift;
  348. my $root = shift;
  349. if (!$self->{'node'}) {
  350. $self->line_warn(sprintf($self->__("\@%s outside of any node"),
  351. $root->{'cmdname'}), $root->{'line_nr'});
  352. }
  353. }
  354. my @directions = ('Next', 'Prev', 'Up');
  355. sub _node($$)
  356. {
  357. my $self = shift;
  358. my $node = shift;
  359. my $result = '';
  360. return '' if (!defined($node->{'extra'}->{'node_content'}));
  361. if (!$self->{'empty_lines_count'}) {
  362. $result .= "\n";
  363. $self->_add_text_count("\n");
  364. # if in the first node, complete the 'text_before_first_node' too.
  365. if (!$self->{'first_node_done'}) {
  366. $self->{'text_before_first_node'} .= "\n";
  367. }
  368. }
  369. if (!$self->{'first_node_done'}) {
  370. $self->{'first_node_done'} = 1;
  371. }
  372. # May happen when only converting a fragment
  373. my $output_filename = $self->{'output_filename'};
  374. if (defined($self->{'output_filename'})) {
  375. $output_filename = $self->{'output_filename'};
  376. } else {
  377. $output_filename = '';
  378. }
  379. $self->_add_location($node);
  380. my $node_begin = "\x{1F}\nFile: $output_filename, Node: ";
  381. $result .= $node_begin;
  382. $self->_add_text_count($node_begin);
  383. my ($node_text, $byte_count) = $self->_node_line($node);
  384. my $pre_quote = '';
  385. my $post_quote = '';
  386. if ($node_text =~ /,/) {
  387. if ($self->get_conf('INFO_SPECIAL_CHARS_WARNING')) {
  388. $self->line_warn(sprintf($self->__(
  389. "\@node name should not contain `,': %s"), $node_text),
  390. $node->{'line_nr'});
  391. }
  392. if ($self->get_conf('INFO_SPECIAL_CHARS_QUOTE')) {
  393. $pre_quote = "\x{7f}";
  394. $post_quote = $pre_quote;
  395. $self->{'count_context'}->[-1]->{'bytes'} += 2;
  396. }
  397. }
  398. $self->{'count_context'}->[-1]->{'bytes'} += $byte_count;
  399. $result .= $pre_quote . $node_text . $post_quote;
  400. foreach my $direction(@directions) {
  401. if ($node->{'node_'.lc($direction)}) {
  402. my $node_direction = $node->{'node_'.lc($direction)};
  403. my $text = ", $direction: ";
  404. $self->_add_text_count($text);
  405. $result .= $text;
  406. if ($node_direction->{'extra'}->{'manual_content'}) {
  407. $result .= $self->convert_line({'type' => '_code',
  408. 'contents' => [{'text' => '('},
  409. @{$node_direction->{'extra'}->{'manual_content'}},
  410. {'text' => ')'}]});
  411. }
  412. if ($node_direction->{'extra'}->{'node_content'}) {
  413. my ($node_text, $byte_count) = $self->_node_line($node_direction);
  414. $self->{'count_context'}->[-1]->{'bytes'} += $byte_count;
  415. $result .= $node_text;
  416. }
  417. }
  418. }
  419. $result .="\n\n";
  420. $self->_add_text_count("\n\n");
  421. $self->{'count_context'}->[-1]->{'lines'} = 3;
  422. $self->{'empty_lines_count'} = 1;
  423. return $result;
  424. }
  425. my @image_files_extensions = ('.png', '.jpg');
  426. sub _image($$)
  427. {
  428. my $self = shift;
  429. my $root = shift;
  430. my @extensions = @image_files_extensions;
  431. my $lines_count = 0;
  432. if (defined($root->{'extra'}->{'brace_command_contents'}->[0])) {
  433. my $basefile = Texinfo::Convert::Text::convert(
  434. {'contents' => $root->{'extra'}->{'brace_command_contents'}->[0]},
  435. {'code' => 1, Texinfo::Common::_convert_text_options($self)});
  436. if (defined($root->{'extra'}->{'brace_command_contents'}->[4])) {
  437. my $extension = Texinfo::Convert::Text::convert(
  438. {'contents' => $root->{'extra'}->{'brace_command_contents'}->[4]},
  439. {'code' => 1, Texinfo::Common::_convert_text_options($self)});
  440. unshift @extensions, ".$extension";
  441. unshift @extensions, "$extension";
  442. }
  443. my $image_file;
  444. foreach my $extension (@extensions) {
  445. if ($self->Texinfo::Common::locate_include_file ($basefile.$extension)) {
  446. # use the basename and not the file found. It is agreed that it is
  447. # better, since in any case the files are moved.
  448. $image_file = $basefile.$extension;
  449. last;
  450. }
  451. }
  452. my ($text, $width) = $self->_image_text($root, $basefile);
  453. my $alt;
  454. if (defined($root->{'extra'}->{'brace_command_contents'}->[3])) {
  455. $alt = Texinfo::Convert::Text::convert(
  456. {'contents' => $root->{'extra'}->{'brace_command_contents'}->[3]},
  457. {Texinfo::Common::_convert_text_options($self)});
  458. }
  459. my $result;
  460. if (defined($image_file) or (defined($text) and defined($alt))) {
  461. $image_file =~ s/\\/\\\\/g;
  462. $image_file =~ s/\"/\\\"/g;
  463. $result = "\x{00}\x{08}[image src=\"$image_file\"";
  464. if (defined($root->{'extra'}->{'brace_command_contents'}->[3])) {
  465. $alt =~ s/\\/\\\\/g;
  466. $alt =~ s/\"/\\\"/g;
  467. $result .= " alt=\"$alt\"";
  468. }
  469. if (defined($text)) {
  470. $text =~ s/\\/\\\\/g;
  471. $text =~ s/\"/\\\"/g;
  472. $result .= " text=\"$text\"";
  473. }
  474. $result .= "\x{00}\x{08}]";
  475. if ($self->{'formatters'}->[-1]->{'_top_formatter'}) {
  476. $result .= "\n";
  477. }
  478. my $image_lines_count = ($result =~ tr/\n/\n/) +1;
  479. $self->_add_image($root, $image_lines_count, $width, 1);
  480. } else {
  481. $result = $self->_image_formatted_text($root, $basefile, $text);
  482. $lines_count = ($result =~ tr/\n/\n/);
  483. $self->_add_image($root, $lines_count+1, $width);
  484. }
  485. return ($result, $lines_count);
  486. }
  487. return ('', 0);
  488. }
  489. 1;
  490. __END__
  491. # $Id: template.pod 6140 2015-02-22 23:34:38Z karl $
  492. # Automatically generated from maintain/template.pod
  493. =head1 NAME
  494. Texinfo::Convert::Info - Convert Texinfo tree to Info
  495. =head1 SYNOPSIS
  496. my $converter
  497. = Texinfo::Convert::Info->converter({'parser' => $parser});
  498. $converter->output($tree);
  499. $converter->convert($tree);
  500. $converter->convert_tree($tree);
  501. =head1 DESCRIPTION
  502. Texinfo::Convert::Info converts a Texinfo tree to Info.
  503. =head1 METHODS
  504. =over
  505. =item $converter = Texinfo::Convert::Info->converter($options)
  506. Initialize converter from Texinfo to Info.
  507. The I<$options> hash reference holds options for the converter. In
  508. this option hash reference a parser object may be associated with the
  509. I<parser> key. The other options should be configuration options
  510. described in the Texinfo manual. Those options, when appropriate,
  511. override the document content.
  512. See L<Texinfo::Convert::Converter> for more informations.
  513. =item $converter->output($tree)
  514. Convert a Texinfo tree I<$tree> and output the result in files as
  515. described in the Texinfo manual.
  516. =item $result = $converter->convert($tree)
  517. Convert a Texinfo tree I<$tree> or tree portion and return
  518. the resulting output.
  519. =item $result = $converter->convert_tree($tree)
  520. Convert a Texinfo tree portion I<$tree> and return the resulting
  521. output. This function does not try to output a full document but only
  522. portions. For a full document use C<convert>.
  523. =back
  524. =head1 AUTHOR
  525. Patrice Dumas, E<lt>pertusus@free.frE<gt>
  526. =head1 COPYRIGHT AND LICENSE
  527. Copyright 2015 Free Software Foundation, Inc.
  528. This library is free software; you can redistribute it and/or modify
  529. it under the terms of the GNU General Public License as published by
  530. the Free Software Foundation; either version 3 of the License, or (at
  531. your option) any later version.
  532. =cut