diff options
author | Danny Lin <danny0838@pchome.com.tw> | 2011-01-26 11:06:41 +0800 |
---|---|---|
committer | Danny Lin <danny0838@pchome.com.tw> | 2011-01-26 11:06:41 +0800 |
commit | 9569a107742372a9dcfac06600e3d59c289ba142 (patch) | |
tree | 372b70a5fb94a869fdf3612343d91811875c6632 /inc/parser/handler.php | |
parent | b5a0b131e99eb6028e5ca5fed9c798982cdfe168 (diff) | |
download | rpg-9569a107742372a9dcfac06600e3d59c289ba142.tar.gz rpg-9569a107742372a9dcfac06600e3d59c289ba142.tar.bz2 |
Major rework of rewrite block in handler.php. (FS#2145)
-Simplify the algorithm. May improve performance.
-Treat footnote as pure block and section as pure stack.
-Remove post-p-open and pre-p-close linefeeds. Affects the effect of xbr plugin.
Diffstat (limited to 'inc/parser/handler.php')
-rw-r--r-- | inc/parser/handler.php | 201 |
1 files changed, 66 insertions, 135 deletions
diff --git a/inc/parser/handler.php b/inc/parser/handler.php index 3bd3a3b3c..e7eb94dd2 100644 --- a/inc/parser/handler.php +++ b/inc/parser/handler.php @@ -1427,14 +1427,8 @@ class Doku_Handler_Table { * @author Harry Fuecks <hfuecks@gmail.com> */ class Doku_Handler_Block { - var $calls = array(); - - var $blockStack = array(); - - var $inParagraph = false; - var $atStart = true; - var $skipEolKey = -1; + var $skipEol = false; // Blocks these should not be inside paragraphs var $blockOpen = array( @@ -1442,9 +1436,9 @@ class Doku_Handler_Block { 'listu_open','listo_open','listitem_open','listcontent_open', 'table_open','tablerow_open','tablecell_open','tableheader_open', 'quote_open', - 'section_open', // Needed to prevent p_open between header and section_open 'code','file','hr','preformatted','rss', 'htmlblock','phpblock', + 'footnote_open', ); var $blockClose = array( @@ -1452,18 +1446,18 @@ class Doku_Handler_Block { 'listu_close','listo_close','listitem_close','listcontent_close', 'table_close','tablerow_close','tablecell_close','tableheader_close', 'quote_close', - 'section_close', // Needed to prevent p_close after section_close 'code','file','hr','preformatted','rss', 'htmlblock','phpblock', + 'footnote_close', ); // Stacks can contain paragraphs var $stackOpen = array( - 'footnote_open','section_open', + 'section_open', ); var $stackClose = array( - 'footnote_close','section_close', + 'section_close', ); @@ -1489,9 +1483,11 @@ class Doku_Handler_Block { } } - function openParagraph($pos){ + function openParagraph($pos){
+ if ($this->inParagraph) return; $this->calls[] = array('p_open',array(), $pos); - $this->inParagraph = true; + $this->inParagraph = true;
+ $this->skipEol = true; } /** @@ -1501,7 +1497,8 @@ class Doku_Handler_Block { * * @author Andreas Gohr <andi@splitbrain.org> */ - function closeParagraph($pos){ + function closeParagraph($pos){
+ if (!$this->inParagraph) return; // look back if there was any content - we don't want empty paragraphs $content = ''; for($i=count($this->calls)-1; $i>=0; $i--){ @@ -1518,11 +1515,29 @@ class Doku_Handler_Block { if(trim($content)==''){ //remove the whole paragraph array_splice($this->calls,$i); - }else{ + }else{
+ // remove ending linebreaks in the paragraph
+ $i=count($this->calls)-1;
+ if ($this->calls[$i][0] == 'cdata') $this->calls[$i][1][0] = rtrim($this->calls[$i][1][0],DOKU_PARSER_EOL); $this->calls[] = array('p_close',array(), $pos); } - $this->inParagraph = false; + $this->inParagraph = false;
+ $this->skipEol = true; + } + + function addCall($call) { + $key = count($this->calls); + if ($key and ($call[0] == 'cdata') and ($this->calls[$key-1][0] == 'cdata')) { + $this->calls[$key-1][1][0] .= $call[1][0]; + } else { + $this->calls[] = $call; + } + } + + // simple version of addCall, without checking cdata + function storeCall($call) { + $this->calls[] = $call; } /** @@ -1530,155 +1545,71 @@ class Doku_Handler_Block { * * @author Harry Fuecks <hfuecks@gmail.com> * @author Andreas Gohr <andi@splitbrain.org> - * @todo This thing is really messy and should be rewritten */ function process($calls) { + // open first paragraph
+ $this->openParagraph(0); foreach ( $calls as $key => $call ) { $cname = $call[0]; - if($cname == 'plugin') { + if ($cname == 'plugin') { $cname='plugin_'.$call[1][0]; - $plugin = true; $plugin_open = (($call[1][2] == DOKU_LEXER_ENTER) || ($call[1][2] == DOKU_LEXER_SPECIAL)); $plugin_close = (($call[1][2] == DOKU_LEXER_EXIT) || ($call[1][2] == DOKU_LEXER_SPECIAL)); } else { $plugin = false; } - - // Process blocks which are stack like... (contain linefeeds) - if ( in_array($cname,$this->stackOpen ) && (!$plugin || $plugin_open) ) { - - // Hack - footnotes shouldn't immediately contain a p_open - if ($this->addToStack($cname != 'footnote_open')) { - $this->closeParagraph($call[2]); - } - $this->calls[] = $call; - $this->skipEolKey = $key+1; + /* stack */ + if ( in_array($cname,$this->stackClose ) && (!$plugin || $plugin_close)) { + $this->closeParagraph($call[2]); + $this->storeCall($call); + $this->openParagraph($call[2]); continue; } - - if ( in_array($cname,$this->stackClose ) && (!$plugin || $plugin_close)) { - - if ( $this->inParagraph ) { - $this->closeParagraph($call[2]); - } - $this->calls[] = $call; - if ($this->removeFromStack()) { - $this->calls[] = array('p_open',array(), $call[2]); - } - $this->skipEolKey = $key+1; + if ( in_array($cname,$this->stackOpen ) && (!$plugin || $plugin_open) ) { + $this->closeParagraph($call[2]); + $this->storeCall($call); + $this->openParagraph($call[2]); continue; } - - // Always opens a paragraph on stack start - // If this is a block start, it will soon be closed later - if ( $this->atStart ) { + /* block */ + // If it's a substition it opens and closes at the same call. + // To make sure next paragraph is correctly started, let close go first. + if ( in_array($cname, $this->blockClose) && (!$plugin || $plugin_close)) { + $this->closeParagraph($call[2]); + $this->storeCall($call); $this->openParagraph($call[2]); - $this->atStart = false; - $this->skipEolKey = $key; + continue; } - + if ( in_array($cname, $this->blockOpen) && (!$plugin || $plugin_open)) { + $this->closeParagraph($call[2]); + $this->storeCall($call); + continue; + } + /* eol */ if ( $cname == 'eol' ) { - // Check this isn't an eol instruction to skip... - if ( $this->skipEolKey != $key ) { - // Look to see if the next instruction is an EOL + if ( !$this->skipEol ) { + // Next is EOL => double eol => mark as paragraph if ( isset($calls[$key+1]) && $calls[$key+1][0] == 'eol' ) { - - if ( $this->inParagraph ) { - $this->closeParagraph($call[2]); - } + $this->closeParagraph($call[2]); $this->openParagraph($call[2]); - // Mark the next instruction for skipping - $this->skipEolKey = $key+1; } else { //if this is just a single eol make a space from it $this->addCall(array('cdata',array(DOKU_PARSER_EOL), $call[2])); } - } else { - $this->skipEolKey = $key+1; } - - - } else { - - $storeCall = true; - if ( $this->inParagraph && (in_array($cname, $this->blockOpen) && (!$plugin || $plugin_open))) { - $this->closeParagraph($call[2]); - $this->calls[] = $call; - $storeCall = false; - // Mark next eol(s) for skipping - $this->skipEolKey = $key+1; - } - - if ( in_array($cname, $this->blockClose) && (!$plugin || $plugin_close)) { - if ( $this->inParagraph ) { - $this->closeParagraph($call[2]); - } - if ( $storeCall ) { - $this->calls[] = $call; - $storeCall = false; - } - $this->openParagraph($call[2]); - // Mark next eol(s) for skipping - $this->skipEolKey = $key+1; - } - if ( $storeCall ) { - $this->addCall($call); - } - } - - } - - if ( $this->inParagraph ) { - $call = end($this->calls); - $cname = $call[0]; - if ( $cname == 'p_open' ) { - // Ditch the last call - array_pop($this->calls); - } else if ( !in_array($cname, $this->blockClose) ) { - //$this->calls[] = array('p_close',array(), $call[2]); - $this->closeParagraph($call[2]); - } else { - $last_call = array_pop($this->calls); - //$this->calls[] = array('p_close',array(), $call[2]); - $this->closeParagraph($call[2]); - $this->calls[] = $last_call; + continue; } + /* normal */ + $this->addCall($call); + $this->skipEol = false; } - + // close last paragraph + $call = end($this->calls); + $this->closeParagraph($call[2]); return $this->calls; } - - /** - * - * @return bool true when a p_close() is required - */ - function addToStack($newStart = true) { - $ret = $this->inParagraph; - $this->blockStack[] = array($this->atStart, $this->inParagraph); - $this->atStart = $newStart; - $this->inParagraph = false; - - return $ret; - } - - function removeFromStack() { - $state = array_pop($this->blockStack); - $this->atStart = $state[0]; - $this->inParagraph = $state[1]; - - return $this->inParagraph; - } - - function addCall($call) { - $key = count($this->calls); - if ($key and ($call[0] == 'cdata') and ($this->calls[$key-1][0] == 'cdata')) { - $this->calls[$key-1][1][0] .= $call[1][0]; - } else { - $this->calls[] = $call; - } - } } //Setup VIM: ex: et ts=4 : |