book.pm 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. # A style that tries to be analogous with a book, in HTML.
  2. #
  3. # This file is in the public domain. Thus it may easily be used as an
  4. # example for further customizations.
  5. #
  6. # Originally written by Patrice Dumas in 2004.
  7. # Modified in 2007, 2008.
  8. #
  9. # This style is based on the scriptbasic style.
  10. use strict;
  11. use vars qw($element_file_name);
  12. set_from_init_file('contents', 1);
  13. set_from_init_file('INLINE_CONTENTS', 1);
  14. set_from_init_file('USE_TITLEPAGE_FOR_TITLE', 1);
  15. my @book_buttons = ('Back', 'Forward', ' ', 'Contents', 'Index', 'About');
  16. foreach my $buttons ('SECTION_BUTTONS', 'CHAPTER_BUTTONS', 'TOP_BUTTONS') {
  17. set_from_init_file($buttons, \@book_buttons);
  18. }
  19. my @book_footer_buttons = ('Contents', 'Index', 'About');
  20. foreach my $buttons ('MISC_BUTTONS', 'SECTION_FOOTER_BUTTONS') {
  21. set_from_init_file($buttons, \@book_footer_buttons);
  22. }
  23. set_from_init_file('NODE_FOOTER_BUTTONS', ['Back', 'Forward']);
  24. set_from_init_file('LINKS_BUTTONS',
  25. ['Top', 'Index', 'Contents', 'About', 'Up', 'NextFile', 'PrevFile']);
  26. set_from_init_file('WORDS_IN_PAGE', undef);
  27. set_from_init_file('SHOW_MENU', 0);
  28. set_from_init_file('USE_NODES', undef);
  29. set_from_init_file('BIG_RULE', '<hr>');
  30. my ($book_previous_default_filename, $book_previous_file_name,
  31. $book_unumbered_nr);
  32. sub book_init($)
  33. {
  34. my $converter = shift;
  35. $book_previous_default_filename = undef;
  36. $book_previous_file_name = undef;
  37. $book_unumbered_nr = 0;
  38. return 1;
  39. }
  40. texinfo_register_handler('init', \&book_init);
  41. my $NO_BULLET_LIST_CLASS = 'no-bullet';
  42. sub book_print_up_toc($$)
  43. {
  44. my $converter = shift;
  45. my $command = shift;
  46. my $result = '';
  47. my $current_command = $command;
  48. my @up_commands;
  49. while (defined($current_command->{'section_up'})
  50. and ($current_command->{'section_up'} ne $current_command)
  51. and defined($current_command->{'section_up'}->{'cmdname'})) {
  52. unshift (@up_commands, $current_command->{'section_up'});
  53. $current_command = $current_command->{'section_up'};
  54. }
  55. # this happens for example for top element
  56. return '' if !(@up_commands);
  57. #print $fh "<ul>" . &$anchor('', $Texi2HTML::HREF{Contents}, '[' . $Texi2HTML::NAME{Contents} . ']') . " <br>\n";
  58. my $up = shift @up_commands;
  59. #print STDERR "$up $up->{'cmdname'} ".Texinfo::Structuring::_print_root_command_texi($up)."\n";
  60. $result .= $converter->_attribute_class('ul', $NO_BULLET_LIST_CLASS)."><li>"
  61. . "<a href=\"".$converter->command_href($up)."\">".$converter->command_text($up)
  62. . "</a> </li>\n";
  63. foreach my $up (@up_commands) {
  64. $result .= '<li>'
  65. .$converter->_attribute_class('ul', $NO_BULLET_LIST_CLASS)."><li>"
  66. . "<a href=\"".$converter->command_href($up)."\">".$converter->command_text($up)
  67. . "</a> </li>\n";
  68. }
  69. foreach my $up (@up_commands) {
  70. $result .= "</ul></li>\n";
  71. }
  72. $result .= "</ul>\n";
  73. return $result;
  74. }
  75. sub book_navigation_header($$$$)
  76. {
  77. my $self = shift;
  78. my $buttons = shift;
  79. my $cmdname = shift;
  80. my $command = shift;
  81. my $element = $command->{'parent'};
  82. if ($element
  83. and $element->{'extra'}->{'section'}
  84. and ($element->{'contents'}->[0] eq $command
  85. or (!$element->{'contents'}->[0]->{'cmdname'}
  86. and $element->{'contents'}->[1] eq $command))
  87. and defined($element->{'filename'})
  88. and $self->{'counter_in_file'}->{$element->{'filename'}} == 1) {
  89. return book_print_up_toc($self, $element->{'extra'}->{'section'}) .
  90. &{$self->default_formatting_function('navigation_header')}($self,
  91. $buttons, $cmdname, $command);
  92. } else {
  93. return &{$self->default_formatting_function('navigation_header')}($self,
  94. $buttons, $cmdname, $command);
  95. }
  96. }
  97. texinfo_register_formatting_function('navigation_header',
  98. \&book_navigation_header);
  99. sub book_print_sub_toc($$$);
  100. sub book_print_sub_toc($$$)
  101. {
  102. my $converter = shift;
  103. my $parent_command = shift;
  104. my $command = shift;
  105. my $result = '';
  106. my $content_href = $converter->command_href($command);
  107. my $heading = $converter->command_text($command);
  108. if ($content_href) {
  109. $result .= "<li> "."<a href=\"$content_href\">$heading</a>" . " </li>\n";
  110. }
  111. #print STDERR "SUB_TOC $element->{'text'}\n"; #sleep 1;
  112. if ($command->{'section_childs'} and @{$command->{'section_childs'}}) {
  113. #print STDERR "SUB_TOC child $element->{'child'}->{'text'}\n";
  114. $result .= '<li>'.$converter->_attribute_class('ul',$NO_BULLET_LIST_CLASS)
  115. .">\n". book_print_sub_toc($converter, $parent_command,
  116. $command->{'section_childs'}->[0])
  117. ."</ul></li>\n";
  118. }
  119. if (exists($command->{'section_next'})) {
  120. #print STDERR "SUB_TOC next($element->{'text'}) $element->{'next'}->{'text'}\n";
  121. $result .= book_print_sub_toc($converter, $parent_command,
  122. $command->{'section_next'});
  123. }
  124. return $result;
  125. }
  126. sub book_convert_heading_command($$$$$)
  127. {
  128. my $self = shift;
  129. my $cmdname = shift;
  130. my $command = shift;
  131. my $args = shift;
  132. my $content = shift;
  133. my $result = '';
  134. # not clear that it may really happen
  135. if ($self->in_string) {
  136. $result .= $self->command_string($command) ."\n" if ($cmdname ne 'node');
  137. $result .= $content if (defined($content));
  138. return $result;
  139. }
  140. my $element_id = $self->command_id($command);
  141. $result .= "<a name=\"$element_id\"></a>\n"
  142. if (defined($element_id) and $element_id ne '');
  143. print STDERR "Process $command "
  144. .Texinfo::Structuring::_print_root_command_texi($command)."\n"
  145. if ($self->get_conf('DEBUG'));
  146. my $element;
  147. if ($Texinfo::Common::root_commands{$command->{'cmdname'}}
  148. and $command->{'parent'}
  149. and $command->{'parent'}->{'type'}
  150. and $command->{'parent'}->{'type'} eq 'element') {
  151. $element = $command->{'parent'};
  152. }
  153. if ($element) {
  154. $result .= &{$self->{'format_element_header'}}($self, $cmdname,
  155. $command, $element);
  156. }
  157. my $heading_level;
  158. # FIXME this is done as in texi2html: node is used as heading if there
  159. # is nothing else. Is it right?
  160. if ($cmdname eq 'node') {
  161. if (!$element or (!$element->{'extra'}->{'section'}
  162. and $element->{'extra'}->{'node'}
  163. and $element->{'extra'}->{'node'} eq $command
  164. # bogus node may not have been normalized
  165. and defined($command->{'extra'}->{'normalized'}))) {
  166. if ($command->{'extra'}->{'normalized'} eq 'Top') {
  167. $heading_level = 0;
  168. } else {
  169. $heading_level = 3;
  170. }
  171. }
  172. } else {
  173. $heading_level = $command->{'level'};
  174. }
  175. my $heading = $self->command_text($command);
  176. # $heading not defined may happen if the command is a @node, for example
  177. # if there is an error in the node.
  178. if (defined($heading) and $heading ne '' and defined($heading_level)) {
  179. if ($self->get_conf('TOC_LINKS')
  180. and $Texinfo::Common::root_commands{$cmdname}
  181. and $Texinfo::Common::sectioning_commands{$cmdname}) {
  182. my $content_href = $self->command_contents_href($command, 'contents',
  183. $self->{'current_filename'});
  184. if ($content_href) {
  185. $heading = "<a href=\"$content_href\">$heading</a>";
  186. }
  187. }
  188. if ($self->in_preformatted()) {
  189. $result .= '<strong>'.$heading.'</strong>'."\n";
  190. } else {
  191. # if the level was changed, set the command name right
  192. if ($cmdname ne 'node'
  193. and $heading_level ne $Texinfo::Common::command_structuring_level{$cmdname}) {
  194. $cmdname
  195. = $Texinfo::Common::level_to_structuring_command{$cmdname}->[$heading_level];
  196. }
  197. $result .= &{$self->{'format_heading_text'}}($self, $cmdname, $heading,
  198. $heading_level, $command);
  199. }
  200. }
  201. if ($command->{'section_childs'} and @{$command->{'section_childs'}}
  202. and $cmdname ne 'top') {
  203. $result .= $self->_attribute_class('ul', $NO_BULLET_LIST_CLASS).">\n";
  204. $result .= book_print_sub_toc($self, $command,
  205. $command->{'section_childs'}->[0]);
  206. $result .= "</ul>\n";
  207. }
  208. $result .= $content if (defined($content));
  209. return $result;
  210. }
  211. foreach my $command (keys(%Texinfo::Common::sectioning_commands), 'node') {
  212. texinfo_register_command_formatting($command,
  213. \&book_convert_heading_command);
  214. }
  215. sub book_element_file_name($$$)
  216. {
  217. my $converter = shift;
  218. my $element = shift;
  219. my $filename = shift;
  220. return undef if ($converter->get_conf('NODE_FILENAMES')
  221. or !$converter->get_conf('SPLIT'));
  222. if (defined($book_previous_default_filename)
  223. and ($filename eq $book_previous_default_filename)) {
  224. return $book_previous_file_name;
  225. }
  226. my $prefix = $converter->{'document_name'};
  227. my $new_file_name;
  228. my $command = $element->{'extra'}->{'section'};
  229. return undef unless ($command);
  230. if ($converter->element_is_top($element)) {
  231. $new_file_name = "${prefix}_top.html";
  232. } elsif (defined($command->{'number'}) and ($command->{'number'} ne '')) {
  233. my $number = $command->{'number'};
  234. $number .= '.' unless ($number =~ /\.$/);
  235. $new_file_name = "${prefix}_$number" . 'html';
  236. } else {
  237. $book_unumbered_nr++;
  238. $new_file_name = "${prefix}_U." . $book_unumbered_nr . '.html';
  239. }
  240. $book_previous_default_filename = $filename;
  241. $book_previous_file_name = $new_file_name;
  242. return $new_file_name;
  243. }
  244. $element_file_name = \&book_element_file_name;
  245. 1;