Skip to content

Instantly share code, notes, and snippets.

@scharan
Created October 10, 2011 06:12
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scharan/1274726 to your computer and use it in GitHub Desktop.
Save scharan/1274726 to your computer and use it in GitHub Desktop.
JS & CSS to display 'side-by-side' diff for Gitweb.
// See http://saicharan.in/blog/2011/10/09/gitweb-with-sidebyside-diff/
$(document).ready(function() {
// Assumption: rem for left file, add for right file.
// => This follows from the assumption that additions
// are possible only for the right file.
$(".patch").each( function( name ) {
$.divp = $('<div/>', { class: "patch", id: $(this).attr('id') }); // div patch
$.diva = $('<div/>', { class: "patch a", id: $(this).attr('id')+'-a' }); // div for left file
$.divb = $('<div/>', { class: "patch b", id: $(this).attr('id')+'-b' }); // div for right file
$.divn = $('<div/>', { class: "no-exist" }).html('&#160;'); // div for non-existent lines
// Insert &nbsp; This seems to be the only way this works
$.diva_count = 0;
$.divb_count = 0;
$.diff_prev = 'none';
$.adjustDiff = function() {
if( $.diff_prev.match(/^add$/) || $.diff_prev.match(/^rem$/) ) {
if( $.diva_count - $.divb_count < 0 ) {
for(i=0; i<$.divb_count-$.diva_count; i++) {
$.diva.append($.divn.clone());
}
} else if( $.diva_count - $.divb_count > 0 ) {
for(i=0; i<$.diva_count-$.divb_count; i++) {
$.divb.append($.divn.clone());
}
}
$.diva_count = 0;
}
}
// If div class is 'diff rem', append to left
// If div class is 'diff add', append to right
// if div class is simply 'diff', append to both.
// Hunks have - & + lines.
$(this).children().each( function(name, value){
if( $(this).attr("class").match(/^diff$/) ) { // Plain block: Add to both sides
$.adjustDiff();
$.divb_count = 0;
$.diva.append($(this));
$.divb.append($(this).clone());
$.diff_prev = 'none';
} else if( $(this).attr("class").match(/^diff chunk_header$/) ) { // chunk header
$.diva.append($(this));
$.divb.append($(this).clone());
$.diff_prev = 'none';
} else if( $(this).attr("class").match(/^diff rem$/) ) { // Remove block
if( $.diff_prev.match(/^add$/) ){
$.adjustDiff();
}
$.diva.append($(this));
$.diva_count++;
$.diff_prev = 'rem';
} else if( $(this).attr("class").match(/^diff add$/) ) { // Add block
$.divb.append($(this));
if( $.diff_prev.match(/^rem$/) ) {
$.divb_count = 0;
}
$.divb_count++;
$.diff_prev = 'add';
} else { // Not part of diff, but of preamble.
$.divp.append($(this));
$.diff_prev = 'none';
}
});
$.adjustDiff(); // Cleanup, when necessary
$.divp.append( $.diva ); // Append diva, divb to divp
$.divp.append( $.divb );
$(this).replaceWith($.divp); // Replace this with divp
// Iterating thru' all .patch divs again. Can be refactored.
$(".patch").filter(function() { // Enable simultaneous scroll
return this.id.match(/patch[1-9]+-./);
}).each( function() {
var ids = this.id.match(/patch([1-9]+)-(.)/);
var otherdiv = ( ids[2].match(/^a$/) ? "b" : "a" );
var scrollid = "#patch" + ids[1] + "-" + otherdiv;
$(this).scroll( function() {
$(scrollid).scrollLeft( $(this).scrollLeft() );
});
});
});
});
/* Append this to gitweb-HOME/static/gitweb.css, or insert it using JS */
div.patch.a {
width: 50%;
overflow-y: hidden;
overflow-x: auto;
padding-bottom: 10px;
position: relative;
float: left;
clear: both;
}
div.patch.b {
width: 50%;
overflow-y: hidden;
overflow-x: auto;
padding-bottom: 10px;
position: relative;
float: right;
clear: right;
}
div.patch {
clear: both;
}
div.page_footer {
clear: both;
}
div.diff.add {
background-color: #F6F9ED;
}
div.diff.rem {
background-color: #FEF1E9;
}
div.no-exist {
background-color: #EBECE4;
width: 100%;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment