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