1<?php
2/**
3 * PHP txt2tags plugin for DokuWiki.
4 *
5 * @license GPL 3 (http://www.gnu.org/licenses/gpl.html) - NOTE: PHP txt2tags
6 *  is licensed under the GPL license.
7 * @version 1.05 - 2014-05-19 - PHP txt2tags 20140518 included.
8 * @author Eric Forgeot, heavily derived from markdownextra plugin by Joonas Pulakka and Jiang Le
9 */
10
11if (!defined('DOKU_INC')) die();
12if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
13require_once (DOKU_PLUGIN . 'syntax.php');
14require_once (DOKU_PLUGIN . 'txt2tags/txt2tags.class.php');
15
16$T2TVersion = "20140518";
17
18class syntax_plugin_txt2tags extends DokuWiki_Syntax_Plugin {
19
20    function getType() {
21        return 'protected';
22    }
23
24    function getPType() {
25        return 'block';
26    }
27
28    function getSort() {
29        return 69;
30    }
31
32    function connectTo($mode) {
33        $this->Lexer->addEntryPattern('<t2t>(?=.*</t2t>)', $mode, 'plugin_txt2tags');
34    }
35
36    function postConnect() {
37        $this->Lexer->addExitPattern('</t2t>', 'plugin_txt2tags');
38    }
39
40    function handle($match, $state, $pos, &$handler) {
41        switch ($state) {
42            case DOKU_LEXER_ENTER :      return array($state, '');
43            case DOKU_LEXER_UNMATCHED :
44				// add a config.t2t file for tweaking your installation
45				$match = "\n\n\n%!includeconf: lib/plugins/txt2tags/config.t2t \n".$match ;
46				$x = new T2T($match);
47                		$x->enableinclude = 1;
48				$x->go();
49				$html = $x->bodyhtml;
50				return array($state, $html);
51            case DOKU_LEXER_EXIT :       return array($state, '');
52        }
53        return array($state,'');
54    }
55
56    function render($mode, &$renderer, $data) {
57        //dbg('function render($mode, &$renderer, $data)-->'.' mode = '.$mode.' data = '.$data);
58        //dbg($data);
59        if ($mode == 'xhtml') {
60            list($state,$match) = $data;
61            switch ($state) {
62                case DOKU_LEXER_ENTER :      break;
63                case DOKU_LEXER_UNMATCHED :
64                    $match = $this->_toc($renderer, $match);
65                    $renderer->doc .= $match;
66                    break;
67                case DOKU_LEXER_EXIT :       break;
68            }
69            return true;
70        }else if ($mode == 'metadata') {
71            //dbg('function render($mode, &$renderer, $data)-->'.' mode = '.$mode.' data = '.$data);
72            //dbg($data);
73            list($state,$match) = $data;
74            switch ($state) {
75                case DOKU_LEXER_ENTER :      break;
76                case DOKU_LEXER_UNMATCHED :
77                    if (!$renderer->meta['title']){
78                        $renderer->meta['title'] = $this->_t2t_header($match);
79                    }
80/** line below includes TOC in the main page.
81 You can tweak this in other places in dokuwiki
82(in your template, add <?php tpl_toc()?> where you need it), so we disable it below
83**/
84// $this->_toc($renderer, $match);
85                    $internallinks = $this->_internallinks($match);
86                    #dbg($internallinks);
87                    if (count($internallinks)>0){
88                        foreach($internallinks as $internallink)
89                        {
90                            $renderer->internallink($internallink);
91                        }
92                    }
93                    break;
94                case DOKU_LEXER_EXIT :       break;
95            }
96            return true;
97        } else {
98            return false;
99        }
100    }
101
102    function _t2t_header($text)
103    {
104        $doc = new DOMDocument('1.0','UTF-8');
105        //dbg($doc);
106        $meta = '<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head>';
107        $doc->loadHTML($meta.$text);
108        //dbg($doc->saveHTML());
109        if ($nodes = $doc->getElementsByTagName('h1')){
110            return $nodes->item(0)->nodeValue;
111        }
112        return false;
113    }
114
115    function _internallinks($text)
116    {
117        $doc = new DOMDocument('1.0', 'UTF-8');
118        $doc->loadHTML($text);
119        $links = array();
120        if ($nodes = $doc->getElementsByTagName('a')){
121            foreach($nodes as $atag)
122            {
123                $href = $atag->getAttribute('href');
124                if (!preg_match('/^(https{0,1}:\/\/|ftp:\/\/|mailto:)/i',$href)){
125                    $links[] = $href;
126                }
127            }
128        }
129        return $links;
130    }
131
132    function _toc(&$renderer, $text)
133    {
134        $doc = new DOMDocument('1.0','UTF-8');
135        //dbg($doc);
136        $meta = '<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head>';
137        $doc->loadHTML($meta.$text);
138        if ($nodes = $doc->getElementsByTagName("*")){
139            foreach($nodes as $node)
140            {
141                if (preg_match('/h([1-7])/',$node->tagName,$match))
142                {
143                    #dbg($node);
144                    $node->setAttribute('class', 'sectionedit'.$match[1]);
145                    $hid = $renderer->_headerToLink($node->nodeValue,'true');
146                    $node->setAttribute('id',$hid);
147                    $renderer->toc_additem($hid, $node->nodeValue, $match[1]);
148                }
149
150            }
151        }
152        //remove outer tags of content
153        $html = $doc->saveHTML();
154        $html = str_replace('<!DOCTYPE html>','',$html);
155        $html = preg_replace('/.+<body>/', '', $html);
156        $html = str_replace('</body>','', $html);
157        $html = preg_replace('/.+<html>/', '', $html);
158        $html = str_replace('</html>','', $html);
159        return $html;
160    }
161
162}
163