1<?php
2
3class syntax_plugin_codeprism_codeprism extends DokuWiki_Syntax_Plugin
4{
5	protected $entry_pattern = '<codeprism\b.*?>(?=.*?</codeprism>)';
6	protected $exit_pattern = '</codeprism>';
7	protected $match_pattern = '/<codeprism (.+?)( \[(.+?)\])* *>/';
8
9	public function gettype()
10	{
11		return 'substition';
12	}
13
14	public function getSort()
15	{
16		return 190;
17	}
18
19	public function connectTo($mode)
20	{
21		$this->Lexer->addEntryPattern($this->entry_pattern, $mode, 'plugin_codeprism_codeprism');
22	}
23
24	public function postConnect()
25	{
26		$this->Lexer->addExitPattern($this->exit_pattern, 'plugin_codeprism_codeprism');
27	}
28
29	public function handle($match, $state, $pos, Doku_Handler $handler)
30	{
31		if (isset($_REQUEST['comment'])) return false;
32
33		$pre_opt_arr['css'] = 'dft';
34
35		if ($state == DOKU_LEXER_ENTER) {
36			/** Default attributes. */
37			if ($this->getConf('hl-brace')) {
38				$code_opt_arr['match-braces'] = 'match-braces';
39			}
40
41			if ($this->getConf('user')) {
42				$pre_opt_arr['data-user'] = $this->getConf('user');
43			}
44
45			if ($this->getConf('host')) {
46				$pre_opt_arr['data-host'] = $this->getConf('host');
47			}
48
49			preg_match_all($this->match_pattern, "{$match}", $chunks, PREG_SET_ORDER);
50
51			if (!empty($chunks)) {
52				$chunk = $chunks[0];
53
54				$basic_option = preg_split('/\s+/', trim($chunk[1]));
55
56				/**chunk[1]: php title sl=* el=* ... */
57				/** Fit <code> syntax */
58				if ($basic_option[0] && false == strpos($basic_option[0], '=')) {
59					if ($basic_option[0] != '.') {
60						$pre_opt_arr['data-language'] = $basic_option[0];
61						$code_opt_arr['lang'] = $basic_option[0];
62					}
63
64					unset($basic_option[0]);
65				}
66
67				if ($basic_option[1] && false == strpos($basic_option[1], '=')) {
68					if ($basic_option[1] != '.') {
69						$pre_opt_arr['data-label'] = $key_val[1];
70					}
71
72					unset($basic_option[1]);
73				}
74
75				foreach($basic_option as $opt) {
76					$key_val = preg_split('/=/', $opt);
77
78					switch ($key_val[0]) {
79					/** Parse <codeprism> syntax. */
80					case 'sl':
81						$pre_opt_arr['data-start'] = $key_val[1];
82						$pre_opt_arr['data-line-offset'] = $key_val[1];
83						break;
84
85					case 'hl':
86						$pre_opt_arr['data-line'] = $key_val[1];
87						break;
88
89					case 'el':
90						$pre_opt_arr['line-numbers'] = 'line-numbers';
91						break;
92
93					case 'lang':
94						$pre_opt_arr['data-language'] = $key_val[1];
95						$code_opt_arr['lang'] = $key_val[1];
96						break;
97
98					case 'cmd':
99						$pre_opt_arr['command-line'] = 'command-line';
100						break;
101
102					case 'cmdout':
103						$pre_opt_arr['data-output'] = $key_val[1];
104						$pre_opt_arr['command-line'] = 'command-line';
105						break;
106
107					case 'user':
108						$pre_opt_arr['data-user'] = $key_val[1];
109						break;
110
111					case 'host':
112						$pre_opt_arr['data-host'] = $key_val[1];
113						break;
114
115					case 'css':
116						$pre_opt_arr['css'] = $key_val[1];
117						break;
118
119					/** Parse <fileprism> syntax. */
120					case 'src':
121						$pre_opt_arr['data-src'] = DOKU_BASE. 'lib/exe/fetch.php?media=' . $key_val[1];
122						break;
123
124					case 'range':
125						$pre_opt_arr['data-range'] = $key_val[1];
126						break;
127
128					case 'title':
129						$pre_opt_arr['data-label'] = $key_val[1];
130						break;
131					}
132				}
133
134				/**chunk[2]: [attr0="val0", attr1="val1", ...] */
135				$extend_option = trim($chunk[2]);
136
137				preg_match_all('/([\w-]+?)="(.*?)"/', "$extend_option", $extend_arr, PREG_SET_ORDER);
138
139				foreach ($extend_arr as $key_val) {
140					switch ($key_val[1]) {
141					case 'start_line_numbers_at':
142						$pre_opt_arr['data-start'] = $key_val[2];
143						$pre_opt_arr['data-line-offset'] = $key_val[2];
144						break;
145
146					case 'enable_line_numbers':
147						$pre_opt_arr['line-numbers'] = 'line-numbers';
148						break;
149
150					case 'highlight_lines_extra':
151						$pre_opt_arr['data-line'] = $key_val[2];
152						break;
153
154					default:
155						$pre_opt_arr[$key_val[1]] = $key_val[2];
156						break;
157					}
158				}
159			}
160
161			/* `data-user` & `data-host` should be only used in command line. */
162			if (!$pre_opt_arr['command-line']) {
163				unset($pre_opt_arr['data-user']);
164				unset($pre_opt_arr['data-host']);
165			}
166
167			return array($state, $pre_opt_arr, $code_opt_arr);
168		}
169
170		return array($state, $match);
171	}
172
173	public function render($mode, Doku_Renderer $renderer, $data)
174	{
175		if ($mode != 'xhtml') return false;
176
177		list($state) = $data;
178
179		switch ($state) {
180		case DOKU_LEXER_ENTER:
181			list(, $pre_opt_arr, $code_opt_arr) = $data;
182
183			$renderer->doc .= '<pre class="dokuwiki-plugin-codeprism-'.$pre_opt_arr['css'].' '.$pre_opt_arr['line-numbers'].' '.$pre_opt_arr['command-line'] . '"';
184			unset($pre_opt_arr['line-numbers']);
185			unset($pre_opt_arr['command-line']);
186			unset($pre_opt_arr['css']);
187
188			foreach($pre_opt_arr as $key => $val) {
189				$renderer->doc .= ' ' . $key . '="' . $val . '"';
190			}
191
192			$renderer->doc .='>';
193			$renderer->doc .='<code class="language-'. $code_opt_arr['lang'] . ' ' . $code_opt_arr['match-braces'] . '">';
194			break;
195
196		case DOKU_LEXER_UNMATCHED:
197			list(, $code) = $data;
198			$code = ltrim($code);
199			$renderer->doc .= $renderer->_xmlEntities($code);
200			break;
201
202		case DOKU_LEXER_EXIT:
203			$renderer->doc .= '</code>';
204			$renderer->doc .= '</pre>';
205			break;
206		}
207
208		return false;
209	}
210}
211