diff options
author | Andreas Gohr <andi@splitbrain.org> | 2010-08-29 14:22:01 +0200 |
---|---|---|
committer | Andreas Gohr <andi@splitbrain.org> | 2010-08-29 14:22:01 +0200 |
commit | 2c053ed58376c6709596ab48fc40dceb90d4e89d (patch) | |
tree | c8d0f78c2f47f373473419396d3c0855ec671eca /inc/parser | |
parent | cb4a07568e84d853fbcd9d5eca37f572fa10786f (diff) | |
parent | 5479a8c3341247ca228026819f20f3ab5c34a80f (diff) | |
download | rpg-2c053ed58376c6709596ab48fc40dceb90d4e89d.tar.gz rpg-2c053ed58376c6709596ab48fc40dceb90d4e89d.tar.bz2 |
Merge branch 'master' into stable
Conflicts:
conf/msg
lib/plugins/acl/ajax.php
Diffstat (limited to 'inc/parser')
-rw-r--r-- | inc/parser/handler.php | 130 | ||||
-rw-r--r-- | inc/parser/lexer.php | 2 | ||||
-rw-r--r-- | inc/parser/metadata.php | 5 | ||||
-rw-r--r-- | inc/parser/parser.php | 6 | ||||
-rw-r--r-- | inc/parser/renderer.php | 29 | ||||
-rw-r--r-- | inc/parser/xhtml.php | 109 |
6 files changed, 171 insertions, 110 deletions
diff --git a/inc/parser/handler.php b/inc/parser/handler.php index 9fe5866ad..0b8b79254 100644 --- a/inc/parser/handler.php +++ b/inc/parser/handler.php @@ -12,15 +12,12 @@ class Doku_Handler { var $status = array( 'section' => false, - 'section_edit_start' => -1, - 'section_edit_level' => 1, - 'section_edit_title' => '' ); var $rewriteBlocks = true; function Doku_Handler() { - $this->CallWriter = & new Doku_Handler_CallWriter($this); + $this->CallWriter = new Doku_Handler_CallWriter($this); } function _addCall($handler, $args, $pos) { @@ -40,14 +37,10 @@ class Doku_Handler { if ( $this->status['section'] ) { $last_call = end($this->calls); array_push($this->calls,array('section_close',array(), $last_call[2])); - if ($this->status['section_edit_start']>1) { - // ignore last edit section if there is only one header - array_push($this->calls,array('section_edit',array($this->status['section_edit_start'], 0, $this->status['section_edit_level'], $this->status['section_edit_title']), $last_call[2])); - } } if ( $this->rewriteBlocks ) { - $B = & new Doku_Handler_Block(); + $B = new Doku_Handler_Block(); $this->calls = $B->process($this->calls); } @@ -97,8 +90,6 @@ class Doku_Handler { } function header($match, $state, $pos) { - global $conf; - // get level and title $title = trim($match); $level = 7 - strspn($title,'='); @@ -108,13 +99,6 @@ class Doku_Handler { if ($this->status['section']) $this->_addCall('section_close',array(),$pos); - if ($level<=$conf['maxseclevel']) { - $this->_addCall('section_edit',array($this->status['section_edit_start'], $pos-1, $this->status['section_edit_level'], $this->status['section_edit_title']), $pos); - $this->status['section_edit_start'] = $pos; - $this->status['section_edit_level'] = $level; - $this->status['section_edit_title'] = $title; - } - $this->_addCall('header',array($title,$level,$pos), $pos); $this->_addCall('section_open',array($level),$pos); @@ -212,7 +196,7 @@ class Doku_Handler { $this->_footnote = true; - $ReWriter = & new Doku_Handler_Nest($this->CallWriter,'footnote_close'); + $ReWriter = new Doku_Handler_Nest($this->CallWriter,'footnote_close'); $this->CallWriter = & $ReWriter; $this->_addCall('footnote_open', array(), $pos); break; @@ -240,7 +224,7 @@ class Doku_Handler { function listblock($match, $state, $pos) { switch ( $state ) { case DOKU_LEXER_ENTER: - $ReWriter = & new Doku_Handler_List($this->CallWriter); + $ReWriter = new Doku_Handler_List($this->CallWriter); $this->CallWriter = & $ReWriter; $this->_addCall('list_open', array($match), $pos); break; @@ -302,7 +286,7 @@ class Doku_Handler { function preformatted($match, $state, $pos) { switch ( $state ) { case DOKU_LEXER_ENTER: - $ReWriter = & new Doku_Handler_Preformatted($this->CallWriter); + $ReWriter = new Doku_Handler_Preformatted($this->CallWriter); $this->CallWriter = & $ReWriter; $this->_addCall('preformatted_start',array(), $pos); break; @@ -328,7 +312,7 @@ class Doku_Handler { switch ( $state ) { case DOKU_LEXER_ENTER: - $ReWriter = & new Doku_Handler_Quote($this->CallWriter); + $ReWriter = new Doku_Handler_Quote($this->CallWriter); $this->CallWriter = & $ReWriter; $this->_addCall('quote_start',array($match), $pos); break; @@ -360,21 +344,16 @@ class Doku_Handler { function code($match, $state, $pos, $type='code') { if ( $state == DOKU_LEXER_UNMATCHED ) { $matches = explode('>',$match,2); - $matches[0] = trim($matches[0]); - - list($language,$filename) = explode(' ',$matches[0],2); - $language = trim($language); - $filename = trim($filename); - if ( $language == '' ) $language = null; - if ( $language == '-' ) $language = null; - if ( $filename == '' ) $filename = null; - # We shortcut html here. - if($language == 'html') $language = 'html4strict'; - $this->_addCall( - $type, - array($matches[1],$language,$filename), - $pos - ); + + $param = preg_split('/\s+/', $matches[0], 2, PREG_SPLIT_NO_EMPTY); + while(count($param) < 2) array_push($param, null); + + // We shortcut html here. + if ($param[0] == 'html') $param[0] = 'html4strict'; + if ($param[0] == '-') $param[0] = null; + array_unshift($param, $matches[1]); + + $this->_addCall($type, $param, $pos); } return true; } @@ -580,10 +559,10 @@ class Doku_Handler { case DOKU_LEXER_ENTER: - $ReWriter = & new Doku_Handler_Table($this->CallWriter); + $ReWriter = new Doku_Handler_Table($this->CallWriter); $this->CallWriter = & $ReWriter; - $this->_addCall('table_start', array(), $pos); + $this->_addCall('table_start', array($pos + 1), $pos); if ( trim($match) == '^' ) { $this->_addCall('tableheader', array(), $pos); } else { @@ -592,7 +571,7 @@ class Doku_Handler { break; case DOKU_LEXER_EXIT: - $this->_addCall('table_end', array(), $pos); + $this->_addCall('table_end', array($pos), $pos); $this->CallWriter->process(); $ReWriter = & $this->CallWriter; $this->CallWriter = & $ReWriter->CallWriter; @@ -1196,7 +1175,7 @@ class Doku_Handler_Table { $this->tableStart($call); break; case 'table_row': - $this->tableRowClose(array('tablerow_close',$call[1],$call[2])); + $this->tableRowClose($call); $this->tableRowOpen(array('tablerow_open',$call[1],$call[2])); break; case 'tableheader': @@ -1204,7 +1183,7 @@ class Doku_Handler_Table { $this->tableCell($call); break; case 'table_end': - $this->tableRowClose(array('tablerow_close',$call[1],$call[2])); + $this->tableRowClose($call); $this->tableEnd($call); break; default: @@ -1216,13 +1195,13 @@ class Doku_Handler_Table { } function tableStart($call) { - $this->tableCalls[] = array('table_open',array(),$call[2]); + $this->tableCalls[] = array('table_open',$call[1],$call[2]); $this->tableCalls[] = array('tablerow_open',array(),$call[2]); $this->firstCell = true; } function tableEnd($call) { - $this->tableCalls[] = array('table_close',array(),$call[2]); + $this->tableCalls[] = array('table_close',$call[1],$call[2]); $this->finalizeTable(); } @@ -1242,7 +1221,7 @@ class Doku_Handler_Table { break; } } - $this->tableCalls[] = $call; + $this->tableCalls[] = array('tablerow_close', array(), $call[2]); if ( $this->currentCols > $this->maxCols ) { $this->maxCols = $this->currentCols; @@ -1287,6 +1266,7 @@ class Doku_Handler_Table { // Adjust to num cols not num col delimeters $this->tableCalls[0][1][] = $this->maxCols - 1; $this->tableCalls[0][1][] = $this->maxRows; + $this->tableCalls[0][1][] = array_shift($this->tableCalls[0][1]); } else { trigger_error('First element in table call list is not table_open'); } @@ -1299,19 +1279,24 @@ class Doku_Handler_Table { // Look for the colspan elements and increment the colspan on the // previous non-empty opening cell. Once done, delete all the cells // that contain colspans - foreach ( $this->tableCalls as $key => $call ) { + for ($key = 0 ; $key < count($this->tableCalls) ; ++$key) { + $call = $this->tableCalls[$key]; - if ( $call[0] == 'tablerow_open' ) { + switch ($call[0]) { + case 'tablerow_open': $lastRow++; $lastCell = 0; + break; - } else if ( $call[0] == 'tablecell_open' || $call[0] == 'tableheader_open' ) { + case 'tablecell_open': + case 'tableheader_open': $lastCell++; $cellKey[$lastRow][$lastCell] = $key; + break; - } else if ( $call[0] == 'table_align' ) { + case 'table_align': $prev = in_array($this->tableCalls[$key-1][0], array('tablecell_open', 'tableheader_open')); $next = in_array($this->tableCalls[$key+1][0], array('tablecell_close', 'tableheader_close')); @@ -1335,8 +1320,9 @@ class Doku_Handler_Table { // Now convert the whitespace back to cdata $this->tableCalls[$key][0] = 'cdata'; + break; - } else if ( $call[0] == 'colspan' ) { + case 'colspan': $this->tableCalls[$key-1][1][0] = false; @@ -1356,8 +1342,9 @@ class Doku_Handler_Table { $toDelete[] = $key-1; $toDelete[] = $key; $toDelete[] = $key+1; + break; - } else if ( $call[0] == 'rowspan' ) { + case 'rowspan': if ( $this->tableCalls[$key-1][0] == 'cdata' ) { // ignore rowspan if previous call was cdata (text mixed with :::) we don't have to check next call as that wont match regex @@ -1365,25 +1352,48 @@ class Doku_Handler_Table { } else { - $this->tableCalls[$key-1][1][2] = false; - + $spanning_cell = null; for($i = $lastRow-1; $i > 0; $i--) { if ( $this->tableCalls[$cellKey[$i][$lastCell]][0] == 'tablecell_open' || $this->tableCalls[$cellKey[$i][$lastCell]][0] == 'tableheader_open' ) { - if ( false !== $this->tableCalls[$cellKey[$i][$lastCell]][1][2] ) { - $this->tableCalls[$cellKey[$i][$lastCell]][1][2]++; + if ($this->tableCalls[$cellKey[$i][$lastCell]][1][2] >= $lastRow - $i) { + $spanning_cell = $i; break; } } } + if (is_null($spanning_cell)) { + // No spanning cell found, so convert this cell to + // an empty one to avoid broken tables + $this->tableCells[$key][1][1] = ''; + continue; + } + $this->tableCalls[$cellKey[$spanning_cell][$lastCell]][1][2]++; + + $this->tableCalls[$key-1][1][2] = false; $toDelete[] = $key-1; $toDelete[] = $key; - $toDelete[] = $key+1; + $toDelete[] = $key+1; } + break; + + case 'tablerow_close': + + // Fix broken tables by adding missing cells + while (++$lastCell < $this->maxCols) { + array_splice($this->tableCalls, $key, 0, array( + array('tablecell_open', array(1, null, 1), $call[2]), + array('cdata', array(''), $call[2]), + array('tablecell_close', array(), $call[2]))); + $key += 3; + } + + break; + } } @@ -1504,13 +1514,7 @@ class Doku_Handler_Block { //remove the whole paragraph array_splice($this->calls,$i); }else{ - if ($this->calls[count($this->calls)-1][0] == 'section_edit') { - $tmp = array_pop($this->calls); - $this->calls[] = array('p_close',array(), $pos); - $this->calls[] = $tmp; - } else { - $this->calls[] = array('p_close',array(), $pos); - } + $this->calls[] = array('p_close',array(), $pos); } $this->inParagraph = false; diff --git a/inc/parser/lexer.php b/inc/parser/lexer.php index afd260a05..211945d8f 100644 --- a/inc/parser/lexer.php +++ b/inc/parser/lexer.php @@ -295,7 +295,7 @@ class Doku_Lexer { $this->_case = $case; $this->_regexes = array(); $this->_parser = &$parser; - $this->_mode = &new Doku_LexerStateStack($start); + $this->_mode = new Doku_LexerStateStack($start); $this->_mode_handlers = array(); } diff --git a/inc/parser/metadata.php b/inc/parser/metadata.php index fc60e5774..f635ea1d5 100644 --- a/inc/parser/metadata.php +++ b/inc/parser/metadata.php @@ -334,8 +334,7 @@ class Doku_Renderer_metadata extends Doku_Renderer { $this->_firstimage($name['src']); if ($this->capture){ - if ($name) $this->doc .= $name; - else $this->doc .= '<'.$url.'>'; + $this->doc .= $this->_getLinkTitle($name, '<' . $url . '>'); } } @@ -345,7 +344,7 @@ class Doku_Renderer_metadata extends Doku_Renderer { if ($this->capture){ list($wikiUri, $hash) = explode('#', $wikiUri, 2); - $name = $this->_getLinkTitle($name, $wikiName.'>'.$wikiUri); + $name = $this->_getLinkTitle($name, $wikiUri); $this->doc .= $name; } } diff --git a/inc/parser/parser.php b/inc/parser/parser.php index a78b08a29..435b8aa46 100644 --- a/inc/parser/parser.php +++ b/inc/parser/parser.php @@ -61,7 +61,7 @@ class Doku_Parser { function addBaseMode(& $BaseMode) { $this->modes['base'] = & $BaseMode; if ( !$this->Lexer ) { - $this->Lexer = & new Doku_Lexer($this->Handler,'base', true); + $this->Lexer = new Doku_Lexer($this->Handler,'base', true); } $this->modes['base']->Lexer = & $this->Lexer; } @@ -413,8 +413,8 @@ class Doku_Parser_Mode_listblock extends Doku_Parser_Mode { } function connectTo($mode) { - $this->Lexer->addEntryPattern('\n {2,}[\-\*]',$mode,'listblock'); - $this->Lexer->addEntryPattern('\n\t{1,}[\-\*]',$mode,'listblock'); + $this->Lexer->addEntryPattern('[ \t]*\n {2,}[\-\*]',$mode,'listblock'); + $this->Lexer->addEntryPattern('[ \t]*\n\t{1,}[\-\*]',$mode,'listblock'); $this->Lexer->addPattern('\n {2,}[\-\*]','listblock'); $this->Lexer->addPattern('\n\t{1,}[\-\*]','listblock'); diff --git a/inc/parser/renderer.php b/inc/parser/renderer.php index 6082e935d..7e52cfce2 100644 --- a/inc/parser/renderer.php +++ b/inc/parser/renderer.php @@ -49,6 +49,15 @@ class Doku_Renderer extends DokuWiki_Plugin { trigger_error('getFormat() not implemented in '.get_class($this), E_USER_WARNING); } + /** + * Allow the plugin to prevent DokuWiki from reusing an instance + * + * @return bool false if the plugin has to be instantiated + */ + function isSingleton() { + return false; + } + //handle plugin rendering function plugin($name,$data){ @@ -85,8 +94,6 @@ class Doku_Renderer extends DokuWiki_Plugin { function header($text, $level, $pos) {} - function section_edit($start, $end, $level, $name) {} - function section_open($level) {} function section_close() {} @@ -231,9 +238,9 @@ class Doku_Renderer extends DokuWiki_Plugin { $src,$title=NULL,$align=NULL,$width=NULL,$height=NULL,$cache=NULL ) {} - function table_open($maxcols = NULL, $numrows = NULL){} + function table_open($maxcols = NULL, $numrows = NULL, $pos){} - function table_close(){} + function table_close($pos){} function tablerow_open(){} @@ -264,20 +271,12 @@ class Doku_Renderer extends DokuWiki_Plugin { list($name,$hash) = explode('#',$name,2); if($hash) return $hash; - //trim colons or slash of a namespace link - $name = rtrim($name,':'); - if($conf['useslash']) - $name = rtrim($name,'/'); - + $name = strtr($name,';',':'); if($conf['useslash']){ - $nssep = '[:;/]'; - }else{ - $nssep = '[:;]'; + $name = strtr($name,'/',':'); } - $name = preg_replace('!.*'.$nssep.'!','',$name); - if(!$name) return $this->_simpleTitle($conf['start']); - return $name; + return noNSorNS($name); } /** diff --git a/inc/parser/xhtml.php b/inc/parser/xhtml.php index 4d5333f7a..5a3d945d1 100644 --- a/inc/parser/xhtml.php +++ b/inc/parser/xhtml.php @@ -29,6 +29,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { var $doc = ''; // will contain the whole document var $toc = array(); // will contain the Table of Contents + private $sectionedits = array(); // A stack of section edit data var $headers = array(); var $footnotes = array(); @@ -39,6 +40,40 @@ class Doku_Renderer_xhtml extends Doku_Renderer { var $_counter = array(); // used as global counter, introduced for table classes var $_codeblock = 0; // counts the code and file blocks, used to provide download links + /** + * Register a new edit section range + * + * @param $type string The section type identifier + * @param $title string The section title + * @param $start int The byte position for the edit start + * @return string A marker class for the starting HTML element + * @author Adrian Lang <lang@cosmocode.de> + */ + public function startSectionEdit($start, $type, $title = null) { + static $lastsecid = 0; + $this->sectionedits[] = array(++$lastsecid, $start, $type, $title); + return 'sectionedit' . $lastsecid; + } + + /** + * Finish an edit section range + * + * @param $end int The byte position for the edit end; null for the rest of + the page + * @author Adrian Lang <lang@cosmocode.de> + */ + public function finishSectionEdit($end = null) { + list($id, $start, $type, $title) = array_pop($this->sectionedits); + if (!is_null($end) && $end <= $start) { + return; + } + $this->doc .= "<!-- EDIT$id " . strtoupper($type) . ' '; + if (!is_null($title)) { + $this->doc .= '"' . str_replace('"', '', $title) . '" '; + } + $this->doc .= "[$start-" . (is_null($end) ? '' : $end) . '] -->'; + } + function getFormat(){ return 'xhtml'; } @@ -51,6 +86,17 @@ class Doku_Renderer_xhtml extends Doku_Renderer { } function document_end() { + // Finish open section edits. + while (count($this->sectionedits) > 0) { + if ($this->sectionedits[count($this->sectionedits) - 1][1] <= 1) { + // If there is only one section, do not write a section edit + // marker. + array_pop($this->sectionedits); + } else { + $this->finishSectionEdit(); + } + } + if ( count ($this->footnotes) > 0 ) { $this->doc .= '<div class="footnotes">'.DOKU_LF; @@ -106,6 +152,8 @@ class Doku_Renderer_xhtml extends Doku_Renderer { } function header($text, $level, $pos) { + global $conf; + if(!$text) return; //skip empty headlines $hid = $this->_headerToLink($text,true); @@ -122,30 +170,24 @@ class Doku_Renderer_xhtml extends Doku_Renderer { } $this->lastlevel = $level; + if ($level <= $conf['maxseclevel'] && + count($this->sectionedits) > 0 && + $this->sectionedits[count($this->sectionedits) - 1][2] === 'section') { + $this->finishSectionEdit($pos - 1); + } + // write the header - $this->doc .= DOKU_LF.'<h'.$level.'><a name="'.$hid.'" id="'.$hid.'">'; + $this->doc .= DOKU_LF.'<h'.$level; + if ($level <= $conf['maxseclevel']) { + $this->doc .= ' class="' . $this->startSectionEdit($pos, 'section', $text) . '"'; + } + $this->doc .= '><a name="'.$hid.'" id="'.$hid.'">'; $this->doc .= $this->_xmlEntities($text); $this->doc .= "</a></h$level>".DOKU_LF; } - /** - * Section edit marker is replaced by an edit button when - * the page is editable. Replacement done in 'inc/html.php#html_secedit' - * - * @author Andreas Gohr <andi@splitbrain.org> - * @author Ben Coburn <btcoburn@silicodon.net> - */ - function section_edit($start, $end, $level, $name) { - global $conf; - - if ($start!=-1 && $level<=$conf['maxseclevel']) { - $name = str_replace('"', '', $name); - $this->doc .= '<!-- SECTION "'.$name.'" ['.$start.'-'.(($end===0)?'':$end).'] -->'; - } - } - function section_open($level) { - $this->doc .= "<div class=\"level$level\">".DOKU_LF; + $this->doc .= '<div class="level' . $level . '">' . DOKU_LF; } function section_close() { @@ -400,6 +442,13 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $this->doc .= '</a></dt>'.DOKU_LF.'<dd>'; } + if ($text{0} == "\n") { + $text = substr($text, 1); + } + if (substr($text, -1) == "\n") { + $text = substr($text, 0, -1); + } + if ( is_null($language) ) { $this->doc .= '<pre class="'.$type.'">'.$this->_xmlEntities($text).'</pre>'.DOKU_LF; } else { @@ -517,6 +566,14 @@ class Doku_Renderer_xhtml extends Doku_Renderer { function internallink($id, $name = NULL, $search=NULL,$returnonly=false,$linktype='content') { global $conf; global $ID; + + $params = ''; + $parts = explode('?', $id, 2); + if (count($parts) === 2) { + $id = $parts[0]; + $params = $parts[1]; + } + // default name is based on $id as given $default = $this->_simpleTitle($id); @@ -550,7 +607,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { } $link['more'] = ''; $link['class'] = $class; - $link['url'] = wl($id); + $link['url'] = wl($id, $params); $link['name'] = $name; $link['title'] = $id; //add search string @@ -845,14 +902,16 @@ class Doku_Renderer_xhtml extends Doku_Renderer { } // $numrows not yet implemented - function table_open($maxcols = NULL, $numrows = NULL){ + function table_open($maxcols = NULL, $numrows = NULL, $pos){ + global $lang; // initialize the row counter used for classes $this->_counter['row_counter'] = 0; - $this->doc .= '<table class="inline">'.DOKU_LF; + $this->doc .= '<div class="table ' . $this->startSectionEdit($pos, 'table') . '"><table class="inline">'.DOKU_LF; } - function table_close(){ - $this->doc .= '</table>'.DOKU_LF; + function table_close($pos){ + $this->doc .= '</table></div>'.DOKU_LF; + $this->finishSectionEdit($pos); } function tablerow_open(){ @@ -966,7 +1025,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { }elseif($ext == 'jpg' || $ext == 'jpeg'){ //try to use the caption from IPTC/EXIF require_once(DOKU_INC.'inc/JpegMeta.php'); - $jpeg =& new JpegMeta(mediaFN($src)); + $jpeg =new JpegMeta(mediaFN($src)); if($jpeg !== false) $cap = $jpeg->getTitle(); if($cap){ $title = $this->_xmlEntities($cap); @@ -1019,7 +1078,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $att['class'] = "media$align"; if($align == 'right') $att['align'] = 'right'; if($align == 'left') $att['align'] = 'left'; - $ret .= html_flashobject(ml($src,array('cache'=>$cache)),$width,$height, + $ret .= html_flashobject(ml($src,array('cache'=>$cache),true,'&'),$width,$height, array('quality' => 'high'), null, $att, |