1<?php
2/**
3* DokuWiki Plugin syntaxhighlighter3 (Syntax Component)
4*
5* @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6* @author  Daniel Lindgren <bd.dali@gmail.com>, based on syntaxhighlighter plugin by David Shin.
7*/
8
9// must be run within Dokuwiki
10if (!defined('DOKU_INC')) {
11    die();
12}
13
14if (!defined('DOKU_LF')) {
15    define('DOKU_LF', "\n");
16}
17if (!defined('DOKU_TAB')) {
18    define('DOKU_TAB', "\t");
19}
20if (!defined('DOKU_PLUGIN')) {
21    define('DOKU_PLUGIN', DOKU_INC.'lib/plugins/');
22}
23
24require_once DOKU_PLUGIN.'syntax.php';
25
26class syntax_plugin_syntaxhighlighter3_syntax extends DokuWiki_Syntax_Plugin
27{
28    public function getType()
29    {
30        return 'protected';
31    }
32
33    public function getPType()
34    {
35        return 'block';
36    }
37
38    public function getSort()
39    {
40        return 195;
41    }
42
43    public function connectTo($mode)
44    {
45        $this->Lexer->addEntryPattern('<sxh(?=[^\r\n]*?>.*?</sxh>)', $mode, 'plugin_syntaxhighlighter3_syntax');
46    }
47
48    public function postConnect()
49    {
50        $this->Lexer->addExitPattern('</sxh>', 'plugin_syntaxhighlighter3_syntax');
51    }
52
53    public function handle($match, $state, $pos, &$handler)
54    {
55        switch ($state) {
56        case DOKU_LEXER_ENTER:
57            $this->syntax = substr($match, 1);
58            return false;
59
60        case DOKU_LEXER_UNMATCHED:
61            // will include everything from <sxh ... to ... </sxh>
62            list($attr, $content) = preg_split('/>/u', $match, 2);
63
64            if ($this->syntax == 'sxh') {
65                $attr = trim($attr);
66                if ($attr == null) {
67                    // No brush and no options, use "text" with default options.
68                    $attr = 'text';
69                } elseif (substr($attr, 0, 1) == ";") {
70                    // Options but no brush, add "text" brush.
71                    $attr = 'text' . $attr;
72                }
73            } else {
74                $attr = null;
75            }
76
77            return array($this->syntax, $attr, $content);
78        }
79        return false;
80    }
81
82    public function render($mode, &$renderer, $data)
83    {
84        if ($mode != 'xhtml') {
85            return false;
86        }
87
88        if (count($data) == 3) {
89            list($syntax, $attr, $content) = $data;
90            if ($syntax == 'sxh') {
91                $title = '';
92                $highlight = '';
93                // Check if there's a title in the $attr string. Block title can't be passed along as a normal parameter to SyntaxHighlighter.
94                if (preg_match("/title:/i", $attr)) {
95                    // Extract title(s) from $attr string.
96                    $attr_array = explode(";", $attr);
97                    $title_array = preg_grep("/title:/i", $attr_array);
98                    // Extract everything BUT title(s) from $attr string.
99                    $not_title_array =  preg_grep("/title:/i", $attr_array, PREG_GREP_INVERT);
100                    $attr = implode(";", $not_title_array);
101                    // If there are multiple titles, use the last one.
102                    $title = array_pop($title_array);
103                    $title = ' title="' . preg_replace("/.*title:\s{0,}(.*)/i", "$1", $title) . '"';
104                }
105                // Check highlight attr for lines ranges
106                if (preg_match("/highlight:/i", $attr, $matches)) {
107                    // Extract highlight from $attr string.
108                    $attr_array = explode(";", $attr);
109                    $highlight_array = preg_grep("/highlight:/i", $attr_array);
110                    // Extract everything BUT highlight from $attr string.
111                    $not_highlight_array = preg_grep("/highlight:/i", $attr_array, PREG_GREP_INVERT);
112                    $attr = implode(";", $not_highlight_array);
113                    // If there are multiple hightlights, use the last one.
114                    $highlight_str = array_pop($highlight_array);
115                    $highlight_str = preg_replace("/.*highlight:\s{0,}(.*)/i", "$1", $highlight_str);
116                    // Remove [ ]
117                    $highlight_str = str_replace(array('[', ']'), '', $highlight_str);
118                    // Process ranges if exists
119                    $highlight_exp = explode(',', $highlight_str);
120                    foreach ($highlight_exp as $highlight_elt) {
121                        if (!empty($highlight)) {
122                            $highlight .= ',';
123                        }
124                        $highlight_elt = trim($highlight_elt);
125                        $highlight_elt_exp = explode('-', $highlight_elt);
126                        if (count($highlight_elt_exp) == 2) {
127                            foreach (range($highlight_elt_exp[0], $highlight_elt_exp[1]) as $key => $lineNumber) {
128                                if ($key > 0) {
129                                    $highlight .= ',';
130                                }
131                                $highlight .= $lineNumber;
132                            }
133                        } else {
134                            $highlight .= $highlight_elt;
135                        }
136                    }
137                    $highlight = ' highlight: [' . $highlight . ']';
138                }
139                $renderer->doc .= '<pre class="brush: ' . strtolower($attr . $highlight) . '"' . $title . '>' . $renderer->_xmlEntities($content) . '</pre>';
140            } else {
141                $renderer->file($content);
142            }
143        }
144
145        return true;
146    }
147}
148
149// vim:ts=4:sw=4:et:
150