Fixed rendering in Firefox which did, unlike Chrome, not expand the last

row's height to fit the up-popping horizontal scrollbar, but all rows
just a little, so the heights did not match. I've reworked this to not
used the ill-advised rowspan any longer, but two separate tables whose
heights match each other now in both browsers.

Also I fixed a bug in the whitespace detection code - utf8 characters
where broken into single bytes, so apparently the [:print:] character
class does not accout for them, even in //u mode, so we're selecting
the characters that we want to make visible on our own (basically
control characters lower than space, I might add more).
This commit is contained in:
Thomas Keller 2011-10-09 00:13:34 +02:00
parent c84afd0f78
commit 2e0995abac
2 changed files with 161 additions and 156 deletions

View File

@ -183,57 +183,61 @@ class IDF_Diff
foreach ($chunk as $line) { foreach ($chunk as $line) {
list($left, $right, $content) = $line; list($left, $right, $content) = $line;
if ($left and $right) { if ($left and $right) {
$class = 'diff diff-c'; $class = 'context';
} elseif ($left) { } elseif ($left) {
$class = 'diff diff-r'; $class = 'removed';
} else { } else {
$class = 'diff diff-a'; $class = 'added';
} }
$offsets[] = sprintf('<td class="diff-lc">%s</td><td class="diff-lc">%s</td>', $left, $right); $offsets[] = sprintf('<td>%s</td><td>%s</td>', $left, $right);
$content = Pluf_esc($content); $content = Pluf_esc($content);
$content = self::makeNonPrintableCharsVisible($content); $content = self::makeNonPrintableCharsVisible($content);
$contents[] = sprintf('<td class="%s%s mono">%s</td>', $class, $pretty, $content); $contents[] = sprintf('<td class="%s%s mono">%s</td>', $class, $pretty, $content);
} }
if (count($file['chunks']) > $cc) { if (count($file['chunks']) > $cc) {
$offsets[] = '<td class="next">...</td><td class="next">...</td>'; $offsets[] = '<td class="next">...</td><td class="next">...</td>';
$contents[] = '<td class="next">&nbsp;</td>'; $contents[] = '<td class="next"></td>';
} }
$cc++; $cc++;
} }
$inner = '<table class="diff-content">' ."\n".
'<tr class="diff-line">' .
implode('</tr>'."\n".'<tr class="diff-line">', $contents) .
'</tr>' ."\n".
'</table>' ."\n";
$rows = count($offsets);
list($added, $removed) = end($file['chunks_def']); list($added, $removed) = end($file['chunks_def']);
$added = $added[0] + $added[1]; $added = $added[0] + $added[1];
$leftwidth = 1; $leftwidth = 1;
if ($added > 0) if ($added > 0)
$leftwidth = (ceil(log10($added)) + 1) * 10; $leftwidth = ((ceil(log10($added)) + 1) * 8) + 12;
$removed = $removed[0] + $removed[1]; $removed = $removed[0] + $removed[1];
$rightwidth = 1; $rightwidth = 1;
if ($removed > 0) if ($removed > 0)
$rightwidth = (ceil(log10($removed)) + 1) * 10; $rightwidth = ((ceil(log10($removed)) + 1) * 8) + 12;
$first = array_shift($offsets); $inner_linecounts =
'<table class="diff-linecounts">' ."\n".
'<colgroup><col width="'.$leftwidth.'" /><col width="'. $rightwidth.'" /></colgroup>' ."\n".
'<tr class="line">' .
implode('</tr>'."\n".'<tr class="line">', $offsets).
'</tr>' ."\n".
'</table>' ."\n";
$out .= '<table class="diff" summary="">' ."\n".
'<colgroup><col width="'.$leftwidth.'" /><col width="'.$rightwidth.'" /><col width="*" /></colgroup>' ."\n". $inner_contents =
'<table class="diff-contents">' ."\n".
'<tr class="line">' .
implode('</tr>'."\n".'<tr class="line">', $contents) .
'</tr>' ."\n".
'</table>' ."\n";
$out .= '<table class="diff">' ."\n".
'<colgroup><col width="'.($leftwidth + $rightwidth + 1).'" /><col width="*" /></colgroup>' ."\n".
'<tr id="diff-'.md5($filename).'">'. '<tr id="diff-'.md5($filename).'">'.
'<th colspan="3">'.Pluf_esc($filename).'</th>'. '<th colspan="2">'.Pluf_esc($filename).'</th>'.
'</tr>' ."\n". '</tr>' ."\n".
'<tr class="line">' . '<tr>' .
$first . sprintf('<td rowspan="%d"><div class="diff-content">%s</div></td>', $rows, $inner) . '<td>'. $inner_linecounts .'</td>'. "\n".
'</tr>' ."\n". '<td><div class="scroll">'. $inner_contents .'</div></td>'.
'<tr class="line">' .
implode('</tr>'."\n".'<tr class="line">', $offsets) .
'</tr>' ."\n". '</tr>' ."\n".
'</table>' ."\n"; '</table>' ."\n";
} }
@ -243,7 +247,7 @@ class IDF_Diff
private static function makeNonPrintableCharsVisible($line) private static function makeNonPrintableCharsVisible($line)
{ {
return preg_replace('/([^[:print:]\t])/e', return preg_replace('/([\x00-\x1F])/ue',
'"<span class=\"non-printable\" title=\"0x".strtoupper(bin2hex("\\1"))."\">".bin2hex("\\1")."</span>"', '"<span class=\"non-printable\" title=\"0x".strtoupper(bin2hex("\\1"))."\">".bin2hex("\\1")."</span>"',
$line); $line);
} }

View File

@ -572,41 +572,39 @@ table.commit table.changes table.properties td.removed {
* syntax highlighting of diffs * syntax highlighting of diffs
*/ */
table.diff { table.diff {
border-bottom: 1px solid #d3d7cf;
width: 100%; width: 100%;
table-layout: fixed; table-layout: fixed;
} }
table.diff td {
border: none;
vertical-align: top;
padding: 0;
}
table.diff > tbody > tr > td + td {
border-right: 1px solid #d3d7cf;
}
table.diff th { table.diff th {
background-color: #e4e8E0; background-color: #e4e8E0;
vertical-align: top; vertical-align: top;
border-color: #d3d7cf; border-color: #d3d7cf;
} }
table.diff div.scroll {
table.diff tr.line {
border: 1px solid #d3d7cf;
}
table.diff tr.line td.diff-lc {
font-size: 90%;
padding: 1px 10px;
text-align: right;
width: 20px;
}
table.diff tr.line div.diff-content {
overflow: auto; overflow: auto;
display: block;
} }
table.diff td { table.diff-contents td,
table.diff-linecounts td {
vertical-align: top; vertical-align: top;
border-color: inherit; border-color: inherit;
padding: 0; padding: 0;
} }
table.diff td.next { table.diff-contents td.next,
table.diff-linecounts td.next {
background-color: #e4e8E0; background-color: #e4e8E0;
vertical-align: top; vertical-align: top;
text-align: right; text-align: right;
@ -614,16 +612,37 @@ table.diff td.next {
padding: 1px 10px; padding: 1px 10px;
} }
table.diff-content { table.diff-linecounts {
border: 0;
/* setting this to 100% sometimes triggers the overflow of the parent container,
when it is not actually needed. we try to prevent that by taking not the
complete available space... */
width: 99.99%;
margin: 0; margin: 0;
} }
table.diff-content td.diff { table.diff-contents {
border-bottom: 1px solid #d3d7cf;
width: 100%;
margin: 0;
}
table.diff-linecounts tr,
table.diff-contents tr {
height: 18px;
}
table.diff-linecounts tr {
border: 1px solid #d3d7cf;
}
table.diff-linecounts tr:first-child {
border-top: 0px;
}
table.diff-linecounts td {
font-size: 90%;
padding: 1px 10px;
text-align: right;
border-left: 1px solid #d3d7cf;
}
table.diff-contents td {
line-height: 12px; line-height: 12px;
padding: 2px; padding: 2px;
font-size: 90%; font-size: 90%;
@ -631,15 +650,15 @@ table.diff-content td.diff {
white-space: pre; white-space: pre;
} }
table.diff-content td.diff-a { table.diff-contents td.added {
background-color: #dfd; background-color: #dfd;
} }
table.diff-content td.diff-r { table.diff-contents td.removed {
background-color: #fdd; background-color: #fdd;
} }
table.diff-content td.diff > span.non-printable { table.diff-contents td > span.non-printable {
visibility: hidden; visibility: hidden;
color: white; color: white;
text-transform: uppercase; text-transform: uppercase;
@ -657,44 +676,27 @@ table.diff-content td.diff > span.non-printable {
vertical-align: 10%; vertical-align: 10%;
} }
table.diff-content td.diff:hover > span.non-printable { table.diff-contents td:hover > span.non-printable {
visibility: visible; visibility: visible;
} }
table.diff-content td.diff-a > span.non-printable { table.diff-contents td.added > span.non-printable {
background: #0A0; background: #0A0;
} }
table.diff-content td.diff-r > span.non-printable { table.diff-contents td.removed > span.non-printable {
background: #A00; background: #A00;
} }
table.diff-content td.diff-c > span.non-printable { table.diff-contents td.context > span.non-printable {
background: black; background: black;
} }
/* override prettify css rule */ /* override prettify css rule */
table.diff-content td.diff > span.non-printable > * { table.diff-contents td > span.non-printable > * {
color: white; color: white;
} }
/*
This is a special hack: the outer td.next has
top/bottom border and padding and comes to a total
height of 20px - BUT it shares the upper border
with the previous row, so the height is actually
only 19px. The inner table has no lines between rows,
so the upper border is counted and we have 20px
in the interior, which is one pixel too much for
every occurrence.
What we now do is to remove the 1px top padding and
therefor lower the total height of the inner one
again by one to match the outer.
*/
table.diff-content td.next {
padding-top: 0;
}
/** /**
* view file content * view file content
*/ */
@ -1210,4 +1212,3 @@ table.issue-summary td.graph-color {
table.issue-summary td.graph-percent { table.issue-summary td.graph-percent {
padding-left: 1em; padding-left: 1em;
} }