[ Index ]
 

Code source de Serendipity 1.2

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

/bundled-libs/Text/Wiki/Rule/ -> list.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: list.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 source text marked as
  25  * a bulleted or numbered list.  In short, if a line starts with '* ' then
  26  * it is a bullet list item; if a line starts with '# ' then it is a 
  27  * number list item.  Spaces in front of the * or # indicate an indented
  28  * sub-list.  The list items must be on sequential lines (no blank lines
  29  * between them) -- a blank line indicates the beginning of a new list.
  30  *
  31  * @author Paul M. Jones <pmjones@ciaweb.net>
  32  *
  33  * @package Text_Wiki
  34  *
  35  */
  36  
  37  class Text_Wiki_Rule_list extends Text_Wiki_Rule {
  38      
  39      
  40      /**
  41      * 
  42      * The regular expression used to parse the source text and find
  43      * matches conforming to this rule.  Used by the parse() method.
  44      * 
  45      * @access public
  46      * 
  47      * @var string
  48      * 
  49      * @see parse()
  50      * 
  51      */
  52      
  53      var $regex = '/\n((\*|#) .*\n)(?! {0,}(\*|#))/Us';
  54      
  55      
  56      /**
  57      * 
  58      * Generates a replacement for the matched text.  Token options are:
  59      * 
  60      * 'type' =>
  61      *     'bullet_start' : the start of a bullet list
  62      *     'bullet_end'   : the end of a bullet list
  63      *     'number_start' : the start of a number list
  64      *     'number_end'   : the end of a number list
  65      *     'item_start'   : the start of item text (bullet or number)
  66      *     'item_end'     : the end of item text (bullet or number)
  67      *     'unknown'      : unknown type of list or item
  68      *
  69      * 'level' => the indent level (0 for the first level, 1 for the
  70      * second, etc)
  71      *
  72      * 'count' => the list item number at this level. not needed for
  73      * xhtml, but very useful for PDF and RTF.
  74      * 
  75      * @access public
  76      *
  77      * @param array &$matches The array of matches from parse().
  78      *
  79      * @return A series of text and delimited tokens marking the different
  80      * list text and list elements.
  81      *
  82      */
  83      
  84      function process(&$matches)
  85      {
  86          // the replacement text we will return
  87          $return = '';
  88          
  89          // the list of post-processing matches
  90          $list = array();
  91          
  92          // a stack of list-start and list-end types; we keep this
  93          // so that we know what kind of list we're working with
  94          // (bullet or number) and what indent level we're at.
  95          $stack = array();
  96          
  97          // the item count is the number of list items for any
  98          // given list-type on the stack
  99          $itemcount = array();
 100          
 101          // populate $list with this set of matches. $matches[1] is the
 102          // text matched as a list set by parse().
 103          preg_match_all(
 104              '=^( {0,})(\*|#) (.*)$=Ums',
 105              $matches[1],
 106              $list,
 107              PREG_SET_ORDER
 108          );
 109          
 110          // loop through each list-item element.
 111          foreach ($list as $key => $val) {
 112              
 113              // $val[0] is the full matched list-item line
 114              // $val[1] is the number of initial spaces (indent level)
 115              // $val[2] is the list item type (* or #)
 116              // $val[3] is the list item text
 117              
 118              // how many levels are we indented? (1 means the "root"
 119              // list level, no indenting.)
 120              $level = strlen($val[1]) + 1;
 121              
 122              // get the list item type
 123              if ($val[2] == '*') {
 124                  $type = 'bullet';
 125              } elseif ($val[2] == '#') {
 126                  $type = 'number';
 127              } else {
 128                  $type = 'unknown';
 129              }
 130              
 131              // get the text of the list item
 132              $text = $val[3];
 133              
 134              // add a level to the list?
 135              if ($level > count($stack)) {
 136                  
 137                  // the current indent level is greater than the
 138                  // number of stack elements, so we must be starting
 139                  // a new list.  push the new list type onto the
 140                  // stack...
 141                  array_push($stack, $type);
 142                  
 143                  // ...and add a list-start token to the return.
 144                  $return .= $this->addToken(
 145                      array(
 146                          'type' => $type . '_start',
 147                          'level' => $level - 1
 148                      )
 149                  );
 150              }
 151              
 152              // remove a level from the list?
 153              while (count($stack) > $level) {
 154                  
 155                  // so we don't keep counting the stack, we set up a temp
 156                  // var for the count.  -1 becuase we're going to pop the
 157                  // stack in the next command.  $tmp will then equal the
 158                  // current level of indent.
 159                  $tmp = count($stack) - 1;
 160                  
 161                  // as long as the stack count is greater than the
 162                  // current indent level, we need to end list types. 
 163                  // continue adding end-list tokens until the stack count
 164                  // and the indent level are the same.
 165                  $return .= $this->addToken(
 166                      array (
 167                          'type' => array_pop($stack) . '_end',
 168                          'level' => $tmp
 169                      )
 170                  );
 171                  
 172                  // reset to the current (previous) list type so that
 173                  // the new list item matches the proper list type.
 174                  $type = $stack[$tmp - 1];
 175                  
 176                  // reset the item count for the popped indent level
 177                  $itemcount[$tmp + 1] = 0;
 178              }
 179              
 180              // add to the item count for this list (taking into account
 181              // which level we are at).
 182              if (! isset($itemcount[$level])) {
 183                  // first count
 184                  $itemcount[$level] = 1;
 185              } else {
 186                  // increment count
 187                  $itemcount[$level]++;
 188              }
 189              
 190              // create a list-item starting token.
 191              $start = $this->addToken(
 192                  array(
 193                      'type' => 'item_start',
 194                      'level' => $level,
 195                      'count' => $itemcount[$level]
 196                  )
 197              );
 198              
 199              // create a list-item ending token.
 200              $end = $this->addToken(
 201                  array(
 202                      'type' => 'item_end',
 203                      'level' => $level,
 204                      'count' => $itemcount[$level]
 205                  )
 206              );
 207              
 208              // add the starting token, list-item text, and ending token
 209              // to the return.
 210              $return .= $start . $val[3] . $end;
 211          }
 212          
 213          // the last list-item may have been indented.  go through the
 214          // list-type stack and create end-list tokens until the stack
 215          // is empty.
 216          while (count($stack) > 0) {
 217              $return .= $this->addToken(
 218                  array (
 219                      'type' => array_pop($stack) . '_end',
 220                      'level' => count($stack)
 221                  )
 222              );
 223          }
 224          
 225          // we're done!  send back the replacement text.
 226          return "\n" . $return . "\n";
 227      }
 228      
 229      
 230      /**
 231      * 
 232      * Renders a token into text matching the requested format.
 233      * 
 234      * @access public
 235      * 
 236      * @param array $options The "options" portion of the token (second
 237      * element).
 238      * 
 239      * @return string The text rendered from the token options.
 240      * 
 241      */
 242      
 243      function renderXhtml($options)
 244      {
 245          // make nice variables (type, level, count)
 246          extract($options);
 247          
 248          // set up indenting so that the results look nice; we do this
 249          // in two steps to avoid str_pad mathematics.  ;-)
 250          $pad = str_pad('', $level, "\t");
 251          $pad = str_replace("\t", '    ', $pad);
 252          
 253          // attempt XHTML compliance so that sub-lists are part
 254          // of a list item, not between list items
 255          if ($level > 0) {
 256              $pre = '<li style="list-style: none;">';
 257              $post = '</li>';
 258          } else {
 259              $pre = '';
 260              $post = '';
 261          }
 262          
 263          switch ($type) {
 264          
 265          case 'bullet_start':
 266              return "$pad$pre<ul>\n";
 267              break;
 268          
 269          case 'bullet_end':
 270              return "$pad</ul>$post\n";
 271              break;
 272          
 273          case 'number_start':
 274              return "$pad$pre<ol>\n";
 275              break;
 276          
 277          case 'number_end':
 278              return "$pad</ol>$post\n";
 279              break;
 280          
 281          case 'item_start':
 282              return "$pad<li>";
 283              break;
 284          
 285          case 'item_end':
 286              return "</li>\n";
 287              break;
 288          
 289          default:
 290              return '';
 291          
 292          }
 293      }
 294  }
 295  ?>


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