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
10 if (!defined('DOKU_INC')) {
11     die();
12 }
13 
14 if (!defined('DOKU_LF')) {
15     define('DOKU_LF', "\n");
16 }
17 if (!defined('DOKU_TAB')) {
18     define('DOKU_TAB', "\t");
19 }
20 if (!defined('DOKU_PLUGIN')) {
21     define('DOKU_PLUGIN', DOKU_INC.'lib/plugins/');
22 }
23 
24 require_once DOKU_PLUGIN.'syntax.php';
25 
26 class 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