6 namespace Muster\Simplewiki;
14 #==========================================================================
15 #-----------------------------[ PARSER ]----------------------------------
16 #==========================================================================
108 $rules =
new StdClass;
110 #================================[ basic processing ]=================================#
111 # no explicit action by user (other than include blank lines between blocks)
117 $rules->char =
'(?P<char> ([^\/\*\\\[{%<~]+|.))';
119 $rules->blankline =
'(?P<blankline> ^ \s* $ )';
121 $rules->paragraph =
'(?P<paragraph>
122 ^\s*(\|:p\s+(?P<paragraph_decorator>'.$argchars.
'+?):\|)?(?P<text_chars>.+)
124 (?P<text_charstream>.+)
126 #================================[ core markup ]===============================#
127 #--------------------------------[ basic markup ]------------------------------#
129 $rules->heading =
'(?P<heading>
130 ^\s*(\|:h\s+(?P<heading_decorator>'.$argchars.
'+?):\|)? \s*
131 (?P<heading_head>={1,6}) \s*
132 (?P<heading_text> .*? ) \s*
133 (?P<heading_tail>=*) \s*
140 $rules->emph =
'(?P<emph> (?<!~)\/\/ )';
142 $rules->strong =
'(?P<strong> \*\* )';
144 $rules->linebreak =
'(?P<linebreak> \\\\\\\\ )';
146 $rules->horizontalrule =
'(?P<horizontalrule>
149 #--------------------------------[ links ]-------------------------------------#
151 $rules->link =
'(?P<link>
152 (%l\s+(?P<link_decorator>'.$argchars.
'+?)%)?
154 (?P<link_target>\S+?) \s*
155 (\| \s* (?P<link_text>.*?) \s* (\| \s* (?P<link_title>[^|\]}]+))? \s*)?
156 \]\](?!]) # allow embedded "]"
158 #--------------------------------[ images ]-------------------------------------#
160 $rules->image =
'(?P<image>
161 (%i\s+(?P<image_decorator>'.$argchars.
'+?)%)?
163 (?P<image_target>\S+?) \s*
164 (\| \s* (?P<image_text>.*?) \s* (\| \s* (?P<image_title>[^|\]}]+))? \s*)?
167 #--------------------------------[ lists ]-------------------------------------#
170 $rules->deflist =
'(?P<deflist>
172 (\|:d[ltd]\s+('.$argchars.
'+?):\|){0,3}
173 (:(?=[^:])).* $ # only one opening list marker allowed
175 (\|:d[ltd]\s+('.$argchars.
'+?):\|){0,3}
180 $rules->defitem =
'(?P<defitem>
182 (\|:dl\s+(?P<deflist_decorator>('.$argchars.
'+?)):\|)?
183 (\|:dt\s+(?P<defterm_decorator>('.$argchars.
'+?)):\|)?
184 (\|:dd\s+(?P<defdesc_decorator>('.$argchars.
'+?)):\|)?
185 (?P<defitem_head> :+) \s*
186 ((?P<defterm_text> .*?)(?<!~)::)?
187 (?P<defdesc_text> .*?)
192 $rules->list =
'(?P<list>
194 (\|:([uo]l|li) \s+('.$argchars.
'+?):\|){0,2}
195 ([*\\#](?=[^*\\#])).* $ # only one opening list marker allowed
197 (\|:([uo]l|li) \s+('.$argchars.
'+?):\|){0,2}
202 $rules->item =
'(?P<item>
204 (\|:[uo]l\s+(?P<list_decorator> ('.$argchars.
'+?)):\|)?
205 (\|:li\s+(?P<item_decorator>('.$argchars.
'+?)):\|)?
206 (?P<item_head> [\#*]+) \s*
210 #--------------------------------[ tables ]-------------------------------------#
212 $rules->table =
'(?P<table>
214 (\|:table\\s+(?P<table_decorator>('.$argchars.
'+?)):\|)?
215 (\|:tr\s+(?P<row_decorator>('.$argchars.
'+?)):\|)?
218 (((?<!~)\|:t[dh]\s+('.$argchars.
'+?):\|)?\|(?!:[a-z]).*?)* \s*
226 (\|:t[dh]\s+(?P<cell_decorator>'.$argchars.
'+?):\|)?
229 (?P<head> = ([^|]|(?<=~)\|)+ ) |
230 (?P<cell> ([^|]|(?<=~)\|)+ )
233 #================================[ escape character ]=================================#
235 $rules->escape =
'(?P<escape> ~ (?P<escaped_char>\S) )'; # embedded in various regex
's
236 #================================[ special decorators ]===============================#
237 #--------------------------------[ span decoration ]----------------------------------#
239 $rules->span = '(?P<span> %(s\s+(?P<span_decorator>
'.$argchars.'+?))?% )
';
240 #--------------------------------[ block dividers ]-----------------------------------#
242 $rules->blockdivider = '(?P<blockdivider>
243 ^\s* \|:b \s+(?P<blockdivider_decorator>(
'.$argchars.'+?)):\| \s* $
245 #===============================[ preformatted text ]=================================#
248 $rules->code = '(?P<code>
249 (%c\s+(?P<code_decorator>
'.$argchars.'+?)%)?{{{ (?P<code_text>.*?) }}}
252 $rules->pre = '(?P<pre>
253 ^\s*(\|:pre\s+(?P<pre_decorator>
'.$argchars.'+?):\|)?(?<!~){{{ \s* $
256 ([\#]!(?P<pre_type>\w*?)(\s+.*)?$)?
263 $rules->pre_escape = ' ^(?P<indent>\s*) ~ (?P<rest> \}\}\} \s*) $
';
264 #================================[ advanced markup ]===============================#
265 #--------------------------------[ block declarations ]------------------------------#
270 \n?(?P<block_indent>[\t\x20]*)\(:(?P<block_selector>\w+)(\s+(?!:\))(?P<block_decorator>
'.$argchars.'+?))? \s* :\)
271 \s*?(?P<block_inline>.*) $
272 (?P<block_content>(\n.*$)*?)
273 \n(?P=block_indent)\(:(?P=block_selector)end\s*:\)\s*$
276 #--------------------------------[ macros ]--------------------------------#
278 $rules->macro = '(?P<macro>
281 ((?P<macro_args>
'.$argchars.'*) )? \s*
282 (\| \s* (?P<macro_text> .+?) \s* )?
286 $rules->blockmacro = '(?P<blockmacro>
289 (?P<blockmacro_name> \w+)
290 ((?P<blockmacro_args>
'.$argchars.'*) )? \s*
291 (\| \s* (?P<blockmacro_text> .+?) \s* )?
296 $rules->decorator = '
297 (?>(?P<variable>[\w-]+)(?P<operator>[:=]))? # optional attribute or
property name, and
operator applied
299 "(?P<ddelim_value>.*?)(?<!\\\)" #
double quote delimited
301 \
'(?P<sdelim_value>.*?)(?<!\\\)\' # single quote delimited
303 (?P<ndelim_value>\S+) # not delimited
306 $this->_rules = $rules;
308 #---------------------------------------------------------------------------------------#
309 #------------------------------[ set regular expressions ]------------------------------#
310 #---------------------------------------------------------------------------------------#
328 $this->pre_escape_re =
'/' . $rules->pre_escape .
'/xm';
330 $this->link_inline_re =
"/\n"
332 array($rules->code, $rules->image, $rules->strong,
333 $rules->emph, $rules->span, $rules->linebreak,
334 $rules->escape, $rules->char))
335 .
"\n/x"; #
for link captions
337 $this->image_inline_re =
"/\n"
339 array($rules->link, $rules->code, $rules->strong,
340 $rules->emph, $rules->span, $rules->linebreak,
341 $rules->escape, $rules->char))
342 .
"\n/x"; #
for image captions
343 $this->item_inline_re =
'/' . $rules->item .
'/xm';
344 $this->defitem_inline_re =
'/' . $rules->defitem .
'/xm';
345 $this->cell_re =
'/' . $rules->cell .
'/x';
347 $this->inline_re =
"/\n"
349 array($rules->link, $rules->macro,
350 $rules->code, $rules->image, $rules->strong, $rules->emph,
351 $rules->span, $rules->linebreak, $rules->escape, $rules->char))
354 $this->tablerow_setaside_re =
"/\n"
355 . implode(
"\n|\n", array($rules->link, $rules->macro,$rules->code,$rules->image))
358 $this->block_re =
"/\n"
360 array($rules->blankline, $rules->blockdef, $rules->heading,
361 $rules->horizontalrule, $rules->blockdivider, $rules->blockmacro,
362 $rules->pre, $rules->list, $rules->deflist, $rules->table, $rules->paragraph))
365 $this->decorator_re =
'/' . $rules->decorator .
'/x';
398 return $this->_preprocessed_markup;
406 if (!is_null($argchars))
408 $this->_argchars = $argchars;
416 #---------------------[ process initiation ]--------------------------#
433 $this->_raw = $markup;
435 $this->_curnode =
$this->_root; # The most recent document node
436 $this->_leaftextnode = NULL; # The node to add
inline characters to
448 # try to clean $raw of unnecessary newlines
449 # parse the text given as $this->_raw...
451 #...and return DOM tree.
465 # Recognize block elements.
466 preg_replace_callback($this->block_re, array($this,
'_create_node'), $raw);
479 # Recognize inline elements inside blocks.
480 preg_replace_callback($this->inline_re, array($this,
'_create_node'), $raw);
482 #---------------------[ process control ]--------------------------#
495 # Invoke appropriate _*_node method. Called for every matched group.
496 foreach ($preg_groups as $name => $text)
498 if ((!is_int($name)) and ($text !=
''))
500 $node_method =
"_{$name}_node";
501 $this->$node_method($preg_groups);
505 # special case: pick up empty line for block boundary
506 $keys = array_keys($preg_groups);
508 if ($keys[count($keys)-2]==$name)
510 $node_method =
"_{$name}_node";
511 $this->$node_method($preg_groups);
532 isset($preg_groups[
'pre']) or ($preg_groups[
'pre'] =
'');
533 isset($preg_groups[
'code']) or ($preg_groups[
'code'] =
'');
534 $this->_pre_markup[] = preg_replace(
'/(\$|\\\\)(?=\d)/',
'\\\\\1',
535 $preg_groups[
'pre'].$preg_groups[
'code']);
537 $marker =
'{{{' . chr(255). $this->_pre_count .
'}}}';
538 $this->_pre_markers[] =
'/{{\\{' . chr(255) . $this->_pre_count .
'\\}}}/';
555 isset($preg_groups[
'link']) or ($preg_groups[
'link'] =
'');
556 isset($preg_groups[
'macro']) or ($preg_groups[
'macro'] =
'');
557 isset($preg_groups[
'code']) or ($preg_groups[
'code'] =
'');
558 isset($preg_groups[
'image']) or ($preg_groups[
'image'] =
'');
559 ($value = $preg_groups[
'link']) or ($value = $preg_groups[
'macro']) or
560 ($value = $preg_groups[
'code']) or ($value = $preg_groups[
'image']);
561 $this->_tablerow_markup[] = $value;
562 $this->_tablerow_count++;
563 $marker =
'{{{' . chr(255). $this->_tablerow_count .
'}}}';
564 $this->_tablerow_markers[] =
'/{{\\{' . chr(255) . $this->_tablerow_count .
'\\}}}/';
582 $raw = preg_replace_callback(
'/\A```##(.*$(\n``.*$)*)/m',array($this,
'preprocess_metadata'),$raw);
583 $raw =
"\n".$raw.
"\n";
586 $raw = preg_replace(
'/```.*$/m',
'',$raw);
587 # remove line continuations
588 $raw = preg_replace(
'/\n``/',
'',$raw);
589 # set aside preformatted blocks
590 $raw = preg_replace_callback(
'/'.$this->_rules->pre .
'|' .$this->_rules->code .
'/xm',array($this,
'add_pre_and_code_markers'),$raw);
591 # add markup around raw url's; this allows "//" emphasis markup to operate without constraint
592 $raw = preg_replace(
'/(^|\W)((?<!\[\[|{{|~)(http[s]?|mailto):\/\/\S+\w)/',
'$1[[$2]]',$raw);
593 # restore preformatted blocks
594 $raw = preg_replace($this->_pre_markers,$this->_pre_markup,$raw);
595 # get marker data and offsets
596 $markerdata = $this->_markerdata =
new StdClass;
597 $markerdata->offset = 0;
598 $markerdata->markercount = 0;
599 $this->_markers = array();
601 $re =
'/(?P<text>[^{]*)|(?<!~)(?P<marker>\{\{##(?P<markername>[a-zA-Z]\w*)(\s+(?P<decorator>'.$this->_argchars.
'+?))?\s*##\}\})|(?P<char>.)/';
602 $raw = preg_replace_callback($re,array($this,
'preprocess_markerdata'),$raw);
604 $this->_markers = NULL;
605 $markerdata->textlength = $markerdata->offset;
606 unset($markerdata->offset);
607 $this->_preprocessed_raw = $raw;
618 isset($matches[
'text']) or ($matches[
'text'] =
'');
619 isset($matches[
'char']) or ($matches[
'char'] =
'');
620 isset($matches[
'marker']) or ($matches[
'marker'] =
'');
621 isset($matches[
'markername']) or ($matches[
'markername'] =
'');
622 isset($matches[
'decorator']) or ($matches[
'decorator'] =
'');
623 $text = $matches[
'text'].$matches[
'char'];
624 $this->_markerdata->offset += strlen($text);
625 if ($marker = $matches[
'marker'])
627 $this->_markerdata->markercount++;
628 $markerobject = $this->_markers[] =
new StdClass;
629 $markerobject->offset = $this->_markerdata->offset;
630 $name = $markerobject->name = $matches[
'markername'];
631 $this->_markers[$name] = $markerobject;
632 if ($decorator = $matches[
'decorator'])
635 $markerobject->decoration = NULL;
647 $arguments = trim($matches[1]);
649 $arguments = preg_replace(
'/\n``/',
'',$arguments);
660 $decoration =
new StdClass;
661 $decoration->classes = array();
662 $decoration->properties = array();
663 $decoration->attributes = array();
665 preg_match_all($this->decorator_re, $decorator_string, $terms, PREG_SET_ORDER);
666 foreach($terms as $term)
668 isset($term[
'variable']) or ($term[
'variable'] =
'');
669 isset($term[
'operator']) or ($term[
'operator'] =
'');
670 isset($term[
'ddelim_value']) or ($term[
'ddelim_value'] =
'');
671 isset($term[
'sdelim_value']) or ($term[
'sdelim_value'] =
'');
672 isset($term[
'ndelim_value']) or ($term[
'ndelim_value'] =
'');
673 $variable = $term[
'variable'];
674 $operator = $term[
'operator'];
675 if ($term[
'ddelim_value']) $delimiter =
'"';
676 elseif ($term[
'sdelim_value']) $delimiter =
"'";
677 else $delimiter =
'';
679 $value = $term[
'ddelim_value'] . $term[
'sdelim_value'] . $term[
'ndelim_value'];
683 $decoration->attributes[$variable] = $value;
684 if ($delimiter ==
'') $delimiter =
'"';
685 $decoration->attributedelimiters[$variable] = $delimiter;
688 $decoration->properties[$variable] = $value;
691 $decoration->classes[] = $value;
705 $node->decoration->markup = $decorator_string;
707 #------------------------------------------------------------------------------#
708 #---------------------------[ utilities ]--------------------------------------#
709 #------------------------------------------------------------------------------#
720 while ((!empty($node->parent)) and (!in_array($node->type,$types)))
722 $node = $node->parent;
735 #=========================[ basic processing ]=================================#
745 $char = $preg_groups[
'char'];
746 if (is_null($this->_leaftextnode))
748 $this->_leaftextnode->textcontent .= $char;
760 $char = $preg_groups[
'escaped_char'];
761 if (is_null($this->_leaftextnode))
763 $this->_leaftextnode->textcontent .= $char;
792 # text not otherwise classified, triggers creation of paragraph for new set
793 isset($preg_groups[
'text_chars']) or ($preg_groups[
'text_chars'] =
'');
794 isset($preg_groups[
'text_charstream']) or ($preg_groups[
'text_charstream'] =
'');
795 isset($preg_groups[
'paragraph_decorator']) or ($preg_groups[
'paragraph_decorator'] =
'');
796 $text = $preg_groups[
'text_chars'] . $preg_groups[
'text_charstream'];
797 $decorator = $preg_groups[
'paragraph_decorator'];
798 if (in_array($this->_curnode->type,
817 $this->_leaftextnode = NULL;
819 #================================[ core markup ]===============================#
820 #--------------------------------[ basic markup ]------------------------------#
834 isset($preg_groups[
'heading_text']) or ($preg_groups[
'heading_text'] =
'');
835 isset($preg_groups[
'heading_head']) or ($preg_groups[
'heading_head'] =
'');
836 isset($preg_groups[
'heading_decorator']) or ($preg_groups[
'heading_decorator'] =
'');
837 $headtext = $preg_groups[
'heading_text'];
838 $headhead = $preg_groups[
'heading_head'];
839 $decorator = $preg_groups[
'heading_decorator'];
845 $node->level = strlen($headhead);
849 $this->_curnode = $node;
850 $this->_leaftextnode = NULL;
854 $this->_curnode = $parent;
855 $this->_leaftextnode = NULL;
871 if (!empty($this->_curnode->parent))
872 $this->_curnode = $this->_curnode->parent;
874 $this->_leaftextnode = NULL;
890 if (!empty($this->_curnode->parent))
891 $this->_curnode = $this->_curnode->parent;
893 $this->_leaftextnode = NULL;
904 $this->_leaftextnode = NULL;
928 # Handle all types of links.
929 isset($preg_groups[
'link_target']) or ($preg_groups[
'link_target'] =
'');
930 isset($preg_groups[
'link_text']) or ($preg_groups[
'link_text'] =
'');
931 isset($preg_groups[
'link_title']) or ($preg_groups[
'link_title'] =
'');
932 isset($preg_groups[
'link_decorator']) or ($preg_groups[
'link_decorator'] =
'');
933 $target = trim($preg_groups[
'link_target']);
934 $text = trim($preg_groups[
'link_text']);
935 $title = trim($preg_groups[
'link_title']);
936 $decorator = trim($preg_groups[
'link_decorator']);
939 $node->target = $target;
941 if ($title) $node->title = $title;
944 $this->_curnode = $node;
945 $this->_leaftextnode = NULL;
947 preg_replace_callback($this->link_inline_re, array($this,
'_create_node'), $text);
949 $this->_curnode = $parent;
950 $this->_leaftextnode = NULL;
952 #--------------------------------[ images ]-------------------------------------#
963 # Handles images included in the page.
964 isset($preg_groups[
'image_target']) or ($preg_groups[
'image_target'] =
'');
965 isset($preg_groups[
'image_text']) or ($preg_groups[
'image_text'] =
'');
966 isset($preg_groups[
'image_title']) or ($preg_groups[
'image_title'] =
'');
967 isset($preg_groups[
'image_decorator']) or ($preg_groups[
'image_decorator'] =
'');
968 $target = trim($preg_groups[
'image_target']);
969 $text = trim($preg_groups[
'image_text']);
970 $title = trim($preg_groups[
'image_title']);
971 $decorator = trim($preg_groups[
'image_decorator']);
974 $node->target = $target;
976 if ($title !=
'') $node->title = $title;
979 $this->_curnode = $node;
980 $this->_leaftextnode = NULL;
982 preg_replace_callback($this->image_inline_re, array($this,
'_create_node'), $text);
984 $this->_curnode = $parent;
985 $this->_leaftextnode = NULL;
987 #--------------------------------[ lists ]-------------------------------------#
995 # collect list markup, detail processing by item
996 $text = $preg_groups[
'list'];
997 preg_replace_callback($this->item_inline_re,array($this,
'_create_node'), $text);
1011 isset($preg_groups[
'item_head']) or ($preg_groups[
'item_head'] =
'');
1012 isset($preg_groups[
'item_text']) or ($preg_groups[
'item_text'] =
'');
1013 isset($preg_groups[
'list_decorator']) or ($preg_groups[
'list_decorator'] =
'');
1014 isset($preg_groups[
'item_decorator']) or ($preg_groups[
'item_decorator'] =
'');
1015 $bullet = $preg_groups[
'item_head'];
1016 $text = $preg_groups[
'item_text'];
1017 $listdecorator = $preg_groups[
'list_decorator'];
1018 $itemdecorator = $preg_groups[
'item_decorator'];
1020 if ($bullet{0} ==
'#')
1025 $level = strlen($bullet);
1026 # Find a node of the same type and level up the tree, or a block to start a list
1034 and $candidate_node->level == $level
1042 $candidate_node = $candidate_node->parent;
1044 # set the found list as the current node for the list item...
1045 # (if $candidate_node is null then no reference candidate was found)
1046 if ($candidate_node and ($candidate_node->type == $listtype))
1047 $this->_curnode = $candidate_node;
1048 else # ... or create a
new level of list
1054 $listnode = $this->_curnode =
new DocNode($listtype, $this->_curnode);
1056 $listnode->level = $level;
1058 # now add the list item to the list
1061 $this->_leaftextnode = NULL;
1062 # parse the text of the list item
1064 $this->_leaftextnode = NULL;
1066 #--------------------------------[ definition list ]-------------------------------------#
1074 # collect list markup, detail processing by item
1075 $text = $preg_groups[
'deflist'];
1076 preg_replace_callback($this->defitem_inline_re,array($this,
'_create_node'), $text);
1091 isset($preg_groups[
'defitem_head']) or ($preg_groups[
'defitem_head'] =
'');
1092 isset($preg_groups[
'defterm_text']) or ($preg_groups[
'defterm_text'] =
'');
1093 isset($preg_groups[
'defdesc_text']) or ($preg_groups[
'defdesc_text'] =
'');
1094 isset($preg_groups[
'deflist_decorator']) or ($preg_groups[
'deflist_decorator'] =
'');
1095 isset($preg_groups[
'defterm_decorator']) or ($preg_groups[
'defterm_decorator'] =
'');
1096 isset($preg_groups[
'defdesc_decorator']) or ($preg_groups[
'defdesc_decorator'] =
'');
1097 $head = $preg_groups[
'defitem_head'];
1098 $term = trim($preg_groups[
'defterm_text']);
1099 $desc = $preg_groups[
'defdesc_text'];
1100 $listdecorator = $preg_groups[
'deflist_decorator'];
1101 $termdecorator = $preg_groups[
'defterm_decorator'];
1102 $descdecorator = $preg_groups[
'defdesc_decorator'];
1106 $level = strlen($head);
1107 # Find a node of the same type and level up the tree, or a block to start a list
1115 and $candidate_node->level == $level
1122 $candidate_node = $candidate_node->parent;
1123 # set the found list as the current node for the list item...
1124 # (if $candidate_node is null then no reference candidate was found)
1125 if ($candidate_node and ($candidate_node->type == $listtype))
1126 $this->_curnode = $candidate_node;
1127 else # ... or create a
new level of list
1133 $listnode = $this->_curnode =
new DocNode($listtype, $this->_curnode);
1135 $listnode->level = $level;
1137 # now add the term to the list, if present
1143 $this->_leaftextnode = NULL;
1144 # parse the text of the term
1146 $this->_leaftextnode = NULL;
1147 $this->_curnode = $curnode;
1149 # ...and add the desc to the list
1152 $this->_leaftextnode = NULL;
1153 # parse the text of the desc
1155 $this->_leaftextnode = NULL;
1157 #--------------------------------[ tables ]-------------------------------------#
1171 # process a table row (any line beginning with '|')
1172 isset($preg_groups[
'table_row']) or ($preg_groups[
'table_row'] =
'');
1173 isset($preg_groups[
'table_decorator']) or ($preg_groups[
'table_decorator'] =
'');
1174 isset($preg_groups[
'row_decorator']) or ($preg_groups[
'row_decoratpor'] =
'');
1175 $rowmarkup = trim($preg_groups[
'table_row']);
1176 # set aside rowmarkup links, preformats, macros and images to simplify markup
1177 $rowmarkup = preg_replace_callback(
1178 $this->tablerow_setaside_re, array($this,
'add_tablerow_markers'),$rowmarkup);
1179 # assure at least content of a space in every cell.
1180 $rowmarkup = preg_replace(
'/((?<!:)\|(?=\|))/',
'| ',$rowmarkup);
1181 $tabledecorator = trim($preg_groups[
'table_decorator']);
1182 $rowdecorator = trim($preg_groups[
'row_decorator']);
1184 # set reference node to nearest table, document, or block ancestor
1187 # create new table node if necessary
1190 # set decoration for table
1194 # create a new row node
1196 # add decoration to new row
1199 # collect all cell markup into $cell_matches
1200 preg_match_all($this->cell_re, $rowmarkup, $cell_matches, PREG_SET_ORDER);
1201 # process cell_matches
1202 $this->_leaftextnode = NULL;
1203 foreach ($cell_matches as $cell_groups) {
1205 isset($cell_groups[
'cell']) or ($cell_groups[
'cell'] =
'');
1206 isset($cell_groups[
'head']) or ($cell_groups[
'head'] =
'');
1207 isset($cell_groups[
'cell_decorator']) or ($cell_groups[
'cell_decorator'] =
'');
1208 $cellmarkup = $cell_groups[
'cell'];
1209 $cellhead = $cell_groups[
'head'];
1210 $celldecorator = $cell_groups[
'cell_decorator'];
1211 # create table header cell or table data cell
1213 $cellmarkup = trim($cellhead,
'=');
1218 # apply decoration to cell node
1220 # restore links, preformats, macros and images to current cell
1221 $cellmarkup = preg_replace($this->_tablerow_markers,$this->_tablerow_markup,$cellmarkup);
1222 # process cell inline markup
1223 $this->_leaftextnode = NULL;
1224 preg_replace_callback($this->inline_re, array($this,
'_create_node'), $cellmarkup);
1226 # set reference back to table node
1227 $this->_curnode = $tablenode;
1228 $this->_leaftextnode = NULL;
1229 # reset table setaside structure
1230 $this->_tablerow_markers = array();
1231 $this->_tablerow_markup = array();
1232 $this->_tablerow_count = 0;
1234 #================================[ special decorators ]=============================#
1235 #--------------------------------[ span decoration ]--------------------------------#
1248 isset($preg_groups[
'span_decorator']) or ($preg_groups[
'span_decorator'] =
'');
1249 $decorator = $preg_groups[
'span_decorator'];
1254 $this->_leaftextnode = NULL;
1258 if (!empty($this->_curnode->parent))
1260 $this->_curnode = $this->_curnode->parent;
1261 $this->_leaftextnode = NULL;
1266 if (is_null($this->_leaftextnode))
1268 $this->_leaftextnode->textcontent .= $preg_groups[
'span'];
1271 #--------------------------------[ block dividers ]--------------------------------#
1282 # empty block acting as block divider
1283 $decorator = $preg_groups[
'blockdivider_decorator'];
1289 #============================[ preformatted text ]=================================#
1299 # preformatted inline text
1300 isset($preg_groups[
'code_text']) or ($preg_groups[
'code_text'] =
'');
1301 isset($preg_groups[
'code_decorator']) or ($preg_groups[
'code_decorator'] =
'');
1302 $codetext = $preg_groups[
'code_text'];
1303 $decorator = trim($preg_groups[
'code_decorator']);
1306 $node->textcontent = $codetext;
1308 $this->_leaftextnode = NULL;
1319 # process preformatted text
1320 isset($preg_groups[
'pre_type']) or ($preg_groups[
'pre_type'] =
'');
1321 isset($preg_groups[
'pre_markup']) or ($preg_groups[
'pre_markup'] =
'');
1322 isset($preg_groups[
'pre_decorator']) or ($preg_groups[
'pre_decorator'] =
'');
1323 $type = $preg_groups[
'pre_type'];
1324 $text = $preg_groups[
'pre_markup'];
1325 $decorator = $preg_groups[
'pre_decorator'];
1329 $text = preg_replace_callback($this->pre_escape_re,array($this,
'remove_tilde'), $text);
1331 $node->textcontent = $text;
1332 $node->section = $type?$type:
'';
1334 $this->_leaftextnode = NULL;
1338 private function remove_tilde($preg_groups)
1340 # used in pre processing of pre element
1341 return $preg_groups[
'indent'] . $preg_groups[
'rest'];
1343 #================================[ advanced markup ]===============================#
1344 #--------------------------------[ block declarations ]------------------------------#
1356 isset($preg_groups[
'block_selector']) or ($preg_groups[
'block_selector'] =
'');
1357 isset($preg_groups[
'block_content']) or ($preg_groups[
'block_content'] =
'');
1358 isset($preg_groups[
'block_decorator']) or ($preg_groups[
'block_decorator'] =
'');
1359 isset($preg_groups[
'block_inline']) or ($preg_groups[
'block_inline'] =
'');
1360 $name = $preg_groups[
'block_selector'];
1361 $content = $preg_groups[
'block_content'];
1362 $decorator = $preg_groups[
'block_decorator'];
1363 $inline = $preg_groups[
'block_inline'];
1371 $node->blocktag = $name;
1374 $this->_leaftextnode = NULL;
1376 $this->_leaftextnode = NULL;
1378 $this->_curnode = $container;
1379 $this->_leaftextnode = NULL;
1382 #-----------------------------------[ macros ]-------------------------------------#
1394 # Handles macros using the placeholder syntax.
1395 isset($preg_groups[
'macro_name']) or ($preg_groups[
'macro_name'] =
'');
1396 isset($preg_groups[
'macro_text']) or ($preg_groups[
'macro_text'] =
'');
1397 isset($preg_groups[
'macro_args']) or ($preg_groups[
'macro_args'] =
'');
1398 $name = $preg_groups[
'macro_name'];
1399 $text = trim($preg_groups[
'macro_text']);
1400 $decorator = $preg_groups[
'macro_args'];
1404 $node->macroname = $name;
1409 $node->textcontent = $text;
1410 $this->_curnode = $node;
1411 $this->_leaftextnode = NULL;
1413 $this->_curnode = $container;
1415 $this->_leaftextnode = NULL;
1428 # Handles macros using the placeholder syntax. block version
1429 isset($preg_groups[
'blockmacro_name']) or ($preg_groups[
'blockmacro_name'] =
'');
1430 isset($preg_groups[
'blockmacro_text']) or ($preg_groups[
'blockmacro_text'] =
'');
1431 isset($preg_groups[
'blockmacro_args']) or ($preg_groups[
'blockmacro_args'] =
'');
1432 $name = $preg_groups[
'blockmacro_name'];
1433 $text = trim($preg_groups[
'blockmacro_text']);
1434 $decorator = $preg_groups[
'blockmacro_args'];
1439 $node->macroname = $name;
1443 $node->textcontent = $text;
1444 $this->_curnode = $node;
1445 $this->_leaftextnode = NULL;
1447 $this->_curnode = $container;
1449 $this->_leaftextnode = NULL;
1454 #------------------------------------------------------------------------------#
1455 #---------------------------[ debug functions ]--------------------------------#
1456 #------------------------------------------------------------------------------#
1462 var_dump($this->block_re);
1464 var_dump($this->inline_re);
1465 echo
'link_inline_re ';
1466 var_dump($this->link_inline_re);
1467 echo
'item_inline_re ';
1468 var_dump($this->image_inline_re);
1469 echo
'item_inline_re ';
1470 var_dump($this->item_inline_re);
1471 echo
'defitem_inline_re ';
1472 var_dump($this->defitem_inline_re);
1474 var_dump($this->cell_re);
1475 echo
'PRE_ESCAPE_RE ';
1476 var_dump($this->pre_escape_re);
1477 echo
'DECORATOR_RE ';
1478 var_dump($this->decorator_re);
1479 echo
'TABLEROW_SETASIDE_RE ';
1480 var_dump($this->tablerow_setaside_re);
1487 $rootarray = array();
1489 $rootarray = $rootarray[0];
1490 print_r($rootarray);
1498 $nodearray = $node->get_display_list();
1499 $children = $node->children;
1501 if (!empty($children))
1503 $nodearray[
'children'] = array();
1504 foreach ($children as $child)
1507 $childarray[] = $nodearray;
1508 return count($children) + $count;