Simplewiki 1

muster_simplewiki_emitter.php

Go to the documentation of this file.
00001 <?php
00008 #==========================================================================#
00009 #-----------------------------[ EMITTER ]----------------------------------#
00010 #==========================================================================#
00011 
00016 // generates the HTML; other emitters could be substituted
00017 class Muster_SimpleWiki_Emitter
00018 {
00020 
00021         protected $_dom;
00023         protected $_rules;
00025         protected $_link_re;
00027         protected $_image_re;
00029         protected $_blocktags = // could be replaced or changed by client
00030                 array
00031                 (
00032                         'div', 'blockquote', # division, blockquote
00033                         'table', 'thead', 'tbody', 'tr', 'td', 'th', 'tfoot', 'caption', # table
00034                         'ul', 'ol', 'li', 'dl', 'dt', 'dd', # lists
00035                         'dlmodule','dlwidget','dlsettings','dlmarker' #dlml
00036                 );
00039 
00040         protected $_class_callouts = array();
00042         protected $_property_callouts = array();
00044         protected $_macro_callouts = array();
00046         protected $_symlinks = array();
00048         protected $_symlink_handler;
00050         protected $_rawlink_handler;
00052         protected $_charfilter_handler;
00054         protected $_events = array();
00056         protected $_blockdef_handler;
00064         public function __construct()
00065         {
00066                 $this->set_rules();
00067                 $this->set_re($this->_rules);
00068         }
00069         #----------------------------------[ init ]-----------------------------------------#
00070 
00073         protected function set_rules()
00074         {
00075                 $rules = new StdClass();
00076                 $proto = 'http[s]?|ftp|nntp|news|telnet|file|irc';
00077                 $rules->extern = "(?P<external_address>(?P<external_proto>$proto)
00078                         :\/\/(?P<external_selector>\S+\w))";
00079                 $rules->mail = "(?P<external_mailaddress>(?P<external_mailproto>mailto)
00080                         :(?P<external_mailselector>\S+\w))";
00081                 $rules->symlink = '
00082             (?P<internal_address> (?P<symlink>[A-Z][a-zA-Z-]+) :
00083             (?P<internal_selector> [^`\s]+)(?P<internal_version>`\S+)?)
00084         ';
00085                 $rules->anchor = '
00086                         (?P<anchor>\#[a-zA-Z][\w-]*)
00087                 ';
00088                 $rules->rawlink = '
00089                         (?P<rawlink>\S*)
00090                 ';
00091                 $this->_rules = $rules;
00092         }
00096         protected function set_re($rules)
00097         {
00098                 $this->_link_re = '/' . implode('|',array($rules->extern,$rules->mail,$rules->symlink,$rules->anchor,$rules->rawlink)) . '/x';
00099                 $this->_image_re =  '/' . implode('|',array($rules->extern,$rules->symlink,$rules->rawlink)) . '/x';
00100         }
00107         public function emit($dom) // main method
00108         {
00109                 $this->_dom = $dom;
00110                 return $this->emit_node($dom);
00111         }
00116         protected function emit_node($node) // controller
00117         {
00118                 $emit = '_' . $node->type . '_emit';
00119                 return $this->$emit($node);
00120         }
00125         public function emit_children($node)
00126         {
00127                 if (empty($node->children)) return '';
00128                 $children = $node->children;
00129                 $childoutput = array();
00130                 foreach ($children as $child)
00131                 {
00132                         $childoutput[] = $this->emit_node($child);
00133                 }
00134                 return implode('',$childoutput);
00135         }
00138         public function emit_node_text($node)
00139         {
00140                 if ($node->type == SimpleWiki_DocNode::TEXT)
00141                         return $node->textcontent;
00142                 else
00143                         return $this->emit_children_text($node);
00144         }
00148         protected function emit_children_text($node)
00149         {
00150                 if (empty($node->children)) return '';
00151                 $children = $node->children;
00152                 $childoutput = array();
00153                 foreach ($children as $child)
00154                 {
00155                         $childoutput[] = $this->emit_node_text($child);
00156                 }
00157                 return implode(' ',$childoutput);
00158         }
00161 
00162         public function symlinks()
00163         {
00164                 return $this->_symlinks;
00165         }
00167         public function symlink_handler()
00168         {
00169                 return $this->_symlink_handler;
00170         }
00172         public function blocktags($blocktaglist = NULL)
00173         {
00174                 if (!is_null($blocktaglist))
00175                         $this->_blocktags = $blocktaglist;
00176                 return $this->_blocktags;
00177         }
00179         #========================[ callout handling ]=======================================#
00180 
00186         public function register_events($callbacks)
00187         {
00188                 $events = $this->_events;
00189                 foreach ($callbacks as $eventname => $callback)
00190                 {
00191                         if (!isset($events[$eventname]))
00192                         {
00193                                 $events[$eventname] = array();
00194                         }
00195                         $events[$eventname][] = $callback;
00196                 }
00197                 $this->_events = $events;
00198         }
00201         public function register_symlinks($symlinks)
00202         {
00203                 $symlinklist = $this->_symlinks;
00204                 foreach ($symlinks as $symlink => $value) {
00205                         $symlinklist[$symlink] = $value;
00206                 }
00207                 $this->_symlinks = $symlinklist;
00208         }
00212         public function register_symlink_handler($handler)
00213         {
00214                 $this->_symlink_handler = $handler;
00215         }
00219         public function register_charfilter_handler($handler)
00220         {
00221                 $this->_charfilter_handler = $handler;
00222         }
00226         public function register_rawlink_handler($handler)
00227         {
00228                 $this->_rawlink_handler = $handler;
00229         }
00233         public function register_class_callouts($callouts) 
00234         {
00235                 // ['nodetype']['class']=>$methodref
00236                 $calloutslist = $this->_class_callouts;
00237                 foreach ($callouts as $nodetype => $classcallouts)
00238                 {
00239                         if (empty($calloutlist[$nodetype]))
00240                         {
00241                                 $calloutlist[$nodetype] = $callouts[$nodetype];
00242                         }
00243                         else
00244                         {
00245                                 $classcallouts = $callouts[$nodetype];
00246                                 foreach($classcallouts as $class =>$methodref)
00247                                 {
00248                                         $calloutlist[$nodetype][$class] = $methodref;
00249                                 }
00250                         }
00251                 }
00252                 $this->_class_callouts = $calloutlist;
00253         }
00257         public function register_property_callouts($callouts) 
00258         {
00259                 // ['nodetype']['property']=>$methodref
00260                 $calloutslist = $this->_property_callouts;
00261                 foreach ($callouts as $nodetype => $propertycallouts)
00262                 {
00263                         if (empty($calloutlist[$nodetype]))
00264                         {
00265                                 $calloutlist[$nodetype] = $callouts[$nodetype];
00266                         }
00267                         else
00268                         {
00269                                 $propertycallouts = $callouts[$nodetype];
00270                                 foreach($propertycallouts as $class =>$methodref)
00271                                 {
00272                                         $calloutlist[$nodetype][$class] = $methodref;
00273                                 }
00274                         }
00275                 }
00276                 $this->_property_callouts = $calloutlist;
00277         }
00280         public function register_macro_callouts($callouts)
00281         {
00282                 // ['macroname']=>$methodref
00283                 $calloutlist = $this->_macro_callouts;
00284                 foreach ($callouts as $macroname => $methodref)
00285                 {
00286                         $calloutlist[$macroname] = $methodref;
00287                 }
00288                 $this->_macro_callouts = $calloutlist;
00289         }
00294         public function register_blockdef_handler($handler)
00295         {
00296                 $this->_blockdef_handler = $handler;
00297         }
00299         #---------------------------[trigger callouts]-------------------------------------#
00300 
00306         protected function expand_symlink($node)
00307         {
00308                 $symlinks = $this->_symlinks;
00309                 if (isset($symlinks[$node->linkparts->symlink]))
00310                         $node->linkparts->symlinkpath = $symlinks[$node->linkparts->symlink];
00311                 elseif (isset($this->_symlink_handler))
00312                         $node = call_user_func($this->_symlink_handler,$node);
00313                 else {
00314                         $node->unknown = TRUE;
00315                         $node->linkparts->symlinkpath = $node->linkparts->symlink . ':'; // stub
00316                 }
00317                 return $node;
00318         }
00324         protected function expand_rawlink($node)
00325         {
00326                 if (isset($this->_rawlink_handler))
00327                         $node = call_user_func($this->_rawlink_handler,$node);
00328                 else {
00329                         $node->unknown = TRUE;
00330                         $node->linkparts->rawlinkaddress = $node->linkparts->rawlink; // stub
00331                 }
00332                 return $node;
00333         }
00339         protected function call_macro($node)
00340         {
00341                 $callbacks = $this->_macro_callouts;
00342                 if (isset($callbacks[$node->macroname]))
00343                 {
00344                         $node = call_user_func($callbacks[$node->macroname],$node);
00345                         $node->processed = TRUE;
00346                 }
00347                 return $node;
00348         }
00353         protected function call_classes($node)
00354         {
00355                 $callbacks = isset($this->_class_callouts[$node->type])?$this->_class_callouts[$node->type]:NULL;
00356                 if (!empty($callbacks)) 
00357                 {
00358                         $classes = !empty($node->decoration->classes)?$node->decoration->classes:NULL;
00359                         if (!empty($classes))
00360                         {
00361                                 foreach ($classes as $class)
00362                                 {
00363                                         $callback = isset($callbacks[$class])?$callbacks[$class]:NULL;
00364                                         if ($callback)
00365                                         {
00366                                                 $node = call_user_func($callback,$node);
00367                                         }
00368                                 }
00369                         }
00370                 }
00371                 return $node;
00372         }
00378         protected function call_properties($node)
00379         {
00380                 $callbacks = isset($this->_property_callouts[$node->type])?$this->_property_callouts[$node->type]:NULL;
00381                 if (!empty($callbacks)) 
00382                 {
00383                         $properties = !empty($node->decoration->properties)?$node->decoration->properties:NULL;
00384                         if (!empty($properties))
00385                         {
00386                                 foreach ($properties as $propertyindex => $property)
00387                                 {
00388                                         $callback = isset($callbacks[$propertyindex])?$callbacks[$propertyindex]:NULL;
00389                                         if ($callback)
00390                                         {
00391                                                 $node = call_user_func($callback,$node);
00392                                         }
00393                                 }
00394                         }
00395                 }
00396                 return $node;
00397         }
00404         protected function call_event($event,$node)
00405         {
00406                 $events = isset($this->_events[$event])?$this->_events[$event]:NULL;
00407                 if (!empty($events)) {
00408                         foreach ($events as $callback) {
00409                                 $node = call_user_func($callback,$node);
00410                         }
00411                 }
00412                 return $node;
00413         }
00415         #--------------------------------[ utilities ]---------------------------------------#
00416 
00417 /*      protected function get_value($value,$default)
00418         {
00419                 return isset($value)? $value: $default;
00420         }
00421 */
00428         protected function prepare_image_node($node)
00429         {
00430                 # symlink for src
00431                 if (!empty($node->linkparts->symlink)) {
00432                         $node = $this->expand_symlink($node);
00433                         $node->decoration->attributes['src'] = 
00434                                 $node->linkparts->symlinkpath . $node->linkparts->internalselector;
00435                         $node->decoration->attributedelimiters['src'] = '"';
00436                 }
00437                 # external address for src
00438                 else {
00439                         $node->decoration->attributes['src'] = 
00440                                 !empty($node->linkparts->externaladdress)?$node->linkparts->externaladdress:NULL;
00441                         $node->decoration->attributedelimiters['src'] = '"';
00442                 }
00443                 # alt attribute
00444                 // caption, or...
00445                 if ($node->caption) {
00446                         $node->decoration->attributes['alt'] = $this->char_filter($node->caption,$node);
00447                         $node->decoration->attributedelimiters['alt'] = '"';
00448                 }
00449                 // ... target.
00450                 elseif ($node->target) 
00451                 {
00452                         $node->decoration->attributes['alt'] = $this->char_filter($node->target,$node);
00453                         $node->decoration->attributedelimiters['alt'] = '"';
00454                 }
00455                 # title attribute
00456                 if (!empty($node->title)) {
00457                         $node->decoration->attributes['title'] = $node->title;
00458                         $node->decoration->attributedelimiters['title'] = '"';
00459                 }
00460                 # standard prepare node...
00461                 $node = $this->prepare_node($node);
00462                 return $node;
00463         }
00471         protected function prepare_link_node($node)
00472         {
00473                 $attributename = 'href';
00474                 if (!empty($node->linkparts->anchor)) {
00475                         if (empty($node->caption)) {
00476                                 $attributename = 'name';
00477                                 $node->linkparts->anchor = substr($node->linkparts->anchor,1);
00478                                 $node->decoration->attributes[$attributename] = $node->linkparts->anchor;
00479                                 $node->decoration->attributedelimiters[$attributename] = '"';
00480                         } else {
00481                                 $node->linkparts->symlink = 'Anchor';
00482                                 $node = $this->expand_symlink($node);
00483                                 $node->decoration->attributes[$attributename] = $node->linkparts->symlinkpath . $node->linkparts->anchor;
00484                                 $node->decoration->attributedelimiters[$attributename] = '"';
00485                         }
00486                 }
00487                 elseif (!empty($node->linkparts->symlink)) {
00488                         $node = $this->expand_symlink($node);
00489                         $node->decoration->attributes[$attributename] = 
00490                                 $node->linkparts->symlinkpath . (!empty($node->linkparts->internalselector)?$node->linkparts->internalselector:'');
00491                         $node->decoration->attributedelimiters[$attributename] = '"';
00492                 }
00493                 elseif (!empty($node->linkparts->externaladdress)) {
00494                         $node->decoration->attributes[$attributename] = 
00495                                 !empty($node->linkparts->externaladdress)?$node->linkparts->externaladdress:NULL;
00496                         $node->decoration->attributedelimiters[$attributename] = '"';
00497                 }
00498                 else {
00499                         $node = $this->expand_rawlink($node);
00500                         $node->decoration->attributes[$attributename] = 
00501                                 !empty($node->linkparts->rawlinkaddress)?$node->linkparts->rawlinkaddress:NULL;
00502                         $node->decoration->attributedelimiters[$attributename] = '"';
00503                 }
00504                 if (!empty($node->title)) {
00505                         $node->decoration->attributes['title'] = $node->title;
00506                         $node->decoration->attributedelimiters['title'] = '"';
00507                 }
00508                 $node = $this->prepare_node($node);
00509                 return $node;
00510         }
00515         protected function prepare_macro_node($node)
00516         {
00517                 $node->output = '';
00518                 $this->call_macro($node);
00519                 if (empty($node->output) and ($node->caption)) {
00520                         $node->output = $node->caption;
00521                 }
00522                 return $node;
00523         }
00531         protected function prepare_node($node)
00532         {
00533                 # trigger callouts
00534                 $node = $this->call_classes($node);
00535                 $node = $this->call_properties($node);
00536                 # convert input decoration attributes, values, and properties into html attributes
00537                 $attributes = array();
00538                 // attributes
00539                 $attr = !empty($node->decoration->attributes)?$node->decoration->attributes:array();
00540                 $attrdelimiters = !empty($node->decoration->attributedelimiters)?$node->decoration->attributedelimiters:array();
00541                 foreach ($attr as $key => $value) {
00542                         $attributes[] = $key . '=' . $attrdelimiters[$key] . $value . $attrdelimiters[$key];
00543                 }
00544                 // classes
00545                 $values = array();
00546                 $values = !empty($node->decoration->classes)?$node->decoration->classes:array();
00547                 $classes = preg_replace('/"/','\\"',implode(' ',$values)); // escape embedded double quotes
00548                 if (!empty($classes)) $attributes[]='class="' . $classes . '"';
00549                 // styles
00550                 $properties = array();
00551                 $properties = !empty($node->decoration->properties)?$node->decoration->properties:array();
00552                 $styles = array();
00553                 foreach ($properties as $key => $value) {
00554                         $styles[] = $key . ':' . $value;
00555                 }
00556                 if (!empty($styles)) {
00557                         $style = implode(';',preg_replace('/"/','\\"',$styles)); // escape embedded double quotes
00558                         $attributes[] = 'style="' . $style . '"';
00559                 }
00560                 if (!empty($attributes)) $node->opentag_head .= ' ';
00561                 $node->attributes = $attributes;
00562                 return $node;
00563         }
00570         protected function standard_assembly($node)
00571         {
00572                 return $node->opentag_head . implode(' ',$node->attributes) . $node->opentag_tail 
00573                         . $node->elementcontent . $node->closetag;
00574         }
00578         protected function char_filter($text, $node = NULL)
00579         {
00580                 if (isset($this->_charfilter_handler)) {
00581                         return call_user_func($this->_charfilter_handler,$text,$node);
00582                 } else {
00583                         return htmlspecialchars($text);
00584                 }
00585         }
00587         #------------------------------------------------------------------------------#
00588         #-----------------------------[ node emitters ]--------------------------------#
00589         #------------------------------------------------------------------------------#
00590         #==============================[ document ]====================================#
00591 
00596         protected function _document_emit($node)
00597         {
00598                 // anticipate event calls
00599                 $node->opentag_head = '';
00600                 $node->closetag = '';
00601                 $node = $this->call_event('onemit',$node);
00602                 $node->elementcontent = $this->emit_children($node);
00603                 $node = $this->call_event('onafteremit',$node);
00604                 return $node->opentag_head . $node->elementcontent . $node->closetag;
00605         }
00606         #=========================[ basic processing ]=================================#
00607 
00611         protected function _paragraph_emit($node) // b decorator "p"
00612         {
00613                 $node->opentag_head = "\n<p";
00614                 $node->opentag_tail = ">";
00615                 $node->elementcontent = $this->emit_children($node);
00616                 $node->closetag = "</p>";
00617                 $node = $this->prepare_node($node);
00618                 return $this->standard_assembly($node);
00619         }
00624         protected function _text_emit($node)
00625         {
00626                 return $this->char_filter($node->textcontent,$node);
00627         }
00628         #================================[ core markup ]===============================#
00629         #--------------------------------[ basic markup ]------------------------------#
00630 
00634         protected function _heading_emit($node) // b decorator "h"
00635         {
00636                 $node->opentag_head = "\n<h" . $node->level;
00637                 $node->opentag_tail = ">";
00638                 $node->elementcontent = $this->emit_children($node);
00639                 $node->closetag = "</h". $node->level . ">";
00640                 $node = $this->prepare_node($node);
00641                 return $this->standard_assembly($node);
00642         }
00647         protected function _emphasis_emit($node)
00648         {
00649                 return "<em>" . $this->emit_children($node) . "</em>";
00650         }
00655         protected function _strong_emit($node)
00656         {
00657                 return "<strong>" . $this->emit_children($node) . "</strong>";
00658         }
00663         protected function _linebreak_emit($node)
00664         {
00665                 return "<br />\n";
00666         }
00671         protected function _horizontalrule_emit($node)
00672         {
00673                 return "\n<hr />";
00674         }
00675         #--------------------------------[ links ]-------------------------------------#
00676 
00680         protected function _link_emit($node) // i decorator "a"
00681         {
00682                 $node->caption = $this->emit_children($node);
00683                 // also available: $node->title
00684                 $address = $node->target;
00685                 $matches = array();
00686                 if (preg_match($this->_link_re,$address,$matches))
00687                 {
00688                         isset($matches['anchor']) or ($matches['anchor'] = '');
00689                         isset($matches['internal_address']) or ($matches['internal_address'] = '');
00690                         isset($matches['symlink']) or ($matches['symlink'] = '');
00691                         isset($matches['internal_selector']) or ($matches['internal_selector'] = '');
00692                         isset($matches['internal_version']) or ($matches['internal_version'] = '');
00693                         isset($matches['external_address']) or ($matches['external_address'] = '');
00694                         isset($matches['external_proto']) or ($matches['external_proto'] = '');
00695                         isset($matches['external_selector']) or ($matches['external_selector'] = '');
00696                         isset($matches['external_mailaddress']) or ($matches['external_mailaddress'] = '');
00697                         isset($matches['external_mailproto']) or ($matches['external_mailproto'] = '');
00698                         isset($matches['external_mailselector']) or ($matches['external_mailselector'] = '');
00699                         isset($matches['rawlink']) or ($matches['rawlink'] = '');
00700                         
00701                         $node->linkparts = new StdClass();
00702                         $node->linkparts->anchor = $matches['anchor'];
00703                         
00704                         $node->linkparts->internaladdress = $matches['internal_address'];
00705                         $node->linkparts->symlink = $matches['symlink'];
00706                         $node->linkparts->internalselector = $matches['internal_selector'];
00707                         $node->linkparts->internalversion = $matches['internal_version'];
00708                         
00709                         $node->linkparts->externaladdress = $matches['external_address'];
00710                         $node->linkparts->externalprotocol = $matches['external_proto'];
00711                         $node->linkparts->externalselector = $matches['external_selector'];
00712                         
00713                         if ($matches['external_mailaddress']) {
00714                                 $node->linkparts->externaladdress = $matches['external_mailaddress'];
00715                                 $node->linkparts->externalprotocol = $matches['external_mailproto'];
00716                                 $node->linkparts->externalselector = $matches['external_mailselector'];
00717                         }
00718                         
00719                         $node->linkparts->rawlink = $matches['rawlink'];
00720                 }
00721                 if (empty($node->caption) and empty($node->linkparts->anchor))
00722                         $node->caption = $node->target;
00723 
00724                 $node->opentag_head = "<a";
00725                 $node->opentag_tail = ">";
00726                 $node->elementcontent = $node->caption;
00727                 $node->closetag = "</a>";
00728                 $node->unknown = FALSE;
00729                 $node = $this->prepare_link_node($node); // might set $node->unknown = TRUE;
00730                 if ($node->unknown) {
00731                         $node->opentag_head .= 'rel="nofollow" ';
00732                         $node->opentag_tail .= '<span style="border-bottom:1px dashed gray">';
00733                         $node->closetag = '</span><sup>?</sup>' . $node->closetag;
00734                 }
00735                 return $this->standard_assembly($node);
00736         }
00737         #--------------------------------[ images ]------------------------------------#
00738 
00742         protected function _image_emit($node) // i decorator "i"
00743         {
00744                 $node->caption = $this->emit_children($node);
00745                 // also available: $node->title
00746                 $address = $node->target;
00747                 $matches = array();
00748                 if (preg_match($this->_image_re,$address,$matches))
00749                 {
00750                         isset($matches['internal_address']) or ($matches['internal_address'] = '');
00751                         isset($matches['symlink']) or ($matches['symlink'] = '');
00752                         isset($matches['internal_selector']) or ($matches['internal_selector'] = '');
00753                         isset($matches['internal_version']) or ($matches['internal_version'] = '');
00754                         isset($matches['external_address']) or ($matches['external_address'] = '');
00755                         isset($matches['external_proto']) or ($matches['external_proto'] = '');
00756                         isset($matches['external_selector']) or ($matches['external_selector'] = '');
00757                         isset($matches['rawlink']) or ($matches['rawlink'] = '');
00758                         
00759                         $node->linkparts = new StdClass();
00760                         $node->linkparts->internaladdress = $matches['internal_address'];
00761                         $node->linkparts->symlink = $matches['symlink'];
00762                         $node->linkparts->internalselector = $matches['internal_selector'];
00763                         $node->linkparts->internalversion = $matches['internal_version'];
00764                         
00765                         $node->linkparts->externaladdress = $matches['external_address'];
00766                         $node->linkparts->externalprotocol = $matches['external_proto'];
00767                         $node->linkparts->externalselector = $matches['external_selector'];
00768                         
00769                         $node->linkparts->rawlink = $matches['rawlink'];
00770                 }
00771                 $node->opentag_head = "<img";
00772                 $node->opentag_tail = "/>";
00773                 $node = $this->prepare_image_node($node); 
00774                 return $node->opentag_head . implode(' ',$node->attributes) . $node->opentag_tail;
00775         }
00776         #--------------------------------[ lists ]-------------------------------------#
00777 
00781         protected function _def_list_emit($node) // b decorator "dl"
00782         {
00783                 $node->opentag_head = "\n<dl";
00784                 $node->opentag_tail = ">";
00785                 $node->elementcontent = $this->emit_children($node);
00786                 $node->closetag = "\n</dl>";
00787                 $node = $this->prepare_node($node);
00788                 return $this->standard_assembly($node);
00789         }
00794         protected function _def_term_emit($node) // decorator "dt"
00795         {
00796                 $node->opentag_head = "\n<dt";
00797                 $node->opentag_tail = ">";
00798                 $node->elementcontent = $this->emit_children($node);
00799                 $node->closetag = "</dt>";
00800                 $node = $this->prepare_node($node);
00801                 return $this->standard_assembly($node);
00802         }
00807         protected function _def_desc_emit($node) // decorator "dd"
00808         {
00809                 $node->opentag_head = "\n<dd";
00810                 $node->opentag_tail = ">";
00811                 $node->elementcontent = $this->emit_children($node);
00812                 $node->closetag = "</dd>";
00813                 $node = $this->prepare_node($node);
00814                 return $this->standard_assembly($node);
00815         }
00820         protected function _ordered_list_emit($node) // b decorator "ol"
00821         {
00822                 $node->opentag_head = "\n<ol";
00823                 $node->opentag_tail = ">";
00824                 $node->elementcontent = $this->emit_children($node);
00825                 $node->closetag = "\n</ol>";
00826                 $node = $this->prepare_node($node);
00827                 return $this->standard_assembly($node);
00828 //              return $node->opentag_head . implode(' ',$node->attributes) . $node->opentag_tail 
00829 //                      . $node->elementcontent . $node->closetag;
00830         }
00835         protected function _unordered_list_emit($node) // b decorator "ul"
00836         {
00837                 $node->opentag_head = "\n<ul";
00838                 $node->opentag_tail = ">";
00839                 $node->elementcontent = $this->emit_children($node);
00840                 $node->closetag = "\n</ul>";
00841                 $node = $this->prepare_node($node);
00842                 return $this->standard_assembly($node);
00843         }
00848         protected function _list_item_emit($node) // decorator "li"
00849         {
00850                 $node->opentag_head = "\n<li";
00851                 $node->opentag_tail = ">";
00852                 $node->elementcontent = $this->emit_children($node);
00853                 $node->closetag = "</li>";
00854                 $node = $this->prepare_node($node);
00855                 return $this->standard_assembly($node);
00856         }
00857         #--------------------------------[ tables ]------------------------------------#
00858 
00862         protected function _table_emit($node) // b decorator "table"
00863         {
00864                 $node->opentag_head = "\n<table";
00865                 $node->opentag_tail = ">";
00866                 $node->elementcontent = $this->emit_children($node);
00867                 $node->closetag = "\n</table>";
00868                 $node = $this->prepare_node($node);
00869                 return $this->standard_assembly($node);
00870         }
00875         protected function _table_row_emit($node) // b decorator "tr"
00876         {
00877                 $node->opentag_head = "\n<tr";
00878                 $node->opentag_tail = ">";
00879                 $node->elementcontent = $this->emit_children($node);
00880                 $node->closetag = "\n</tr>";
00881                 $node = $this->prepare_node($node);
00882                 return $this->standard_assembly($node);
00883         }
00888         protected function _table_headcell_emit($node) // b decorator "th"
00889         {
00890                 $node->opentag_head = "\n<th";
00891                 $node->opentag_tail = ">\n";
00892                 $node->elementcontent = $this->emit_children($node);
00893                 $node->closetag = "</th>";
00894                 $node = $this->prepare_node($node);
00895                 return $this->standard_assembly($node);
00896         }
00901         protected function _table_cell_emit($node) // b decorator "td"
00902         {
00903                 $node->opentag_head = "\n<td";
00904                 $node->opentag_tail = ">\n";
00905                 $node->elementcontent = $this->emit_children($node);
00906                 $node->closetag = "</td>";
00907                 $node = $this->prepare_node($node);
00908                 return $this->standard_assembly($node);
00909         }
00910         #=========================[ special decorators ]===============================#
00911         #---------------------------[ span decoration ]--------------------------------#
00912 
00916         protected function _span_emit($node) // i decorator "s"
00917         {
00918                 $node->opentag_head = "<span";
00919                 $node->opentag_tail = ">";
00920                 $node->elementcontent = $this->emit_children($node);
00921                 $node->closetag = "</span>";
00922                 $node = $node = $this->prepare_node($node);
00923                 return $this->standard_assembly($node);
00924         }
00925         #----------------------------[ block dividers ]--------------------------------#
00926 
00930         protected function _blockdivider_emit($node) // b decorator "b"
00931         {
00932                 $node->opentag_head = "\n<div";
00933                 $node->opentag_tail = ">";
00934                 $node->elementcontent = '';
00935                 $node->closetag = "\n</div>";
00936                 $node = $this->prepare_node($node);
00937                 return $this->standard_assembly($node);
00938         }
00939         #============================[ preformatted text ]=============================#
00940 
00944         protected function _code_emit($node) // i decorator "c"
00945         {
00946                 $node->opentag_head = "<code";
00947                 $node->opentag_tail = ">";
00948                 $node->elementcontent = $node->textcontent;
00949                 $node->escapecontent = TRUE;
00950                 $node->closetag = "</code>";
00951                 $node = $this->prepare_node($node);
00952                 if ($node->escapecontent) $node->elementcontent = $this->char_filter($node->elementcontent,$node);
00953                 return $this->standard_assembly($node);
00954         }
00959         protected function _preformatted_emit($node) // b decorator "pre"
00960         {
00961                 $node->opentag_head = "\n<pre";
00962                 $node->opentag_tail = ">\n";
00963                 $node->elementcontent = $node->textcontent;
00964                 $node->escapecontent = TRUE;
00965                 $node->closetag = "</pre>";
00966                 $node = $this->prepare_node($node);
00967                 if ($node->escapecontent) $node->elementcontent = $this->char_filter($node->elementcontent,$node);
00968                 return $this->standard_assembly($node);
00969         }
00970         #==============================[ advanced markup ]=============================#
00971         #------------------------------[ block declarations ]----------------------------#
00972 
00976         protected function _blockdef_emit($node) // declaration decorator (various)
00977         {
00978                 $blocktag = $node->blocktag;
00979                 $node->knowntag = in_array($blocktag,$this->_blocktags);
00980                 if (!$node->knowntag)
00981                 {
00982                         $node->opentag_head = "\n(:$blocktag " . $node->decoration->markup;
00983                         $node->opentag_tail = ":)";
00984                         $node->closetag = "\n(:{$blocktag}end:)";
00985                 }
00986                 elseif (substr($blocktag,0,2) == 'dl')
00987                 {
00988                         $dlmltag = substr($blocktag,2);
00989                         $node->opentag_head = "\n<dl:" . $dlmltag;
00990                         $node->opentag_tail = ">";
00991                         $node->closetag = "\n</dl:" . $dlmltag. '>';
00992                 }
00993                 else
00994                 {
00995                         $node->opentag_head = "\n<$blocktag";
00996                         $node->opentag_tail = ">";
00997                         $node->closetag = "\n</$blocktag>";
00998                 }
00999                 $node->elementcontent = '';
01000                 if (isset($this->_blockdef_handler))
01001                         $node = call_user_func($this->_blockdef_handler,$node);
01002                 if (!$node->elementcontent) $node->elementcontent = $this->emit_children($node);
01003                 if ($node->knowntag)
01004                 {       
01005                         $node = $this->prepare_node($node);
01006                         return $this->standard_assembly($node);
01007                 }
01008                 else
01009                 {
01010                         return $node->opentag_head . $node->opentag_tail 
01011                                 . $node->elementcontent . $node->closetag;
01012                 }
01013         }
01014         #--------------------------------[ macros ]--------------------------------#
01015 
01019         protected function _macro_emit($node) // macro decorator
01020         {
01021                 $node->caption = $this->emit_children($node);
01022                 $node->processed = FALSE; // set to TRUE by prepare_macro_node if macro found.
01023                 $node = $this->prepare_macro_node($node);
01024                 if ($node->processed)
01025                 {
01026                         return $node->output;
01027                 } else { // return re-assembled source markup
01028                         $opentag_head = '<<' . $node->macroname;
01029                         $arguments = property_exists($node,"decoration")? $node->decoration->markup: '';
01030                         if ($arguments != '') $arguments = ' ' . $arguments;
01031                         $caption = $node->caption;
01032                         if ($caption) 
01033                                 $caption = '|' . $caption;
01034                         $closetag = '>>';
01035                         return $this->char_filter($opentag_head . $arguments .  $caption . $closetag,$node);
01036                 }
01037         }
01039 }