f585731f4efbc813838fad4957910d6071a6165f
[paste/199.git] / build-toc.php
1 #!/usr/bin/env php
2 <?php
3 /**
4  * Creates a TOC (table of contents) from a given HTML file.
5  * <h1> is ignored; all other headings are used.
6  *
7  * @author Christian Weiske <cweiske@cweiske.de>
8  *
9  * Alternative if you have an XSLT 2 processor: http://xmlplease.com/tocxhtml
10  */
11 if ($argc < 2) {
12     echo "Please pass a file\n";
13     exit(1);
14 }
15 $file = $argv[1];
16 if (!file_exists($file)) {
17     echo "File does not exist: $file\n";
18     exit(2);
19 }
20 if (substr($file, -4) != '.htm') {
21     echo "build-toc.php works only on htm files\n";
22     exit(3);
23 }
24
25 $sx = simplexml_load_file($file);
26 if ($sx === false) {
27     echo "Failed to load XML\n";
28     exit(4);    
29 }
30
31 $body = $sx->body;
32 $body->registerXPathNamespace('h', 'http://www.w3.org/1999/xhtml');
33 $elems = $body->xpath(
34     '//*['
35     //XHTML
36     . 'self::h:h2 or self::h:h3 or self::h:h4 or self::h:h5 or self::h:h6'
37     //HTML
38     . ' or self::h2 or self::h3 or self::h4 or self::h5 or self::h6'
39     . ']'
40 );
41
42 $data = array();
43 $n = -1;
44 foreach ($elems as $elem) {
45     $name = $elem->getName();
46     $level = (int) $name{1};
47     $data[] = (object) array(
48         'title' => (string) $elem,
49         'id'    => (string) $elem['id'],
50         'level' => $level,
51         'nextLevel' => null
52     );
53     if (++$n >= 1) {
54         $data[$n - 1]->nextLevel = $level;
55     }
56 }
57
58 $html = "<ul class=\"toc\">\n";
59 foreach ($data as $h) {
60     $i = str_repeat(' ', ($h->level -1) * 2 - 1);
61     $html .= $i
62         . '<li><a href="#' . $h->id . '">'
63         . htmlspecialchars($h->title)
64         . '</a>';
65     if ($h->nextLevel > $h->level) {
66         $html .= "\n"
67             . $i . ' <ul>' . "\n";
68     } else {
69         $html .= '</li>' . "\n";
70     }
71     if ($h->nextLevel < $h->level) {
72         $html .= substr($i, 0, -1) . "</ul>\n"
73             . substr($i, 0, -2) . "</li>\n";
74     }
75 }
76
77 $html .= "</ul>\n";
78 echo $html;
79 ?>