Text_Wiki
[ class tree: Text_Wiki ] [ index: Text_Wiki ] [ all elements ]

Source for file toc.php

Documentation is available at toc.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available through the world-wide-web at                              |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: toc.php,v 1.3 2004/03/02 22:37:18 pmjones Exp $
  20.  
  21.  
  22. /**
  23. * This class implements a Text_Wiki_Rule to find all heading tokens and
  24. * build a table of contents.  The [[toc]] tag gets replaced with a list
  25. * of all the level-2 through level-6 headings.
  26. *
  27. @author Paul M. Jones <pmjones@ciaweb.net>
  28. *
  29. @package Text_Wiki
  30. *
  31. */
  32.  
  33.  
  34.     
  35.     
  36.     /**
  37.     * 
  38.     * The regular expression used to parse the source text and find
  39.     * matches conforming to this rule.  Used by the parse() method.
  40.     * 
  41.     * @access public
  42.     * 
  43.     * @var string 
  44.     * 
  45.     * @see parse()
  46.     * 
  47.     */
  48.     
  49.     var $regex = "/\[\[toc\]\]/m";
  50.     
  51.     
  52.     /**
  53.     * 
  54.     * The collection of headings (text and levels).
  55.     * 
  56.     * @access public
  57.     * 
  58.     * @var array 
  59.     * 
  60.     * @see _getEntries()
  61.     * 
  62.     */
  63.     
  64.     var $entry = array();
  65.     
  66.     
  67.     /**
  68.     * 
  69.     * Custom parsing (have to process heading entries first).
  70.     * 
  71.     * @access public
  72.     * 
  73.     * @see Text_Wiki::parse()
  74.     * 
  75.     */
  76.     
  77.     function parse()
  78.     {
  79.         $this->_getEntries();
  80.         parent::parse();
  81.     }
  82.     
  83.     
  84.     /**
  85.     * 
  86.     * Generates a replacement for the matched text.  Token options are:
  87.     * 
  88.     * 'type' => ['list_start'|'list_end'|'item_end'|'item_end'|'target']
  89.     *
  90.     * 'level' => The heading level (1-6).
  91.     *
  92.     * 'count' => Which heading this is in the list.
  93.     * 
  94.     * @access public
  95.     *
  96.     * @param array &$matches The array of matches from parse().
  97.     *
  98.     * @return string A token indicating the TOC collection point.
  99.     *
  100.     */
  101.     
  102.     function process(&$matches)
  103.     {
  104.         $output $this->addToken(array('type' => 'list_start'));
  105.         
  106.         foreach ($this->entry as $key => $val{
  107.         
  108.             $options = array(
  109.                 'type' => 'item_start',
  110.                 'count' => $val['count'],
  111.                 'level' => $val['level']
  112.             );
  113.             
  114.             $output .= $this->addToken($options);
  115.             
  116.             $output .= $val['text'];
  117.             
  118.             $output .= $this->addToken(array('type' => 'item_end'));
  119.         }
  120.         
  121.         $output .= $this->addToken(array('type' => 'list_end'));
  122.         return $output;
  123.     }
  124.     
  125.     
  126.     /**
  127.     * 
  128.     * Finds all headings in the text and saves them in $this->entry.
  129.     * 
  130.     * @access private
  131.     *
  132.     * @return void 
  133.     * 
  134.     */
  135.     
  136.     function _getEntries()
  137.     {
  138.         // the wiki delimiter
  139.         $delim $this->_wiki->delim;
  140.         
  141.         // list of all TOC entries (h2, h3, etc)
  142.         $this->entry = array();
  143.         
  144.         // the new source text with TOC entry tokens
  145.         $newsrc '';
  146.         
  147.         // when passing through the parsed source text, keep track of when
  148.         // we are in a delimited section
  149.         $in_delim = false;
  150.         
  151.         // when in a delimited section, capture the token key number
  152.         $key '';
  153.         
  154.         // TOC entry count
  155.         $count = 0;
  156.         
  157.         // pass through the parsed source text character by character
  158.         $k strlen($this->_wiki->_source);
  159.         for ($i = 0; $i $k$i++{
  160.             
  161.             // the current character
  162.             $char $this->_wiki->_source{$i};
  163.             
  164.             // are alredy in a delimited section?
  165.             if ($in_delim{
  166.             
  167.                 // yes; are we ending the section?
  168.                 if ($char == $delim{
  169.                     
  170.                     // yes, get the replacement text for the delimited
  171.                     // token number and unset the flag.
  172.                     $key = (int)$key;
  173.                     $rule $this->_wiki->_tokens[$key][0];
  174.                     $opts $this->_wiki->_tokens[$key][1];
  175.                     $in_delim = false;
  176.                     
  177.                     // is the key a start heading token
  178.                     // of level 2 or deeper?
  179.                     if ($rule == 'heading' &&
  180.                         $opts['type'== 'start' &&
  181.                         $opts['level'> 1{
  182.                         
  183.                         // yes, add a TOC target link to the
  184.                         // tokens array...
  185.                         $token $this->addToken(
  186.                             array(
  187.                                 'type' => 'target',
  188.                                 'count' => $count,
  189.                                 'level' => $opts['level']
  190.                             )
  191.                         );
  192.                         
  193.                         // ... and to the new source, before the
  194.                         // heading-start token.
  195.                         $newsrc .= $token $delim $key $delim;
  196.                         
  197.                         // retain the toc item
  198.                         $this->entry[= array (
  199.                             'count' => $count,
  200.                             'level' => $opts['level'],
  201.                             'text' => $opts['text']
  202.                         );
  203.                         
  204.                         // increase the count for the next entry
  205.                         $count++;
  206.                         
  207.                     else {
  208.                         // not a heading-start of 2 or deeper.
  209.                         // re-add the delimited token number
  210.                         // as it was in the original source.
  211.                         $newsrc .= $delim $key $delim;
  212.                     }
  213.                     
  214.                 else {
  215.                 
  216.                     // no, add to the delimited token key number
  217.                     $key .= $char;
  218.                     
  219.                 }
  220.                 
  221.             else {
  222.                 
  223.                 // not currently in a delimited section.
  224.                 // are we starting into a delimited section?
  225.                 if ($char == $delim{
  226.                     // yes, reset the previous key and
  227.                     // set the flag.
  228.                     $key '';
  229.                     $in_delim = true;
  230.                 else {
  231.                     // no, add to the output as-is
  232.                     $newsrc .= $char;
  233.                 }
  234.             }
  235.         }
  236.         
  237.         // replace with changed source text
  238.         $this->_wiki->_source = $newsrc;
  239.         
  240.         
  241.         /*
  242.         // PRIOR VERSION
  243.         // has problems mistaking marked-up numbers for delimited tokens
  244.         
  245.         // creates target tokens, retrieves heading level and text
  246.         $this->entry = array();
  247.         $count = 0;
  248.         
  249.         // loop through all tokens and get headings
  250.         foreach ($this->_wiki->_tokens as $key => $val) {
  251.             
  252.             // only get heading starts of level 2 or deeper
  253.             if ($val[0] == 'heading' &&
  254.                 $val[1]['type'] == 'start' &&
  255.                 $val[1]['level'] > 1) {
  256.                 
  257.                 // the level of this header
  258.                 $level = $val[1]['level'];
  259.                 
  260.                 // the text of this header
  261.                 $text = $val[1]['text'];
  262.                 
  263.                 // add a toc-target link to the tokens array
  264.                 $token = $this->addToken(
  265.                     array(
  266.                         'type' => 'target',
  267.                         'count' => $count,
  268.                         'level' => $level
  269.                     )
  270.                 );
  271.                 
  272.                 // put the toc target token in front of the
  273.                 // heading-start token
  274.                 $start = $delim . $key . $delim;
  275.                 $this->_wiki->_source = str_replace($start, $token.$start,
  276.                     $this->_wiki->_source);
  277.                 
  278.                 // retain the toc item
  279.                 $this->entry[] = array (
  280.                     'count' => $count,
  281.                     'level' => $level,
  282.                     'text' => $text
  283.                 );
  284.                 
  285.                 // increase the count for the next item
  286.                 $count++;
  287.             }
  288.         }
  289.         */
  290.     }
  291.  
  292.     
  293.     /**
  294.     * 
  295.     * Renders a token into text matching the requested format.
  296.     * 
  297.     * @access public
  298.     * 
  299.     * @param array $options The "options" portion of the token (second
  300.     *  element).
  301.     * 
  302.     * @return string The text rendered from the token options.
  303.     * 
  304.     */
  305.     
  306.     function renderXhtml($options)
  307.     {
  308.         // type, count, level
  309.         extract($options);
  310.         
  311.         // the prefix used for anchor names
  312.         $prefix 'toc';
  313.         
  314.         if ($type == 'target'{
  315.             // ... generate an anchor.
  316.             return "<a name=\"$prefix$count\"></a>";
  317.         }
  318.         
  319.         if ($type == 'list_start'{
  320.             return "<p>\n";
  321.         }
  322.         
  323.         if ($type == 'list_end'{
  324.             return "</p>\n";
  325.         }
  326.         
  327.         if ($type == 'item_start'{
  328.             
  329.             // build some indenting spaces for the text
  330.             $indent ($level - 2* 4;
  331.             $pad str_pad(''$indent);
  332.             $pad str_replace(' ''&nbsp;'$pad);
  333.             
  334.             // add an extra linebreak in front of heading-2
  335.             // entries (makes for nice section separations)
  336.             if ($level <= 2 && $count > 0{
  337.                 $pad = "<br />\n$pad";
  338.             }
  339.             
  340.             // create the entry line as a link to the toc anchor
  341.             return "$pad<a href=\"#$prefix$count\">";
  342.         }
  343.         
  344.         if ($type == 'item_end'{
  345.             return "</a><br />\n";
  346.         }
  347.     }
  348.  
  349. }
  350. ?>

Documentation generated on Mon, 11 Mar 2019 10:14:15 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.