Simplewiki 1
|
00001 <?php 00009 #========================================================================== 00010 #-----------------------------[ PARSER ]---------------------------------- 00011 #========================================================================== 00012 00026 class Muster_SimpleWiki_Parser 00027 { 00038 protected $link_inline_re; 00039 protected $image_inline_re; 00040 protected $item_inline_re; 00041 protected $defitem_inline_re; 00042 protected $cell_re; 00043 protected $decorator_re; 00044 protected $tablerow_setaside_re; 00045 protected $pre_escape_re; 00046 protected $_rules; 00047 protected $block_re; 00048 protected $inline_re; 00049 00052 00053 protected $_curnode; 00055 protected $_leaftextnode; 00057 protected $_root; 00060 00061 protected $_raw; 00063 protected $_preprocessed_raw; 00065 protected $_argchars = '^()'; // no parenthesis 00066 // protected $_argchars = '\\w\\s:="\'%\\\#.-'; // for decorators, notably parentheses omitted for security 00068 protected $_metadata; // from first line ```## arguments 00070 protected $_markerdata; // from preprocessing 00074 protected $_markers; 00082 public function __construct($text) 00083 { 00084 $this->_set_rules(); 00085 $this->_set_re($this->_rules); 00086 $this->prepare($text); 00087 } 00099 protected function _set_rules() 00100 { 00101 // the first group name of each rule, if set, is used by controller (_create_node($preg_groups)) 00102 // for further processing of parsed data 00103 $rules = new StdClass(); 00104 $argchars = $this->_argchars; 00105 #================================[ basic processing ]=================================# 00106 # no explicit action by user (other than include blank lines between blocks) 00107 // $rules->char = '(?P<char> . )'; // slower, but allows capture of raw url's 00108 // $rules->char = '(?P<char> ([\\w\\s]+$|. ))'; //faster, but misses raw url's, twice as slow as markup filter 00109 // markup characters: =/*-\[]|#{}%:<>~ 00112 $rules->char = '(?P<char> ([^\/\*\\\[{%<~]+|.))'; // characters before next inline markup start, or markup start char 00114 $rules->blankline = '(?P<blankline> ^ \s* $ )'; 00116 $rules->paragraph = '(?P<paragraph> 00117 ^\s*(\|:p\s+(?P<paragraph_decorator>['.$argchars.']+?):\|)?(?P<text_chars>.+) 00118 | 00119 (?P<text_charstream>.+) 00120 )'; 00121 #================================[ core markup ]===============================# 00122 #--------------------------------[ basic markup ]------------------------------# 00123 00124 $rules->heading = '(?P<heading> 00125 ^\s*(\|:h\s+(?P<heading_decorator>['.$argchars.']+?):\|)? \s* 00126 (?P<heading_head>={1,6}) \s* 00127 (?P<heading_text> .*? ) \s* 00128 (?P<heading_tail>=*) \s* 00129 $ 00130 )'; 00135 $rules->emph = '(?P<emph> (?<!~)\/\/ )'; 00137 $rules->strong = '(?P<strong> \*\* )'; 00139 $rules->linebreak = '(?P<linebreak> \\\\\\\\ )'; 00140 // \b horizontalrule: horizontal rule: "-----*" 00141 $rules->horizontalrule = '(?P<horizontalrule> 00142 ^ \s* -----* \s* $ 00143 )'; 00144 #--------------------------------[ links ]-------------------------------------# 00145 00146 $rules->link = '(?P<link> 00147 (%l\s+(?P<link_decorator>['.$argchars.']+?)%)? 00148 \[\[ 00149 (?P<link_target>\S+?) \s* 00150 (\| \s* (?P<link_text>.*?) \s* (\| \s* (?P<link_title>[^|\]}]+))? \s*)? 00151 \]\](?!]) # allow embedded "]" 00152 )'; 00153 #--------------------------------[ images ]-------------------------------------# 00154 00155 $rules->image = '(?P<image> 00156 (%i\s+(?P<image_decorator>['.$argchars.']+?)%)? 00157 {{ 00158 (?P<image_target>\S+?) \s* 00159 (\| \s* (?P<image_text>.*?) \s* (\| \s* (?P<image_title>[^|\]}]+))? \s*)? 00160 }} 00161 )'; 00162 #--------------------------------[ lists ]-------------------------------------# 00163 00164 00165 $rules->deflist = '(?P<deflist> 00166 ^ \s* 00167 (\|:d[ltd]\s+(['.$argchars.']+?):\|){0,3} 00168 (:(?=[^:])).* $ # only one opening list marker allowed 00169 (\n [\t\x20]* 00170 (\|:d[ltd]\s+(['.$argchars.']+?):\|){0,3} 00171 :+.* $ 00172 )* 00173 )'; 00175 $rules->defitem = '(?P<defitem> 00176 ^\s* 00177 (\|:dl\s+(?P<deflist_decorator>(['.$argchars.']+?)):\|)? 00178 (\|:dt\s+(?P<defterm_decorator>(['.$argchars.']+?)):\|)? 00179 (\|:dd\s+(?P<defdesc_decorator>(['.$argchars.']+?)):\|)? 00180 (?P<defitem_head> :+) \s* 00181 ((?P<defterm_text> .*?)(?<!~)::)? 00182 (?P<defdesc_text> .*?) 00183 \s*$ 00184 )'; 00187 $rules->list = '(?P<list> 00188 ^\s* 00189 (\|:([uo]l|li) \s+(['.$argchars.']+?):\|){0,2} 00190 ([*\\#](?=[^*\\#])).* $ # only one opening list marker allowed 00191 (\n [\t\x20]* 00192 (\|:([uo]l|li) \s+(['.$argchars.']+?):\|){0,2} 00193 [*\#]+.* $ 00194 )* 00195 )'; 00197 $rules->item = '(?P<item> 00198 ^\s* 00199 (\|:[uo]l\s+(?P<list_decorator> (['.$argchars.']+?)):\|)? 00200 (\|:li\s+(?P<item_decorator>(['.$argchars.']+?)):\|)? 00201 (?P<item_head> [\#*]+) \s* 00202 (?P<item_text> .*) 00203 \s*$ 00204 )'; 00205 #--------------------------------[ tables ]-------------------------------------# 00206 00207 $rules->table = '(?P<table> 00208 ^\s* 00209 (\|:table\\s+(?P<table_decorator>(['.$argchars.']+?)):\|)? 00210 (\|:tr\s+(?P<row_decorator>(['.$argchars.']+?)):\|)? 00211 \s* 00212 (?P<table_row> 00213 (((?<!~)\|:t[dh]\s+(['.$argchars.']+?):\|)?\|(?!:[a-z]).*?)* \s* 00214 \| \s* 00215 ) 00216 \s*$ 00217 )'; 00219 $rules->cell = ' 00220 (\|:t[dh]\s+(?P<cell_decorator>['.$argchars.']+?):\|)? 00221 \| \s* 00222 ( 00223 (?P<head> = ([^|]|(?<=~)\|)+ ) | 00224 (?P<cell> ([^|]|(?<=~)\|)+ ) 00225 ) \s* 00226 '; 00227 #================================[ escape character ]=================================# 00228 00229 $rules->escape = '(?P<escape> ~ (?P<escaped_char>\S) )'; # embedded in various regex's 00230 #================================[ special decorators ]===============================# 00231 #--------------------------------[ span decoration ]----------------------------------# 00233 $rules->span = '(?P<span> %(s\s+(?P<span_decorator>['.$argchars.']+?))?% )'; 00234 #--------------------------------[ block dividers ]-----------------------------------# 00236 $rules->blockdivider = '(?P<blockdivider> 00237 ^\s* \|:b \s+(?P<blockdivider_decorator>(['.$argchars.']+?)):\| \s* $ 00238 )'; # generic block 00239 #===============================[ preformatted text ]=================================# 00240 // inline 00242 $rules->code = '(?P<code> 00243 (%c\s+(?P<code_decorator>['.$argchars.']+?)%)?{{{ (?P<code_text>.*?) }}} 00244 )'; 00246 $rules->pre = '(?P<pre> 00247 ^\s*(\|:pre\s+(?P<pre_decorator>['.$argchars.']+?):\|)?(?<!~){{{ \s* $ 00248 (\n)? 00249 (?P<pre_markup> 00250 ([\#]!(?P<pre_type>\w*?)(\s+.*)?$)? 00251 (.|\n)+? 00252 ) 00253 \n? 00254 ^\s*}}} \s*$ 00255 )'; 00257 $rules->pre_escape = ' ^(?P<indent>\s*) ~ (?P<rest> \}\}\} \s*) $'; 00258 #================================[ advanced markup ]===============================# 00259 #--------------------------------[ block declarations ]------------------------------# 00262 $rules->blockdef = ' 00263 ^(?P<blockdef> 00264 \n?(?P<block_indent>[\t\x20]*)\(:(?P<block_selector>\w+)(\s+(?P<block_decorator>['.$argchars.']+?))? \s* :\) 00265 \s*?(?P<block_inline>.*) $ 00266 (?P<block_content>(\n.*$)*?) 00267 \n(?P=block_indent)\(:(?P=block_selector)end\s*:\)\s*$ 00268 )'; 00269 00270 #--------------------------------[ macros ]--------------------------------# 00272 $rules->macro = '(?P<macro> 00273 << 00274 (?P<macro_name> \w+) 00275 ((?P<macro_args> ['.$argchars.']*) )? \s* 00276 (\| \s* (?P<macro_text> .+?) \s* )? 00277 >> 00278 )'; 00280 $rules->blockmacro = '(?P<blockmacro> 00281 ^ \s* 00282 << 00283 (?P<blockmacro_name> \w+) 00284 ((?P<blockmacro_args> ['.$argchars.']*) )? \s* 00285 (\| \s* (?P<blockmacro_text> .+?) \s* )? 00286 >> \s* 00287 $ 00288 )'; 00290 $rules->decorator = ' 00291 (?>(?P<variable>[\w-]+)(?P<operator>[:=]))? # optional attribute or property name, and operator applied 00292 ( 00293 "(?P<ddelim_value>.*?)(?<!\\\)" # double quote delimited 00294 | 00295 \'(?P<sdelim_value>.*?)(?<!\\\)\' # single quote delimited 00296 | 00297 (?P<ndelim_value>\S+) # not delimited 00298 ) 00299 '; 00300 $this->_rules = $rules; 00301 } 00302 #---------------------------------------------------------------------------------------# 00303 #------------------------------[ set regular expressions ]------------------------------# 00304 #---------------------------------------------------------------------------------------# 00305 00318 protected function _set_re($rules) 00319 { 00320 // from least to most general 00321 // For special case pre escaping, in creole 1.0 done with ~: 00322 $this->pre_escape_re = '/' . $rules->pre_escape . '/xm'; 00323 // For sub-processing: includes image, but excludes links 00324 $this->link_inline_re = "/\n" 00325 . implode("\n|\n", 00326 array($rules->code, $rules->image, $rules->strong, 00327 $rules->emph, $rules->span, $rules->linebreak, 00328 $rules->escape, $rules->char)) 00329 . "\n/x"; # for link captions 00330 // For sub-processing: includes links, but excludes images 00331 $this->image_inline_re = "/\n" 00332 . implode("\n|\n", 00333 array($rules->link, $rules->code, $rules->strong, 00334 $rules->emph, $rules->span, $rules->linebreak, 00335 $rules->escape, $rules->char)) 00336 . "\n/x"; # for image captions 00337 $this->item_inline_re = '/' . $rules->item . '/xm'; // for list items 00338 $this->defitem_inline_re = '/' . $rules->defitem . '/xm'; // for def list items 00339 $this->cell_re = '/' . $rules->cell . '/x'; // for quick table cells 00340 // For inline elements: 00341 $this->inline_re = "/\n" 00342 . implode("\n|\n", 00343 array($rules->link, $rules->macro, 00344 $rules->code, $rules->image, $rules->strong, $rules->emph, 00345 $rules->span, $rules->linebreak, $rules->escape, $rules->char)) 00346 . "\n/x"; 00347 // set aside table row contents 00348 $this->tablerow_setaside_re = "/\n" 00349 . implode("\n|\n", array($rules->link, $rules->macro,$rules->code,$rules->image)) 00350 . "\n/x"; 00351 // For block elements: 00352 $this->block_re = "/\n" 00353 . implode("\n|\n", 00354 array($rules->blankline, $rules->blockdef, $rules->heading, 00355 $rules->horizontalrule, $rules->blockdivider, $rules->blockmacro, 00356 $rules->pre, $rules->list, $rules->deflist, $rules->table, $rules->paragraph)) 00357 . "\n/xm"; 00358 $this->decorator_re = '/' . $rules->decorator . '/x'; 00359 } 00369 public function metadata() 00370 { 00371 return $this->_metadata; 00372 } 00380 public function markerdata() 00381 { 00382 return $this->_markerdata; 00383 } 00389 public function preprocessed_markup() 00390 { 00391 return $this->_preprocessed_markup; 00392 } 00397 public function argchars($argchars = NULL) 00398 { 00399 if (!is_null($argchars)) 00400 { 00401 $this->_argchars = $argchars; 00402 // recompile regex 00403 $this->_set_rules(); 00404 $this->_set_re($this->_rules); 00405 } 00406 return $this->_argchars; 00407 } 00409 #---------------------[ process initiation ]--------------------------# 00410 00424 public function prepare($markup) 00425 { 00426 $this->_raw = $markup; 00427 $this->_root = new SimpleWiki_DocNode(SimpleWiki_DocNode::DOCUMENT); # 'document' is the top level node 00428 $this->_curnode = $this->_root; # The most recent document node 00429 $this->_leaftextnode = NULL; # The node to add inline characters to 00430 $raw = $this->preprocess_raw_markup($this->_raw); 00431 return $this; 00432 } 00439 public function parse() // initiate parsing 00440 { 00441 # try to clean $raw of unnecessary newlines 00442 # parse the text given as $this->_raw... 00443 $this->_parse_block($this->_preprocessed_raw); 00444 #...and return DOM tree. 00445 return $this->_root; 00446 } 00456 protected function _parse_block($raw) 00457 { 00458 # Recognize block elements. 00459 preg_replace_callback($this->block_re, array($this,'_create_node'), $raw); 00460 } 00470 protected function _parse_inline($raw) 00471 { 00472 # Recognize inline elements inside blocks. 00473 preg_replace_callback($this->inline_re, array($this,'_create_node'), $raw); 00474 } 00475 #---------------------[ process control ]--------------------------# 00476 00486 protected function _create_node($preg_groups) // controller 00487 { 00488 # Invoke appropriate _*_node method. Called for every matched group. 00489 foreach ($preg_groups as $name => $text) 00490 { 00491 if ((!is_int($name)) and ($text != '')) 00492 { 00493 $node_method = "_{$name}_node"; 00494 $this->$node_method($preg_groups); 00495 return; 00496 } 00497 } 00498 # special case: pick up empty line for block boundary 00499 $keys = array_keys($preg_groups); 00500 $name = 'blankline'; 00501 if ($keys[count($keys)-2]==$name) // last name in key array indicates returned as found 00502 { 00503 $node_method = "_{$name}_node"; 00504 $this->$node_method($preg_groups); 00505 return; 00506 } 00507 } 00510 00511 protected $_pre_markers = array(); 00513 protected $_pre_markup = array(); 00515 protected $_pre_count = 0; 00523 protected function add_pre_and_code_markers($preg_groups) 00524 { 00525 isset($preg_groups['pre']) or ($preg_groups['pre'] = ''); 00526 isset($preg_groups['code']) or ($preg_groups['code'] = ''); 00527 $this->_pre_markup[] = preg_replace('/(\$|\\\\)(?=\d)/', '\\\\\1', // escape backreference markup 00528 $preg_groups['pre'].$preg_groups['code']); // one or the other 00529 $this->_pre_count++; 00530 $marker = '{{{' . chr(255). $this->_pre_count . '}}}'; 00531 $this->_pre_markers[] = '/{{\\{' . chr(255) . $this->_pre_count . '\\}}}/'; 00532 return $marker; 00533 } 00535 protected $_tablerow_markers = array(); 00537 protected $_tablerow_markup = array(); 00539 protected $_tablerow_count = 0; 00546 protected function add_tablerow_markers($preg_groups) 00547 { 00548 isset($preg_groups['link']) or ($preg_groups['link'] = ''); 00549 isset($preg_groups['macro']) or ($preg_groups['macro'] = ''); 00550 isset($preg_groups['code']) or ($preg_groups['code'] = ''); 00551 isset($preg_groups['image']) or ($preg_groups['image'] = ''); 00552 ($value = $preg_groups['link']) or ($value = $preg_groups['macro']) or 00553 ($value = $preg_groups['code']) or ($value = $preg_groups['image']); 00554 $this->_tablerow_markup[] = $value; 00555 $this->_tablerow_count++; 00556 $marker = '{{{' . chr(255). $this->_tablerow_count . '}}}'; 00557 $this->_tablerow_markers[] = '/{{\\{' . chr(255) . $this->_tablerow_count . '\\}}}/'; 00558 return $marker; 00559 } 00572 protected function preprocess_raw_markup($raw) 00573 { 00574 # get metadata 00575 $raw = preg_replace_callback('/\A```##(.*$(\n``.*$)*)/m',array($this,'preprocess_metadata'),$raw); 00576 $raw = "\n".$raw."\n"; // in case there is comment on first line, lookahead on last 00577 # remove comments 00578 $raw = preg_replace('/\n```.*$/m','',$raw); 00579 # remove line continuations 00580 $raw = preg_replace('/\n``/','',$raw); 00581 # set aside preformatted blocks 00582 $raw = preg_replace_callback('/'.$this->_rules->pre .'|' .$this->_rules->code .'/xm',array($this,'add_pre_and_code_markers'),$raw); 00583 # add markup around raw url's; this allows "//" emphasis markup to operate without constraint 00584 $raw = preg_replace('/(^|\W)((?<!\[\[|{{|~)(http[s]?|mailto):\/\/\S+\w)/','$1[[$2]]',$raw); // add markup to raw url 00585 # restore preformatted blocks 00586 $raw = preg_replace($this->_pre_markers,$this->_pre_markup,$raw); 00587 # get marker data and offsets 00588 $markerdata = $this->_markerdata = new StdClass(); 00589 $markerdata->offset = 0; 00590 $markerdata->markercount = 0; 00591 $this->_markers = array(); 00592 // pull out markers {{##markername marker decoration##}} 00593 $re = '/(?P<text>[^{]*)|(?<!~)(?P<marker>\{\{##(?P<markername>[a-zA-Z]\w*)(\s+(?P<decorator>['.$this->_argchars.']+?))?\s*##\}\})|(?P<char>.)/'; 00594 $raw = preg_replace_callback($re,array($this,'preprocess_markerdata'),$raw); 00595 $markerdata->markers = $this->_markers; 00596 $this->_markers = NULL; 00597 $markerdata->textlength = $markerdata->offset; 00598 unset($markerdata->offset); 00599 $this->_preprocessed_raw = $raw; 00600 return $raw; 00601 } 00608 protected function preprocess_markerdata($matches) 00609 { 00610 isset($matches['text']) or ($matches['text'] = ''); 00611 isset($matches['char']) or ($matches['char'] = ''); 00612 isset($matches['marker']) or ($matches['marker'] = ''); 00613 isset($matches['markername']) or ($matches['markername'] = ''); 00614 isset($matches['decorator']) or ($matches['decorator'] = ''); 00615 $text = $matches['text'].$matches['char']; 00616 $this->_markerdata->offset += strlen($text); 00617 if ($marker = $matches['marker']) 00618 { 00619 $this->_markerdata->markercount++; 00620 $markerobject = $this->_markers[] = new StdClass(); 00621 $markerobject->offset = $this->_markerdata->offset; 00622 $name = $markerobject->name = $matches['markername']; 00623 $this->_markers[$name] = $markerobject; 00624 if ($decorator = $matches['decorator']) 00625 $markerobject->decoration = $this->get_decoration($decorator); 00626 else 00627 $markerobject->decoration = NULL; 00628 } 00629 return $text; 00630 } 00637 protected function preprocess_metadata($matches) 00638 { 00639 $arguments = trim($matches[1]); 00640 // remove line continuations 00641 $arguments = preg_replace('/\n``/','',$arguments); 00642 // save data 00643 $this->_metadata = $this->get_decoration($arguments); 00644 return ''; 00645 } 00650 public function get_decoration($decorator_string) 00651 { 00652 $decoration = new StdClass(); 00653 $decoration->classes = array(); 00654 $decoration->properties = array(); 00655 $decoration->attributes = array(); 00656 $terms = array(); 00657 preg_match_all($this->decorator_re, $decorator_string, $terms, PREG_SET_ORDER); // returns terms 00658 foreach($terms as $term) 00659 { 00660 isset($term['variable']) or ($term['variable'] = ''); 00661 isset($term['operator']) or ($term['operator'] = ''); 00662 isset($term['ddelim_value']) or ($term['ddelim_value'] = ''); 00663 isset($term['sdelim_value']) or ($term['sdelim_value'] = ''); 00664 isset($term['ndelim_value']) or ($term['ndelim_value'] = ''); 00665 $variable = $term['variable']; 00666 $operator = $term['operator']; 00667 if ($term['ddelim_value']) $delimiter = '"'; 00668 elseif ($term['sdelim_value']) $delimiter = "'"; 00669 else $delimiter = ''; 00670 // only one of the following will not be empty 00671 $value = $term['ddelim_value'] . $term['sdelim_value'] . $term['ndelim_value']; 00672 switch ($operator) 00673 { 00674 case '=': 00675 $decoration->attributes[$variable] = $value; 00676 if ($delimiter == '') $delimiter = '"'; 00677 $decoration->attributedelimiters[$variable] = $delimiter; 00678 break; 00679 case ':': 00680 $decoration->properties[$variable] = $value; 00681 break; 00682 default: 00683 $decoration->classes[] = $value; 00684 break; 00685 } 00686 } 00687 return $decoration; 00688 } 00694 protected function set_node_decoration($node,$decorator_string) 00695 { 00696 $node->decoration = $this->get_decoration($decorator_string); 00697 $node->decoration->markup = $decorator_string; 00698 } 00699 #------------------------------------------------------------------------------# 00700 #---------------------------[ utilities ]--------------------------------------# 00701 #------------------------------------------------------------------------------# 00702 00710 public function get_selected_ancestor($node, $types) // public as can be used by registered callbacks 00711 { 00712 while ((!empty($node->parent)) and (!in_array($node->type,$types))) 00713 { 00714 $node = $node->parent; 00715 } 00716 return $node; 00717 } 00727 #=========================[ basic processing ]=================================# 00728 00735 protected function _char_node($preg_groups) // can create text leaf node 00736 { 00737 $char = $preg_groups['char']; 00738 if (is_null($this->_leaftextnode)) 00739 $this->_leaftextnode = new SimpleWiki_DocNode(SimpleWiki_DocNode::TEXT, $this->_curnode); 00740 $this->_leaftextnode->textcontent .= $char; 00741 } 00750 protected function _escape_node($preg_groups) 00751 { 00752 $char = $preg_groups['escaped_char']; 00753 if (is_null($this->_leaftextnode)) 00754 $this->_leaftextnode = new SimpleWiki_DocNode(SimpleWiki_DocNode::TEXT, $this->_curnode); 00755 $this->_leaftextnode->textcontent .= $char; 00756 } 00762 protected function _blankline_node($preg_groups) 00763 { 00764 # triggers new block 00765 $this->_curnode = $this->get_selected_ancestor($this->_curnode, 00766 array(SimpleWiki_DocNode::DOCUMENT,SimpleWiki_DocNode::BLOCKDEF)); 00767 } 00782 protected function _paragraph_node($preg_groups) // can create paragraph for new text 00783 { 00784 # text not otherwise classified, triggers creation of paragraph for new set 00785 isset($preg_groups['text_chars']) or ($preg_groups['text_chars'] = ''); 00786 isset($preg_groups['text_charstream']) or ($preg_groups['text_charstream'] = ''); 00787 isset($preg_groups['paragraph_decorator']) or ($preg_groups['paragraph_decorator'] = ''); 00788 $text = $preg_groups['text_chars'] . $preg_groups['text_charstream']; 00789 $decorator = $preg_groups['paragraph_decorator']; 00790 if (in_array($this->_curnode->type, 00791 array( 00792 SimpleWiki_DocNode::TABLE, 00793 SimpleWiki_DocNode::TABLE_ROW, 00794 SimpleWiki_DocNode::UNORDERED_LIST, 00795 SimpleWiki_DocNode::ORDERED_LIST, 00796 SimpleWiki_DocNode::DEF_LIST))) // text cannot exist in these blocks 00797 { 00798 $this->_curnode = $this->get_selected_ancestor($this->_curnode, 00799 array(SimpleWiki_DocNode::DOCUMENT,SimpleWiki_DocNode::BLOCKDEF)); 00800 } 00801 if (in_array($this->_curnode->type, array(SimpleWiki_DocNode::DOCUMENT,SimpleWiki_DocNode::BLOCKDEF))) 00802 { 00803 $node = $this->_curnode = new SimpleWiki_DocNode(SimpleWiki_DocNode::PARAGRAPH, $this->_curnode); 00804 if ($decorator) $this->set_node_decoration($node,$decorator); 00805 } else { 00806 $text = ' ' . $text; 00807 } 00808 $this->_parse_inline($text); 00809 $this->_leaftextnode = NULL; 00810 } 00811 #================================[ core markup ]===============================# 00812 #--------------------------------[ basic markup ]------------------------------# 00813 00823 protected function _heading_node($preg_groups) 00824 { 00825 # headings 00826 isset($preg_groups['heading_text']) or ($preg_groups['heading_text'] = ''); 00827 isset($preg_groups['heading_head']) or ($preg_groups['heading_head'] = ''); 00828 isset($preg_groups['heading_decorator']) or ($preg_groups['heading_decorator'] = ''); 00829 $headtext = $preg_groups['heading_text']; 00830 $headhead = $preg_groups['heading_head']; 00831 $decorator = $preg_groups['heading_decorator']; 00832 00833 $this->_curnode = $this->get_selected_ancestor($this->_curnode, 00834 array(SimpleWiki_DocNode::DOCUMENT,SimpleWiki_DocNode::BLOCKDEF)); 00835 00836 $node = new SimpleWiki_DocNode(SimpleWiki_DocNode::HEADING,$this->_curnode); 00837 $node->level = strlen($headhead); 00838 if ($decorator) $this->set_node_decoration($node,$decorator); 00839 00840 $parent = $this->_curnode; 00841 $this->_curnode = $node; 00842 $this->_leaftextnode = NULL; 00843 00844 $this->_parse_inline($headtext); 00845 00846 $this->_curnode = $parent; 00847 $this->_leaftextnode = NULL; 00848 } 00856 protected function _emph_node($preg_groups) 00857 { 00858 # emphasis 00859 if ($this->_curnode->type != SimpleWiki_DocNode::EMPHASIS) 00860 $this->_curnode = new SimpleWiki_DocNode(SimpleWiki_DocNode::EMPHASIS, $this->_curnode); 00861 else 00862 { 00863 if (!empty($this->_curnode->parent)) 00864 $this->_curnode = $this->_curnode->parent; 00865 } 00866 $this->_leaftextnode = NULL; 00867 } 00875 protected function _strong_node($preg_groups) 00876 { 00877 # strong 00878 if ($this->_curnode->type != SimpleWiki_DocNode::STRONG) 00879 $this->_curnode = new SimpleWiki_DocNode(SimpleWiki_DocNode::STRONG, $this->_curnode); 00880 else 00881 { 00882 if (!empty($this->_curnode->parent)) 00883 $this->_curnode = $this->_curnode->parent; 00884 } 00885 $this->_leaftextnode = NULL; 00886 } 00892 protected function _linebreak_node($preg_groups) 00893 { 00894 # line break 00895 new SimpleWiki_DocNode(SimpleWiki_DocNode::LINEBREAK, $this->_curnode); 00896 $this->_leaftextnode = NULL; 00897 } 00904 protected function _horizontalrule_node($preg_groups) 00905 { 00906 $this->_curnode = $this->get_selected_ancestor($this->_curnode, 00907 array(SimpleWiki_DocNode::DOCUMENT,SimpleWiki_DocNode::BLOCKDEF)); 00908 new SimpleWiki_DocNode(SimpleWiki_DocNode::HORIZONTALRULE, $this->_curnode); 00909 } 00918 protected function _link_node($preg_groups) 00919 { 00920 # Handle all types of links. 00921 isset($preg_groups['link_target']) or ($preg_groups['link_target'] = ''); 00922 isset($preg_groups['link_text']) or ($preg_groups['link_text'] = ''); 00923 isset($preg_groups['link_title']) or ($preg_groups['link_title'] = ''); 00924 isset($preg_groups['link_decorator']) or ($preg_groups['link_decorator'] = ''); 00925 $target = trim($preg_groups['link_target']); 00926 $text = trim($preg_groups['link_text']); 00927 $title = trim($preg_groups['link_title']); 00928 $decorator = trim($preg_groups['link_decorator']); 00929 00930 $node = new SimpleWiki_DocNode(SimpleWiki_DocNode::LINK, $this->_curnode); 00931 $node->target = $target; 00932 if ($decorator) $this->set_node_decoration($node,$decorator); 00933 if ($title) $node->title = $title; 00934 00935 $parent = $this->_curnode; 00936 $this->_curnode = $node; 00937 $this->_leaftextnode = NULL; 00938 00939 preg_replace_callback($this->link_inline_re, array($this,'_create_node'), $text); 00940 00941 $this->_curnode = $parent; 00942 $this->_leaftextnode = NULL; 00943 } 00944 #--------------------------------[ images ]-------------------------------------# 00945 00953 protected function _image_node($preg_groups) 00954 { 00955 # Handles images included in the page. 00956 isset($preg_groups['image_target']) or ($preg_groups['image_target'] = ''); 00957 isset($preg_groups['image_text']) or ($preg_groups['image_text'] = ''); 00958 isset($preg_groups['image_title']) or ($preg_groups['image_title'] = ''); 00959 isset($preg_groups['image_decorator']) or ($preg_groups['image_decorator'] = ''); 00960 $target = trim($preg_groups['image_target']); 00961 $text = trim($preg_groups['image_text']); 00962 $title = trim($preg_groups['image_title']); 00963 $decorator = trim($preg_groups['image_decorator']); 00964 00965 $node = new SimpleWiki_DocNode(SimpleWiki_DocNode::IMAGE, $this->_curnode); 00966 $node->target = $target; 00967 if ($decorator) $this->set_node_decoration($node,$decorator); 00968 if ($title != '') $node->title = $title; 00969 00970 $parent = $this->_curnode; 00971 $this->_curnode = $node; 00972 $this->_leaftextnode = NULL; 00973 00974 preg_replace_callback($this->image_inline_re, array($this,'_create_node'), $text); 00975 00976 $this->_curnode = $parent; 00977 $this->_leaftextnode = NULL; 00978 } 00979 #--------------------------------[ lists ]-------------------------------------# 00980 00985 protected function _list_node($preg_groups) 00986 { 00987 # collect list markup, detail processing by item 00988 $text = $preg_groups['list']; 00989 preg_replace_callback($this->item_inline_re,array($this,'_create_node'), $text); 00990 } 01000 protected function _item_node($preg_groups) 01001 { 01002 # list item 01003 isset($preg_groups['item_head']) or ($preg_groups['item_head'] = ''); 01004 isset($preg_groups['item_text']) or ($preg_groups['item_text'] = ''); 01005 isset($preg_groups['list_decorator']) or ($preg_groups['list_decorator'] = ''); 01006 isset($preg_groups['item_decorator']) or ($preg_groups['item_decorator'] = ''); 01007 $bullet = $preg_groups['item_head']; 01008 $text = $preg_groups['item_text']; 01009 $listdecorator = $preg_groups['list_decorator']; 01010 $itemdecorator = $preg_groups['item_decorator']; 01011 // determine the type of list being processed 01012 if ($bullet{0} == '#') 01013 $listtype = SimpleWiki_DocNode::ORDERED_LIST; 01014 else 01015 $listtype = SimpleWiki_DocNode::UNORDERED_LIST; 01016 // determine the level by measuring the number of list markup characters 01017 $level = strlen($bullet); 01018 # Find a node of the same type and level up the tree, or a block to start a list 01019 $candidate_node = $this->_curnode; 01020 while // find a reference node if current list doesn't match, and if we're not in a block node to start 01021 ( 01022 ($candidate_node) // searching an existing node 01023 and ! // this is a not a list of the same level... 01024 ( 01025 in_array($candidate_node->type, array(SimpleWiki_DocNode::ORDERED_LIST, SimpleWiki_DocNode::UNORDERED_LIST)) 01026 and $candidate_node->level == $level 01027 ) 01028 and ! // ... and this is not a block ... 01029 ( 01030 in_array($candidate_node->type, array(SimpleWiki_DocNode::DOCUMENT,SimpleWiki_DocNode::BLOCKDEF)) 01031 ) 01032 ) // ... so keep looking. 01033 { 01034 $candidate_node = $candidate_node->parent; 01035 } 01036 # set the found list as the current node for the list item... 01037 # (if $candidate_node is null then no reference candidate was found) 01038 if ($candidate_node and ($candidate_node->type == $listtype)) // found a match for list 01039 $this->_curnode = $candidate_node; 01040 else # ... or create a new level of list 01041 { 01042 // get the nearest ancestor candidate for creating a new list 01043 $this->_curnode = $this->get_selected_ancestor($this->_curnode, 01044 array(SimpleWiki_DocNode::LIST_ITEM, SimpleWiki_DocNode::DOCUMENT,SimpleWiki_DocNode::BLOCKDEF)); 01045 // create the list 01046 $listnode = $this->_curnode = new SimpleWiki_DocNode($listtype, $this->_curnode); 01047 if ($listdecorator) $this->set_node_decoration($listnode,$listdecorator); 01048 $listnode->level = $level; 01049 } 01050 # now add the list item to the list 01051 $itemnode = $this->_curnode = new SimpleWiki_DocNode(SimpleWiki_DocNode::LIST_ITEM, $this->_curnode); 01052 if ($itemdecorator) $this->set_node_decoration($itemnode,$itemdecorator); 01053 $this->_leaftextnode = NULL; 01054 # parse the text of the list item 01055 $this->_parse_inline($text); 01056 $this->_leaftextnode = NULL; 01057 } 01058 #--------------------------------[ definition list ]-------------------------------------# 01059 01064 protected function _deflist_node($preg_groups) 01065 { 01066 # collect list markup, detail processing by item 01067 $text = $preg_groups['deflist']; 01068 preg_replace_callback($this->defitem_inline_re,array($this,'_create_node'), $text); 01069 } 01080 protected function _defitem_node($preg_groups) 01081 { 01082 # list item 01083 isset($preg_groups['defitem_head']) or ($preg_groups['defitem_head'] = ''); 01084 isset($preg_groups['defterm_text']) or ($preg_groups['defterm_text'] = ''); 01085 isset($preg_groups['defdesc_text']) or ($preg_groups['defdesc_text'] = ''); 01086 isset($preg_groups['deflist_decorator']) or ($preg_groups['deflist_decorator'] = ''); 01087 isset($preg_groups['defterm_decorator']) or ($preg_groups['defterm_decorator'] = ''); 01088 isset($preg_groups['defdesc_decorator']) or ($preg_groups['defdesc_decorator'] = ''); 01089 $head = $preg_groups['defitem_head']; 01090 $term = trim($preg_groups['defterm_text']); 01091 $desc = $preg_groups['defdesc_text']; 01092 $listdecorator = $preg_groups['deflist_decorator']; 01093 $termdecorator = $preg_groups['defterm_decorator']; 01094 $descdecorator = $preg_groups['defdesc_decorator']; 01095 // set the type of list being processed 01096 $listtype = SimpleWiki_DocNode::DEF_LIST; 01097 // determine the level by measuring the number of list markup characters 01098 $level = strlen($head); 01099 # Find a node of the same type and level up the tree, or a block to start a list 01100 $candidate_node = $this->_curnode; 01101 while // find a reference node if current list doesn't match, and if we're not in a block node to start 01102 ( 01103 ($candidate_node) // searching an existing node 01104 and ! // this is a not a list of the same level... 01105 ( 01106 ($candidate_node->type == SimpleWiki_DocNode::DEF_LIST) 01107 and $candidate_node->level == $level 01108 ) 01109 and ! // ... and this is not a block ... 01110 ( 01111 in_array($candidate_node->type, array(SimpleWiki_DocNode::DOCUMENT,SimpleWiki_DocNode::BLOCKDEF)) 01112 ) 01113 ) // ... so keep looking. 01114 $candidate_node = $candidate_node->parent; 01115 # set the found list as the current node for the list item... 01116 # (if $candidate_node is null then no reference candidate was found) 01117 if ($candidate_node and ($candidate_node->type == $listtype)) // found a match for list 01118 $this->_curnode = $candidate_node; 01119 else # ... or create a new level of list 01120 { 01121 // get the nearest ancestor candidate for creating a new list 01122 $this->_curnode = $this->get_selected_ancestor($this->_curnode, 01123 array(SimpleWiki_DocNode::DEF_DESC, SimpleWiki_DocNode::DOCUMENT,SimpleWiki_DocNode::BLOCKDEF)); 01124 // create the list 01125 $listnode = $this->_curnode = new SimpleWiki_DocNode($listtype, $this->_curnode); 01126 if ($listdecorator) $this->set_node_decoration($listnode,$listdecorator); 01127 $listnode->level = $level; 01128 } 01129 # now add the term to the list, if present 01130 if ($term) 01131 { 01132 $curnode = $this->_curnode; 01133 $termnode = $this->_curnode = new SimpleWiki_DocNode(SimpleWiki_DocNode::DEF_TERM, $this->_curnode); 01134 if ($termdecorator) $this->set_node_decoration($termnode,$termdecorator); 01135 $this->_leaftextnode = NULL; 01136 # parse the text of the term 01137 $this->_parse_inline($term); 01138 $this->_leaftextnode = NULL; 01139 $this->_curnode = $curnode; 01140 } 01141 # ...and add the desc to the list 01142 $descnode = $this->_curnode = new SimpleWiki_DocNode(SimpleWiki_DocNode::DEF_DESC, $this->_curnode); 01143 if ($descdecorator) $this->set_node_decoration($descnode,$descdecorator); 01144 $this->_leaftextnode = NULL; 01145 # parse the text of the desc 01146 $this->_parse_inline($desc); 01147 $this->_leaftextnode = NULL; 01148 } 01149 #--------------------------------[ tables ]-------------------------------------# 01150 01161 protected function _table_node($preg_groups) 01162 { 01163 # process a table row (any line beginning with '|') 01164 isset($preg_groups['table_row']) or ($preg_groups['table_row'] = ''); 01165 isset($preg_groups['table_decorator']) or ($preg_groups['table_decorator'] = ''); 01166 isset($preg_groups['row_decorator']) or ($preg_groups['row_decoratpor'] = ''); 01167 $rowmarkup = trim($preg_groups['table_row']); 01168 # set aside rowmarkup links, preformats, macros and images to simplify markup 01169 $rowmarkup = preg_replace_callback( 01170 $this->tablerow_setaside_re, array($this,'add_tablerow_markers'),$rowmarkup); 01171 # assure at least content of a space in every cell. 01172 $rowmarkup = preg_replace('/((?<!:)\|(?=\|))/','| ',$rowmarkup); // ensure content for every cell 01173 $tabledecorator = trim($preg_groups['table_decorator']); 01174 $rowdecorator = trim($preg_groups['row_decorator']); 01175 01176 # set reference node to nearest table, document, or block ancestor 01177 $this->_curnode = $this->get_selected_ancestor($this->_curnode, 01178 array(SimpleWiki_DocNode::TABLE,SimpleWiki_DocNode::DOCUMENT,SimpleWiki_DocNode::BLOCKDEF)); 01179 # create new table node if necessary 01180 if ($this->_curnode->type != SimpleWiki_DocNode::TABLE) 01181 $this->_curnode = new SimpleWiki_DocNode(SimpleWiki_DocNode::TABLE, $this->_curnode); 01182 # set decoration for table 01183 $tablenode = $this->_curnode; 01184 if ($tabledecorator) $this->set_node_decoration($tablenode,$tabledecorator); 01185 01186 # create a new row node 01187 $row_node = $this->_curnode = new SimpleWiki_DocNode(SimpleWiki_DocNode::TABLE_ROW, $tablenode); 01188 # add decoration to new row 01189 if ($rowdecorator) $this->set_node_decoration($row_node,$rowdecorator); 01190 01191 # collect all cell markup into $cell_matches 01192 preg_match_all($this->cell_re, $rowmarkup, $cell_matches, PREG_SET_ORDER); 01193 # process cell_matches 01194 $this->_leaftextnode = NULL; 01195 foreach ($cell_matches as $cell_groups) { 01196 # get cell markup 01197 isset($cell_groups['cell']) or ($cell_groups['cell'] = ''); 01198 isset($cell_groups['head']) or ($cell_groups['head'] = ''); 01199 isset($cell_groups['cell_decorator']) or ($cell_groups['cell_decorator'] = ''); 01200 $cellmarkup = $cell_groups['cell']; 01201 $cellhead = $cell_groups['head']; 01202 $celldecorator = $cell_groups['cell_decorator']; 01203 # create table header cell or table data cell 01204 if ($cellhead) { 01205 $cellmarkup = trim($cellhead,'='); 01206 $cell_node = $this->_curnode = new SimpleWiki_DocNode(SimpleWiki_DocNode::TABLE_HEADCELL, $row_node); 01207 } else { 01208 $cell_node = $this->_curnode = new SimpleWiki_DocNode(SimpleWiki_DocNode::TABLE_CELL, $row_node); 01209 } 01210 # apply decoration to cell node 01211 if ($celldecorator) $this->set_node_decoration($cell_node,$celldecorator); 01212 # restore links, preformats, macros and images to current cell 01213 $cellmarkup = preg_replace($this->_tablerow_markers,$this->_tablerow_markup,$cellmarkup); 01214 # process cell inline markup 01215 $this->_leaftextnode = NULL; 01216 preg_replace_callback($this->inline_re, array($this,'_create_node'), $cellmarkup); 01217 } 01218 # set reference back to table node 01219 $this->_curnode = $tablenode; 01220 $this->_leaftextnode = NULL; 01221 # reset table setaside structure 01222 $this->_tablerow_markers = array(); 01223 $this->_tablerow_markup = array(); 01224 $this->_tablerow_count = 0; 01225 } 01226 #================================[ special decorators ]=============================# 01227 #--------------------------------[ span decoration ]--------------------------------# 01228 01237 protected function _span_node($preg_groups) 01238 { 01239 # span 01240 isset($preg_groups['span_decorator']) or ($preg_groups['span_decorator'] = ''); 01241 $decorator = $preg_groups['span_decorator']; 01242 if ($decorator) // new span 01243 { 01244 $node = $this->_curnode = new SimpleWiki_DocNode(SimpleWiki_DocNode::SPAN, $this->_curnode); 01245 $this->set_node_decoration($node,$decorator); 01246 $this->_leaftextnode = NULL; 01247 } 01248 elseif ($this->_curnode->type == SimpleWiki_DocNode::SPAN) // closing existing span 01249 { 01250 if (!empty($this->_curnode->parent)) 01251 { 01252 $this->_curnode = $this->_curnode->parent; 01253 $this->_leaftextnode = NULL; 01254 } 01255 } 01256 else // error, return text 01257 { 01258 if (is_null($this->_leaftextnode)) 01259 $this->_leaftextnode = new SimpleWiki_DocNode(SimpleWiki_DocNode::TEXT, $this->_curnode); 01260 $this->_leaftextnode->textcontent .= $preg_groups['span']; 01261 } 01262 } 01263 #--------------------------------[ block dividers ]--------------------------------# 01264 01272 protected function _blockdivider_node($preg_groups) 01273 { 01274 # empty block acting as block divider 01275 $decorator = $preg_groups['blockdivider_decorator']; 01276 $this->_curnode = $this->get_selected_ancestor($this->_curnode, 01277 array(SimpleWiki_DocNode::DOCUMENT,SimpleWiki_DocNode::BLOCKDEF)); 01278 $node = new SimpleWiki_DocNode(SimpleWiki_DocNode::BLOCKDIVIDER, $this->_curnode); 01279 if ($decorator) $this->set_node_decoration($node,$decorator); 01280 } 01281 #============================[ preformatted text ]=================================# 01282 01289 protected function _code_node($preg_groups) 01290 { 01291 # preformatted inline text 01292 isset($preg_groups['code_text']) or ($preg_groups['code_text'] = ''); 01293 isset($preg_groups['code_decorator']) or ($preg_groups['code_decorator'] = ''); 01294 $codetext = $preg_groups['code_text']; 01295 $decorator = trim($preg_groups['code_decorator']); 01296 01297 $node = new SimpleWiki_DocNode(SimpleWiki_DocNode::CODE, $this->_curnode); 01298 $node->textcontent = $codetext; 01299 if ($decorator) $this->set_node_decoration($node,$decorator); 01300 $this->_leaftextnode = NULL; 01301 } 01309 protected function _pre_node($preg_groups) 01310 { 01311 # process preformatted text 01312 isset($preg_groups['pre_type']) or ($preg_groups['pre_type'] = ''); 01313 isset($preg_groups['pre_markup']) or ($preg_groups['pre_markup'] = ''); 01314 isset($preg_groups['pre_decorator']) or ($preg_groups['pre_decorator'] = ''); 01315 $type = $preg_groups['pre_type']; 01316 $text = $preg_groups['pre_markup']; 01317 $decorator = $preg_groups['pre_decorator']; 01318 01319 $this->_curnode = $this->get_selected_ancestor($this->_curnode, 01320 array(SimpleWiki_DocNode::DOCUMENT,SimpleWiki_DocNode::BLOCKDEF)); 01321 $text = preg_replace_callback($this->pre_escape_re,array($this,'remove_tilde'), $text); 01322 $node = new SimpleWiki_DocNode(SimpleWiki_DocNode::PREFORMATTED, $this->_curnode); 01323 $node->textcontent = $text; 01324 $node->section = $type?$type:''; 01325 if ($decorator) $this->set_node_decoration($node,$decorator); 01326 $this->_leaftextnode = NULL; 01327 } 01330 private function remove_tilde($preg_groups) 01331 { 01332 # used in pre processing of pre element 01333 return $preg_groups['indent'] . $preg_groups['rest']; 01334 } 01335 #================================[ advanced markup ]===============================# 01336 #--------------------------------[ block declarations ]------------------------------# 01337 01345 protected function _blockdef_node($preg_groups) 01346 { 01347 # block definitions 01348 isset($preg_groups['block_selector']) or ($preg_groups['block_selector'] = ''); 01349 isset($preg_groups['block_content']) or ($preg_groups['block_content'] = ''); 01350 isset($preg_groups['block_decorator']) or ($preg_groups['block_decorator'] = ''); 01351 isset($preg_groups['block_inline']) or ($preg_groups['block_inline'] = ''); 01352 $name = $preg_groups['block_selector']; 01353 $content = $preg_groups['block_content']; 01354 $decorator = $preg_groups['block_decorator']; 01355 $inline = $preg_groups['block_inline']; 01356 01357 $container = $this->_curnode = $this->get_selected_ancestor($this->_curnode, 01358 array(SimpleWiki_DocNode::DOCUMENT, 01359 SimpleWiki_DocNode::BLOCKDEF, 01360 SimpleWiki_DocNode::LIST_ITEM, 01361 SimpleWiki_DocNode::DEF_DESC)); 01362 $node = $this->_curnode = new SimpleWiki_DocNode(SimpleWiki_DocNode::BLOCKDEF, $container); 01363 $node->blocktag = $name; 01364 if ($decorator) $this->set_node_decoration($node,$decorator); 01365 01366 $this->_leaftextnode = NULL; 01367 if ($inline) $this->_parse_inline($inline); 01368 $this->_leaftextnode = NULL; 01369 if ($content) $this->_parse_block($content); 01370 $this->_curnode = $container; 01371 $this->_leaftextnode = NULL; 01372 01373 } 01374 #-----------------------------------[ macros ]-------------------------------------# 01375 01384 protected function _macro_node($preg_groups) 01385 { 01386 # Handles macros using the placeholder syntax. 01387 isset($preg_groups['macro_name']) or ($preg_groups['macro_name'] = ''); 01388 isset($preg_groups['macro_text']) or ($preg_groups['macro_text'] = ''); 01389 isset($preg_groups['macro_args']) or ($preg_groups['macro_args'] = ''); 01390 $name = $preg_groups['macro_name']; 01391 $text = trim($preg_groups['macro_text']); 01392 $decorator = $preg_groups['macro_args']; 01393 01394 $container = $this->_curnode; 01395 $node = new SimpleWiki_DocNode(SimpleWiki_DocNode::MACRO, $container); 01396 $node->macroname = $name; 01397 01398 if ($decorator) $this->set_node_decoration($node,$decorator); 01399 if ($text) 01400 { 01401 $node->textcontent = $text; 01402 $this->_curnode = $node; 01403 $this->_leaftextnode = NULL; 01404 $this->_parse_inline($text); 01405 $this->_curnode = $container; 01406 } 01407 $this->_leaftextnode = NULL; 01408 } 01418 protected function _blockmacro_node($preg_groups) 01419 { 01420 # Handles macros using the placeholder syntax. block version 01421 isset($preg_groups['blockmacro_name']) or ($preg_groups['blockmacro_name'] = ''); 01422 isset($preg_groups['blockmacro_text']) or ($preg_groups['blockmacro_text'] = ''); 01423 isset($preg_groups['blockmacro_args']) or ($preg_groups['blockmacro_args'] = ''); 01424 $name = $preg_groups['blockmacro_name']; 01425 $text = trim($preg_groups['blockmacro_text']); 01426 $decorator = $preg_groups['blockmacro_args']; 01427 01428 $container = $this->_curnode = $this->get_selected_ancestor($this->_curnode, 01429 array(SimpleWiki_DocNode::DOCUMENT,SimpleWiki_DocNode::BLOCKDEF)); // different from macro 01430 $node = new SimpleWiki_DocNode(SimpleWiki_DocNode::MACRO, $this->_curnode); 01431 $node->macroname = $name; 01432 if ($decorator) $this->set_node_decoration($node,$decorator); 01433 if ($text) 01434 { 01435 $node->textcontent = $text; 01436 $this->_curnode = $node; 01437 $this->_leaftextnode = NULL; 01438 $this->_parse_inline($text); 01439 $this->_curnode = $container; 01440 } 01441 $this->_leaftextnode = NULL; 01442 } 01446 #------------------------------------------------------------------------------# 01447 #---------------------------[ debug functions ]--------------------------------# 01448 #------------------------------------------------------------------------------# 01449 01451 public function display_regex() // for debug 01452 { 01453 echo 'BLOCK_RE '; 01454 var_dump($this->block_re); 01455 echo 'INLINE_RE '; 01456 var_dump($this->inline_re); 01457 echo 'link_inline_re '; 01458 var_dump($this->link_inline_re); 01459 echo 'item_inline_re '; 01460 var_dump($this->image_inline_re); 01461 echo 'item_inline_re '; 01462 var_dump($this->item_inline_re); 01463 echo 'defitem_inline_re '; 01464 var_dump($this->defitem_inline_re); 01465 echo 'CELL_RE '; 01466 var_dump($this->cell_re); 01467 echo 'PRE_ESCAPE_RE '; 01468 var_dump($this->pre_escape_re); 01469 echo 'DECORATOR_RE '; 01470 var_dump($this->decorator_re); 01471 echo 'TABLEROW_SETASIDE_RE '; 01472 var_dump($this->tablerow_setaside_re); 01473 } 01476 public function display_dom($root) // for debug 01477 { 01478 $count = 1; 01479 $rootarray = array(); 01480 $count += $this->display_dom_add_child($root,$rootarray); 01481 $rootarray = $rootarray[0]; 01482 print_r($rootarray); 01483 return $count; 01484 } 01488 protected function display_dom_add_child($node,&$childarray) // for debug 01489 { 01490 $nodearray = $node->get_display_list(); 01491 $children = $node->children; 01492 $count = 0; 01493 if (!empty($children)) 01494 { 01495 $nodearray['children'] = array(); 01496 foreach ($children as $child) 01497 $count+= $this->display_dom_add_child($child,$nodearray['children']); 01498 } 01499 $childarray[] = $nodearray; 01500 return count($children) + $count; 01501 } 01503 } 01504