1<?php 2/** 3 * DokuWiki Plugin caption (Syntax Component) 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author Till Biskup <till@till-biskup> 7 */ 8 9// must be run within Dokuwiki 10if (!defined('DOKU_INC')) die(); 11 12if (!defined('DOKU_LF')) define('DOKU_LF', "\n"); 13if (!defined('DOKU_TAB')) define('DOKU_TAB', "\t"); 14if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 15 16require_once DOKU_PLUGIN.'syntax.php'; 17 18class syntax_plugin_caption_caption extends DokuWiki_Syntax_Plugin { 19 20 /** 21 * Array containing the types of environment supported by the plugin 22 */ 23 private $_types = array('figure','table','codeblock','fileblock'); 24 25 private $_type = ''; 26 private $_incaption = false; 27 28 private $_fignum = 1; 29 private $_tabnum = 1; 30 private $_codenum = 1; 31 private $_filenum = 1; 32 33 private $_label = ''; 34 35 private $_figlabels = array(); 36 private $_tablabels = array(); 37 private $_codelabels = array(); 38 private $_filelabels = array(); 39 40 /** 41 * return some info 42 */ 43 function getInfo(){ 44 return confToHash(dirname(__FILE__).'/../plugin.info.txt'); 45 } 46 47 public function getType() { 48 return 'container'; 49 } 50 51 public function getAllowedTypes() { 52 return array('formatting', 'substition', 'disabled', 'container', 'protected'); 53 } 54 55 public function getPType() { 56 return 'block'; 57 } 58 59 public function getSort() { 60 return 319; 61 } 62 63 64 public function connectTo($mode) { 65 $this->Lexer->addSpecialPattern('{{setcounter [a-z0-9=]+?}}',$mode,'plugin_caption_caption'); 66 $this->Lexer->addEntryPattern('<figure.*?>(?=.*</figure>)',$mode,'plugin_caption_caption'); 67 $this->Lexer->addEntryPattern('<table.*?>(?=.*</table>)',$mode,'plugin_caption_caption'); 68 $this->Lexer->addEntryPattern('<codeblock.*?>(?=.*</codeblock>)',$mode,'plugin_caption_caption'); 69 $this->Lexer->addEntryPattern('<fileblock.*?>(?=.*</fileblock>)',$mode,'plugin_caption_caption'); 70 $this->Lexer->addPattern('<caption>(?=.*</caption>)','plugin_caption_caption'); 71 $this->Lexer->addPattern('</caption>','plugin_caption_caption'); 72 } 73 74 public function postConnect() { 75 $this->Lexer->addExitPattern('</figure>','plugin_caption_caption'); 76 $this->Lexer->addExitPattern('</table>','plugin_caption_caption'); 77 $this->Lexer->addExitPattern('</codeblock>','plugin_caption_caption'); 78 $this->Lexer->addExitPattern('</fileblock>','plugin_caption_caption'); 79 } 80 81 public function handle($match, $state, $pos, Doku_Handler $handler){ 82 switch ($state) { 83 case DOKU_LEXER_ENTER : 84 $match = substr($match,1,-1); 85 return array($state, $match); 86 case DOKU_LEXER_MATCHED : 87 return array($state, $match); 88 case DOKU_LEXER_UNMATCHED : 89 return array($state, $match); 90 case DOKU_LEXER_EXIT : 91 $match = substr($match,1,-1); 92 return array($state, $match); 93 case DOKU_LEXER_SPECIAL : 94 if (!(strpos($match,'{{setcounter')===false)) { 95 return array($state, substr($match,13,-2)); 96 } 97 } 98 return array(); 99 } 100 101 public function render($mode, Doku_Renderer $renderer, $data) { 102 if ($mode == 'xhtml') { 103 104 list($state,$match) = $data; 105 106 switch ($state) { 107 case DOKU_LEXER_ENTER : 108 // Handle case that there is a label in the opening tag 109 list($match,$label) = explode(' ',$match); 110 if (in_array($match,$this->_types)) { 111 $this->_type = $match; 112 switch ($this->_type) { 113 case "figure" : 114 $renderer->doc .= '<figure class="plugin_caption_figure"'; 115 // If we have a label, assign it to the global label array 116 if ($label) { 117 global $caption_labels; 118 $caption_labels[$label] = $this->_fignum; 119 $this->_figlabels[$this->_fignum] = $label; 120 $renderer->doc .= ' id="'.$renderer->_xmlEntities($label).'"'; 121 // WARNING: Potential harmful way of handling references 122 // that have already been printed 123 $pattern = '##REF:'.$this->_figlabels[$this->_fignum].'##'; 124 if (strpos($renderer->doc, $pattern) !== FALSE) { 125 $renderer->doc = str_replace($pattern, $this->_fignum, $renderer->doc); 126 } 127 } 128 $renderer->doc .= '>'; 129 break; 130 case "table" : 131 $renderer->doc .= '<div class="plugin_caption_table"'; 132 // If we have a label, assign it to the global label array 133 if ($label) { 134 global $caption_labels; 135 $caption_labels[$label] = $this->_tabnum; 136 $this->_tablabels[$this->_tabnum] = $label; 137 $renderer->doc .= ' id="'.$renderer->_xmlEntities($label).'"'; 138 // WARNING: Potential harmful way of handling references 139 // that have already been printed 140 $pattern = '##REF:'.$this->_tablabels[$this->_tabnum].'##'; 141 if (strpos($renderer->doc, $pattern) !== FALSE) { 142 $renderer->doc = str_replace($pattern, $this->_tabnum, $renderer->doc); 143 } 144 } 145 $renderer->doc .= '>'; 146 break; 147 case "codeblock" : 148 $renderer->doc .= '<div class="plugin_caption_codeblock"'; 149 // If we have a label, assign it to the global label array 150 if ($label) { 151 global $caption_labels; 152 $caption_labels[$label] = $this->_tabnum; 153 $this->_tablabels[$this->_codenum] = $label; 154 $renderer->doc .= ' id="'.$renderer->_xmlEntities($label).'"'; 155 // WARNING: Potential harmful way of handling references 156 // that have already been printed 157 $pattern = '##REF:'.$this->_codelabels[$this->_codenum].'##'; 158 if (strpos($renderer->doc, $pattern) !== FALSE) { 159 $renderer->doc = str_replace($pattern, $this->_codenum, $renderer->doc); 160 } 161 } 162 $renderer->doc .= '>'; 163 break; 164 case "fileblock" : 165 $renderer->doc .= '<div class="plugin_caption_fileblock"'; 166 // If we have a label, assign it to the global label array 167 if ($label) { 168 global $caption_labels; 169 $caption_labels[$label] = $this->_filenum; 170 $this->_tablabels[$this->_filenum] = $label; 171 $renderer->doc .= ' id="'.$renderer->_xmlEntities($label).'"'; 172 // WARNING: Potential harmful way of handling references 173 // that have already been printed 174 $pattern = '##REF:'.$this->_filelabels[$this->_filenum].'##'; 175 if (strpos($renderer->doc, $pattern) !== FALSE) { 176 $renderer->doc = str_replace($pattern, $this->_filenum, $renderer->doc); 177 } 178 } 179 $renderer->doc .= '>'; 180 break; 181 } 182 } 183 break; 184 185 case DOKU_LEXER_MATCHED : 186 // return the dokuwiki markup within the caption tags 187 if (!$this->_incaption) { 188 $this->_incaption = true; 189 switch ($this->_type) { 190 case "figure" : 191 $renderer->doc .= '<figcaption class="plugin_caption_caption"><span class="plugin_caption_caption_number"'; 192 if(array_key_exists($this->_fignum,$this->_figlabels)) { 193 $renderer->doc .= ' title="' 194 .$this->_figlabels[$this->_fignum].'"'; 195 } 196 $renderer->doc .= '>'; 197 if ($this->getConf('abbrev')) { 198 $renderer->doc .= $this->getLang('figureabbrev'); 199 } else { 200 $renderer->doc .= $this->getLang('figurelong'); 201 } 202 $renderer->doc .= ' ' . $this->_fignum . ':</span>'; 203 $renderer->doc .= ' <span class="plugin_caption_caption_text">'; 204 break; 205 case "table" : 206 $renderer->doc .= '<div class="plugin_caption_caption"><span class="plugin_caption_caption_number"'; 207 if(array_key_exists($this->_tabnum,$this->_tablabels)) { 208 $renderer->doc .= ' title="' 209 .$this->_tablabels[$this->_tabnum].'"'; 210 } 211 $renderer->doc .= '>'; 212 if ($this->getConf('abbrev')) { 213 $renderer->doc .= $this->getLang('tableabbrev'); 214 } else { 215 $renderer->doc .= $this->getLang('tablelong'); 216 } 217 $renderer->doc .= ' ' . $this->_tabnum . ':</span>'; 218 $renderer->doc .= ' <span class="captiontext">'; 219 break; 220 case "codeblock" : 221 $renderer->doc .= '<div class="plugin_caption_caption"><span class="plugin_caption_caption_number"'; 222 if(array_key_exists($this->_codenum,$this->_codelabels)) { 223 $renderer->doc .= ' title="' 224 .$this->_codelabels[$this->_codenum].'"'; 225 } 226 $renderer->doc .= '>'; 227 if ($this->getConf('abbrev')) { 228 $renderer->doc .= $this->getLang('codeabbrev'); 229 } else { 230 $renderer->doc .= $this->getLang('codelong'); 231 } 232 $renderer->doc .= ' ' . $this->_codenum . ':</span>'; 233 $renderer->doc .= ' <span class="captiontext">'; 234 break; 235 case "fileblock" : 236 $renderer->doc .= '<div class="plugin_caption_caption"><span class="plugin_caption_caption_number"'; 237 if(array_key_exists($this->_filenum,$this->_filelabels)) { 238 $renderer->doc .= ' title="' 239 .$this->_tablabels[$this->_filenum].'"'; 240 } 241 $renderer->doc .= '>'; 242 if ($this->getConf('abbrev')) { 243 $renderer->doc .= $this->getLang('fileabbrev'); 244 } else { 245 $renderer->doc .= $this->getLang('filelong'); 246 } 247 $renderer->doc .= ' ' . $this->_filenum . ':</span>'; 248 $renderer->doc .= ' <span class="captiontext">'; 249 break; 250 } 251 } else { 252 $this->_incaption = false; 253 switch ($this->_type) { 254 case "figure" : 255 $renderer->doc .= '</span></figcaption>'; 256 break; 257 case "table" : 258 $renderer->doc .= '</span></div>'; 259 break; 260 case "codeblock" : 261 $renderer->doc .= '</span></div>'; 262 break; 263 case "fileblock" : 264 $renderer->doc .= '</span></div>'; 265 break; 266 } 267 } 268 break; 269 270 case DOKU_LEXER_UNMATCHED : 271 // return the dokuwiki markup within the figure tags 272 $renderer->doc .= $renderer->_xmlEntities($match); 273 break; 274 275 case DOKU_LEXER_EXIT : 276 // increment figure/table number 277 switch ($this->_type) { 278 case "figure" : 279 $this->_fignum++; 280 $renderer->doc .= '</figure>'; 281 break; 282 case "table" : 283 $this->_tabnum++; 284 $renderer->doc .= '</div>'; 285 break; 286 case "codeblock" : 287 $this->_codenum++; 288 $renderer->doc .= '</div>'; 289 break; 290 case "fileblock" : 291 $this->_filenum++; 292 $renderer->doc .= '</div>'; 293 break; 294 } 295 $this->_type = ''; 296 break; 297 298 case DOKU_LEXER_SPECIAL : 299 list($_type,$_num) = explode('=',trim($match)); 300 $_type = trim($_type); 301 $_num = (int) trim($_num); 302 if (in_array($_type,$this->_types)) { 303 switch ($_type) { 304 case "figure" : 305 $this->_fignum = $_num; 306 break; 307 case "table" : 308 $this->_tabnum = $_num; 309 break; 310 case "codeblock" : 311 $this->_codenum = $_num; 312 break; 313 case "fileblock" : 314 $this->_filenum = $_num; 315 break; 316 } 317 } 318 break; 319 } 320 return true; 321 } 322 323 if ($mode == 'latex') { 324 325 list($state,$match) = $data; 326 327 switch ($state) { 328 case DOKU_LEXER_ENTER : 329 // Handle case that there is a label in the opening tag 330 list($match,$label) = explode(' ',$match); 331 if (in_array($match,$this->_types)) { 332 $this->_type = $match; 333 switch ($this->_type) { 334 case "figure" : 335 $renderer->doc .= '\begin{figure}'; 336 // If we have a label, assign it to the global label array 337 if ($label) { 338 $this->_label = $label; 339 } 340 break; 341 case "table" : 342 $renderer->doc .= '\begin{table}'; 343 if ($label) { 344 $this->_label = $label; 345 } 346 break; 347 } 348 } 349 break; 350 351 case DOKU_LEXER_MATCHED : 352 // return the dokuwiki markup within the caption tags 353 if (!$this->_incaption) { 354 $this->_incaption = true; 355 $renderer->doc .= '\caption{'; 356 } else { 357 $renderer->doc .= '}'; 358 $this->_incaption = false; 359 if ($this->_label) { 360 $renderer->doc .= "\n" . '\label{'.$this->_label.'}'; 361 $this->_label = ''; 362 } 363 } 364 break; 365 366 case DOKU_LEXER_UNMATCHED : 367 // return the dokuwiki markup within the figure tags 368 $renderer->doc .= $match; //$renderer->_xmlEntities($match); 369 break; 370 371 case DOKU_LEXER_EXIT : 372 switch ($this->_type) { 373 case "figure" : 374 $renderer->doc .= '\end{figure}' . "\n\n"; 375 break; 376 case "table" : 377 $renderer->doc .= '\end{table}' . "\n\n"; 378 break; 379 } 380 $this->_type = ''; 381 break; 382 } 383 return true; 384 } 385 386 /** 387 * WARNING: The odt mode seems to work in general, but strange things happen 388 * with the tables - therefore, within the table tags only a table 389 * is allowed, without any additional markup. 390 */ 391 if ($mode == 'odt') { 392 393 list($state,$match) = $data; 394 395 switch ($state) { 396 case DOKU_LEXER_ENTER : 397 // Handle case that there is a label in the opening tag 398 list($match,$label) = explode(' ',$match); 399 if (in_array($match,$this->_types)) { 400 $this->_type = $match; 401 switch ($this->_type) { 402 case "figure" : 403 // If we have a label, assign it to the global label array 404 if ($label) { 405 global $caption_labels; 406 $caption_labels[$label] = $this->_fignum; 407 $this->_label = $label; 408 } 409 break; 410 case "table" : 411 // If we have a label, assign it to the global label array 412 if ($label) { 413 global $caption_labels; 414 $caption_labels[$label] = $this->_tabnum; 415 $this->_label = $label; 416 } 417 break; 418 } 419 $renderer->p_open(); 420 } 421 break; 422 423 case DOKU_LEXER_MATCHED : 424 // return the dokuwiki markup within the caption tags 425 if (!$this->_incaption) { 426 $this->_incaption = true; 427 $renderer->p_close(); 428 switch ($this->_type) { 429 case "figure" : 430 $renderer->doc .= '<text:p text:style-name="Illustration">'; 431 if ($this->getConf('abbrev')) { 432 $renderer->doc .= $this->getLang('figureabbrev'); 433 } else { 434 $renderer->doc .= $this->getLang('figurelong'); 435 } 436 $renderer->doc .= '<text:sequence text:ref-name="'; 437 if ($this->_label) { 438 $renderer->doc .= $this->_label; 439 $this->_label = ''; 440 } else { 441 $renderer->doc .= 'refIllustration' . $this->_fignum; 442 } 443 $renderer->doc .= '" text:name="Illustration" text:formula="ooow:Illustration+1" style:num-format="1">'; 444 $renderer->doc .= ' ' . $this->_fignum . '</text:sequence>: '; 445 break; 446 case "table" : 447 $renderer->doc .= '<text:p text:style-name="Table">'; 448 if ($this->getConf('abbrev')) { 449 $renderer->doc .= $this->getLang('tableabbrev'); 450 } else { 451 $renderer->doc .= $this->getLang('tablelong'); 452 } 453 $renderer->doc .= '<text:sequence text:ref-name="'; 454 if ($this->_label) { 455 $renderer->doc .= $this->_label; 456 $this->_label = ''; 457 } else { 458 $renderer->doc .= 'refTable' . $this->_tabnum; 459 } 460 $renderer->doc .= '" text:name="Table" text:formula="ooow:Table+1" style:num-format="1">'; 461 $renderer->doc .= ' ' . $this->_tabnum . '</text:sequence>: '; 462 break; 463 } 464 } else { 465 $renderer->doc .= '</text:p>'; 466 $this->_incaption = false; 467 switch ($this->_type) { 468 case "figure" : 469 $renderer->p_open(); 470 break; 471 case "table" : 472// $renderer->p_open(); 473 break; 474 } 475 } 476 break; 477 478 case DOKU_LEXER_UNMATCHED : 479 // return the dokuwiki markup within the figure tags 480 $renderer->cdata($match); 481 break; 482 483 case DOKU_LEXER_EXIT : 484 // increment figure/table number 485 switch ($this->_type) { 486 case "figure" : 487 $this->_fignum++; 488 $renderer->p_close(); 489 break; 490 case "table" : 491 $this->_tabnum++; 492 break; 493 } 494 $this->_type = ''; 495 break; 496 } 497 return true; 498 } 499 500 // unsupported $mode 501 return false; 502 } 503} 504 505// vim:ts=4:sw=4:et: 506