diff --git a/diff2html.js b/diff2html.js index e6365df..d0268d4 100644 --- a/diff2html.js +++ b/diff2html.js @@ -3,7 +3,7 @@ * Diff to HTML (diff2html.js) * Author: rtfpessoa * Date: Friday 29 August 2014 - * Last Update: Saturday 27 September 2014 + * Last Update: Saturday 24 January 2015 * * Diff command: * git diff @@ -77,14 +77,17 @@ }; var saveFile = function () { - /* add previous file(if exists) before start a new one */ - if (currentFile) { + /* + * add previous file(if exists) before start a new one + * if it has name (to avoid binary files errors) + */ + if (currentFile && currentFile.newName) { files.push(currentFile); currentFile = null; } }; - var startFile = function (line) { + var startFile = function () { saveBlock(); saveFile(); @@ -93,24 +96,17 @@ currentFile.blocks = []; currentFile.deletedLines = 0; currentFile.addedLines = 0; - - /* save file paths, before and after the diff */ - var values = /^diff --git a\/(\S+) b\/(\S+).*$/.exec(line); - currentFile.oldName = values[1]; - currentFile.newName = values[2]; }; var startBlock = function (line) { saveBlock(); - var values; - if (values = /^(@@ -(\d+),(\d+) \+(\d+),(\d+) @@).*/.exec(line)) { - oldLine = values[2]; - newLine = values[4]; - } else { - oldLine = 0; - newLine = 0; - } + var values = /^@@ -(\d+),\d+ \+(\d+),\d+ @@.*/.exec(line) || + /^@@@ -(\d+),\d+ -\d+,\d+ \+(\d+),\d+ @@@.*/.exec(line) || + [0, 0, 0]; + + oldLine = values[1]; + newLine = values[2]; /* create block metadata */ currentBlock = {}; @@ -125,7 +121,7 @@ currentLine.content = line; /* fill the line data */ - if (startsWith(line, "+")) { + if (startsWith(line, "+") || startsWith(line, " +")) { currentFile.addedLines++; currentLine.type = LINE_TYPE.INSERTS; @@ -134,7 +130,7 @@ currentBlock.lines.push(currentLine); - } else if (startsWith(line, "-")) { + } else if (startsWith(line, "-") || startsWith(line, " -")) { currentFile.deletedLines++; currentLine.type = LINE_TYPE.DELETES; @@ -158,13 +154,17 @@ // https://github.com/scottgonzalez/pretty-diff/issues/11 // Also, remove some useless lines if (!line || startsWith(line, "*") || - startsWith(line, "new") || startsWith(line, "index") || - startsWith(line, "---") || startsWith(line, "+++")) { + startsWith(line, "new") || startsWith(line, "index")) { return; } + var values = []; if (startsWith(line, "diff")) { - startFile(line); + startFile(); + } else if (currentFile && !currentFile.oldName && (values = /^--- a\/(\S+).*$/.exec(line))) { + currentFile.oldName = values[1]; + } else if (currentFile && !currentFile.newName && (values = /^\+\+\+ b\/(\S+).*$/.exec(line))) { + currentFile.newName = values[1]; } else if (currentFile && startsWith(line, "@@")) { startBlock(line); } else if (currentBlock) { @@ -237,7 +237,7 @@ var diff = diffHighlight(escapedLine, nextEscapedLine); lines += generateLineHtml(line.type, line.oldNumber, line.newNumber, diff.o) + - generateLineHtml(newLine.type, newLine.oldNumber, newLine.newNumber, diff.n); + generateLineHtml(newLine.type, newLine.oldNumber, newLine.newNumber, diff.n); i++; } else { @@ -311,18 +311,18 @@ file.blocks.forEach(function (block) { fileHtml.left += "\n" + - " \n" + - " " + - "
" + escape(block.header) + "
" + - " \n" + - "\n"; + " \n" + + " " + + "
" + escape(block.header) + "
" + + " \n" + + "\n"; fileHtml.right += "\n" + - " \n" + - " " + - "
" + - " \n" + - "\n"; + " \n" + + " " + + "
" + + " \n" + + "\n"; for (var i = 0; i < block.lines.length; i++) { var prevLine = block.lines[i - 1]; @@ -363,7 +363,7 @@ }; var generateSingleLineHtml = function (type, number, content) { - return"\n" + + return "\n" + " " + number + "\n" + " " + "
" + content + "
" + @@ -376,7 +376,15 @@ */ var getDiffName = function (oldFilename, newFilename) { - return oldFilename === newFilename ? newFilename : oldFilename + " -> " + newFilename; + if (oldFilename && newFilename && oldFilename !== newFilename) { + return oldFilename + " -> " + newFilename; + } else if (newFilename) { + return newFilename; + } else if (oldFilename) { + return oldFilename; + } else { + return "Unknown filename"; + } }; var removeIns = function (line) { diff --git a/diff2html.min.js b/diff2html.min.js index 164e953..9071c99 100644 --- a/diff2html.min.js +++ b/diff2html.min.js @@ -1 +1 @@ -!function(window){var ClassVariable;return ClassVariable=function(){function Diff2Html(){}function escape(str){return str.slice(0).replace(/&/g,"&").replace(//g,">").replace(/\t/g," ")}function startsWith(str,start){return 0===str.indexOf(start)}function valueOrEmpty(value){return value?value:""}function diffHighlight(diffLine1,diffLine2){var highlightedLine=diffString(diffLine1.substr(1),diffLine2.substr(1));return{o:diffLine1.charAt(0)+removeIns(highlightedLine),n:diffLine2.charAt(0)+removeDel(highlightedLine)}}var LINE_TYPE={INSERTS:"d2h-ins",DELETES:"d2h-del",CONTEXT:"d2h-cntx",INFO:"d2h-info"};Diff2Html.prototype.getPrettyHtmlFromDiff=function(diffInput){var diffJson=generateDiffJson(diffInput);return generateJsonHtml(diffJson)},Diff2Html.prototype.getJsonFromDiff=function(diffInput){return generateDiffJson(diffInput)},Diff2Html.prototype.getPrettyHtmlFromJson=function(diffJson){return generateJsonHtml(diffJson)},Diff2Html.prototype.getPrettySideBySideHtmlFromDiff=function(diffInput){var diffJson=generateDiffJson(diffInput);return generateSideBySideJsonHtml(diffJson)},Diff2Html.prototype.getPrettySideBySideHtmlFromJson=function(diffJson){return generateSideBySideJsonHtml(diffJson)};var instance,generateDiffJson=function(diffInput){var files=[],currentFile=null,currentBlock=null,oldLine=null,newLine=null,saveBlock=function(){currentBlock&&(currentFile.blocks.push(currentBlock),currentBlock=null)},saveFile=function(){currentFile&&(files.push(currentFile),currentFile=null)},startFile=function(line){saveBlock(),saveFile(),currentFile={},currentFile.blocks=[],currentFile.deletedLines=0,currentFile.addedLines=0;var values=/^diff --git a\/(\S+) b\/(\S+).*$/.exec(line);currentFile.oldName=values[1],currentFile.newName=values[2]},startBlock=function(line){saveBlock();var values;(values=/^(@@ -(\d+),(\d+) \+(\d+),(\d+) @@).*/.exec(line))?(oldLine=values[2],newLine=values[4]):(oldLine=0,newLine=0),currentBlock={},currentBlock.lines=[],currentBlock.oldStartLine=oldLine,currentBlock.newStartLine=newLine,currentBlock.header=line},createLine=function(line){var currentLine={};currentLine.content=line,startsWith(line,"+")?(currentFile.addedLines++,currentLine.type=LINE_TYPE.INSERTS,currentLine.oldNumber=null,currentLine.newNumber=newLine++,currentBlock.lines.push(currentLine)):startsWith(line,"-")?(currentFile.deletedLines++,currentLine.type=LINE_TYPE.DELETES,currentLine.oldNumber=oldLine++,currentLine.newNumber=null,currentBlock.lines.push(currentLine)):(currentLine.type=LINE_TYPE.CONTEXT,currentLine.oldNumber=oldLine++,currentLine.newNumber=newLine++,currentBlock.lines.push(currentLine))},diffLines=diffInput.split("\n");return diffLines.forEach(function(line){!line||startsWith(line,"*")||startsWith(line,"new")||startsWith(line,"index")||startsWith(line,"---")||startsWith(line,"+++")||(startsWith(line,"diff")?startFile(line):currentFile&&startsWith(line,"@@")?startBlock(line):currentBlock&&createLine(line))}),saveBlock(),saveFile(),files},generateJsonHtml=function(diffFiles){return'
\n'+diffFiles.map(function(file){return'
\n
\n
\n +'+file.addedLines+'\n -'+file.deletedLines+'\n
\n
'+getDiffName(file.oldName,file.newName)+'
\n
\n
\n
\n \n \n '+generateFileHtml(file)+" \n
\n
\n
\n
\n"}).join("\n")+"
\n"},generateFileHtml=function(file){return file.blocks.map(function(block){for(var lines='\n \n
'+escape(block.header)+"
\n\n",i=0;i\n
'+valueOrEmpty(oldNumber)+'
'+valueOrEmpty(newNumber)+'
\n
'+content+"
\n\n"},generateSideBySideJsonHtml=function(diffFiles){return'
\n'+diffFiles.map(function(file){var diffs=generateSideBySideFileHtml(file);return'
\n
\n
\n +'+file.addedLines+'\n -'+file.deletedLines+'\n
\n
'+getDiffName(file.oldName,file.newName)+'
\n
\n
\n
\n
\n \n \n '+diffs.left+' \n
\n
\n
\n
\n
\n \n \n '+diffs.right+" \n
\n
\n
\n
\n
\n"}).join("\n")+"
\n"},generateSideBySideFileHtml=function(file){var fileHtml={};return fileHtml.left="",fileHtml.right="",file.blocks.forEach(function(block){fileHtml.left+='\n \n
'+escape(block.header)+"
\n\n",fileHtml.right+='\n \n
\n\n';for(var i=0;i\n '+number+'\n
'+content+"
\n \n"},getDiffName=function(oldFilename,newFilename){return oldFilename===newFilename?newFilename:oldFilename+" -> "+newFilename},removeIns=function(line){return line.replace(/(((.|\n)*?)<\/ins>)/g,"")},removeDel=function(line){return line.replace(/(((.|\n)*?)<\/del>)/g,"")};return{getInstance:function(){return void 0===instance&&(instance=new Diff2Html,instance.constructor=null),instance}}}(),window.Diff2Html=ClassVariable.getInstance(),window.Diff2Html}(window); \ No newline at end of file +!function(window){var ClassVariable;return ClassVariable=function(){function Diff2Html(){}function escape(str){return str.slice(0).replace(/&/g,"&").replace(//g,">").replace(/\t/g," ")}function startsWith(str,start){return 0===str.indexOf(start)}function valueOrEmpty(value){return value?value:""}function diffHighlight(diffLine1,diffLine2){var highlightedLine=diffString(diffLine1.substr(1),diffLine2.substr(1));return{o:diffLine1.charAt(0)+removeIns(highlightedLine),n:diffLine2.charAt(0)+removeDel(highlightedLine)}}var LINE_TYPE={INSERTS:"d2h-ins",DELETES:"d2h-del",CONTEXT:"d2h-cntx",INFO:"d2h-info"};Diff2Html.prototype.getPrettyHtmlFromDiff=function(diffInput){var diffJson=generateDiffJson(diffInput);return generateJsonHtml(diffJson)},Diff2Html.prototype.getJsonFromDiff=function(diffInput){return generateDiffJson(diffInput)},Diff2Html.prototype.getPrettyHtmlFromJson=function(diffJson){return generateJsonHtml(diffJson)},Diff2Html.prototype.getPrettySideBySideHtmlFromDiff=function(diffInput){var diffJson=generateDiffJson(diffInput);return generateSideBySideJsonHtml(diffJson)},Diff2Html.prototype.getPrettySideBySideHtmlFromJson=function(diffJson){return generateSideBySideJsonHtml(diffJson)};var instance,generateDiffJson=function(diffInput){var files=[],currentFile=null,currentBlock=null,oldLine=null,newLine=null,saveBlock=function(){currentBlock&&(currentFile.blocks.push(currentBlock),currentBlock=null)},saveFile=function(){currentFile&¤tFile.newName&&(files.push(currentFile),currentFile=null)},startFile=function(){saveBlock(),saveFile(),currentFile={},currentFile.blocks=[],currentFile.deletedLines=0,currentFile.addedLines=0},startBlock=function(line){saveBlock();var values=/^@@ -(\d+),\d+ \+(\d+),\d+ @@.*/.exec(line)||/^@@@ -(\d+),\d+ -\d+,\d+ \+(\d+),\d+ @@@.*/.exec(line)||[0,0,0];oldLine=values[1],newLine=values[2],currentBlock={},currentBlock.lines=[],currentBlock.oldStartLine=oldLine,currentBlock.newStartLine=newLine,currentBlock.header=line},createLine=function(line){var currentLine={};currentLine.content=line,startsWith(line,"+")||startsWith(line," +")?(currentFile.addedLines++,currentLine.type=LINE_TYPE.INSERTS,currentLine.oldNumber=null,currentLine.newNumber=newLine++,currentBlock.lines.push(currentLine)):startsWith(line,"-")||startsWith(line," -")?(currentFile.deletedLines++,currentLine.type=LINE_TYPE.DELETES,currentLine.oldNumber=oldLine++,currentLine.newNumber=null,currentBlock.lines.push(currentLine)):(currentLine.type=LINE_TYPE.CONTEXT,currentLine.oldNumber=oldLine++,currentLine.newNumber=newLine++,currentBlock.lines.push(currentLine))},diffLines=diffInput.split("\n");return diffLines.forEach(function(line){if(line&&!startsWith(line,"*")&&!startsWith(line,"new")&&!startsWith(line,"index")){var values=[];startsWith(line,"diff")?startFile():currentFile&&!currentFile.oldName&&(values=/^--- a\/(\S+).*$/.exec(line))?currentFile.oldName=values[1]:currentFile&&!currentFile.newName&&(values=/^\+\+\+ b\/(\S+).*$/.exec(line))?currentFile.newName=values[1]:currentFile&&startsWith(line,"@@")?startBlock(line):currentBlock&&createLine(line)}}),saveBlock(),saveFile(),files},generateJsonHtml=function(diffFiles){return'
\n'+diffFiles.map(function(file){return'
\n
\n
\n +'+file.addedLines+'\n -'+file.deletedLines+'\n
\n
'+getDiffName(file.oldName,file.newName)+'
\n
\n
\n
\n \n \n '+generateFileHtml(file)+" \n
\n
\n
\n
\n"}).join("\n")+"
\n"},generateFileHtml=function(file){return file.blocks.map(function(block){for(var lines='\n \n
'+escape(block.header)+"
\n\n",i=0;i\n
'+valueOrEmpty(oldNumber)+'
'+valueOrEmpty(newNumber)+'
\n
'+content+"
\n\n"},generateSideBySideJsonHtml=function(diffFiles){return'
\n'+diffFiles.map(function(file){var diffs=generateSideBySideFileHtml(file);return'
\n
\n
\n +'+file.addedLines+'\n -'+file.deletedLines+'\n
\n
'+getDiffName(file.oldName,file.newName)+'
\n
\n
\n
\n
\n \n \n '+diffs.left+' \n
\n
\n
\n
\n
\n \n \n '+diffs.right+" \n
\n
\n
\n
\n
\n"}).join("\n")+"
\n"},generateSideBySideFileHtml=function(file){var fileHtml={};return fileHtml.left="",fileHtml.right="",file.blocks.forEach(function(block){fileHtml.left+='\n \n
'+escape(block.header)+"
\n\n",fileHtml.right+='\n \n
\n\n';for(var i=0;i\n '+number+'\n
'+content+"
\n \n"},getDiffName=function(oldFilename,newFilename){return oldFilename&&newFilename&&oldFilename!==newFilename?oldFilename+" -> "+newFilename:newFilename?newFilename:oldFilename?oldFilename:"Unknown filename"},removeIns=function(line){return line.replace(/(((.|\n)*?)<\/ins>)/g,"")},removeDel=function(line){return line.replace(/(((.|\n)*?)<\/del>)/g,"")};return{getInstance:function(){return void 0===instance&&(instance=new Diff2Html,instance.constructor=null),instance}}}(),window.Diff2Html=ClassVariable.getInstance(),window.Diff2Html}(window); \ No newline at end of file diff --git a/jsdiff.js b/jsdiff.js index 6362ed8..70792d4 100644 --- a/jsdiff.js +++ b/jsdiff.js @@ -2,6 +2,7 @@ * Javascript Diff Algorithm * By John Resig (http://ejohn.org/) * Modified by Chu Alan "sprite" + * Modified by Rodrigo Fernandes "rtfpessoa" * * Released under the MIT license. * @@ -9,21 +10,11 @@ * http://ejohn.org/projects/javascript-diff-algorithm/ */ -function escape(s) { - var n = s; - n = n.replace(/&/g, "&"); - n = n.replace(//g, ">"); - n = n.replace(/"/g, """); - - return n; -} - -function diffString( o, n ) { +function diffString(o, n) { o = o.replace(/\s+$/, ''); n = n.replace(/\s+$/, ''); - var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/) ); + var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/)); var str = ""; var oSpace = o.match(/\s+/g); @@ -41,23 +32,23 @@ function diffString( o, n ) { if (out.n.length == 0) { for (var i = 0; i < out.o.length; i++) { - str += '' + escape(out.o[i]) + oSpace[i] + ""; + str += '' + out.o[i] + oSpace[i] + ""; } } else { if (out.n[0].text == null) { for (n = 0; n < out.o.length && out.o[n].text == null; n++) { - str += '' + escape(out.o[n]) + oSpace[n] + ""; + str += '' + out.o[n] + oSpace[n] + ""; } } - for ( var i = 0; i < out.n.length; i++ ) { + for (var i = 0; i < out.n.length; i++) { if (out.n[i].text == null) { - str += '' + escape(out.n[i]) + nSpace[i] + ""; + str += '' + out.n[i] + nSpace[i] + ""; } else { var pre = ""; - for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) { - pre += '' + escape(out.o[n]) + oSpace[n] + ""; + for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) { + pre += '' + out.o[n] + oSpace[n] + ""; } str += " " + out.n[i].text + nSpace[i] + pre; } @@ -67,94 +58,44 @@ function diffString( o, n ) { return str; } -function randomColor() { - return "rgb(" + (Math.random() * 100) + "%, " + - (Math.random() * 100) + "%, " + - (Math.random() * 100) + "%)"; -} -function diffString2( o, n ) { - o = o.replace(/\s+$/, ''); - n = n.replace(/\s+$/, ''); - - var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/) ); - - var oSpace = o.match(/\s+/g); - if (oSpace == null) { - oSpace = ["\n"]; - } else { - oSpace.push("\n"); - } - var nSpace = n.match(/\s+/g); - if (nSpace == null) { - nSpace = ["\n"]; - } else { - nSpace.push("\n"); - } - - var os = ""; - var colors = new Array(); - for (var i = 0; i < out.o.length; i++) { - colors[i] = randomColor(); - - if (out.o[i].text != null) { - os += '' + - escape(out.o[i].text) + oSpace[i] + ""; - } else { - os += "" + escape(out.o[i]) + oSpace[i] + ""; - } - } - - var ns = ""; - for (var i = 0; i < out.n.length; i++) { - if (out.n[i].text != null) { - ns += '' + - escape(out.n[i].text) + nSpace[i] + ""; - } else { - ns += "" + escape(out.n[i]) + nSpace[i] + ""; - } - } - - return { o : os , n : ns }; -} - -function diff( o, n ) { +function diff(o, n) { var ns = new Object(); var os = new Object(); - for ( var i = 0; i < n.length; i++ ) { - if ( ns[ n[i] ] == null ) - ns[ n[i] ] = { rows: new Array(), o: null }; - ns[ n[i] ].rows.push( i ); + for (var i = 0; i < n.length; i++) { + if (ns[n[i]] == null) + ns[n[i]] = {rows: new Array(), o: null}; + ns[n[i]].rows.push(i); } - for ( var i = 0; i < o.length; i++ ) { - if ( os[ o[i] ] == null ) - os[ o[i] ] = { rows: new Array(), n: null }; - os[ o[i] ].rows.push( i ); + for (var i = 0; i < o.length; i++) { + if (os[o[i]] == null) + os[o[i]] = {rows: new Array(), n: null}; + os[o[i]].rows.push(i); } - for ( var i in ns ) { - if ( ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1 ) { - n[ ns[i].rows[0] ] = { text: n[ ns[i].rows[0] ], row: os[i].rows[0] }; - o[ os[i].rows[0] ] = { text: o[ os[i].rows[0] ], row: ns[i].rows[0] }; + for (var i in ns) { + if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) { + n[ns[i].rows[0]] = {text: n[ns[i].rows[0]], row: os[i].rows[0]}; + o[os[i].rows[0]] = {text: o[os[i].rows[0]], row: ns[i].rows[0]}; } } - for ( var i = 0; i < n.length - 1; i++ ) { - if ( n[i].text != null && n[i+1].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null && - n[i+1] == o[ n[i].row + 1 ] ) { - n[i+1] = { text: n[i+1], row: n[i].row + 1 }; - o[n[i].row+1] = { text: o[n[i].row+1], row: i + 1 }; + for (var i = 0; i < n.length - 1; i++) { + if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null && + n[i + 1] == o[n[i].row + 1]) { + n[i + 1] = {text: n[i + 1], row: n[i].row + 1}; + o[n[i].row + 1] = {text: o[n[i].row + 1], row: i + 1}; } } - for ( var i = n.length - 1; i > 0; i-- ) { - if ( n[i].text != null && n[i-1].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null && - n[i-1] == o[ n[i].row - 1 ] ) { - n[i-1] = { text: n[i-1], row: n[i].row - 1 }; - o[n[i].row-1] = { text: o[n[i].row-1], row: i - 1 }; + for (var i = n.length - 1; i > 0; i--) { + if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null && + n[i - 1] == o[n[i].row - 1]) { + n[i - 1] = {text: n[i - 1], row: n[i].row - 1}; + o[n[i].row - 1] = {text: o[n[i].row - 1], row: i - 1}; } } - return { o: o, n: n }; + return {o: o, n: n}; }