diff --git a/src/IDF/Diff.php b/src/IDF/Diff.php index 501b2b1..8f10e7f 100644 --- a/src/IDF/Diff.php +++ b/src/IDF/Diff.php @@ -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".''."\n"; - $out .= ''."\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(''."\n", $line[0], $line[1], $class, $pretty, $line_content); + + $offsets[] = sprintf('', $left, $right); + $content = Pluf_esc($content); + $content = self::makeNonPrintableCharsVisible($content); + $contents[] = sprintf('', $class, $pretty, $content); + + $maxlinenum = max($maxlinenum, max($left, $right)); + } + if (count($file['chunks']) > $cc) { + $offsets[] = ''; + $contents[] = ''; } - if (count($file['chunks']) > $cc) - $out .= ''."\n"; $cc++; } - $out .= '
'.Pluf_esc($filename).'
%s%s%s
%s%s%s...... 
...... 
'; + + $inner = '' ."\n". + '' . + implode(''."\n".'', $contents) . + '' ."\n". + '
' ."\n"; + + $rows = count($offsets); + $colwidth = (ceil(log10($maxlinenum)) + 1) * 10; + $first = array_shift($offsets); + + $out .= '' ."\n". + '' ."\n". + ''. + ''. + '' ."\n". + '' . + $first . sprintf('', $rows, $inner) . + '' ."\n". + '' . + implode(''."\n".'', $offsets) . + '' ."\n". + '
'.Pluf_esc($filename).'
%s
' ."\n"; } + return Pluf_Template::markSafe($out); } private static function makeNonPrintableCharsVisible($line) { - return preg_replace('/([^[:print:]])/e', + return preg_replace('/([^[:print:]\t])/e', '"".bin2hex("\\1").""', $line); } diff --git a/www/media/idf/css/style.css b/www/media/idf/css/style.css index 98f0b1f..08371e9 100644 --- a/www/media/idf/css/style.css +++ b/www/media/idf/css/style.css @@ -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 */