From 5ab4d2eb8443c98d99574c3841b416f704e5a8fc Mon Sep 17 00:00:00 2001 From: Rodrigo Fernandes Date: Sat, 11 Apr 2015 20:59:56 +0100 Subject: [PATCH 1/3] depend on the library project --- README.md | 8 +- package.json | 19 ++- src/diff2html.js | 426 ---------------------------------------------- src/lib/jsdiff.js | 103 ----------- src/main.js | 12 +- 5 files changed, 20 insertions(+), 548 deletions(-) delete mode 100755 src/diff2html.js delete mode 100644 src/lib/jsdiff.js diff --git a/README.md b/README.md index 0c0c266..1b82278 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# Diff to Html Node Module by [rtfpessoa](https://github.com/rtfpessoa) +# Diff to Html Node Module (CLI) by [rtfpessoa](https://github.com/rtfpessoa) Diff to Html generates pretty HTML diffs. ### Inspiration -This project uses [diff2html](https://github.com/rtfpessoa/diff2html) as base. +This project is just a CLI for [diff2html-nodejs](https://github.com/rtfpessoa/diff2html-nodejs). ## Features @@ -26,9 +26,11 @@ This project uses [diff2html](https://github.com/rtfpessoa/diff2html) as base. * Manually download and import [diff2html.js](https://github.com/rtfpessoa/diff2html) into your page +* Import Node library [diff2html-nodejs](https://github.com/rtfpessoa/diff2html-nodejs) into your package.json + ## Setup - sudo npm install -g diff2html + sudo npm install -g diff2html-cli ## Usage diff --git a/package.json b/package.json index 1c6cbb1..b999edf 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { - "name": "diff2html", - "version": "0.1.9", + "name": "diff2html-cli", + "version": "0.1.0", - "homepage": "https://www.github.com/rtfpessoa/diff2html-nodejs", + "homepage": "https://www.github.com/rtfpessoa/diff2html-nodejs-cli", "description": "Fast Diff to colorized HTML", "keywords": [ "git", @@ -29,15 +29,15 @@ "repository": { "type": "git", - "url": "https://www.github.com/rtfpessoa/diff2html-nodejs.git" + "url": "https://www.github.com/rtfpessoa/diff2html-nodejs-cli.git" }, "bugs": { - "url": "https://www.github.com/rtfpessoa/diff2html-nodejs/issues" + "url": "https://www.github.com/rtfpessoa/diff2html-nodejs-cli/issues" }, "engines": { - "node": ">=0.10" + "node": ">=0.12.2" }, "preferGlobal": "true", @@ -50,12 +50,13 @@ "diff2html": "./bin/diff2html" }, - "main": "./src/diff2html.js", + "main": "./src/main.js", "dependencies": { "commander": "2.7.1", "extend": "2.0.0", - "pkginfo": "0.3.0" + "pkginfo": "0.3.0", + "diff2html": "0.1.9" }, "devDependencies": { @@ -64,7 +65,7 @@ "licenses": [ { "type": "MIT", - "url": "https://github.com/rtfpessoa/diff2html-node/blob/master/LICENSE" + "url": "https://github.com/rtfpessoa/diff2html-node-cli/blob/master/LICENSE" } ], diff --git a/src/diff2html.js b/src/diff2html.js deleted file mode 100755 index 0dae058..0000000 --- a/src/diff2html.js +++ /dev/null @@ -1,426 +0,0 @@ -/* - * - * Diff to HTML (diff2html.js) - * Author: rtfpessoa - * - * Diff commands: - * git diff - */ - -var JsDiff = require("./lib/jsdiff.js").JsDiff; - -var LINE_TYPE = { - INSERTS: "d2h-ins", - DELETES: "d2h-del", - CONTEXT: "d2h-cntx", - INFO: "d2h-info" -}; - -function Diff2Html() { -} - -/* - * Generates pretty html from string diff input - */ -Diff2Html.prototype.getPrettyHtmlFromDiff = function (diffInput) { - var diffJson = generateDiffJson(diffInput); - return generateJsonHtml(diffJson); -}; - -/* - * Generates json object from string diff input - */ -Diff2Html.prototype.getJsonFromDiff = function (diffInput) { - return generateDiffJson(diffInput); -}; - -/* - * Generates pretty html from a json object - */ -Diff2Html.prototype.getPrettyHtmlFromJson = function (diffJson) { - return generateJsonHtml(diffJson); -}; - -/* - * Generates pretty side by side html from string diff input - */ -Diff2Html.prototype.getPrettySideBySideHtmlFromDiff = function (diffInput) { - var diffJson = generateDiffJson(diffInput); - return generateSideBySideJsonHtml(diffJson); -}; - -/* - * Generates pretty side by side html from a json object - */ -Diff2Html.prototype.getPrettySideBySideHtmlFromJson = function (diffJson) { - return generateSideBySideJsonHtml(diffJson); -}; - -var generateDiffJson = function (diffInput) { - var files = [], - currentFile = null, - currentBlock = null, - oldLine = null, - newLine = null; - - var saveBlock = function () { - /* add previous block(if exists) before start a new file */ - if (currentBlock) { - currentFile.blocks.push(currentBlock); - currentBlock = null; - } - }; - - 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; - } - }; - - var startFile = function () { - saveBlock(); - saveFile(); - - /* create file structure */ - currentFile = {}; - currentFile.blocks = []; - currentFile.deletedLines = 0; - currentFile.addedLines = 0; - }; - - var 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]; - - /* create block metadata */ - currentBlock = {}; - currentBlock.lines = []; - currentBlock.oldStartLine = oldLine; - currentBlock.newStartLine = newLine; - currentBlock.header = line; - }; - - var createLine = function (line) { - var currentLine = {}; - currentLine.content = line; - - /* fill the line data */ - if (startsWith(line, "+") || startsWith(line, " +")) { - currentFile.addedLines++; - - currentLine.type = LINE_TYPE.INSERTS; - currentLine.oldNumber = null; - currentLine.newNumber = newLine++; - - currentBlock.lines.push(currentLine); - - } else if (startsWith(line, "-") || startsWith(line, " -")) { - currentFile.deletedLines++; - - currentLine.type = LINE_TYPE.DELETES; - currentLine.oldNumber = oldLine++; - currentLine.newNumber = null; - - currentBlock.lines.push(currentLine); - - } else { - currentLine.type = LINE_TYPE.CONTEXT; - currentLine.oldNumber = oldLine++; - currentLine.newNumber = newLine++; - - currentBlock.lines.push(currentLine); - } - }; - - var diffLines = diffInput.split("\n"); - diffLines.forEach(function (line) { - // Unmerged paths, and possibly other non-diffable files - // https://github.com/scottgonzalez/pretty-diff/issues/11 - // Also, remove some useless lines - if (!line || startsWith(line, "*") || - startsWith(line, "new") || startsWith(line, "index")) { - return; - } - - var values = []; - if (startsWith(line, "diff")) { - 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]; - - var fileSplit = currentFile.newName.split("."); - currentFile.language = fileSplit[fileSplit.length - 1]; - } else if (currentFile && startsWith(line, "@@")) { - startBlock(line); - } else if (currentBlock) { - createLine(line); - } - }); - - saveBlock(); - saveFile(); - - return files; -}; - -/* - * Line By Line HTML - */ - -var 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"; -}; - -var generateFileHtml = function (file) { - return file.blocks.map(function (block) { - - var lines = "\n" + - " \n" + - " " + - "
" + escape(block.header) + "
" + - " \n" + - "\n"; - - for (var i = 0; i < block.lines.length; i++) { - var prevLine = block.lines[i - 1]; - var line = block.lines[i]; - var newLine = block.lines[i + 1]; - var nextNewLine = block.lines[i + 2]; - - var isOppositeTypeTwoLineBlock = - line.type == LINE_TYPE.DELETES && - newLine && newLine.type == LINE_TYPE.INSERTS && - (!nextNewLine || nextNewLine && nextNewLine.type != LINE_TYPE.INSERTS) && - (!prevLine || prevLine && prevLine.type != LINE_TYPE.DELETES); - - var escapedLine = escape(line.content); - - if (isOppositeTypeTwoLineBlock) { - var nextEscapedLine = escape(newLine.content); - - var diff = diffHighlight(escapedLine, nextEscapedLine); - - lines += generateLineHtml(line.type, line.oldNumber, line.newNumber, diff.o) + - generateLineHtml(newLine.type, newLine.oldNumber, newLine.newNumber, diff.n); - - i++; - } else { - lines += generateLineHtml(line.type, line.oldNumber, line.newNumber, escapedLine); - } - } - - return lines; - }).join("\n"); -}; - -var generateLineHtml = function (type, oldNumber, newNumber, content) { - return "\n" + - " " + - "
" + valueOrEmpty(oldNumber) + "
" + - "
" + valueOrEmpty(newNumber) + "
" + - " \n" + - " " + - "
" + content + "
" + - " \n" + - "\n"; -}; - -/* - * Side By Side HTML (work in progress) - */ - -var 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"; -}; - -var generateSideBySideFileHtml = function (file) { - var fileHtml = {}; - 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 < block.lines.length; i++) { - var prevLine = block.lines[i - 1]; - var line = block.lines[i]; - var newLine = block.lines[i + 1]; - var nextNewLine = block.lines[i + 2]; - - var isOpositeTypeTwoLineBlock = line.type == LINE_TYPE.DELETES && newLine && newLine.type == LINE_TYPE.INSERTS && - (!nextNewLine || nextNewLine && nextNewLine.type != LINE_TYPE.INSERTS) && - (!prevLine || prevLine && prevLine.type != LINE_TYPE.DELETES); - - var escapedLine = escape(line.content); - - if (isOpositeTypeTwoLineBlock) { - var nextEscapedLine = escape(newLine.content); - - var diff = diffHighlight(escapedLine, nextEscapedLine); - - fileHtml.left += generateSingleLineHtml(line.type, line.oldNumber, diff.o); - fileHtml.right += generateSingleLineHtml(newLine.type, newLine.newNumber, diff.n); - - i++; - } else if (line.type == LINE_TYPE.DELETES) { - fileHtml.left += generateSingleLineHtml(line.type, line.oldNumber, escapedLine); - fileHtml.right += generateSingleLineHtml(LINE_TYPE.CONTEXT, "", "", ""); - } else if (line.type == LINE_TYPE.INSERTS) { - fileHtml.left += generateSingleLineHtml(LINE_TYPE.CONTEXT, "", "", ""); - fileHtml.right += generateSingleLineHtml(line.type, line.newNumber, escapedLine); - } else { - fileHtml.left += generateSingleLineHtml(line.type, line.oldNumber, escapedLine); - fileHtml.right += generateSingleLineHtml(line.type, line.newNumber, escapedLine); - } - } - - }); - - return fileHtml; -}; - -var generateSingleLineHtml = function (type, number, content) { - return "\n" + - " " + number + "\n" + - " " + - "
" + content + "
" + - " \n" + - " \n"; -}; - -/* - * HTML Helpers - */ - -var getDiffName = function (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) { - return line.replace(/(((.|\n)*?)<\/ins>)/g, ""); -}; - -var removeDel = function (line) { - return line.replace(/(((.|\n)*?)<\/del>)/g, ""); -}; - -/* - * Utils - */ - -function escape(str) { - return str.slice(0) - .replace(/&/g, "&") - .replace(//g, ">") - .replace(/\t/g, " "); -} - -function startsWith(str, start) { - return str.indexOf(start) === 0; -} - -function valueOrEmpty(value) { - return value ? value : ""; -} - -function diffHighlight(diffLine1, diffLine2) { - /* remove the initial -/+ to avoid always having diff in the first char */ - var highlightedLine = JsDiff(diffLine1.substr(1), diffLine2.substr(1)); - - return { - o: diffLine1.charAt(0) + removeIns(highlightedLine), - n: diffLine2.charAt(0) + removeDel(highlightedLine) - } -} - -module.exports.Diff2Html = new Diff2Html(); diff --git a/src/lib/jsdiff.js b/src/lib/jsdiff.js deleted file mode 100644 index 7fe8275..0000000 --- a/src/lib/jsdiff.js +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Javascript Diff Algorithm - * By John Resig (http://ejohn.org/) - * Modified by Chu Alan "sprite" - * Modified by Rodrigo Fernandes "rtfpessoa" - * - * Released under the MIT license. - * - * More Info: - * http://ejohn.org/projects/javascript-diff-algorithm/ - */ - -function JsDiff(o, n) { - o = o.replace(/\s+$/, ''); - n = n.replace(/\s+$/, ''); - - var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/)); - var str = ""; - - 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"); - } - - if (out.n.length == 0) { - for (var i = 0; i < out.o.length; 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 += '' + out.o[n] + oSpace[n] + ""; - } - } - - for (var i = 0; i < out.n.length; i++) { - if (out.n[i].text == null) { - 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 += '' + out.o[n] + oSpace[n] + ""; - } - str += " " + out.n[i].text + nSpace[i] + pre; - } - } - } - - return str; -} - -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 < 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 = 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}; - } - } - - return {o: o, n: n}; -} - -module.exports.JsDiff = JsDiff; diff --git a/src/main.js b/src/main.js index 6079cf0..92e4134 100644 --- a/src/main.js +++ b/src/main.js @@ -36,6 +36,7 @@ function main(program) { console.log(content); } } else { + console.error("Input is empty"); program.help(); } @@ -60,18 +61,15 @@ function getInput(program) { if (program.input) { return fs.readFileSync(program.input, "utf8"); } else { - console.error("Input is required."); - process.exit(1); + var childProcess = require('child_process'); + var lineDiffCommand = 'git diff ' + program.args; - //var childProcess = require('child_process'); - //var lineDiffCommand = 'git diff ' + program.args; - // - //return childProcess.execSync(lineDiffCommand).toString('utf8'); + return childProcess.execSync(lineDiffCommand).toString('utf8'); } } function getHtml(program, input) { - var Diff2Html = require('./diff2html.js').Diff2Html; + var Diff2Html = require('diff2html').Diff2Html; if (program.side) { return Diff2Html.getPrettySideBySideHtmlFromDiff(input); From 19f7441c328f6eb97a25220646ea1d3dfbf8403a Mon Sep 17 00:00:00 2001 From: Rodrigo Fernandes Date: Sun, 12 Apr 2015 02:57:52 +0100 Subject: [PATCH 2/3] new version --- package.json | 4 ++-- src/main.js | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index b999edf..64f36d1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "diff2html-cli", - "version": "0.1.0", + "version": "0.2.0-2", "homepage": "https://www.github.com/rtfpessoa/diff2html-nodejs-cli", "description": "Fast Diff to colorized HTML", @@ -56,7 +56,7 @@ "commander": "2.7.1", "extend": "2.0.0", "pkginfo": "0.3.0", - "diff2html": "0.1.9" + "diff2html": "0.2.0-6" }, "devDependencies": { diff --git a/src/main.js b/src/main.js index 92e4134..4350dc0 100644 --- a/src/main.js +++ b/src/main.js @@ -36,7 +36,7 @@ function main(program) { console.log(content); } } else { - console.error("Input is empty"); + console.error("The diff is empty. Try another command."); program.help(); } @@ -69,13 +69,13 @@ function getInput(program) { } function getHtml(program, input) { - var Diff2Html = require('diff2html').Diff2Html; + var diff2Html = require('diff2html').Diff2Html; if (program.side) { - return Diff2Html.getPrettySideBySideHtmlFromDiff(input); + return diff2Html.getPrettySideBySideHtmlFromDiff(input); } else if (program.json) { - return JSON.stringify(Diff2Html.getJsonFromDiff(input)); + return JSON.stringify(diff2Html.getJsonFromDiff(input)); } else { - return Diff2Html.getPrettyHtmlFromDiff(input); + return diff2Html.getPrettyHtmlFromDiff(input); } } From e1d7088f1a9e7c4513b035feb4d4cdef508bc416 Mon Sep 17 00:00:00 2001 From: Rodrigo Fernandes Date: Sun, 12 Apr 2015 11:35:52 +0100 Subject: [PATCH 3/3] add support for both wordByWord and charByChar hightlight --- package.json | 4 ++-- src/main.js | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 64f36d1..b38aceb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "diff2html-cli", - "version": "0.2.0-2", + "version": "0.2.0-3", "homepage": "https://www.github.com/rtfpessoa/diff2html-nodejs-cli", "description": "Fast Diff to colorized HTML", @@ -56,7 +56,7 @@ "commander": "2.7.1", "extend": "2.0.0", "pkginfo": "0.3.0", - "diff2html": "0.2.0-6" + "diff2html": "0.2.0-7" }, "devDependencies": { diff --git a/src/main.js b/src/main.js index 4350dc0..cb03d7e 100644 --- a/src/main.js +++ b/src/main.js @@ -13,6 +13,8 @@ program .option('-p, --preview', 'Open preview in the browser.') .option('-l, --line', 'Line by Line diff.') .option('-s, --side', 'Side by Side diff.') + .option('-w, --word', 'Word by Word highlight.') + .option('-c, --char', 'Char by Char highlight.') .option('-j, --json', 'Export diff in json format.'); program.on('--help', function () { @@ -71,11 +73,15 @@ function getInput(program) { function getHtml(program, input) { var diff2Html = require('diff2html').Diff2Html; + var config = {}; + config.wordByWord = program.word; + config.charByChar = program.char; + if (program.side) { - return diff2Html.getPrettySideBySideHtmlFromDiff(input); + return diff2Html.getPrettySideBySideHtmlFromDiff(input, config); } else if (program.json) { - return JSON.stringify(diff2Html.getJsonFromDiff(input)); + return JSON.stringify(diff2Html.getJsonFromDiff(input, config)); } else { - return diff2Html.getPrettyHtmlFromDiff(input); + return diff2Html.getPrettyHtmlFromDiff(input, config); } }