diff --git a/README.md b/README.md
index 4348ac1..bd92a31 100644
--- a/README.md
+++ b/README.md
@@ -32,29 +32,25 @@ Diff to Html generates pretty HTML diffs from git diff output.
## How to use
-> Pretty Line-by-Line Html From Git Word Diff Output
+> Pretty HTML diff
- Diff2Html.getPrettyHtmlFromDiff(exInput)
-
-> Pretty Side-by-Side Html From Git Word Diff Output
-
- Diff2Html.getPrettySideBySideHtmlFromDiff(exInput)
+ Diff2Html.getPrettyHtml(exInput, configuration)
> Intermediate Json From Git Word Diff Output
Diff2Html.getJsonFromDiff(exInput)
-> Pretty Line-by-Line Html From Json
-
- Diff2Html.getPrettyHtmlFromJson(exInput)
-
-> Pretty Side-by-Side Html From Json
-
- Diff2Html.getPrettySideBySideHtmlFromJson(exInput)
-
> Check out the `index.html` for a complete example.
-## Sintax Hightlight
+## Configuration
+The HTML output accepts a Javascript object with configuration. Possible options:
+
+ - `inputFormat`: the format of the input data: `'diff'` or `'json'`, default is `'diff'`
+ - `outputFormat`: the format of the output data: `'line-by-line'` or `'side-by-side'`, default is `'line-by-line'`
+ - `showFiles`: show a file list before the diff: `true` or `false`, default is `false`
+
+
+## Syntax Highlight
> Add the dependencies.
Choose one color scheme, and add the main highlight code.
@@ -90,8 +86,8 @@ document.addEventListener("DOMContentLoaded", function () {
hljs.configure({languages: distinctLanguages});
// generate and inject the diff HTML into the desired place
- document.getElementById("line-by-line").innerHTML = Diff2Html.getPrettyHtmlFromJson(diffJson);
- document.getElementById("side-by-side").innerHTML = Diff2Html.getPrettySideBySideHtmlFromJson(diffJson);
+ document.getElementById("line-by-line").innerHTML = Diff2Html.getPrettyHtml(diffJson, { inputFormat: 'json' });
+ document.getElementById("side-by-side").innerHTML = Diff2Html.getPrettyHtml(diffJson, { inputFormat: 'json', outputFormat: 'side-by-side' });
// collect all the code lines and execute the highlight on them
var codeLines = document.getElementsByClassName("d2h-code-line-ctn");
diff --git a/css/diff2html.css b/css/diff2html.css
index df448ba..fc4b5f8 100644
--- a/css/diff2html.css
+++ b/css/diff2html.css
@@ -207,3 +207,61 @@
color: rgba(0, 0, 0, 0.3);
border-color: #d5e4f2;
}
+
+.d2h-file-list-wrapper {
+ margin-bottom: 10px;
+ padding: 0 10px;
+}
+
+.d2h-file-list-wrapper a {
+ text-decoration: none;
+ color: #3572b0;
+}
+
+.d2h-file-list-wrapper a:visited {
+ color: #3572b0;
+}
+
+.d2h-file-list-header {
+ font-weight: bold;
+ margin-bottom: 5px;
+ text-align: left;
+ display: inline;
+ float:left;
+}
+
+.d2h-file-list-line {
+ text-align: left;
+ font: 13px Helvetica, arial, freesans, clean, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol";
+}
+
+.d2h-file-list-line .d2h-file-name {
+ line-height: 21px;
+}
+
+.d2h-file-list {
+ display:none;
+}
+
+.d2h-clear {
+ display:block;
+ clear: both;
+}
+
+/* CSS only show/hide */
+.d2h-show {
+ display: none;
+ float:left;
+}
+.d2h-hide {
+ float:left;
+}
+.d2h-hide:target + .d2h-show {
+ display: inline;
+}
+.d2h-hide:target {
+ display: none;
+}
+.d2h-hide:target ~ .d2h-file-list {
+ display:block;
+}
diff --git a/dist/diff2html.css b/dist/diff2html.css
index df448ba..fc4b5f8 100644
--- a/dist/diff2html.css
+++ b/dist/diff2html.css
@@ -207,3 +207,61 @@
color: rgba(0, 0, 0, 0.3);
border-color: #d5e4f2;
}
+
+.d2h-file-list-wrapper {
+ margin-bottom: 10px;
+ padding: 0 10px;
+}
+
+.d2h-file-list-wrapper a {
+ text-decoration: none;
+ color: #3572b0;
+}
+
+.d2h-file-list-wrapper a:visited {
+ color: #3572b0;
+}
+
+.d2h-file-list-header {
+ font-weight: bold;
+ margin-bottom: 5px;
+ text-align: left;
+ display: inline;
+ float:left;
+}
+
+.d2h-file-list-line {
+ text-align: left;
+ font: 13px Helvetica, arial, freesans, clean, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol";
+}
+
+.d2h-file-list-line .d2h-file-name {
+ line-height: 21px;
+}
+
+.d2h-file-list {
+ display:none;
+}
+
+.d2h-clear {
+ display:block;
+ clear: both;
+}
+
+/* CSS only show/hide */
+.d2h-show {
+ display: none;
+ float:left;
+}
+.d2h-hide {
+ float:left;
+}
+.d2h-hide:target + .d2h-show {
+ display: inline;
+}
+.d2h-hide:target {
+ display: none;
+}
+.d2h-hide:target ~ .d2h-file-list {
+ display:block;
+}
diff --git a/dist/diff2html.js b/dist/diff2html.js
index 80c191d..1d17685 100644
--- a/dist/diff2html.js
+++ b/dist/diff2html.js
@@ -54,7 +54,8 @@
(function(ctx, undefined) {
var diffParser = __webpack_require__(1).DiffParser;
- var htmlPrinter = __webpack_require__(3).HtmlPrinter;
+ var fileLister = __webpack_require__(3).FileListPrinter;
+ var htmlPrinter = __webpack_require__(6).HtmlPrinter;
function Diff2Html() {
}
@@ -68,15 +69,6 @@
};
*/
- /*
- * Generates pretty html from string diff input
- */
- Diff2Html.prototype.getPrettyHtmlFromDiff = function(diffInput, config) {
- var diffJson = diffParser.generateDiffJson(diffInput);
- var configOrEmpty = config || {};
- return htmlPrinter.generateLineByLineJsonHtml(diffJson, configOrEmpty);
- };
-
/*
* Generates json object from string diff input
*/
@@ -84,22 +76,65 @@
return diffParser.generateDiffJson(diffInput);
};
+ /*
+ * Generates the html diff. The config parameter configures the output/input formats and other options
+ */
+ Diff2Html.prototype.getPrettyHtml = function(diffInput, config) {
+ var configOrEmpty = config || {};
+
+ var diffJson = diffInput;
+ if(!configOrEmpty.inputFormat || configOrEmpty.inputFormat === 'diff') {
+ diffJson = diffParser.generateDiffJson(diffInput);
+ }
+
+ var fileList = "";
+ if(configOrEmpty.showFiles === true) {
+ fileList = fileLister.generateFileList(diffJson, configOrEmpty);
+ }
+
+ var diffOutput = "";
+ if(configOrEmpty.outputFormat === 'side-by-side') {
+ diffOutput = htmlPrinter.generateSideBySideJsonHtml(diffJson, configOrEmpty);
+ } else {
+ diffOutput = htmlPrinter.generateLineByLineJsonHtml(diffJson, configOrEmpty);
+ }
+
+ return fileList + diffOutput
+ };
+
+
+ /*
+ * Deprecated methods - The following methods exist only to maintain compatibility with previous versions
+ */
+
+ /*
+ * Generates pretty html from string diff input
+ */
+ Diff2Html.prototype.getPrettyHtmlFromDiff = function(diffInput, config) {
+ var configOrEmpty = config || {};
+ configOrEmpty['inputFormat'] = 'diff';
+ configOrEmpty['outputFormat'] = 'line-by-line';
+ return this.getPrettyHtml(diffInput, configOrEmpty)
+ };
+
/*
* Generates pretty html from a json object
*/
Diff2Html.prototype.getPrettyHtmlFromJson = function(diffJson, config) {
var configOrEmpty = config || {};
- return htmlPrinter.generateLineByLineJsonHtml(diffJson, configOrEmpty);
+ configOrEmpty['inputFormat'] = 'json';
+ configOrEmpty['outputFormat'] = 'line-by-line';
+ return this.getPrettyHtml(diffJson, configOrEmpty)
};
/*
* Generates pretty side by side html from string diff input
*/
Diff2Html.prototype.getPrettySideBySideHtmlFromDiff = function(diffInput, config) {
- var diffJson = diffParser.generateDiffJson(diffInput);
-
var configOrEmpty = config || {};
- return htmlPrinter.generateSideBySideJsonHtml(diffJson, configOrEmpty);
+ configOrEmpty['inputFormat'] = 'diff';
+ configOrEmpty['outputFormat'] = 'side-by-side';
+ return this.getPrettyHtml(diffInput, configOrEmpty)
};
/*
@@ -107,7 +142,9 @@
*/
Diff2Html.prototype.getPrettySideBySideHtmlFromJson = function(diffJson, config) {
var configOrEmpty = config || {};
- return htmlPrinter.generateSideBySideJsonHtml(diffJson, configOrEmpty);
+ configOrEmpty['inputFormat'] = 'json';
+ configOrEmpty['outputFormat'] = 'side-by-side';
+ return this.getPrettyHtml(diffJson, configOrEmpty)
};
var diffName = 'Diff2Html';
@@ -373,6 +410,10 @@
.replace(/\t/g, ' ');
};
+ Utils.prototype.getRandomId = function(prefix) {
+ return prefix + "-" + Math.random().toString(36).slice(-3);
+ };
+
Utils.prototype.startsWith = function(str, start) {
if (typeof start === 'object') {
var result = false;
@@ -403,204 +444,49 @@
/*
*
- * HtmlPrinter (html-printer.js)
- * Author: rtfpessoa
+ * FileListPrinter (file-list-printer.js)
+ * Author: nmatpt
*
*/
- (function(ctx, undefined) {
+ (function (ctx, undefined) {
- var lineByLinePrinter = __webpack_require__(4).LineByLinePrinter;
- var sideBySidePrinter = __webpack_require__(7).SideBySidePrinter;
+ var printerUtils = __webpack_require__(4).PrinterUtils;
+ var utils = __webpack_require__(2).Utils;
- function HtmlPrinter() {
- }
+ function FileListPrinter() {
+ }
- HtmlPrinter.prototype.generateLineByLineJsonHtml = lineByLinePrinter.generateLineByLineJsonHtml;
+ FileListPrinter.prototype.generateFileList = function (diffFiles) {
+ var hideId = utils.getRandomId("d2h-hide");
+ var showId = utils.getRandomId("d2h-show");
+ return '
\n' +
+ ' \n' +
+ '
+\n' +
+ '
-\n' +
+ '
\n' +
+ '
\n' +
- HtmlPrinter.prototype.generateSideBySideJsonHtml = sideBySidePrinter.generateSideBySideJsonHtml;
- module.exports['HtmlPrinter'] = new HtmlPrinter();
+ diffFiles.map(function (file) {
+ return '
\n' +
+ '
\n' +
+ ' +' + file.addedLines + '\n' +
+ ' -' + file.deletedLines + '\n' +
+ '
\n' +
+ '
\n' +
+ '
\n'
+ }).join('\n') +
+ '
\n';
+ };
+
+ module.exports['FileListPrinter'] = new FileListPrinter();
})(this);
/***/ },
/* 4 */
-/***/ function(module, exports, __webpack_require__) {
-
- /*
- *
- * LineByLinePrinter (line-by-line-printer.js)
- * Author: rtfpessoa
- *
- */
-
- (function(ctx, undefined) {
-
- var diffParser = __webpack_require__(1).DiffParser;
- var printerUtils = __webpack_require__(5).PrinterUtils;
- var utils = __webpack_require__(2).Utils;
-
- function LineByLinePrinter() {
- }
-
- LineByLinePrinter.prototype.generateLineByLineJsonHtml = function(diffFiles, config) {
- return '\n' +
- diffFiles.map(function(file) {
-
- var diffs;
- if (file.blocks.length) {
- diffs = generateFileHtml(file, config);
- } else {
- diffs = generateEmptyDiff();
- }
-
- return '
\n' +
- ' \n' +
- '
\n' +
- '
\n' +
- '
\n' +
- ' \n' +
- ' ' + diffs +
- ' \n' +
- '
\n' +
- '
\n' +
- '
\n' +
- '
\n';
- }).join('\n') +
- '
\n';
- };
-
- function generateFileHtml(file, config) {
- return file.blocks.map(function(block) {
-
- var lines = '\n' +
- ' | \n' +
- ' ' +
- ' ' + utils.escape(block.header) + ' ' +
- ' | \n' +
- '
\n';
-
- var oldLines = [];
- var newLines = [];
- var processedOldLines = [];
- var processedNewLines = [];
-
- for (var i = 0; i < block.lines.length; i++) {
- var line = block.lines[i];
- var escapedLine = utils.escape(line.content);
-
- if (line.type == diffParser.LINE_TYPE.CONTEXT && !oldLines.length && !newLines.length) {
- lines += generateLineHtml(line.type, line.oldNumber, line.newNumber, escapedLine);
- } else if (line.type == diffParser.LINE_TYPE.INSERTS && !oldLines.length && !newLines.length) {
- lines += generateLineHtml(line.type, line.oldNumber, line.newNumber, escapedLine);
- } else if (line.type == diffParser.LINE_TYPE.DELETES && !newLines.length) {
- oldLines.push(line);
- } else if (line.type == diffParser.LINE_TYPE.INSERTS && oldLines.length > newLines.length) {
- newLines.push(line);
- } else {
- var j = 0;
- var oldLine, newLine;
-
- if (oldLines.length === newLines.length) {
- for (j = 0; j < oldLines.length; j++) {
- oldLine = oldLines[j];
- newLine = newLines[j];
-
- config.isCombined = file.isCombined;
- var diff = printerUtils.diffHighlight(oldLine.content, newLine.content, config);
-
- processedOldLines +=
- generateLineHtml(oldLine.type, oldLine.oldNumber, oldLine.newNumber,
- diff.first.line, diff.first.prefix);
- processedNewLines +=
- generateLineHtml(newLine.type, newLine.oldNumber, newLine.newNumber,
- diff.second.line, diff.second.prefix);
- }
-
- lines += processedOldLines + processedNewLines;
- } else {
- lines += processLines(oldLines, newLines);
- }
-
- oldLines = [];
- newLines = [];
- processedOldLines = [];
- processedNewLines = [];
- i--;
- }
- }
-
- lines += processLines(oldLines, newLines);
-
- return lines;
- }).join('\n');
- }
-
- function processLines(oldLines, newLines) {
- var lines = '';
-
- for (j = 0; j < oldLines.length; j++) {
- var oldLine = oldLines[j];
- var oldEscapedLine = utils.escape(oldLine.content);
- lines += generateLineHtml(oldLine.type, oldLine.oldNumber, oldLine.newNumber, oldEscapedLine);
- }
-
- for (j = 0; j < newLines.length; j++) {
- var newLine = newLines[j];
- var newEscapedLine = utils.escape(newLine.content);
- lines += generateLineHtml(newLine.type, newLine.oldNumber, newLine.newNumber, newEscapedLine);
- }
-
- return lines;
- }
-
- function generateLineHtml(type, oldNumber, newNumber, content, prefix) {
- var htmlPrefix = '';
- if (prefix) {
- htmlPrefix = '' + prefix + '';
- }
-
- var htmlContent = '';
- if (content) {
- htmlContent = '' + content + '';
- }
-
- return '\n' +
- ' | ' +
- ' ' + utils.valueOrEmpty(oldNumber) + ' ' +
- ' ' + utils.valueOrEmpty(newNumber) + ' ' +
- ' | \n' +
- ' ' +
- ' ' + htmlPrefix + htmlContent + ' ' +
- ' | \n' +
- '
\n';
- }
-
- function generateEmptyDiff() {
- return '\n' +
- ' | ' +
- ' ' +
- 'File without changes' +
- ' ' +
- ' | \n' +
- '
\n';
- }
-
- module.exports['LineByLinePrinter'] = new LineByLinePrinter();
-
- })(this);
-
-
-/***/ },
-/* 5 */
/***/ function(module, exports, __webpack_require__) {
/*
@@ -612,12 +498,16 @@
(function(ctx, undefined) {
- var jsDiff = __webpack_require__(6);
+ var jsDiff = __webpack_require__(5);
var utils = __webpack_require__(2).Utils;
function PrinterUtils() {
}
+ PrinterUtils.prototype.getHtmlId = function(file) {
+ return "d2h-" + this.getDiffName(file);
+ };
+
PrinterUtils.prototype.getDiffName = function(file) {
var oldFilename = file.oldName;
var newFilename = file.newName;
@@ -700,7 +590,7 @@
/***/ },
-/* 6 */
+/* 5 */
/***/ function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* See LICENSE file for terms of use */
@@ -1324,8 +1214,210 @@
}(this));
+/***/ },
+/* 6 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /*
+ *
+ * HtmlPrinter (html-printer.js)
+ * Author: rtfpessoa
+ *
+ */
+
+ (function(ctx, undefined) {
+
+ var lineByLinePrinter = __webpack_require__(7).LineByLinePrinter;
+ var sideBySidePrinter = __webpack_require__(8).SideBySidePrinter;
+
+ function HtmlPrinter() {
+ }
+
+ HtmlPrinter.prototype.generateLineByLineJsonHtml = lineByLinePrinter.generateLineByLineJsonHtml;
+
+ HtmlPrinter.prototype.generateSideBySideJsonHtml = sideBySidePrinter.generateSideBySideJsonHtml;
+
+ module.exports['HtmlPrinter'] = new HtmlPrinter();
+
+ })(this);
+
+
/***/ },
/* 7 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /*
+ *
+ * LineByLinePrinter (line-by-line-printer.js)
+ * Author: rtfpessoa
+ *
+ */
+
+ (function(ctx, undefined) {
+
+ var diffParser = __webpack_require__(1).DiffParser;
+ var printerUtils = __webpack_require__(4).PrinterUtils;
+ var utils = __webpack_require__(2).Utils;
+
+ function LineByLinePrinter() {
+ }
+
+ LineByLinePrinter.prototype.generateLineByLineJsonHtml = function(diffFiles, config) {
+ return '\n' +
+ diffFiles.map(function(file) {
+
+ var diffs;
+ if (file.blocks.length) {
+ diffs = generateFileHtml(file, config);
+ } else {
+ diffs = generateEmptyDiff();
+ }
+
+ return '
\n' +
+ ' \n' +
+ '
\n' +
+ '
\n' +
+ '
\n' +
+ ' \n' +
+ ' ' + diffs +
+ ' \n' +
+ '
\n' +
+ '
\n' +
+ '
\n' +
+ '
\n';
+ }).join('\n') +
+ '
\n';
+ };
+
+ function generateFileHtml(file, config) {
+ return file.blocks.map(function(block) {
+
+ var lines = '\n' +
+ ' | \n' +
+ ' ' +
+ ' ' + utils.escape(block.header) + ' ' +
+ ' | \n' +
+ '
\n';
+
+ var oldLines = [];
+ var newLines = [];
+ var processedOldLines = [];
+ var processedNewLines = [];
+
+ for (var i = 0; i < block.lines.length; i++) {
+ var line = block.lines[i];
+ var escapedLine = utils.escape(line.content);
+
+ if (line.type == diffParser.LINE_TYPE.CONTEXT && !oldLines.length && !newLines.length) {
+ lines += generateLineHtml(line.type, line.oldNumber, line.newNumber, escapedLine);
+ } else if (line.type == diffParser.LINE_TYPE.INSERTS && !oldLines.length && !newLines.length) {
+ lines += generateLineHtml(line.type, line.oldNumber, line.newNumber, escapedLine);
+ } else if (line.type == diffParser.LINE_TYPE.DELETES && !newLines.length) {
+ oldLines.push(line);
+ } else if (line.type == diffParser.LINE_TYPE.INSERTS && oldLines.length > newLines.length) {
+ newLines.push(line);
+ } else {
+ var j = 0;
+ var oldLine, newLine;
+
+ if (oldLines.length === newLines.length) {
+ for (j = 0; j < oldLines.length; j++) {
+ oldLine = oldLines[j];
+ newLine = newLines[j];
+
+ config.isCombined = file.isCombined;
+ var diff = printerUtils.diffHighlight(oldLine.content, newLine.content, config);
+
+ processedOldLines +=
+ generateLineHtml(oldLine.type, oldLine.oldNumber, oldLine.newNumber,
+ diff.first.line, diff.first.prefix);
+ processedNewLines +=
+ generateLineHtml(newLine.type, newLine.oldNumber, newLine.newNumber,
+ diff.second.line, diff.second.prefix);
+ }
+
+ lines += processedOldLines + processedNewLines;
+ } else {
+ lines += processLines(oldLines, newLines);
+ }
+
+ oldLines = [];
+ newLines = [];
+ processedOldLines = [];
+ processedNewLines = [];
+ i--;
+ }
+ }
+
+ lines += processLines(oldLines, newLines);
+
+ return lines;
+ }).join('\n');
+ }
+
+ function processLines(oldLines, newLines) {
+ var lines = '';
+
+ for (j = 0; j < oldLines.length; j++) {
+ var oldLine = oldLines[j];
+ var oldEscapedLine = utils.escape(oldLine.content);
+ lines += generateLineHtml(oldLine.type, oldLine.oldNumber, oldLine.newNumber, oldEscapedLine);
+ }
+
+ for (j = 0; j < newLines.length; j++) {
+ var newLine = newLines[j];
+ var newEscapedLine = utils.escape(newLine.content);
+ lines += generateLineHtml(newLine.type, newLine.oldNumber, newLine.newNumber, newEscapedLine);
+ }
+
+ return lines;
+ }
+
+ function generateLineHtml(type, oldNumber, newNumber, content, prefix) {
+ var htmlPrefix = '';
+ if (prefix) {
+ htmlPrefix = '' + prefix + '';
+ }
+
+ var htmlContent = '';
+ if (content) {
+ htmlContent = '' + content + '';
+ }
+
+ return '\n' +
+ ' | ' +
+ ' ' + utils.valueOrEmpty(oldNumber) + ' ' +
+ ' ' + utils.valueOrEmpty(newNumber) + ' ' +
+ ' | \n' +
+ ' ' +
+ ' ' + htmlPrefix + htmlContent + ' ' +
+ ' | \n' +
+ '
\n';
+ }
+
+ function generateEmptyDiff() {
+ return '\n' +
+ ' | ' +
+ ' ' +
+ 'File without changes' +
+ ' ' +
+ ' | \n' +
+ '
\n';
+ }
+
+ module.exports['LineByLinePrinter'] = new LineByLinePrinter();
+
+ })(this);
+
+
+/***/ },
+/* 8 */
/***/ function(module, exports, __webpack_require__) {
/*
@@ -1338,7 +1430,7 @@
(function(ctx, undefined) {
var diffParser = __webpack_require__(1).DiffParser;
- var printerUtils = __webpack_require__(5).PrinterUtils;
+ var printerUtils = __webpack_require__(4).PrinterUtils;
var utils = __webpack_require__(2).Utils;
function SideBySidePrinter() {
@@ -1355,7 +1447,7 @@
diffs = generateEmptyDiff();
}
- return '