Add dependency checking for included files.
[xhtml-compiler.git] / XHTMLCompiler / DOMFilter / GenerateTableOfContents.php
blob11cbab24c0439cdbf89dcc6fba803020b1e98f17
1 <?php
3 /**
4 * Generates a table of contents based on the heading structure of the
5 * document.
6 */
7 class XHTMLCompiler_DOMFilter_GenerateTableOfContents extends XHTMLCompiler_DOMFilter
10 protected $name = 'GenerateTableOfContents';
12 public function process(DOMDocument $dom, $page, $manager) {
14 // test for ToC container, if not present don't bother
15 $container = $this->query("//html:div[@id='toc']")->item(0);
16 if (!$container) return;
18 // grab all headings h2 and down from the document
19 $headings = array('h2', 'h3', 'h4', 'h5', 'h6');
20 foreach ($headings as $k => $v) $headings[$k] = "self::html:$v";
21 $query_headings = implode(' or ', $headings);
22 $query = "//*[$query_headings]"; // looks like "//*[self::html:h2 or ...]"
23 $headings = $this->query($query);
25 // setup the table of contents element
26 $toc = $dom->createElement('ul');
27 $container->appendChild($dom->createElement('h2', 'Table of Contents'));
28 $container->appendChild($toc);
30 // iterate through headings and build the table of contents
31 $current_level = 2;
32 $parents = array(false, $toc);
33 $indexes = array(0);
34 $i = 0;
35 foreach ($headings as $node) {
36 $level = (int) $node->tagName[1];
37 $name = $node->textContent; // no support for formatting
39 while ($level > $current_level) {
40 if (!$parents[$current_level-1]->lastChild) {
41 $parents[$current_level-1]->appendChild(
42 $dom->createElement('li')
45 $sublist = $dom->createElement('ul');
46 $parents[$current_level - 1]->lastChild->appendChild($sublist);
47 $parents[$current_level] = $sublist;
48 $current_level++;
49 $indexes[$current_level - 2] = 0;
52 while ($level < $current_level) {
53 unset($indexes[$current_level - 2]);
54 $current_level--;
57 $indexes[$current_level - 2]++;
60 $line = $dom->createElement('li');
61 $label = $dom->createElement('span', implode('.', $indexes) . '.');
62 $label->setAttribute('class', 'toc-label');
63 $line->appendChild($label);
64 $link = $dom->createElement('a', $name);
65 $line->appendChild($link);
66 $parents[$current_level-1]->appendChild($line);
68 // setup the anchors
69 $header_id = $node->getAttribute('id');
70 if (!$header_id) {
71 $header_id = 'toclink' . $i;
72 $node->setAttribute('id', $header_id);
74 $link->setAttribute('href', '#' . $header_id);