[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/inc/parser/ -> renderer.php (source)

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