From cb145eddf6338e86c0cb15f22a277dd59f105cd8 Mon Sep 17 00:00:00 2001 From: Rodrigo Fernandes Date: Fri, 6 May 2016 23:02:05 +0100 Subject: [PATCH] Add support for parsing unified diffs * Refactor code to separate parser parts * Add test for unified example --- sample/index.html | 480 +++++++++++++++++++------------------- src/diff-parser.js | 82 +++++-- test/diff-parser-tests.js | 48 +++- test/diff2html-tests.js | 1 - 4 files changed, 345 insertions(+), 266 deletions(-) diff --git a/sample/index.html b/sample/index.html index 1ca86bc..fed8128 100644 --- a/sample/index.html +++ b/sample/index.html @@ -1,252 +1,258 @@ - - Diff to HTML by rtfpessoa + + Diff to HTML by rtfpessoa - + - + - + - - + + - - - - - + + + + + - + diff2htmlUi.draw('#side-by-side', { + inputFormat: 'json', + showFiles: true, + matching: 'lines', + outputFormat: 'side-by-side' + }); + diff2htmlUi.fileListCloseable('#side-by-side', false); + diff2htmlUi.highlightCode('#side-by-side'); + }); + diff --git a/src/diff-parser.js b/src/diff-parser.js index f42aed4..82cbfc6 100644 --- a/src/diff-parser.js +++ b/src/diff-parser.js @@ -33,32 +33,30 @@ var oldLine2 = null; // Used for combined diff var newLine = null; + /* Add previous block(if exists) before start a new file */ var saveBlock = function() { - - /* Add previous block(if exists) before start a new file */ if (currentBlock) { currentFile.blocks.push(currentBlock); currentBlock = null; } }; + /* + * Add previous file(if exists) before start a new one + * if it has name (to avoid binary files errors) + */ var saveFile = function() { - - /* - * 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; } }; + /* Create file structure */ var startFile = function() { saveBlock(); saveFile(); - /* Create file structure */ currentFile = {}; currentFile.blocks = []; currentFile.deletedLines = 0; @@ -179,18 +177,72 @@ return; } - var values = []; - if (utils.startsWith(line, 'diff')) { + if ( + utils.startsWith(line, 'diff') || // Git diffs always start with diff + !currentFile || // If we do not have a file yet, we should crete one + ( + currentFile && // If we already have some file in progress and + ( + currentFile.oldName && utils.startsWith(line, '---') || // Either we reached a old file identification line + currentFile.newName && utils.startsWith(line, '+++') // Or we reached a new file identification line + ) + ) + ) { startFile(); - } else if (currentFile && !currentFile.oldName && (values = getSrcFilename(line, config))) { + } + + var values; + + /* + * --- Date Timestamp[FractionalSeconds] TimeZone + * --- 2002-02-21 23:30:39.942229878 -0800 + */ + if (currentFile && !currentFile.oldName && + line.startsWith('---') && (values = getSrcFilename(line, config))) { currentFile.oldName = values; currentFile.language = getExtension(currentFile.oldName, currentFile.language); - } else if (currentFile && !currentFile.newName && (values = getDstFilename(line, config))) { + return; + } + + /* + * +++ Date Timestamp[FractionalSeconds] TimeZone + * +++ 2002-02-21 23:30:39.942229878 -0800 + */ + if (currentFile && !currentFile.newName && + line.startsWith('+++') && (values = getDstFilename(line, config))) { currentFile.newName = values; currentFile.language = getExtension(currentFile.newName, currentFile.language); - } else if (currentFile && utils.startsWith(line, '@@')) { + return; + } + + if (currentFile && utils.startsWith(line, '@')) { startBlock(line); - } else if ((values = oldMode.exec(line))) { + return; + } + + /* + * There are three types of diff lines. These lines are defined by the way they start. + * 1. New line starts with: + + * 2. Old line starts with: - + * 3. Context line starts with: + */ + if (currentBlock && (line.startsWith('+') || line.startsWith('-') || line.startsWith(' '))) { + createLine(line); + return; + } + + if ( + (currentFile && currentFile.blocks.length) || + (currentBlock && currentBlock.lines.length) + ) { + startFile(); + } + + /* + * Git diffs provide more information regarding files modes, renames, copies, + * commits between changes and similarity indexes + */ + if ((values = oldMode.exec(line))) { currentFile.oldMode = values[1]; } else if ((values = newMode.exec(line))) { currentFile.newMode = values[1]; @@ -232,8 +284,6 @@ } else if ((values = combinedDeletedFile.exec(line))) { currentFile.deletedFileMode = values[1]; currentFile.isDeleted = true; - } else if (currentBlock) { - createLine(line); } }); diff --git a/test/diff-parser-tests.js b/test/diff-parser-tests.js index 9aac03f..af8d3b6 100644 --- a/test/diff-parser-tests.js +++ b/test/diff-parser-tests.js @@ -54,7 +54,7 @@ describe('DiffParser', function() { }); function checkDiffSample(diff) { - var result = Diff2Html.getJsonFromDiff(diff); + var result = DiffParser.generateDiffJson(diff); var file1 = result[0]; assert.equal(1, result.length); assert.equal(1, file1.addedLines); @@ -75,7 +75,7 @@ describe('DiffParser', function() { '+cenas com ananas\n' + '+bananas'; - var result = Diff2Html.getJsonFromDiff(diff); + var result = DiffParser.generateDiffJson(diff); var file1 = result[0]; assert.equal(1, result.length); assert.equal(2, file1.addedLines); @@ -96,7 +96,7 @@ describe('DiffParser', function() { '+cenas com ananas\n' + '+bananas'; - var result = Diff2Html.getJsonFromDiff(diff, {"srcPrefix": "\t", "dstPrefix": "\t"}); + var result = DiffParser.generateDiffJson(diff, {"srcPrefix": "\t", "dstPrefix": "\t"}); var file1 = result[0]; assert.equal(1, result.length); assert.equal(2, file1.addedLines); @@ -118,7 +118,7 @@ describe('DiffParser', function() { '- return typeof undefined;\n' + '-});\n'; - var result = Diff2Html.getJsonFromDiff(diff); + var result = DiffParser.generateDiffJson(diff); assert.equal(1, result.length); var file1 = result[0]; @@ -147,7 +147,7 @@ describe('DiffParser', function() { '+\n' + '+console.log(parser.parsePatchDiffResult(text, patchLineList));\n'; - var result = Diff2Html.getJsonFromDiff(diff); + var result = DiffParser.generateDiffJson(diff); assert.equal(1, result.length); var file1 = result[0]; @@ -177,7 +177,7 @@ describe('DiffParser', function() { '+\n' + '+console.log(parser.parsePatchDiffResult(text, patchLineList));\n'; - var result = Diff2Html.getJsonFromDiff(diff); + var result = DiffParser.generateDiffJson(diff); assert.equal(1, result.length); var file1 = result[0]; @@ -220,7 +220,7 @@ describe('DiffParser', function() { ' // store className if set\n' + ' dataPriv.set( this, "__className__", this.className );\n'; - var result = Diff2Html.getJsonFromDiff(diff); + var result = DiffParser.generateDiffJson(diff); assert.equal(1, result.length); var file1 = result[0]; @@ -263,7 +263,7 @@ describe('DiffParser', function() { ' "./var/hasOwn",\n' + ' "./var/slice",\n'; - var result = Diff2Html.getJsonFromDiff(diff); + var result = DiffParser.generateDiffJson(diff); assert.equal(2, result.length); var file1 = result[0]; @@ -319,7 +319,7 @@ describe('DiffParser', function() { ' initialized = 1;\n' + ' for_each_ref(get_name);\n'; - var result = Diff2Html.getJsonFromDiff(diff); + var result = DiffParser.generateDiffJson(diff); assert.equal(1, result.length); var file1 = result[0]; @@ -341,7 +341,7 @@ describe('DiffParser', function() { 'copy from index.js\n' + 'copy to more-index.js\n'; - var result = Diff2Html.getJsonFromDiff(diff); + var result = DiffParser.generateDiffJson(diff); assert.equal(1, result.length); var file1 = result[0]; @@ -361,7 +361,7 @@ describe('DiffParser', function() { 'rename from more-index.js\n' + 'rename to other-index.js\n'; - var result = Diff2Html.getJsonFromDiff(diff); + var result = DiffParser.generateDiffJson(diff); assert.equal(1, result.length); var file1 = result[0]; @@ -384,7 +384,7 @@ describe('DiffParser', function() { '-test\n' + '+test1r\n'; - var result = Diff2Html.getJsonFromDiff(diff); + var result = DiffParser.generateDiffJson(diff); assert.equal(1, result.length); var file1 = result[0]; @@ -400,5 +400,29 @@ describe('DiffParser', function() { assert.equal(1, file1.blocks[0].lines[1].newNumber); }); + it('should parse unified non git diff', function() { + var diff = + '--- a/sample.js\n' + + '+++ b/sample.js\n' + + '@@ -1 +1,2 @@\n' + + '-test\n' + + '+test1r\n' + + '+test2r\n'; + + var result = DiffParser.generateDiffJson(diff); + var file1 = result[0]; + assert.equal(1, result.length); + assert.equal(2, file1.addedLines); + assert.equal(1, file1.deletedLines); + assert.equal('sample.js', file1.oldName); + assert.equal('sample.js', file1.newName); + assert.equal(1, file1.blocks.length); + + var linesContent = file1.blocks[0].lines.map(function(line) { + return line.content; + }); + assert.deepEqual(linesContent, ['-test', '+test1r', '+test2r']); + }); + }); }); diff --git a/test/diff2html-tests.js b/test/diff2html-tests.js index 765df8a..ef87ef5 100644 --- a/test/diff2html-tests.js +++ b/test/diff2html-tests.js @@ -191,7 +191,6 @@ describe('Diff2Html', function() { '+test1\n'; var result = Diff2Html.getJsonFromDiff(diff); - console.log(result); var file1 = result[0]; assert.equal(1, result.length); assert.equal(1, file1.addedLines);