summaryrefslogtreecommitdiff
path: root/inc/parser
diff options
context:
space:
mode:
authorDanny Lin <danny0838@pchome.com.tw>2011-01-26 11:06:41 +0800
committerDanny Lin <danny0838@pchome.com.tw>2011-01-26 11:06:41 +0800
commit9569a107742372a9dcfac06600e3d59c289ba142 (patch)
tree372b70a5fb94a869fdf3612343d91811875c6632 /inc/parser
parentb5a0b131e99eb6028e5ca5fed9c798982cdfe168 (diff)
downloadrpg-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')
-rw-r--r--inc/parser/handler.php201
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 :