toc-headers.pl 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. # Copyright (C) 2004 Alex Schroeder <alex@emacswiki.org>
  2. # Copyright (C) 2006 Igor Afanasyev <afan@mail.ru>
  3. #
  4. # This program is free software; you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation; either version 2 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program; if not, write to the
  16. # Free Software Foundation, Inc.
  17. # 59 Temple Place, Suite 330
  18. # Boston, MA 02111-1307 USA
  19. #
  20. # This is a simplified mix of headers.pl and toc.pl to work together.
  21. # It is based on headers.pl 1.12 and toc.pl 1.30.
  22. use strict;
  23. use v5.10;
  24. AddModuleDescription('toc-headers.pl');
  25. our ($q, $bol, %Page, @MyRules);
  26. our ($MinTocSize, $OrderedLists);
  27. push(@MyRules, \&HeadersRule);
  28. $MinTocSize = 4; # show toc only if the number of headings is greater or equal to this value
  29. $OrderedLists = 0; # 1 if use <ol> instead of <ul>
  30. my $TocCounter = 0; # private
  31. my $TocShown = 0; # private
  32. sub HeadersRule {
  33. my $html = undef;
  34. if (!$TocShown) {
  35. $html = CloseHtmlEnvironments() . TocHeadings() . AddHtmlEnvironment('p');
  36. $TocShown = 1;
  37. }
  38. if ($bol && (m/\G((.+?)[ \t]*\n(---+|===+)[ \t]*\n)/cg)) {
  39. $html .= CloseHtmlEnvironments();
  40. $TocCounter++;
  41. $html .= "<a name=\"#$TocCounter\"></a>";
  42. if (substr($3,0,1) eq '=') {
  43. $html .= $q->h2($2);
  44. } else {
  45. $html .= $q->h3($2);
  46. }
  47. $html .= AddHtmlEnvironment('p');
  48. }
  49. return $html;
  50. }
  51. sub TocHeadings {
  52. my $oldpos = pos; # make this sub not destroy the value of pos
  53. my $page = $Page{text}; # work on the page that is currently open!
  54. # ignore all the stuff that gets processed anyway
  55. foreach my $tag ('nowiki', 'pre', 'code') {
  56. $page =~ s|<$tag>(.*\n)*?</$tag>||gi;
  57. }
  58. my $Headings = "<h2>" . T('Contents') . "</h2>";
  59. my $HeadingsLevel = undef;
  60. my $HeadingsLevelStart = undef;
  61. my $count = 1;
  62. my $tag = $OrderedLists ? 'ol' : 'ul';
  63. while ($page =~ m/((.+?)[ \t]*\n(---+|===+)[ \t]*\n)/g) {
  64. my $depth = (substr($3,0,1) eq '=') ? 2 : 3;
  65. my $text = $2;
  66. next unless $text;
  67. my $link = "$count"; #1, #2, etc. links seem to work fine
  68. $text = QuoteHtml($text);
  69. if (not defined $HeadingsLevelStart) {
  70. # $HeadingsLevel is set to $depth - 1 so that we get an opening
  71. # of the list. We need $HeadingsLevelStart to close all open
  72. # tags at the end.
  73. $HeadingsLevel = $depth - 1;
  74. $HeadingsLevelStart = $depth - 1;
  75. }
  76. $count++;
  77. # if the first subheading is has depth 2, then
  78. # $HeadingsLevelStart is 1, and later subheadings may not be
  79. # at level 1 or below.
  80. $depth = $HeadingsLevelStart + 1 if $depth <= $HeadingsLevelStart;
  81. # the order of the three expressions is important!
  82. while ($HeadingsLevel > $depth) {
  83. $Headings .= "</li></$tag>";
  84. $HeadingsLevel--;
  85. }
  86. if ($HeadingsLevel == $depth) {
  87. $Headings .= '</li><li>';
  88. }
  89. while ($HeadingsLevel < $depth) {
  90. $Headings .= "<$tag class=\"h$depth\"><li>";
  91. $HeadingsLevel++;
  92. }
  93. $Headings .= "<a href=\"#$link\">$text</a>";
  94. }
  95. while ($HeadingsLevel > $HeadingsLevelStart) {
  96. $Headings .= "</li></$tag>";
  97. $HeadingsLevel--;
  98. }
  99. pos = $oldpos;
  100. return '' if $count <= $MinTocSize;
  101. return $q->div({-class=>'toc'}, $Headings)
  102. if $Headings;
  103. }