[ Index ]
 

Code source de Serendipity 1.2

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

/bundled-libs/Text/Wiki/Parse/Default/ -> List.php (source)

   1  <?php
   2  // $Id: List.php,v 1.1 2005/01/31 15:46:52 pmjones Exp $
   3  
   4  
   5  /**
   6  * 
   7  * This class implements a Text_Wiki_Parse to find source text marked as
   8  * a bulleted or numbered list.  In short, if a line starts with '* ' then
   9  * it is a bullet list item; if a line starts with '# ' then it is a 
  10  * number list item.  Spaces in front of the * or # indicate an indented
  11  * sub-list.  The list items must be on sequential lines, and may be 
  12  * separated by blank lines to improve readability.  Using a non-* non-#
  13  * non-whitespace character at the beginning of a line ends the list.
  14  *
  15  * @author Paul M. Jones <pmjones@ciaweb.net>
  16  *
  17  * @package Text_Wiki
  18  *
  19  */
  20  
  21  class Text_Wiki_Parse_List extends Text_Wiki_Parse {
  22      
  23      
  24      /**
  25      * 
  26      * The regular expression used to parse the source text and find
  27      * matches conforming to this rule.  Used by the parse() method.
  28      * 
  29      * @access public
  30      * 
  31      * @var string
  32      * 
  33      * @see parse()
  34      * 
  35      */
  36      
  37      var $regex = '/\n((\*|#) .*\n)(?! {0,}(\* |# |\n))/Us';
  38      
  39      
  40      /**
  41      * 
  42      * Generates a replacement for the matched text.  Token options are:
  43      * 
  44      * 'type' =>
  45      *     'bullet_start' : the start of a bullet list
  46      *     'bullet_end'   : the end of a bullet list
  47      *     'number_start' : the start of a number list
  48      *     'number_end'   : the end of a number list
  49      *     'item_start'   : the start of item text (bullet or number)
  50      *     'item_end'     : the end of item text (bullet or number)
  51      *     'unknown'      : unknown type of list or item
  52      *
  53      * 'level' => the indent level (0 for the first level, 1 for the
  54      * second, etc)
  55      *
  56      * 'count' => the list item number at this level. not needed for
  57      * xhtml, but very useful for PDF and RTF.
  58      * 
  59      * @access public
  60      *
  61      * @param array &$matches The array of matches from parse().
  62      *
  63      * @return A series of text and delimited tokens marking the different
  64      * list text and list elements.
  65      *
  66      */
  67      
  68      function process(&$matches)
  69      {
  70          // the replacement text we will return
  71          $return = '';
  72          
  73          // the list of post-processing matches
  74          $list = array();
  75          
  76          // a stack of list-start and list-end types; we keep this
  77          // so that we know what kind of list we're working with
  78          // (bullet or number) and what indent level we're at.
  79          $stack = array();
  80          
  81          // the item count is the number of list items for any
  82          // given list-type on the stack
  83          $itemcount = array();
  84          
  85          // have we processed the very first list item?
  86          $pastFirst = false;
  87          
  88          // populate $list with this set of matches. $matches[1] is the
  89          // text matched as a list set by parse().
  90          preg_match_all(
  91              '=^( {0,})(\*|#) (.*)$=Ums',
  92              $matches[1],
  93              $list,
  94              PREG_SET_ORDER
  95          );
  96          
  97          // loop through each list-item element.
  98          foreach ($list as $key => $val) {
  99              
 100              // $val[0] is the full matched list-item line
 101              // $val[1] is the number of initial spaces (indent level)
 102              // $val[2] is the list item type (* or #)
 103              // $val[3] is the list item text
 104              
 105              // how many levels are we indented? (1 means the "root"
 106              // list level, no indenting.)
 107              $level = strlen($val[1]) + 1;
 108              
 109              // get the list item type
 110              if ($val[2] == '*') {
 111                  $type = 'bullet';
 112              } elseif ($val[2] == '#') {
 113                  $type = 'number';
 114              } else {
 115                  $type = 'unknown';
 116              }
 117              
 118              // get the text of the list item
 119              $text = $val[3];
 120              
 121              // add a level to the list?
 122              if ($level > count($stack)) {
 123                  
 124                  // the current indent level is greater than the
 125                  // number of stack elements, so we must be starting
 126                  // a new list.  push the new list type onto the
 127                  // stack...
 128                  array_push($stack, $type);
 129                  
 130                  // ...and add a list-start token to the return.
 131                  $return .= $this->wiki->addToken(
 132                      $this->rule, 
 133                      array(
 134                          'type' => $type . '_list_start',
 135                          'level' => $level - 1
 136                      )
 137                  );
 138              }
 139              
 140              // remove a level from the list?
 141              while (count($stack) > $level) {
 142                  
 143                  // so we don't keep counting the stack, we set up a temp
 144                  // var for the count.  -1 becuase we're going to pop the
 145                  // stack in the next command.  $tmp will then equal the
 146                  // current level of indent.
 147                  $tmp = count($stack) - 1;
 148                  
 149                  // as long as the stack count is greater than the
 150                  // current indent level, we need to end list types. 
 151                  // continue adding end-list tokens until the stack count
 152                  // and the indent level are the same.
 153                  $return .= $this->wiki->addToken(
 154                      $this->rule, 
 155                      array (
 156                          'type' => array_pop($stack) . '_list_end',
 157                          'level' => $tmp
 158                      )
 159                  );
 160                  
 161                  // reset to the current (previous) list type so that
 162                  // the new list item matches the proper list type.
 163                  $type = $stack[$tmp - 1];
 164                  
 165                  // reset the item count for the popped indent level
 166                  unset($itemcount[$tmp + 1]);
 167              }
 168              
 169              // add to the item count for this list (taking into account
 170              // which level we are at).
 171              if (! isset($itemcount[$level])) {
 172                  // first count
 173                  $itemcount[$level] = 0;
 174              } else {
 175                  // increment count
 176                  $itemcount[$level]++;
 177              }
 178              
 179              // is this the very first item in the list?
 180              if (! $pastFirst) {
 181                  $first = true;
 182                  $pastFirst = true;
 183              } else {
 184                  $first = false;
 185              }
 186              
 187              // create a list-item starting token.
 188              $start = $this->wiki->addToken(
 189                  $this->rule, 
 190                  array(
 191                      'type' => $type . '_item_start',
 192                      'level' => $level,
 193                      'count' => $itemcount[$level],
 194                      'first' => $first
 195                  )
 196              );
 197              
 198              // create a list-item ending token.
 199              $end = $this->wiki->addToken(
 200                  $this->rule, 
 201                  array(
 202                      'type' => $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->wiki->addToken(
 218                  $this->rule, 
 219                  array (
 220                      'type' => array_pop($stack) . '_list_end',
 221                      'level' => count($stack)
 222                  )
 223              );
 224          }
 225          
 226          // we're done!  send back the replacement text.
 227          return "\n" . $return . "\n\n";
 228      }
 229  }
 230  ?>


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