[ Index ]
 

Code source de Serendipity 1.2

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

/bundled-libs/Text/Wiki/Rule/ -> toc.php (source)

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


Généré le : Sat Nov 24 09:00:37 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics