1<?php
2/**
3 * TocTweak plugin for DokuWiki; Syntax sidetoc
4 *
5 * provide compatibility for Andreone's inlinetoc plugin
6 * @see also https://www.dokuwiki.org/plugin:inlinetoc
7 *
8 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
9 * @author     Satoshi Sahara <sahara.satoshi@gmail.com>
10 */
11
12require_once(dirname(__FILE__).'/metatoc.php');
13
14class syntax_plugin_toctweak_sidetoc extends syntax_plugin_toctweak_metatoc {
15
16    protected $pattern = array(
17        5 => '{{SIDETOC\b.*?}}',  // DOKU_LEXER_SPECIAL
18    );
19    protected $tocStyle = array(  // default toc visual design
20        'SIDETOC' => 'toc_shrinken',
21    );
22
23    /**
24     * Handle the match
25     */
26    function handle($match, $state, $pos, Doku_Handler $handler) {
27        global $INFO, $ID;
28
29        // disable using cache
30        $handler->_addCall('nocache', array(), $pos);
31
32        $data = parent::handle($match, $state, $pos, $handler);
33        list($id, $topLv, $maxLv, $tocClass, $tocTitle) = $data;
34
35        // sidetoc (in sidebar page) must show toc of different page
36        // $id, $topLv, $maxLv dose not appropriate values for sidetoc
37        $id = '@ID@';
38        $topLv = $maxLv = null;
39
40        // check basic tocStyle
41        if (!preg_match('/\btoc_.*\b/', $tocClass)) {
42            $tocClass = implode(' ', array($this->tocStyle['SIDETOC'], $tocClass));
43        }
44
45        $data = array($id, $topLv, $maxLv, $tocClass, $tocTitle);
46        return $data;
47    }
48
49    /**
50     * Create output
51     */
52    function render($format, Doku_Renderer $renderer, $data) {
53        global $INFO, $conf, $lang;
54
55        list($id, $topLv, $maxLv, $tocClass, $tocTitle) = $data;
56
57        $id = $INFO['id'];     // str_replace('@ID@', $INFO['id'], $id);
58
59        // retrieve toc config parameters from metadata
60        $meta = p_get_metadata($id, 'toc');
61        $topLv = @$meta['toptoclevel'] ?: $this->getConf('toptoclevel');
62        $maxLv = @$meta['maxtoclevel'] ?: $this->getConf('maxtoclevel');
63
64        switch ($format) {
65            case 'metadata':
66                return false;
67
68            case 'xhtml':
69                // load helper object
70                isset($tocTweak) || $tocTweak = $this->loadHelper($this->getPluginName());
71
72                // retrieve TableOfContents from metadata
73                $toc = $tocTweak->get_metatoc($id, $topLv, $maxLv, $section);
74
75                // toc wrapper attributes
76                $attr['class'] = $tocClass;
77                $title = isset($tocTitle) ? $tocTitle : $lang['toc'];
78
79                $html = '<!-- SIDETOC START -->'.DOKU_LF;
80                $html.= '<div '.buildAttributes($attr).'>';
81                $html.= $title ? '<h3>'.hsc($title).'</h3>' : '';
82                $html.= '<div>';
83                $html.= html_buildlist($toc, 'toc', array($this, 'html_list_metatoc'));
84                $html.= '</div>';
85                $html.= '</div>'.DOKU_LF;
86                $html.= '<!-- SIDETOC END -->'.DOKU_LF;
87
88                $renderer->doc .= $html;
89                return true;
90        } // end of switch
91        return false;
92    }
93
94    /**
95     * Callback for html_buildlist called from $this->render()
96     * Builds html of each list item
97     * In case of {{SIDETOC}}, href attribute of TOC items must be locallink.
98     */
99    function html_list_metatoc($item) {
100        $html = '<span class="li">';
101        $html.= '<a href="#'.$item['hid'].'">';
102        $html.= hsc($item['title']).'</a>';
103        $html.= '</span>';
104        return $html;
105    }
106
107}
108