Page MenuHomePhabricator
Authored By
bzimport
Nov 21 2014, 9:02 PM
Size
13 KB
Referenced Files
None
Subscribers
None

diff.txt

Index: skins/common/wikibits.js
===================================================================
--- skins/common/wikibits.js (revision 40784)
+++ skins/common/wikibits.js (working copy)
@@ -534,14 +534,8 @@
}
function ts_makeSortable(table) {
- var firstRow;
- if (table.rows && table.rows.length > 0) {
- if (table.tHead && table.tHead.rows.length > 0) {
- firstRow = table.tHead.rows[table.tHead.rows.length-1];
- } else {
- firstRow = table.rows[0];
- }
- }
+ var firstRow = table.rows[0];
+
if (!firstRow) return;
// We have a first row: assume it's the header, and make its contents clickable links
@@ -595,7 +589,7 @@
if (table.rows.length <= 1) return;
// Skip the first row if that's where the headings are
- var rowStart = (table.tHead && table.tHead.rows.length > 0 ? 0 : 1);
+ var rowStart = 1;
var itm = "";
for (var i = rowStart; i < table.rows.length; i++) {
Index: includes/parser/Parser.php
===================================================================
--- includes/parser/Parser.php (revision 40784)
+++ includes/parser/Parser.php (working copy)
@@ -768,196 +768,252 @@
wfProfileIn( __METHOD__ );
$lines = StringUtils::explode( "\n", $text );
+
+ $tables = array();
$out = '';
- $td_history = array (); // Is currently a td tag open?
- $last_tag_history = array (); // Save history of last lag activated (td, th or caption)
- $tr_history = array (); // Is currently a tr tag open?
- $tr_attributes = array (); // history of tr attributes
- $has_opened_tr = array(); // Did this table open a <tr> element?
- $indent_level = 0; // indent level of the table
+ $output =& $out;
foreach ( $lines as $outLine ) {
$line = trim( $outLine );
- if( $line == '' ) { // empty line, go to next line
- $out .= $outLine."\n";
+ if($line === '' ) {
+ $output .= "\n" . $outLine;
continue;
}
- $first_character = $line[0];
+
+ $first_chars = $line[0];
+ if ( strlen($line) > 1)
+ $first_chars .= in_array($line[1], array('}', '+', '-')) ? $line[1] : '';
+
$matches = array();
-
if ( preg_match( '/^(:*)\{\|(.*)$/', $line , $matches ) ) {
- // First check if we are starting a new table
- $indent_level = strlen( $matches[1] );
+ $tables[] = array();
+ $table =& $this->last($tables);
+ $table[0] = array(); //first row
+ $current_row =& $table[0];
+ $table['indent'] = strlen( $matches[1] );
+
$attributes = $this->mStripState->unstripBoth( $matches[2] );
$attributes = Sanitizer::fixTagAttributes ( $attributes , 'table' );
- $outLine = str_repeat( '<dl><dd>' , $indent_level ) . "<table{$attributes}>";
- array_push ( $td_history , false );
- array_push ( $last_tag_history , '' );
- array_push ( $tr_history , false );
- array_push ( $tr_attributes , '' );
- array_push ( $has_opened_tr , false );
- } else if ( count ( $td_history ) == 0 ) {
- // Don't do any of the following
- $out .= $outLine."\n";
- continue;
- } else if ( substr ( $line , 0 , 2 ) === '|}' ) {
- // We are ending a table
- $line = '</table>' . substr ( $line , 2 );
- $last_tag = array_pop ( $last_tag_history );
+ if ( $attributes !== '' ) $table['attributes'] = $attributes;
+ }
+ else if ( !isset($tables[0]) ) {
+ // we're outside the table
+ $output .= "\n" . $outLine;
+ }
+ else if ( $first_chars === '|}' ) {
+ // trim the |} code from the line
+ $line = substr ( $line , 2 );
+
+ // Shorthand for last row
+ $last_row =& $this->last($table);
- if ( !array_pop ( $has_opened_tr ) ) {
- $line = "<tr><td></td></tr>{$line}";
+ // a thead at the end becomes a tfoot, unless there is only one row
+ // Do this before deleting empty last lines to allow headers at the bottom of tables
+ if(isset($last_row['type']) && $last_row['type'] == 'thead' && isset($table[1])) {
+ $last_row['type'] = 'tfoot';
+ for($i = 0; isset($last_row[$i]); $i++ ) {
+ $last_row[$i]['type'] = 'td';
+ }
}
+
+ // Delete empty last lines
+ if( empty($last_row) ) $last_row = NULL;
- if ( array_pop ( $tr_history ) ) {
- $line = "</tr>{$line}";
+ $o = $this->printTableHtml( array_pop($tables) ) . $line;
+
+ if( count($tables) > 0 ) {
+ $table =& $this->last($tables);
+ $current_row =& $this->last($table);
+ $current_element =& $this->last($current_row);
+
+ $output =& $current_element['content'];
+ } else {
+ $output =& $out;
}
- if ( array_pop ( $td_history ) ) {
- $line = "</{$last_tag}>{$line}";
+ $output .= $o;
+ }
+ else if ( $first_chars === '|-' ) {
+ // start a new row element
+ // but only when we haven't started one already
+ if( count($current_row) != 0 ) {
+ $table[] = array();
+ $current_row =& $this->last($table);
}
- array_pop ( $tr_attributes );
- $outLine = $line . str_repeat( '</dd></dl>' , $indent_level );
- } else if ( substr ( $line , 0 , 2 ) === '|-' ) {
- // Now we have a table row
- $line = preg_replace( '#^\|-+#', '', $line );
- // Whats after the tag is now only attributes
+ // Get the attributes, there's nothing else useful in $line now
+ $line = substr ( $line , 2 );
$attributes = $this->mStripState->unstripBoth( $line );
$attributes = Sanitizer::fixTagAttributes ( $attributes , 'tr' );
- array_pop ( $tr_attributes );
- array_push ( $tr_attributes , $attributes );
+ if( $attributes !== '') $current_row['attributes'] = $attributes;
+ }
+ else if ( $first_chars === '|+' ) {
+ // a table caption
+ $line = substr ( $line , 2 );
- $line = '';
- $last_tag = array_pop ( $last_tag_history );
- array_pop ( $has_opened_tr );
- array_push ( $has_opened_tr , true );
+ $c = $this->getCellAttr($line , 'caption');
+ $table['caption'] = array();
+ $table['caption']['content'] = $c[0];
+ if(isset($c[1])) $table['caption']['attributes'] = $c[1];
+ unset($c);
- if ( array_pop ( $tr_history ) ) {
- $line = '</tr>';
- }
-
- if ( array_pop ( $td_history ) ) {
- $line = "</{$last_tag}>{$line}";
- }
-
- $outLine = $line;
- array_push ( $tr_history , false );
- array_push ( $td_history , false );
- array_push ( $last_tag_history , '' );
+ $output =& $table['caption'];
}
- else if ( $first_character === '|' || $first_character === '!' || substr ( $line , 0 , 2 ) === '|+' ) {
- // This might be cell elements, td, th or captions
- if ( substr ( $line , 0 , 2 ) === '|+' ) {
- $first_character = '+';
- $line = substr ( $line , 1 );
- }
-
+ else if ( $first_chars === '|' || $first_chars === '!' ) {
+ // Which kind of cells are we dealing with
+ $this_tag = 'td';
$line = substr ( $line , 1 );
- if ( $first_character === '!' ) {
+ if ( $first_chars === '!' ) {
$line = str_replace ( '!!' , '||' , $line );
+ $this_tag = 'th';
}
// Split up multiple cells on the same line.
- // FIXME : This can result in improper nesting of tags processed
- // by earlier parser steps, but should avoid splitting up eg
- // attribute values containing literal "||".
$cells = StringUtils::explodeMarkup( '||' , $line );
+ $line = ''; // save memory
- $outLine = '';
+ // decide whether thead to tbody
+ if ( !array_key_exists('type', $current_row) ) {
+ $current_row['type'] = ( $first_chars === '!' ) ? 'thead' : 'tbody' ;
+ } else if( $first_chars === '|' ) {
+ $current_row['type'] = 'tbody';
+ }
// Loop through each table cell
- foreach ( $cells as $cell )
- {
- $previous = '';
- if ( $first_character !== '+' )
- {
- $tr_after = array_pop ( $tr_attributes );
- if ( !array_pop ( $tr_history ) ) {
- $previous = "<tr{$tr_after}>\n";
- }
- array_push ( $tr_history , true );
- array_push ( $tr_attributes , '' );
- array_pop ( $has_opened_tr );
- array_push ( $has_opened_tr , true );
- }
+ foreach ( $cells as $cell ) {
+ // a new cell
+ $current_row[] = array();
+ $current_element =& $this->last($current_row);
- $last_tag = array_pop ( $last_tag_history );
+ $current_element['type'] = $this_tag;
- if ( array_pop ( $td_history ) ) {
- $previous = "</{$last_tag}>{$previous}";
- }
+ $c = $this->getCellAttr($cell , $this_tag);
+ $current_element['content'] = $c[0];
+ if(isset($c[1])) $current_element['attributes'] = $c[1];
+ unset($c);
+ }
+ $output =& $current_element['content'];
+ }
+ else {
+ $output .= "\n" . $outLine;
+ }
+ }
- if ( $first_character === '|' ) {
- $last_tag = 'td';
- } else if ( $first_character === '!' ) {
- $last_tag = 'th';
- } else if ( $first_character === '+' ) {
- $last_tag = 'caption';
- } else {
- $last_tag = '';
- }
+ wfProfileOut( __METHOD__ );
- array_push ( $last_tag_history , $last_tag );
+ return $out;
+ }
- // A cell could contain both parameters and data
- $cell_data = explode ( '|' , $cell , 2 );
- // Bug 553: Note that a '|' inside an invalid link should not
- // be mistaken as delimiting cell parameters
- if ( strpos( $cell_data[0], '[[' ) !== false ) {
- $cell = "{$previous}<{$last_tag}>{$cell}";
- } else if ( count ( $cell_data ) == 1 )
- $cell = "{$previous}<{$last_tag}>{$cell_data[0]}";
- else {
- $attributes = $this->mStripState->unstripBoth( $cell_data[0] );
- $attributes = Sanitizer::fixTagAttributes( $attributes , $last_tag );
- $cell = "{$previous}<{$last_tag}{$attributes}>{$cell_data[1]}";
- }
+ /**
+ * Helper function for doTableStuff() separating the contents of cells from
+ * attributes. Particularly useful as there's a possible bug and this action
+ * is repeated twice.
+ *
+ * @private
+ */
+ function getCellAttr ($cell , $tag_name) {
+ $content = null;
+ $attributes = null;
- $outLine .= $cell;
- array_push ( $td_history , true );
- }
- }
- $out .= $outLine . "\n";
- }
+ $cell = trim ( $cell );
- // Closing open td, tr && table
- while ( count ( $td_history ) > 0 )
- {
- if ( array_pop ( $td_history ) ) {
- $out .= "</td>\n";
- }
- if ( array_pop ( $tr_history ) ) {
- $out .= "</tr>\n";
- }
- if ( !array_pop ( $has_opened_tr ) ) {
- $out .= "<tr><td></td></tr>\n" ;
- }
+ // A cell could contain both parameters and data
+ $cell_data = explode ( '|' , $cell , 2 );
- $out .= "</table>\n";
+ // Bug 553: Note that a '|' inside an invalid link should not
+ // be mistaken as delimiting cell parameters
+ if ( strpos( $cell_data[0], '[[' ) !== false ) {
+ $content = trim ( $cell );
}
+ else if ( count ( $cell_data ) == 1 ) {
+ $content = trim ( $cell_data[0] );
+ }
+ else {
+ $attributes = $this->mStripState->unstripBoth( $cell_data[0] );
+ $attributes = Sanitizer::fixTagAttributes( $attributes , $tag_name );
- // Remove trailing line-ending (b/c)
- if ( substr( $out, -1 ) === "\n" ) {
- $out = substr( $out, 0, -1 );
+ $content = trim ( $cell_data[1] );
}
+ return array($content, $attributes);
+ }
- // special case: don't return empty table
- if( $out === "<table>\n<tr><td></td></tr>\n</table>" ) {
- $out = '';
+
+ /**
+ * Helper function for doTableStuff(). This converts the structured array into html.
+ *
+ * @private
+ */
+ function printTableHtml (&$t) {
+ $r = "\n";
+ $r .= str_repeat( '<dl><dd>' , $t['indent'] );
+ $r .= '<table';
+ $r .= isset($t['attributes']) ? $t['attributes'] : '';
+ $r .= '>';
+ unset($t['attributes']);
+
+ if ( isset($t['caption']) ) {
+ $r .= "\n<caption";
+ $r .= isset($t['caption']['attributes']) ? $t['caption']['attributes'] : '';
+ $r .= '>';
+ $r .= $t['caption']['content'];
+ $r .= '</caption>';
}
+ unset($t['caption']);
- wfProfileOut( __METHOD__ );
+ $last_section = '';
+ for($i = 0; isset($t[$i]); $i++ ) {
+ if( $t[$i]['type'] != $last_section ) {
+ $r .= '<' . $t[$i]['type'] . '>';
+ }
- return $out;
+ $r .= "\n<tr";
+ $r .= isset($t[$i]['attributes']) ? $t[$i]['attributes'] : '';
+ $r .= '>';
+ for($j = 0; isset($t[$i][$j]); $j++ ) {
+ $r .= '<' . $t[$i][$j]['type'];
+ $r .= isset($t[$i][$j]['attributes']) ? $t[$i][$j]['attributes'] : '';
+ $r .= '>';
+
+ $r .= $t[$i][$j]['content'];
+
+ $r .= '</' . $t[$i][$j]['type'] . '>';
+ unset($t[$i][$j]);
+ }
+ $r .= '</tr>';
+
+ if( !isset($t[$i+1]) || ( isset($t[$i+1]) && ($t[$i]['type'] != $t[$i+1]['type'])) ) {
+ $r .= '</' . $t[$i]['type'] . '>';
+ }
+ $last_section = $t[$i]['type'];
+ unset($t[$i]);
+ }
+
+ $r .= "\n</table>";
+ $r .= str_repeat( '</dd></dl>' , $t['indent'] );
+ unset($t);
+
+ return $r;
}
/**
+ * like end() but only works on the numeric array index and php's internal pointers
+ * returns a reference to the last element of an array much like "\$arr[-1]" in perl
+ * ignores associative elements and will create a 0 key will a NULL value if there were
+ * no numric elements and an array itself if not previously defined.
+ *
+ * @private
+ */
+ function &last (&$arr) {
+ for($i = count($arr); (!isset($arr[$i]) && $i > 0); $i--) { }
+ return $arr[$i];
+ }
+
+ /**
* Helper function for parse() that transforms wiki markup into
* HTML. Only called for $mOutputType == self::OT_HTML.
*

File Metadata

Mime Type
text/x-diff
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2155
Default Alt Text
diff.txt (13 KB)

Event Timeline