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