1<?php 2/** 3 * Renderer output base class 4 * 5 * @author Harry Fuecks <hfuecks@gmail.com> 6 * @author Andreas Gohr <andi@splitbrain.org> 7 */ 8if(!defined('DOKU_INC')) die('meh.'); 9 10/** 11 * An empty renderer, produces no output 12 * 13 * Inherits from DokuWiki_Plugin for giving additional functions to render plugins 14 * 15 * The renderer transforms the syntax instructions created by the parser and handler into the 16 * desired output format. For each instruction a corresponding method defined in this class will 17 * be called. That method needs to produce the desired output for the instruction and add it to the 18 * $doc field. When all instructions are processed, the $doc field contents will be cached by 19 * DokuWiki and sent to the user. 20 */ 21class Doku_Renderer extends DokuWiki_Plugin { 22 /** @var array Settings, control the behavior of the renderer */ 23 public $info = array( 24 'cache' => true, // may the rendered result cached? 25 'toc' => true, // render the TOC? 26 ); 27 28 /** @var array contains the smiley configuration, set in p_render() */ 29 public $smileys = array(); 30 /** @var array contains the entity configuration, set in p_render() */ 31 public $entities = array(); 32 /** @var array contains the acronym configuration, set in p_render() */ 33 public $acronyms = array(); 34 /** @var array contains the interwiki configuration, set in p_render() */ 35 public $interwiki = array(); 36 37 /** 38 * @var string the rendered document, this will be cached after the renderer ran through 39 */ 40 public $doc = ''; 41 42 /** 43 * clean out any per-use values 44 * 45 * This is called before each use of the renderer object and should be used to 46 * completely reset the state of the renderer to be reused for a new document 47 */ 48 function reset() { 49 } 50 51 /** 52 * Allow the plugin to prevent DokuWiki from reusing an instance 53 * 54 * Since most renderer plugins fail to implement Doku_Renderer::reset() we default 55 * to reinstantiating the renderer here 56 * 57 * @return bool false if the plugin has to be instantiated 58 */ 59 function isSingleton() { 60 return false; 61 } 62 63 /** 64 * Returns the format produced by this renderer. 65 * 66 * Has to be overidden by sub classes 67 * 68 * @return string 69 */ 70 function getFormat() { 71 trigger_error('getFormat() not implemented in '.get_class($this), E_USER_WARNING); 72 return ''; 73 } 74 75 /** 76 * Disable caching of this renderer's output 77 */ 78 function nocache() { 79 $this->info['cache'] = false; 80 } 81 82 /** 83 * Disable TOC generation for this renderer's output 84 * 85 * This might not be used for certain sub renderer 86 */ 87 function notoc() { 88 $this->info['toc'] = false; 89 } 90 91 /** 92 * Handle plugin rendering 93 * 94 * Most likely this needs NOT to be overwritten by sub classes 95 * 96 * @param string $name Plugin name 97 * @param mixed $data custom data set by handler 98 * @param string $state matched state if any 99 * @param string $match raw matched syntax 100 */ 101 function plugin($name, $data, $state = '', $match = '') { 102 /** @var DokuWiki_Syntax_Plugin $plugin */ 103 $plugin = plugin_load('syntax', $name); 104 if($plugin != null) { 105 $plugin->render($this->getFormat(), $this, $data); 106 } 107 } 108 109 /** 110 * handle nested render instructions 111 * this method (and nest_close method) should not be overloaded in actual renderer output classes 112 * 113 * @param array $instructions 114 */ 115 function nest($instructions) { 116 foreach($instructions as $instruction) { 117 // execute the callback against ourself 118 if(method_exists($this, $instruction[0])) { 119 call_user_func_array(array($this, $instruction[0]), $instruction[1] ? $instruction[1] : array()); 120 } 121 } 122 } 123 124 /** 125 * dummy closing instruction issued by Doku_Handler_Nest 126 * 127 * normally the syntax mode should override this instruction when instantiating Doku_Handler_Nest - 128 * however plugins will not be able to - as their instructions require data. 129 */ 130 function nest_close() { 131 } 132 133 #region Syntax modes - sub classes will need to implement them to fill $doc 134 135 /** 136 * Initialize the document 137 */ 138 function document_start() { 139 } 140 141 /** 142 * Finalize the document 143 */ 144 function document_end() { 145 } 146 147 /** 148 * Render the Table of Contents 149 * 150 * @return string 151 */ 152 function render_TOC() { 153 return ''; 154 } 155 156 /** 157 * Add an item to the TOC 158 * 159 * @param string $id the hash link 160 * @param string $text the text to display 161 * @param int $level the nesting level 162 */ 163 function toc_additem($id, $text, $level) { 164 } 165 166 /** 167 * Render a heading 168 * 169 * @param string $text the text to display 170 * @param int $level header level 171 * @param int $pos byte position in the original source 172 */ 173 function header($text, $level, $pos) { 174 } 175 176 /** 177 * Open a new section 178 * 179 * @param int $level section level (as determined by the previous header) 180 */ 181 function section_open($level) { 182 } 183 184 /** 185 * Close the current section 186 */ 187 function section_close() { 188 } 189 190 /** 191 * Render plain text data 192 * 193 * @param $text 194 */ 195 function cdata($text) { 196 } 197 198 /** 199 * Open a paragraph 200 */ 201 function p_open() { 202 } 203 204 /** 205 * Close a paragraph 206 */ 207 function p_close() { 208 } 209 210 /** 211 * Create a line break 212 */ 213 function linebreak() { 214 } 215 216 /** 217 * Create a horizontal line 218 */ 219 function hr() { 220 } 221 222 /** 223 * Start strong (bold) formatting 224 */ 225 function strong_open() { 226 } 227 228 /** 229 * Stop strong (bold) formatting 230 */ 231 function strong_close() { 232 } 233 234 /** 235 * Start emphasis (italics) formatting 236 */ 237 function emphasis_open() { 238 } 239 240 /** 241 * Stop emphasis (italics) formatting 242 */ 243 function emphasis_close() { 244 } 245 246 /** 247 * Start underline formatting 248 */ 249 function underline_open() { 250 } 251 252 /** 253 * Stop underline formatting 254 */ 255 function underline_close() { 256 } 257 258 /** 259 * Start monospace formatting 260 */ 261 function monospace_open() { 262 } 263 264 /** 265 * Stop monospace formatting 266 */ 267 function monospace_close() { 268 } 269 270 /** 271 * Start a subscript 272 */ 273 function subscript_open() { 274 } 275 276 /** 277 * Stop a subscript 278 */ 279 function subscript_close() { 280 } 281 282 /** 283 * Start a superscript 284 */ 285 function superscript_open() { 286 } 287 288 /** 289 * Stop a superscript 290 */ 291 function superscript_close() { 292 } 293 294 /** 295 * Start deleted (strike-through) formatting 296 */ 297 function deleted_open() { 298 } 299 300 /** 301 * Stop deleted (strike-through) formatting 302 */ 303 function deleted_close() { 304 } 305 306 /** 307 * Start a footnote 308 */ 309 function footnote_open() { 310 } 311 312 /** 313 * Stop a footnote 314 */ 315 function footnote_close() { 316 } 317 318 /** 319 * Open an unordered list 320 */ 321 function listu_open() { 322 } 323 324 /** 325 * Close an unordered list 326 */ 327 function listu_close() { 328 } 329 330 /** 331 * Open an ordered list 332 */ 333 function listo_open() { 334 } 335 336 /** 337 * Close an ordered list 338 */ 339 function listo_close() { 340 } 341 342 /** 343 * Open a list item 344 * 345 * @param int $level the nesting level 346 */ 347 function listitem_open($level) { 348 } 349 350 /** 351 * Close a list item 352 */ 353 function listitem_close() { 354 } 355 356 /** 357 * Start the content of a list item 358 */ 359 function listcontent_open() { 360 } 361 362 /** 363 * Stop the content of a list item 364 */ 365 function listcontent_close() { 366 } 367 368 /** 369 * Output unformatted $text 370 * 371 * Defaults to $this->cdata() 372 * 373 * @param string $text 374 */ 375 function unformatted($text) { 376 $this->cdata($text); 377 } 378 379 /** 380 * Output inline PHP code 381 * 382 * If $conf['phpok'] is true this should evaluate the given code and append the result 383 * to $doc 384 * 385 * @param string $text The PHP code 386 */ 387 function php($text) { 388 } 389 390 /** 391 * Output block level PHP code 392 * 393 * If $conf['phpok'] is true this should evaluate the given code and append the result 394 * to $doc 395 * 396 * @param string $text The PHP code 397 */ 398 function phpblock($text) { 399 } 400 401 /** 402 * Output raw inline HTML 403 * 404 * If $conf['htmlok'] is true this should add the code as is to $doc 405 * 406 * @param string $text The HTML 407 */ 408 function html($text) { 409 } 410 411 /** 412 * Output raw block-level HTML 413 * 414 * If $conf['htmlok'] is true this should add the code as is to $doc 415 * 416 * @param string $text The HTML 417 */ 418 function htmlblock($text) { 419 } 420 421 /** 422 * Output preformatted text 423 * 424 * @param string $text 425 */ 426 function preformatted($text) { 427 } 428 429 /** 430 * Start a block quote 431 */ 432 function quote_open() { 433 } 434 435 /** 436 * Stop a block quote 437 */ 438 function quote_close() { 439 } 440 441 /** 442 * Display text as file content, optionally syntax highlighted 443 * 444 * @param string $text text to show 445 * @param string $lang programming language to use for syntax highlighting 446 * @param string $file file path label 447 */ 448 function file($text, $lang = null, $file = null) { 449 } 450 451 /** 452 * Display text as code content, optionally syntax highlighted 453 * 454 * @param string $text text to show 455 * @param string $lang programming language to use for syntax highlighting 456 * @param string $file file path label 457 */ 458 function code($text, $lang = null, $file = null) { 459 } 460 461 /** 462 * Format an acronym 463 * 464 * Uses $this->acronyms 465 * 466 * @param string $acronym 467 */ 468 function acronym($acronym) { 469 } 470 471 /** 472 * Format a smiley 473 * 474 * Uses $this->smiley 475 * 476 * @param string $smiley 477 */ 478 function smiley($smiley) { 479 } 480 481 /** 482 * Format an entity 483 * 484 * Entities are basically small text replacements 485 * 486 * Uses $this->entities 487 * 488 * @param string $entity 489 */ 490 function entity($entity) { 491 } 492 493 /** 494 * Typographically format a multiply sign 495 * 496 * Example: ($x=640, $y=480) should result in "640×480" 497 * 498 * @param string|int $x first value 499 * @param string|int $y second value 500 */ 501 function multiplyentity($x, $y) { 502 } 503 504 /** 505 * Render an opening single quote char (language specific) 506 */ 507 function singlequoteopening() { 508 } 509 510 /** 511 * Render a closing single quote char (language specific) 512 */ 513 function singlequoteclosing() { 514 } 515 516 /** 517 * Render an apostrophe char (language specific) 518 */ 519 function apostrophe() { 520 } 521 522 /** 523 * Render an opening double quote char (language specific) 524 */ 525 function doublequoteopening() { 526 } 527 528 /** 529 * Render an closinging double quote char (language specific) 530 */ 531 function doublequoteclosing() { 532 } 533 534 /** 535 * Render a CamelCase link 536 * 537 * @param string $link The link name 538 * @see http://en.wikipedia.org/wiki/CamelCase 539 */ 540 function camelcaselink($link) { 541 } 542 543 /** 544 * Render a page local link 545 * 546 * @param string $hash hash link identifier 547 * @param string $name name for the link 548 */ 549 function locallink($hash, $name = null) { 550 } 551 552 /** 553 * Render a wiki internal link 554 * 555 * @param string $link page ID to link to. eg. 'wiki:syntax' 556 * @param string|array $title name for the link, array for media file 557 */ 558 function internallink($link, $title = null) { 559 } 560 561 /** 562 * Render an external link 563 * 564 * @param string $link full URL with scheme 565 * @param string|array $title name for the link, array for media file 566 */ 567 function externallink($link, $title = null) { 568 } 569 570 /** 571 * Render the output of an RSS feed 572 * 573 * @param string $url URL of the feed 574 * @param array $params Finetuning of the output 575 */ 576 function rss($url, $params) { 577 } 578 579 /** 580 * Render an interwiki link 581 * 582 * You may want to use $this->_resolveInterWiki() here 583 * 584 * @param string $link original link - probably not much use 585 * @param string|array $title name for the link, array for media file 586 * @param string $wikiName indentifier (shortcut) for the remote wiki 587 * @param string $wikiUri the fragment parsed from the original link 588 */ 589 function interwikilink($link, $title = null, $wikiName, $wikiUri) { 590 } 591 592 /** 593 * Link to file on users OS 594 * 595 * @param string $link the link 596 * @param string|array $title name for the link, array for media file 597 */ 598 function filelink($link, $title = null) { 599 } 600 601 /** 602 * Link to windows share 603 * 604 * @param string $link the link 605 * @param string|array $title name for the link, array for media file 606 */ 607 function windowssharelink($link, $title = null) { 608 } 609 610 /** 611 * Render a linked E-Mail Address 612 * 613 * Should honor $conf['mailguard'] setting 614 * 615 * @param string $address Email-Address 616 * @param string|array $name name for the link, array for media file 617 */ 618 function emaillink($address, $name = null) { 619 } 620 621 /** 622 * Render an internal media file 623 * 624 * @param string $src media ID 625 * @param string $title descriptive text 626 * @param string $align left|center|right 627 * @param int $width width of media in pixel 628 * @param int $height height of media in pixel 629 * @param string $cache cache|recache|nocache 630 * @param string $linking linkonly|detail|nolink 631 */ 632 function internalmedia($src, $title = null, $align = null, $width = null, 633 $height = null, $cache = null, $linking = null) { 634 } 635 636 /** 637 * Render an external media file 638 * 639 * @param string $src full media URL 640 * @param string $title descriptive text 641 * @param string $align left|center|right 642 * @param int $width width of media in pixel 643 * @param int $height height of media in pixel 644 * @param string $cache cache|recache|nocache 645 * @param string $linking linkonly|detail|nolink 646 */ 647 function externalmedia($src, $title = null, $align = null, $width = null, 648 $height = null, $cache = null, $linking = null) { 649 } 650 651 /** 652 * Render a link to an internal media file 653 * 654 * @param string $src media ID 655 * @param string $title descriptive text 656 * @param string $align left|center|right 657 * @param int $width width of media in pixel 658 * @param int $height height of media in pixel 659 * @param string $cache cache|recache|nocache 660 */ 661 function internalmedialink($src, $title = null, $align = null, 662 $width = null, $height = null, $cache = null) { 663 } 664 665 /** 666 * Render a link to an external media file 667 * 668 * @param string $src media ID 669 * @param string $title descriptive text 670 * @param string $align left|center|right 671 * @param int $width width of media in pixel 672 * @param int $height height of media in pixel 673 * @param string $cache cache|recache|nocache 674 */ 675 function externalmedialink($src, $title = null, $align = null, 676 $width = null, $height = null, $cache = null) { 677 } 678 679 /** 680 * Start a table 681 * 682 * @param int $maxcols maximum number of columns 683 * @param int $numrows NOT IMPLEMENTED 684 * @param int $pos byte position in the original source 685 */ 686 function table_open($maxcols = null, $numrows = null, $pos = null) { 687 } 688 689 /** 690 * Close a table 691 * 692 * @param int $pos byte position in the original source 693 */ 694 function table_close($pos = null) { 695 } 696 697 /** 698 * Open a table header 699 */ 700 function tablethead_open() { 701 } 702 703 /** 704 * Close a table header 705 */ 706 function tablethead_close() { 707 } 708 709 /** 710 * Open a table row 711 */ 712 function tablerow_open() { 713 } 714 715 /** 716 * Close a table row 717 */ 718 function tablerow_close() { 719 } 720 721 /** 722 * Open a table header cell 723 * 724 * @param int $colspan 725 * @param string $align left|center|right 726 * @param int $rowspan 727 */ 728 function tableheader_open($colspan = 1, $align = null, $rowspan = 1) { 729 } 730 731 /** 732 * Close a table header cell 733 */ 734 function tableheader_close() { 735 } 736 737 /** 738 * Open a table cell 739 * 740 * @param int $colspan 741 * @param string $align left|center|right 742 * @param int $rowspan 743 */ 744 function tablecell_open($colspan = 1, $align = null, $rowspan = 1) { 745 } 746 747 /** 748 * Close a table cell 749 */ 750 function tablecell_close() { 751 } 752 753 #endregion 754 755 #region util functions, you probably won't need to reimplement them 756 757 /** 758 * Removes any Namespace from the given name but keeps 759 * casing and special chars 760 * 761 * @author Andreas Gohr <andi@splitbrain.org> 762 */ 763 function _simpleTitle($name) { 764 global $conf; 765 766 //if there is a hash we use the ancor name only 767 @list($name, $hash) = explode('#', $name, 2); 768 if($hash) return $hash; 769 770 if($conf['useslash']) { 771 $name = strtr($name, ';/', ';:'); 772 } else { 773 $name = strtr($name, ';', ':'); 774 } 775 776 return noNSorNS($name); 777 } 778 779 /** 780 * Resolve an interwikilink 781 */ 782 function _resolveInterWiki(&$shortcut, $reference, &$exists = null) { 783 //get interwiki URL 784 if(isset($this->interwiki[$shortcut])) { 785 $url = $this->interwiki[$shortcut]; 786 } else { 787 // Default to Google I'm feeling lucky 788 $url = 'http://www.google.com/search?q={URL}&btnI=lucky'; 789 $shortcut = 'go'; 790 } 791 792 //split into hash and url part 793 @list($reference, $hash) = explode('#', $reference, 2); 794 795 //replace placeholder 796 if(preg_match('#\{(URL|NAME|SCHEME|HOST|PORT|PATH|QUERY)\}#', $url)) { 797 //use placeholders 798 $url = str_replace('{URL}', rawurlencode($reference), $url); 799 $url = str_replace('{NAME}', $reference, $url); 800 $parsed = parse_url($reference); 801 if(!$parsed['port']) $parsed['port'] = 80; 802 $url = str_replace('{SCHEME}', $parsed['scheme'], $url); 803 $url = str_replace('{HOST}', $parsed['host'], $url); 804 $url = str_replace('{PORT}', $parsed['port'], $url); 805 $url = str_replace('{PATH}', $parsed['path'], $url); 806 $url = str_replace('{QUERY}', $parsed['query'], $url); 807 } else { 808 //default 809 $url = $url.rawurlencode($reference); 810 } 811 //handle as wiki links 812 if($url{0} === ':') { 813 list($id, $urlparam) = explode('?', $url, 2); 814 $url = wl(cleanID($id), $urlparam); 815 $exists = page_exists($id); 816 } 817 if($hash) $url .= '#'.rawurlencode($hash); 818 819 return $url; 820 } 821 822 #endregion 823} 824 825 826//Setup VIM: ex: et ts=4 : 827