From e1c10e4d58dad58f2a8b4b121b62bd56045bf852 Mon Sep 17 00:00:00 2001 From: chris <chris@jalakai.co.uk> Date: Sun, 9 Apr 2006 23:49:58 +0200 Subject: [PATCH] Parser Update: - revisions to header class and section handling header pattern simplified header class now writes section open and close instructions section call writer removed check for and update meta['first_header'] if required (see below) - meta instruction added written by _finalize to front of instruction stack holds first header information plugins can now write first header information, or other page meta information to this data structure. - get_first_heading updated to make use of meta['first_header'] - plugin instruction structure changed to include lexer state in the data portion of the instruction. OLD INSTRUCTION: array('plugin', array(<plugin name>,<plugin_data>,$pos), $pos) NEW INSTRUCTION: array('plugin', array(<plugin name>,<plugin_data>,$state), $pos) - block handler/call writer update to better handle plugin PTypes 'block' & 'stack'. Lexer states are mapped as follows: DOKU_LEXER_ENTER, DOKU_LEXER_SPECIAL : block_open, stack_open DOKU_LEXER_EXIT, DOKU_LEXER_SPECIAL : block_close, stack_close DOKU_LEXER_MATCHED, DOKU_LEXER_UNMATCHED : plugin must handle <p> Plugin writers can now use these PTypes as intended ! darcs-hash:20060409214958-9b6ab-cd2cef97a6a2521e3a02175075b8ff4648035f69.gz --- inc/parser/handler.php | 123 ++++++++++++++++++++--------------------- inc/parser/parser.php | 13 +---- inc/parser/xhtml.php | 9 ++- inc/parserutils.php | 7 +-- 4 files changed, 72 insertions(+), 80 deletions(-) diff --git a/inc/parser/handler.php b/inc/parser/handler.php index 1b73c458f..2088942a1 100644 --- a/inc/parser/handler.php +++ b/inc/parser/handler.php @@ -10,6 +10,10 @@ class Doku_Handler { var $calls = array(); var $meta = array( + 'first_heading' => '', + ); + + var $status = array( 'section' => FALSE, ); @@ -25,9 +29,10 @@ class Doku_Handler { } function _finalize(){ - if ( $this->meta['section'] ) { - $S = & new Doku_Handler_Section(); - $this->calls = $S->process($this->calls); + + if ( $this->status['section'] ) { + $last_call = end($this->calls); + array_push($this->calls,array('section_close',array(), $last_call[2])); } if ( $this->rewriteBlocks ) { @@ -36,6 +41,7 @@ class Doku_Handler { } array_unshift($this->calls,array('document_start',array(),0)); + array_unshift($this->calls,array('meta',array($this->meta),0)); $last_call = end($this->calls); array_push($this->calls,array('document_end',array(),$last_call[2])); } @@ -63,7 +69,7 @@ class Doku_Handler { if($plugin != null){ $data = $plugin->handle($match, $state, $pos, $this); } - $this->_addCall('plugin',array($pluginname,$data,$pos),$pos); + $this->_addCall('plugin',array($pluginname,$data,$state),$pos); return TRUE; } @@ -79,29 +85,21 @@ class Doku_Handler { function header($match, $state, $pos) { $match = trim($match); - $levels = array( - '======'=>1, - '====='=>2, - '===='=>3, - '==='=>4, - '=='=>5, - ); - $hsplit = preg_split( '/(={2,})/u', $match,-1, - PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY ); - // Locate the level - default to level 1 if no match (title contains == signs) - if ( isset($hsplit[0]) && array_key_exists($hsplit[0], $levels) ) { - $level = $levels[$hsplit[0]]; - } else { - $level = 1; - } + list($header,$title) = split(' ',$match,2); + $level = 7 - strlen($header); // Strip markers and whitespaces $title = trim($match,'='); $title = trim($title,' '); + if ($this->status['section']) $this->_addCall('section_close',array(),$pos); + $this->_addCall('header',array($title,$level,$pos), $pos); - $this->meta['section'] = TRUE; + + $this->_addCall('section_open',array($level),$pos); + $this->status['section'] = TRUE; + if (!$this->meta['first_heading']) $this->meta['first_heading'] = $title; return TRUE; } @@ -1203,6 +1201,12 @@ class Doku_Handler_Section { $inSection = TRUE; } else { + + if ($call[0] == 'section_open' ) { + $inSection = TRUE; + } else if ($call[0] == 'section_open' ) { + $inSection = FALSE; + } $sectionCalls[] = $call; } } @@ -1274,14 +1278,10 @@ class Doku_Handler_Block { $ptype = $p->getPType(); if($ptype == 'block'){ $this->blockOpen[] = 'plugin_'.$n; - $this->blockOpen[] = 'plugin_'.$n.'_open'; $this->blockClose[] = 'plugin_'.$n; - $this->blockClose[] = 'plugin_'.$n.'_close'; }elseif($ptype == 'stack'){ $this->stackOpen[] = 'plugin_'.$n; - $this->stackOpen[] = 'plugin_'.$n.'_open'; $this->stackClose[] = 'plugin_'.$n; - $this->stackClose[] = 'plugin_'.$n.'_close'; } } } @@ -1313,6 +1313,8 @@ class Doku_Handler_Block { }else{ $this->calls[] = array('p_close',array(), $pos); } + + $this->inParagraph = FALSE; } /** @@ -1325,17 +1327,19 @@ class Doku_Handler_Block { function process($calls) { foreach ( $calls as $key => $call ) { $cname = $call[0]; - if($cname == 'plugin') $cname='plugin_'.$call[1][0]; + 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 ) ) { - /* - if ( $this->atStart ) { - $this->calls[] = array('p_open',array(), $call[2]); - $this->atStart = FALSE; - $this->inParagraph = TRUE; - } - */ + if ( in_array($cname,$this->stackOpen ) && (!$plugin || $plugin_open) ) { + $this->calls[] = $call; // Hack - footnotes shouldn't immediately contain a p_open @@ -1347,10 +1351,9 @@ class Doku_Handler_Block { continue; } - if ( in_array($cname,$this->stackClose ) ) { + if ( in_array($cname,$this->stackClose ) && (!$plugin || $plugin_close)) { if ( $this->inParagraph ) { - //$this->calls[] = array('p_close',array(), $call[2]); $this->closeParagraph($call[2]); } $this->calls[] = $call; @@ -1362,18 +1365,9 @@ class Doku_Handler_Block { if ( $cname == 'eol' ) { - - /* XXX - if ( $this->inParagraph ) { - $this->calls[] = array('p_close',array(), $call[2]); - } - $this->calls[] = array('p_open',array(), $call[2]); - $this->inParagraph = TRUE; - */ - - # Check this isn't an eol instruction to skip... + // Check this isn't an eol instruction to skip... if ( $this->skipEolKey != $key ) { - # Look to see if the next instruction is an EOL + // Look to see if the next instruction is an EOL if ( isset($calls[$key+1]) && $calls[$key+1][0] == 'eol' ) { if ( $this->inParagraph ) { @@ -1385,7 +1379,7 @@ class Doku_Handler_Block { $this->inParagraph = TRUE; - # Mark the next instruction for skipping + // Mark the next instruction for skipping $this->skipEolKey = $key+1; }else{ @@ -1398,19 +1392,15 @@ class Doku_Handler_Block { } else { $storeCall = TRUE; - if ( $this->inParagraph && in_array($cname, $this->blockOpen) ) { - //$this->calls[] = array('p_close',array(), $call[2]); + if ( $this->inParagraph && (in_array($cname, $this->blockOpen) && (!$plugin || $plugin_open))) { $this->closeParagraph($call[2]); - $this->inParagraph = FALSE; $this->calls[] = $call; $storeCall = FALSE; } - if ( in_array($cname, $this->blockClose) ) { + if ( in_array($cname, $this->blockClose) && (!$plugin || $plugin_close)) { if ( $this->inParagraph ) { - //$this->calls[] = array('p_close',array(), $call[2]); $this->closeParagraph($call[2]); - $this->inParagraph = FALSE; } if ( $storeCall ) { $this->calls[] = $call; @@ -1418,15 +1408,24 @@ class Doku_Handler_Block { } // This really sucks and suggests this whole class sucks but... - if ( isset($calls[$key+1]) - && - !in_array($calls[$key+1][0], $this->blockOpen) - && - !in_array($calls[$key+1][0], $this->blockClose) - ) { + if ( isset($calls[$key+1])) { + $cname_plusone = $calls[$key+1][0]; + if ($cname_plusone == 'plugin') { + $cname_plusone = 'plugin'.$calls[$key+1][1][0]; + + // plugin test, true if plugin has a state which precludes it requiring blockOpen or blockClose + $plugin_plusone = true; + $plugin_test = ($call[$key+1][1][2] == DOKU_LEXER_MATCHED) || ($call[$key+1][1][2] == DOKU_LEXER_MATCHED); + } else { + $plugin_plusone = false; + } + if ((!in_array($cname_plusone, $this->blockOpen) && !in_array($cname_plusone, $this->blockClose)) || + ($plugin_plusone && $plugin_test) + ) { - $this->calls[] = array('p_open',array(), $call[2]); - $this->inParagraph = TRUE; + $this->calls[] = array('p_open',array(), $call[2]); + $this->inParagraph = TRUE; + } } } @@ -1487,4 +1486,4 @@ class Doku_Handler_Block { } } -//Setup VIM: ex: et ts=4 enc=utf-8 : +//Setup VIM: ex: et ts=4 enc=utf-8 : \ No newline at end of file diff --git a/inc/parser/parser.php b/inc/parser/parser.php index a99d8da34..e5a58f336 100644 --- a/inc/parser/parser.php +++ b/inc/parser/parser.php @@ -222,22 +222,11 @@ class Doku_Parser_Mode_header extends Doku_Parser_Mode { function preConnect() { //we're not picky about the closing ones, two are enough - - // Header 1 is special case - match 6 or more $this->Lexer->addSpecialPattern( - '[ \t]*={6,}[^\n]+={2,}[ \t]*(?=\n)', + '[ \t]*={2,6}[^\n]+={2,}[ \t]*(?=\n)', 'base', 'header' ); - - // For the rest, match exactly - for ( $i = 5; $i > 1; $i--) { - $this->Lexer->addSpecialPattern( - '[ \t]*={'.$i.'}[^\n]+={2,}[ \t]*(?=\n)', - 'base', - 'header' - ); - } } function getSort() { diff --git a/inc/parser/xhtml.php b/inc/parser/xhtml.php index 221e18da0..b3b341f9b 100644 --- a/inc/parser/xhtml.php +++ b/inc/parser/xhtml.php @@ -45,6 +45,12 @@ class Doku_Renderer_xhtml extends Doku_Renderer { var $store = ''; + var $meta = array(); + + function meta($data) { + if (is_array($data)) $this->meta = $data; + } + function document_start() { //reset some internals $this->toc = array(); @@ -562,6 +568,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $link['more'] = ''; $link['class'] = $class; $link['url'] = $url; + $link['name'] = $name; $link['title'] = $this->_xmlEntities($url); if($conf['relnofollow']) $link['more'] .= ' rel="nofollow"'; @@ -1060,4 +1067,4 @@ class Doku_Renderer_xhtml extends Doku_Renderer { } } -//Setup VIM: ex: et ts=4 enc=utf-8 : +//Setup VIM: ex: et ts=4 enc=utf-8 : \ No newline at end of file diff --git a/inc/parserutils.php b/inc/parserutils.php index 13c9396a0..b295ae152 100644 --- a/inc/parserutils.php +++ b/inc/parserutils.php @@ -390,11 +390,8 @@ function p_get_first_heading($id){ $file = wikiFN($id); if (@file_exists($file)) { $instructions = p_cached_instructions($file,true); - foreach ( $instructions as $instruction ) { - if ($instruction[0] == 'header') { - return trim($instruction[1][0]); - } - } + $meta = $instructions[0][1]; + return isset($meta[0]['first_heading']) ? trim($meta[0]['first_heading']) : NULL; } return NULL; } -- GitLab