Change the unidiff rendering by letting the actual content be rendered
into a separate container that can overflow and side-scroll for long lines. This effectively removes the need for all kinds of line-breaking hacks that have been applied before and only worked when the browser was actually able to break a word group apart somewhere. Lines are now always rendered as-is; as a nice side effect the line numbers are always visible, independently how far one scrolled into one direction, so the context is always clear. If the rendering area is made smaller, the table rendering also degrades gracefully and provides horizontal scrolling for views that did not need them before. The size that is occupied by the number display is now also automatically determined by the size that is needed to render the biggest line number in a column. Empty columns are rendered with a zero size. Currently all this works nicely with a recent version of Chrome, Firefox still needs some fine tuning for the vertical positioning. Other browsers are untested as of now.
This commit is contained in:
parent
83761c66c5
commit
f19f07ec59
@ -168,41 +168,73 @@ class IDF_Diff
|
||||
public function as_html()
|
||||
{
|
||||
$out = '';
|
||||
foreach ($this->files as $filename=>$file) {
|
||||
foreach ($this->files as $filename => $file) {
|
||||
$pretty = '';
|
||||
$fileinfo = IDF_FileUtil::getMimeType($filename);
|
||||
if (IDF_FileUtil::isSupportedExtension($fileinfo[2])) {
|
||||
$pretty = ' prettyprint';
|
||||
}
|
||||
$out .= "\n".'<table class="diff" summary="">'."\n";
|
||||
$out .= '<tr id="diff-'.md5($filename).'"><th colspan="3">'.Pluf_esc($filename).'</th></tr>'."\n";
|
||||
|
||||
$cc = 1;
|
||||
$offsets = array();
|
||||
$contents = array();
|
||||
$maxlinenum = 0;
|
||||
|
||||
foreach ($file['chunks'] as $chunk) {
|
||||
foreach ($chunk as $line) {
|
||||
if ($line[0] and $line[1]) {
|
||||
list($left, $right, $content) = $line;
|
||||
if ($left and $right) {
|
||||
$class = 'diff diff-c';
|
||||
} elseif ($line[0]) {
|
||||
} elseif ($left) {
|
||||
$class = 'diff diff-r';
|
||||
} else {
|
||||
$class = 'diff diff-a';
|
||||
}
|
||||
$line_content = Pluf_esc($line[2]);
|
||||
$line_content = preg_replace("/\t/", " ", $line_content);
|
||||
$line_content = self::makeNonPrintableCharsVisible($line_content);
|
||||
$out .= sprintf('<tr class="diff-line"><td class="diff-lc">%s</td><td class="diff-lc">%s</td><td class="%s%s mono">%s</td></tr>'."\n", $line[0], $line[1], $class, $pretty, $line_content);
|
||||
|
||||
$offsets[] = sprintf('<td class="diff-lc">%s</td><td class="diff-lc">%s</td>', $left, $right);
|
||||
$content = Pluf_esc($content);
|
||||
$content = self::makeNonPrintableCharsVisible($content);
|
||||
$contents[] = sprintf('<td class="%s%s mono">%s</td>', $class, $pretty, $content);
|
||||
|
||||
$maxlinenum = max($maxlinenum, max($left, $right));
|
||||
}
|
||||
if (count($file['chunks']) > $cc) {
|
||||
$offsets[] = '<td class="next">...</td><td class="next">...</td>';
|
||||
$contents[] = '<td class="next"> </td>';
|
||||
}
|
||||
if (count($file['chunks']) > $cc)
|
||||
$out .= '<tr class="diff-next"><td>...</td><td>...</td><td> </td></tr>'."\n";
|
||||
$cc++;
|
||||
}
|
||||
$out .= '</table>';
|
||||
|
||||
$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);
|
||||
$colwidth = (ceil(log10($maxlinenum)) + 1) * 10;
|
||||
$first = array_shift($offsets);
|
||||
|
||||
$out .= '<table class="diff" summary="">' ."\n".
|
||||
'<colgroup><col width="'.$colwidth.'" /><col width="'.$colwidth.'" /><col width="*" /></colgroup>' ."\n".
|
||||
'<tr id="diff-'.md5($filename).'">'.
|
||||
'<th colspan="3">'.Pluf_esc($filename).'</th>'.
|
||||
'</tr>' ."\n".
|
||||
'<tr class="line">' .
|
||||
$first . sprintf('<td rowspan="%d"><div class="diff-content">%s</div></td>', $rows, $inner) .
|
||||
'</tr>' ."\n".
|
||||
'<tr class="line">' .
|
||||
implode('</tr>'."\n".'<tr class="line">', $offsets) .
|
||||
'</tr>' ."\n".
|
||||
'</table>' ."\n";
|
||||
}
|
||||
|
||||
return Pluf_Template::markSafe($out);
|
||||
}
|
||||
|
||||
private static function makeNonPrintableCharsVisible($line)
|
||||
{
|
||||
return preg_replace('/([^[:print:]])/e',
|
||||
return preg_replace('/([^[:print:]\t])/e',
|
||||
'"<span class=\"non-printable\" title=\"0x".strtoupper(bin2hex("\\1"))."\">".bin2hex("\\1")."</span>"',
|
||||
$line);
|
||||
}
|
||||
|
@ -574,6 +574,7 @@ table.commit table.changes table.properties td.removed {
|
||||
table.diff {
|
||||
border-bottom: 1px solid #d3d7cf;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
table.diff th {
|
||||
@ -583,45 +584,63 @@ table.diff th {
|
||||
}
|
||||
|
||||
|
||||
table.diff tr {
|
||||
border-left: 1px solid #d3d7cf;
|
||||
border-right: 1px solid #d3d7cf;
|
||||
border-bottom: none;
|
||||
border-top: none;
|
||||
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;
|
||||
display: block;
|
||||
}
|
||||
|
||||
table.diff td {
|
||||
font-size: 90%;
|
||||
vertical-align: top;
|
||||
padding: 1px;
|
||||
border-color: inherit;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table.diff td.diff-lc {
|
||||
table.diff td.next {
|
||||
background-color: #e4e8E0;
|
||||
vertical-align: top;
|
||||
text-align: right;
|
||||
padding: 1px 5px;
|
||||
border-color: inherit;
|
||||
border-top: 1px solid #d3d7cf;
|
||||
border-bottom: 1px solid #d3d7cf;
|
||||
width: 3em;
|
||||
border-color: #d3d7cf;
|
||||
padding: 1px 10px;
|
||||
}
|
||||
|
||||
td.diff-a {
|
||||
table.diff-content {
|
||||
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;
|
||||
}
|
||||
|
||||
table.diff-content td.diff {
|
||||
line-height: 12px;
|
||||
padding: 2px;
|
||||
font-size: 90%;
|
||||
border: none;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
table.diff-content td.diff-a {
|
||||
background-color: #dfd;
|
||||
}
|
||||
|
||||
td.diff-r {
|
||||
table.diff-content td.diff-r {
|
||||
background-color: #fdd;
|
||||
}
|
||||
|
||||
td.diff {
|
||||
border-bottom: none;
|
||||
border-top: none;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
td.diff > span.non-printable {
|
||||
visibility: hidden;
|
||||
table.diff-content td.diff > span.non-printable {
|
||||
visibility: hidden;
|
||||
color: white;
|
||||
text-transform: uppercase;
|
||||
float: none;
|
||||
@ -638,39 +657,44 @@ td.diff > span.non-printable {
|
||||
vertical-align: 10%;
|
||||
}
|
||||
|
||||
td.diff:hover > span.non-printable {
|
||||
visibility: visible;
|
||||
table.diff-content td.diff:hover > span.non-printable {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
td.diff-a > span.non-printable {
|
||||
background: #0A0;
|
||||
table.diff-content td.diff-a > span.non-printable {
|
||||
background: #0A0;
|
||||
}
|
||||
|
||||
td.diff-r > span.non-printable {
|
||||
background: #A00;
|
||||
table.diff-content td.diff-r > span.non-printable {
|
||||
background: #A00;
|
||||
}
|
||||
|
||||
td.diff-c > span.non-printable {
|
||||
background: black;
|
||||
table.diff-content td.diff-c > span.non-printable {
|
||||
background: black;
|
||||
}
|
||||
|
||||
/* override prettify css rule */
|
||||
td.diff > span.non-printable > * {
|
||||
color: white;
|
||||
table.diff-content td.diff > span.non-printable > * {
|
||||
color: white;
|
||||
}
|
||||
|
||||
table.diff tr.diff-next {
|
||||
background-color: #e4e8E0;
|
||||
vertical-align: top;
|
||||
text-align: right;
|
||||
border-color: #d3d7cf;
|
||||
/*
|
||||
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;
|
||||
}
|
||||
|
||||
table.diff tr.diff-next td {
|
||||
padding: 1px 5px;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* view file content
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user