======Yet another way to make rowspan possible====== I tried to emprove syntax for tables in such a way. Besides the common syntax you may use cells with colspan and rowspan parameters implictly set. You can see it in work at the page [[http://nvcamc.ipsys.net/doku.php?id=playground:playground]] FIXME To make this possible you must open table cell. Then without any spaces you must put colspan and rowspan parameters, separated by comma and a closing tag (like the opening cell). For example: |2,2| A 2x2 cell A11,A12,A21,A22| A13 | | A23 | | A31 | A32 | A33 | The same syntax I made for header cells. The closing tag must repeat the opening tag. The example, where spanned cell is a header style cell is shown below ^2,2^ A 2x2 cell A11,A12,A21,A22| A13 | | A23 | | A31 | A32 | A33 | The same way you can force cells to have any rowspan and colspan values. For this I had to emprove [[wiki:parser]], handler and renderer I show only differencies between current version (2006.11.06). The same thing I made on version 2006.03.09 So here are parser changes in inc/parser/parser.inc: class Doku_Parser_Mode_table extends Doku_Parser_Mode { function Doku_Parser_Mode_table() { global $PARSER_MODES; $this->allowedModes = array_merge ( $PARSER_MODES['formatting'], $PARSER_MODES['substition'], $PARSER_MODES['disabled'], $PARSER_MODES['protected'] ); } function connectTo($mode) { + $this->Lexer->addEntryPattern('\n\^[0-9]{1,},[0-9]{1,}\^',$mode,'table'); + $this->Lexer->addEntryPattern('\n\|[0-9]{1,},[0-9]{1,}\|',$mode,'table'); $this->Lexer->addEntryPattern('\n\^',$mode,'table'); $this->Lexer->addEntryPattern('\n\|',$mode,'table'); } function postConnect() { + $this->Lexer->addPattern('\n\^[0-9]{1,},[0-9]{1,}\^','table'); + $this->Lexer->addPattern('\n\|[0-9]{1,},[0-9]{1,}\|','table'); $this->Lexer->addPattern('\n\^','table'); $this->Lexer->addPattern('\n\|','table'); #$this->Lexer->addPattern(' {2,}','table'); $this->Lexer->addPattern('[\t ]+','table'); + $this->Lexer->addPattern('\^[0-9]{1,},[0-9]{1,}\^','table'); + $this->Lexer->addPattern('\|[0-9]{1,},[0-9]{1,}\|','table'); $this->Lexer->addPattern('\^','table'); $this->Lexer->addPattern('\|','table'); $this->Lexer->addExitPattern('\n','table'); } function getSort() { return 60; } } Handler changes in inc/parser/handler.inc: function table($match, $state, $pos) { switch ( $state ) { case DOKU_LEXER_ENTER: $ReWriter = & new Doku_Handler_Table($this->CallWriter); $this->CallWriter = & $ReWriter; $this->_addCall('table_start', array(), $pos); //$this->_addCall('table_row', array(), $pos); + if ( preg_match('/\n\^[0-9]{1,},[0-9]{1,}\^/',$match) ) { + list($colspan,$rowspan) = preg_split("/\,/u", substr($match, 2, -1), 2); + $this->_addCall('tableheader',array($colspan, $rowspan), $pos); //DEBUG + }else if ( preg_match('/\n\|[0-9]{1,},[0-9]{1,}\|/',$match) ) { + list($colspan,$rowspan) = preg_split("/\,/u", substr($match, 2, -1), 2); + $this->_addCall('tablecell',array($colspan, $rowspan), $pos); //DEBUG * }else if ( trim($match) == '^' ) { $this->_addCall('tableheader', array(), $pos); }else{ $this->_addCall('tablecell', array(), $pos); } break; case DOKU_LEXER_EXIT: $this->_addCall('table_end', array(), $pos); $this->CallWriter->process(); $ReWriter = & $this->CallWriter; $this->CallWriter = & $ReWriter->CallWriter; break; case DOKU_LEXER_UNMATCHED: if ( trim($match) != '' ) { $this->_addCall('cdata',array($match), $pos); } break; case DOKU_LEXER_MATCHED: if ( $match == ' ' ){ $this->_addCall('cdata', array($match), $pos); } else if ( preg_match('/\t+/',$match) ) { $this->_addCall('table_align', array($match), $pos); } else if ( preg_match('/ {2,}/',$match) ) { $this->_addCall('table_align', array($match), $pos); + } else if ( preg_match('/\n\|[0-9]{1,},[0-9]{1,}\|/',$match) ) { + $this->_addCall('table_row', array(), $pos); + list($colspan,$rowspan) = preg_split("/\,/u", substr($match, 2, -1), 2); + $this->_addCall('tablecell',array($colspan, $rowspan), $pos); //DEBUG } else if ( $match == "\n|" ) { $this->_addCall('table_row', array(), $pos); $this->_addCall('tablecell', array(), $pos); + } else if ( preg_match('/\n\^[0-9]{1,},[0-9]{1,}\^/',$match) ) { + $this->_addCall('table_row', array(), $pos); + list($colspan,$rowspan) = preg_split("/\,/u", substr($match, 2, -1), 2); + $this->_addCall('tableheader',array($colspan, $rowspan), $pos); //DEBUG } else if ( $match == "\n^" ) { $this->_addCall('table_row', array(), $pos); $this->_addCall('tableheader', array(), $pos); + } else if ( preg_match('/\|[0-9]{1,},[0-9]{1,}\|/',$match) ) { + list($colspan,$rowspan) = preg_split("/\,/u", substr($match, 1, -1), 2); + $this->_addCall('tablecell',array($colspan, $rowspan), $pos); //DEBUG } else if ( $match == '|' ) { $this->_addCall('tablecell', array(), $pos); + } else if ( preg_match('/\^[0-9]{1,},[0-9]{1,}\^/',$match) ) { + list($colspan,$rowspan) = preg_split("/\,/u", substr($match, 1, -1), 2); + $this->_addCall('tableheader',array($colspan, $rowspan), $pos); //DEBUG } else if ( $match == '^' ) { $this->_addCall('tableheader', array(), $pos); } break; } return TRUE; } AND function tableCell($call) { if ( !$this->firstCell ) { // Increase the span $lastCall = end($this->tableCalls); // A cell call which follows an open cell means an empty cell so span if ( $lastCall[0] == 'tablecell_open' || $lastCall[0] == 'tableheader_open' ) { $this->tableCalls[] = array('colspan',array(),$call[2]); } $this->tableCalls[] = array($this->lastCellType.'_close',array(),$call[2]); * $this->tableCalls[] = array($call[0].'_open',array($call[1][0],$call[1][1],NULL),$call[2]); $this->lastCellType = $call[0]; } else { * $this->tableCalls[] = array($call[0].'_open',array($call[1][0],$call[1][1],NULL),$call[2]); $this->lastCellType = $call[0]; $this->firstCell = FALSE; } $this->currentCols++; } function tableDefault($call) { $this->tableCalls[] = $call; } function finalizeTable() { // Add the max cols and rows to the table opening if ( $this->tableCalls[0][0] == 'table_open' ) { // Adjust to num cols not num col delimeters $this->tableCalls[0][1][] = $this->maxCols - 1; $this->tableCalls[0][1][] = $this->maxRows; } else { trigger_error('First element in table call list is not table_open'); } $lastRow = 0; $lastCell = 0; $toDelete = array(); // 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 ) { if ( $call[0] == 'tablerow_open' ) { $lastRow = $key; } else if ( $call[0] == 'tablecell_open' || $call[0] == 'tableheader_open' ) { $lastCell = $key; } else if ( $call[0] == 'table_align' ) { // If the previous element was a cell open, align right if ( $this->tableCalls[$key-1][0] == 'tablecell_open' || $this->tableCalls[$key-1][0] == 'tableheader_open' ) { * $this->tableCalls[$key-1][1][2] = 'right'; // If the next element if the close of an element, align either center or left } else if ( $this->tableCalls[$key+1][0] == 'tablecell_close' || $this->tableCalls[$key+1][0] == 'tableheader_close' ) { * if ( $this->tableCalls[$lastCell][1][2] == 'right' ) { * $this->tableCalls[$lastCell][1][2] = 'center'; } else { * $this->tableCalls[$lastCell][1][2] = 'left'; } } // Now convert the whitespace back to cdata $this->tableCalls[$key][0] = 'cdata'; } else if ( $call[0] == 'colspan' ) { $this->tableCalls[$key-1][1][0] = FALSE; for($i = $key-2; $i > $lastRow; $i--) { if ( $this->tableCalls[$i][0] == 'tablecell_open' || $this->tableCalls[$i][0] == 'tableheader_open' ) { if ( FALSE !== $this->tableCalls[$i][1][0] ) { $this->tableCalls[$i][1][0]++; break; } } } $toDelete[] = $key-1; $toDelete[] = $key; $toDelete[] = $key+1; } } renderer changes in inc/parser/renderer.inc and renderer changes in inc/parser/wiki.inc function table_open($maxcols = NULL, $numrows = NULL){} function table_close(){} function tablerow_open(){} function tablerow_close(){} * function tableheader_open($colspan = 1, $rowspan = 1, $align = NULL){} function tableheader_close(){} * function tablecell_open($colspan = 1, $rowspan = 1, $align = NULL){} function tablecell_close(){} and renderer changes in inc/parser/xhtml.inc function tableheader_open($colspan = 1, $rowspan = 1, $align = NULL){ $this->doc .= 'doc .= ' class="'.$align.'align"'; } * if ( $rowspan > 1 ) { * $this->doc .= ' rowspan="'.$rowspan.'"'; * } if ( $colspan > 1 ) { $this->doc .= ' colspan="'.$colspan.'"'; } $this->doc .= '>'; } function tableheader_close(){ $this->doc .= ''; } *function tablecell_open($colspan = 1, $rowspan = 1, $align = NULL){ $this->doc .= 'doc .= ' class="'.$align.'align"'; } * if ( $rowspan > 1 ) { * $this->doc .= ' rowspan="'.$rowspan.'"'; * } if ( $colspan > 1 ) { $this->doc .= ' colspan="'.$colspan.'"'; } $this->doc .= '>'; } and renderer changes in inc/parser/metadata.inc function table_open($maxcols = NULL, $numrows = NULL){} function table_close(){} function tablerow_open(){} function tablerow_close(){} * function tableheader_open($colspan = 1, $rowspan = 1, $align = NULL){} function tableheader_close(){} * function tablecell_open($colspan = 1, $rowspan = 1, $align = NULL){} function tablecell_close(){} |2,2| A 2x2 cell A11,A12,A21,A22| A13 | | A23 | | A31 | A32 | A33 | ^2,2^ A 2x2 cell A11,A12,A21,A22| A13 | | A23 | | A31 | A32 | A33 | --- //[[serg_stetsuk@ukr.net|Sergiy Stetsuk]] 2007-10-25 00:04//