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