Show the list of changed files

- Optionally show the file list before the diff
- Change usage to accept configuration instead of multiple methods
This commit is contained in:
Nuno Teixeira 2015-10-19 12:47:49 +01:00
parent 0bb7341d76
commit f1db9a9d6f
13 changed files with 530 additions and 240 deletions

View file

@ -32,29 +32,25 @@ Diff to Html generates pretty HTML diffs from git diff output.
## How to use ## How to use
> Pretty Line-by-Line Html From Git Word Diff Output > Pretty HTML diff
Diff2Html.getPrettyHtmlFromDiff(exInput) Diff2Html.getPrettyHtml(exInput, configuration)
> Pretty Side-by-Side Html From Git Word Diff Output
Diff2Html.getPrettySideBySideHtmlFromDiff(exInput)
> Intermediate Json From Git Word Diff Output > Intermediate Json From Git Word Diff Output
Diff2Html.getJsonFromDiff(exInput) 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. > 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. > Add the dependencies.
Choose one color scheme, and add the main highlight code. Choose one color scheme, and add the main highlight code.
@ -90,8 +86,8 @@ document.addEventListener("DOMContentLoaded", function () {
hljs.configure({languages: distinctLanguages}); hljs.configure({languages: distinctLanguages});
// generate and inject the diff HTML into the desired place // generate and inject the diff HTML into the desired place
document.getElementById("line-by-line").innerHTML = Diff2Html.getPrettyHtmlFromJson(diffJson); document.getElementById("line-by-line").innerHTML = Diff2Html.getPrettyHtml(diffJson, { inputFormat: 'json' });
document.getElementById("side-by-side").innerHTML = Diff2Html.getPrettySideBySideHtmlFromJson(diffJson); 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 // collect all the code lines and execute the highlight on them
var codeLines = document.getElementsByClassName("d2h-code-line-ctn"); var codeLines = document.getElementsByClassName("d2h-code-line-ctn");

View file

@ -207,3 +207,61 @@
color: rgba(0, 0, 0, 0.3); color: rgba(0, 0, 0, 0.3);
border-color: #d5e4f2; 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;
}

58
dist/diff2html.css vendored
View file

@ -207,3 +207,61 @@
color: rgba(0, 0, 0, 0.3); color: rgba(0, 0, 0, 0.3);
border-color: #d5e4f2; 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;
}

494
dist/diff2html.js vendored
View file

@ -54,7 +54,8 @@
(function(ctx, undefined) { (function(ctx, undefined) {
var diffParser = __webpack_require__(1).DiffParser; 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() { 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 * Generates json object from string diff input
*/ */
@ -84,22 +76,65 @@
return diffParser.generateDiffJson(diffInput); 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 * Generates pretty html from a json object
*/ */
Diff2Html.prototype.getPrettyHtmlFromJson = function(diffJson, config) { Diff2Html.prototype.getPrettyHtmlFromJson = function(diffJson, config) {
var configOrEmpty = 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 * Generates pretty side by side html from string diff input
*/ */
Diff2Html.prototype.getPrettySideBySideHtmlFromDiff = function(diffInput, config) { Diff2Html.prototype.getPrettySideBySideHtmlFromDiff = function(diffInput, config) {
var diffJson = diffParser.generateDiffJson(diffInput);
var configOrEmpty = config || {}; 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) { Diff2Html.prototype.getPrettySideBySideHtmlFromJson = function(diffJson, config) {
var configOrEmpty = 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'; var diffName = 'Diff2Html';
@ -373,6 +410,10 @@
.replace(/\t/g, ' '); .replace(/\t/g, ' ');
}; };
Utils.prototype.getRandomId = function(prefix) {
return prefix + "-" + Math.random().toString(36).slice(-3);
};
Utils.prototype.startsWith = function(str, start) { Utils.prototype.startsWith = function(str, start) {
if (typeof start === 'object') { if (typeof start === 'object') {
var result = false; var result = false;
@ -403,204 +444,49 @@
/* /*
* *
* HtmlPrinter (html-printer.js) * FileListPrinter (file-list-printer.js)
* Author: rtfpessoa * Author: nmatpt
* *
*/ */
(function (ctx, undefined) { (function (ctx, undefined) {
var lineByLinePrinter = __webpack_require__(4).LineByLinePrinter; var printerUtils = __webpack_require__(4).PrinterUtils;
var sideBySidePrinter = __webpack_require__(7).SideBySidePrinter; 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 '<div class="d2h-file-list-wrapper">\n' +
' <div class="d2h-file-list-header">Files changed (' + diffFiles.length + ')&nbsp&nbsp</div>\n' +
' <a id="' + hideId + '" class="d2h-hide" href="#' + hideId + '">+</a>\n' +
' <a id="' + showId + 'd2h-show" class="d2h-show" href="#' + showId + '">-</a>\n' +
' <div class="d2h-clear"></div>\n' +
' <div class="d2h-file-list">\n' +
HtmlPrinter.prototype.generateSideBySideJsonHtml = sideBySidePrinter.generateSideBySideJsonHtml;
module.exports['HtmlPrinter'] = new HtmlPrinter(); diffFiles.map(function (file) {
return ' <div class="d2h-file-list-line">\n' +
' <div class="d2h-file-stats">\n' +
' <span class="d2h-lines-added">+' + file.addedLines + '</span>\n' +
' <span class="d2h-lines-deleted">-' + file.deletedLines + '</span>\n' +
' </div>\n' +
' <div class="d2h-file-name"><a href="#' + printerUtils.getHtmlId(file) + '">&nbsp;' + printerUtils.getDiffName(file) + '</a></div>\n' +
' </div>\n'
}).join('\n') +
'</div></div>\n';
};
module.exports['FileListPrinter'] = new FileListPrinter();
})(this); })(this);
/***/ }, /***/ },
/* 4 */ /* 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 '<div class="d2h-wrapper">\n' +
diffFiles.map(function(file) {
var diffs;
if (file.blocks.length) {
diffs = generateFileHtml(file, config);
} else {
diffs = generateEmptyDiff();
}
return '<div class="d2h-file-wrapper" data-lang="' + file.language + '">\n' +
' <div class="d2h-file-header">\n' +
' <div class="d2h-file-stats">\n' +
' <span class="d2h-lines-added">+' + file.addedLines + '</span>\n' +
' <span class="d2h-lines-deleted">-' + file.deletedLines + '</span>\n' +
' </div>\n' +
' <div class="d2h-file-name">' + printerUtils.getDiffName(file) + '</div>\n' +
' </div>\n' +
' <div class="d2h-file-diff">\n' +
' <div class="d2h-code-wrapper">\n' +
' <table class="d2h-diff-table">\n' +
' <tbody class="d2h-diff-tbody">\n' +
' ' + diffs +
' </tbody>\n' +
' </table>\n' +
' </div>\n' +
' </div>\n' +
' </div>\n';
}).join('\n') +
'</div>\n';
};
function generateFileHtml(file, config) {
return file.blocks.map(function(block) {
var lines = '<tr>\n' +
' <td class="d2h-code-linenumber ' + diffParser.LINE_TYPE.INFO + '"></td>\n' +
' <td class="' + diffParser.LINE_TYPE.INFO + '">' +
' <div class="d2h-code-line ' + diffParser.LINE_TYPE.INFO + '">' + utils.escape(block.header) + '</div>' +
' </td>\n' +
'</tr>\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 = '<span class="d2h-code-line-prefix">' + prefix + '</span>';
}
var htmlContent = '';
if (content) {
htmlContent = '<span class="d2h-code-line-ctn">' + content + '</span>';
}
return '<tr>\n' +
' <td class="d2h-code-linenumber ' + type + '">' +
' <div class="line-num1">' + utils.valueOrEmpty(oldNumber) + '</div>' +
' <div class="line-num2">' + utils.valueOrEmpty(newNumber) + '</div>' +
' </td>\n' +
' <td class="' + type + '">' +
' <div class="d2h-code-line ' + type + '">' + htmlPrefix + htmlContent + '</div>' +
' </td>\n' +
'</tr>\n';
}
function generateEmptyDiff() {
return '<tr>\n' +
' <td class="' + diffParser.LINE_TYPE.INFO + '">' +
' <div class="d2h-code-line ' + diffParser.LINE_TYPE.INFO + '">' +
'File without changes' +
' </div>' +
' </td>\n' +
'</tr>\n';
}
module.exports['LineByLinePrinter'] = new LineByLinePrinter();
})(this);
/***/ },
/* 5 */
/***/ function(module, exports, __webpack_require__) { /***/ function(module, exports, __webpack_require__) {
/* /*
@ -612,12 +498,16 @@
(function(ctx, undefined) { (function(ctx, undefined) {
var jsDiff = __webpack_require__(6); var jsDiff = __webpack_require__(5);
var utils = __webpack_require__(2).Utils; var utils = __webpack_require__(2).Utils;
function PrinterUtils() { function PrinterUtils() {
} }
PrinterUtils.prototype.getHtmlId = function(file) {
return "d2h-" + this.getDiffName(file);
};
PrinterUtils.prototype.getDiffName = function(file) { PrinterUtils.prototype.getDiffName = function(file) {
var oldFilename = file.oldName; var oldFilename = file.oldName;
var newFilename = file.newName; var newFilename = file.newName;
@ -700,7 +590,7 @@
/***/ }, /***/ },
/* 6 */ /* 5 */
/***/ function(module, exports, __webpack_require__) { /***/ function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* See LICENSE file for terms of use */ var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* See LICENSE file for terms of use */
@ -1324,8 +1214,210 @@
}(this)); }(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 */ /* 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 '<div class="d2h-wrapper">\n' +
diffFiles.map(function(file) {
var diffs;
if (file.blocks.length) {
diffs = generateFileHtml(file, config);
} else {
diffs = generateEmptyDiff();
}
return '<div id="' + printerUtils.getHtmlId(file) + '" class="d2h-file-wrapper" data-lang="' + file.language + '">\n' +
' <div class="d2h-file-header">\n' +
' <div class="d2h-file-stats">\n' +
' <span class="d2h-lines-added">+' + file.addedLines + '</span>\n' +
' <span class="d2h-lines-deleted">-' + file.deletedLines + '</span>\n' +
' </div>\n' +
' <div class="d2h-file-name">' + printerUtils.getDiffName(file) + '</div>\n' +
' </div>\n' +
' <div class="d2h-file-diff">\n' +
' <div class="d2h-code-wrapper">\n' +
' <table class="d2h-diff-table">\n' +
' <tbody class="d2h-diff-tbody">\n' +
' ' + diffs +
' </tbody>\n' +
' </table>\n' +
' </div>\n' +
' </div>\n' +
' </div>\n';
}).join('\n') +
'</div>\n';
};
function generateFileHtml(file, config) {
return file.blocks.map(function(block) {
var lines = '<tr>\n' +
' <td class="d2h-code-linenumber ' + diffParser.LINE_TYPE.INFO + '"></td>\n' +
' <td class="' + diffParser.LINE_TYPE.INFO + '">' +
' <div class="d2h-code-line ' + diffParser.LINE_TYPE.INFO + '">' + utils.escape(block.header) + '</div>' +
' </td>\n' +
'</tr>\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 = '<span class="d2h-code-line-prefix">' + prefix + '</span>';
}
var htmlContent = '';
if (content) {
htmlContent = '<span class="d2h-code-line-ctn">' + content + '</span>';
}
return '<tr>\n' +
' <td class="d2h-code-linenumber ' + type + '">' +
' <div class="line-num1">' + utils.valueOrEmpty(oldNumber) + '</div>' +
' <div class="line-num2">' + utils.valueOrEmpty(newNumber) + '</div>' +
' </td>\n' +
' <td class="' + type + '">' +
' <div class="d2h-code-line ' + type + '">' + htmlPrefix + htmlContent + '</div>' +
' </td>\n' +
'</tr>\n';
}
function generateEmptyDiff() {
return '<tr>\n' +
' <td class="' + diffParser.LINE_TYPE.INFO + '">' +
' <div class="d2h-code-line ' + diffParser.LINE_TYPE.INFO + '">' +
'File without changes' +
' </div>' +
' </td>\n' +
'</tr>\n';
}
module.exports['LineByLinePrinter'] = new LineByLinePrinter();
})(this);
/***/ },
/* 8 */
/***/ function(module, exports, __webpack_require__) { /***/ function(module, exports, __webpack_require__) {
/* /*
@ -1338,7 +1430,7 @@
(function(ctx, undefined) { (function(ctx, undefined) {
var diffParser = __webpack_require__(1).DiffParser; var diffParser = __webpack_require__(1).DiffParser;
var printerUtils = __webpack_require__(5).PrinterUtils; var printerUtils = __webpack_require__(4).PrinterUtils;
var utils = __webpack_require__(2).Utils; var utils = __webpack_require__(2).Utils;
function SideBySidePrinter() { function SideBySidePrinter() {
@ -1355,7 +1447,7 @@
diffs = generateEmptyDiff(); diffs = generateEmptyDiff();
} }
return '<div class="d2h-file-wrapper" data-lang="' + file.language + '">\n' + return '<div id="' + printerUtils.getHtmlId(file) + '" class="d2h-file-wrapper" data-lang="' + file.language + '">\n' +
' <div class="d2h-file-header">\n' + ' <div class="d2h-file-header">\n' +
' <div class="d2h-file-stats">\n' + ' <div class="d2h-file-stats">\n' +
' <span class="d2h-lines-added">+' + file.addedLines + '</span>\n' + ' <span class="d2h-lines-added">+' + file.addedLines + '</span>\n' +

View file

@ -1 +1 @@
.d2h-wrapper{display:block;margin:0 auto;text-align:left;width:100%}.d2h-file-wrapper{border:1px solid #ddd;border-radius:3px;margin-bottom:1em}.d2h-file-header{padding:5px 10px;border-bottom:1px solid #d8d8d8;background-color:#f7f7f7;font:13px Helvetica,arial,freesans,clean,sans-serif,"Segoe UI Emoji","Segoe UI Symbol"}.d2h-file-stats{display:inline;font-size:12px;text-align:center;max-width:15%}.d2h-lines-added{background-color:#ceffce;border:1px solid #b4e2b4;color:#399839;border-radius:5px 0 0 5px;padding:2px;width:25px}.d2h-lines-deleted{background-color:#f7c8c8;border:1px solid #e9aeae;color:#c33;border-radius:0 5px 5px 0;padding:2px;width:25px}.d2h-file-name{display:inline;height:33px;line-height:33px;max-width:80%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.d2h-diff-table{border-collapse:collapse;font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:12px;height:18px;line-height:18px;width:100%}.d2h-files-diff{width:100%}.d2h-file-diff{overflow-x:scroll;overflow-y:hidden}.d2h-file-side-diff{display:inline-block;overflow-x:scroll;overflow-y:hidden;width:50%;margin-right:-4px}.d2h-code-line{display:block;white-space:pre;padding:0 10px;height:18px;line-height:18px;margin-left:80px;color:inherit;overflow-x:inherit;background:none}.d2h-code-side-line{display:block;white-space:pre;padding:0 10px;height:18px;line-height:18px;margin-left:50px;color:inherit;overflow-x:inherit;background:none}.d2h-code-line del,.d2h-code-side-line del{display:inline-block;margin-top:-1px;text-decoration:none;background-color:#ffb6ba;border-radius:.2em}.d2h-code-line ins,.d2h-code-side-line ins{display:inline-block;margin-top:-1px;text-decoration:none;background-color:#97f295;border-radius:.2em}.d2h-code-line-prefix{float:left;background:none;padding:0}.d2h-code-line-ctn{background:none;padding:0}.line-num1{display:inline-block;float:left;width:30px;overflow:hidden;text-overflow:ellipsis}.line-num2{display:inline-block;float:right;width:30px;overflow:hidden;text-overflow:ellipsis}.d2h-code-linenumber{position:absolute;width:2%;min-width:65px;padding-left:10px;padding-right:10px;height:18px;line-height:18px;background-color:#fff;color:rgba(0,0,0,0.3);text-align:right;border:solid #eee;border-width:0 1px 0 1px;cursor:pointer}.d2h-code-side-linenumber{position:absolute;width:35px;padding-left:10px;padding-right:10px;height:18px;line-height:18px;background-color:#fff;color:rgba(0,0,0,0.3);text-align:right;border:solid #eee;border-width:0 1px 0 1px;cursor:pointer;overflow:hidden;text-overflow:ellipsis}.d2h-del{background-color:#fee8e9;border-color:#e9aeae}.d2h-ins{background-color:#dfd;border-color:#b4e2b4}.d2h-info{background-color:#f8fafd;color:rgba(0,0,0,0.3);border-color:#d5e4f2} .d2h-wrapper{display:block;margin:0 auto;text-align:left;width:100%}.d2h-file-wrapper{border:1px solid #ddd;border-radius:3px;margin-bottom:1em}.d2h-file-header{padding:5px 10px;border-bottom:1px solid #d8d8d8;background-color:#f7f7f7;font:13px Helvetica,arial,freesans,clean,sans-serif,"Segoe UI Emoji","Segoe UI Symbol"}.d2h-file-stats{display:inline;font-size:12px;text-align:center;max-width:15%}.d2h-lines-added{background-color:#ceffce;border:1px solid #b4e2b4;color:#399839;border-radius:5px 0 0 5px;padding:2px;width:25px}.d2h-lines-deleted{background-color:#f7c8c8;border:1px solid #e9aeae;color:#c33;border-radius:0 5px 5px 0;padding:2px;width:25px}.d2h-file-name{display:inline;height:33px;line-height:33px;max-width:80%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.d2h-diff-table{border-collapse:collapse;font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:12px;height:18px;line-height:18px;width:100%}.d2h-files-diff{width:100%}.d2h-file-diff{overflow-x:scroll;overflow-y:hidden}.d2h-file-side-diff{display:inline-block;overflow-x:scroll;overflow-y:hidden;width:50%;margin-right:-4px}.d2h-code-line{display:block;white-space:pre;padding:0 10px;height:18px;line-height:18px;margin-left:80px;color:inherit;overflow-x:inherit;background:none}.d2h-code-side-line{display:block;white-space:pre;padding:0 10px;height:18px;line-height:18px;margin-left:50px;color:inherit;overflow-x:inherit;background:none}.d2h-code-line del,.d2h-code-side-line del{display:inline-block;margin-top:-1px;text-decoration:none;background-color:#ffb6ba;border-radius:.2em}.d2h-code-line ins,.d2h-code-side-line ins{display:inline-block;margin-top:-1px;text-decoration:none;background-color:#97f295;border-radius:.2em}.d2h-code-line-prefix{float:left;background:none;padding:0}.d2h-code-line-ctn{background:none;padding:0}.line-num1{display:inline-block;float:left;width:30px;overflow:hidden;text-overflow:ellipsis}.line-num2{display:inline-block;float:right;width:30px;overflow:hidden;text-overflow:ellipsis}.d2h-code-linenumber{position:absolute;width:2%;min-width:65px;padding-left:10px;padding-right:10px;height:18px;line-height:18px;background-color:#fff;color:rgba(0,0,0,0.3);text-align:right;border:solid #eeeeee;border-width:0 1px 0 1px;cursor:pointer}.d2h-code-side-linenumber{position:absolute;width:35px;padding-left:10px;padding-right:10px;height:18px;line-height:18px;background-color:#fff;color:rgba(0,0,0,0.3);text-align:right;border:solid #eeeeee;border-width:0 1px 0 1px;cursor:pointer;overflow:hidden;text-overflow:ellipsis}.d2h-del{background-color:#fee8e9;border-color:#e9aeae}.d2h-ins{background-color:#dfd;border-color:#b4e2b4}.d2h-info{background-color:#f8fafd;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}.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}

File diff suppressed because one or more lines are too long

View file

@ -245,8 +245,8 @@
hljs.configure({languages: distinctLanguages}); hljs.configure({languages: distinctLanguages});
// generate and inject the diff HTML into the desired place // generate and inject the diff HTML into the desired place
document.getElementById("line-by-line").innerHTML = Diff2Html.getPrettyHtmlFromJson(diffJson); document.getElementById("line-by-line").innerHTML = Diff2Html.getPrettyHtml(diffJson, { inputFormat: 'json', showFiles: true });
document.getElementById("side-by-side").innerHTML = Diff2Html.getPrettySideBySideHtmlFromJson(diffJson); 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 // collect all the code lines and execute the highlight on them
var codeLines = document.getElementsByClassName("d2h-code-line-ctn"); var codeLines = document.getElementsByClassName("d2h-code-line-ctn");

View file

@ -8,6 +8,7 @@
(function(ctx, undefined) { (function(ctx, undefined) {
var diffParser = require('./diff-parser.js').DiffParser; var diffParser = require('./diff-parser.js').DiffParser;
var fileLister = require('./file-list-printer.js').FileListPrinter;
var htmlPrinter = require('./html-printer.js').HtmlPrinter; var htmlPrinter = require('./html-printer.js').HtmlPrinter;
function Diff2Html() { function Diff2Html() {
@ -22,15 +23,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 * Generates json object from string diff input
*/ */
@ -38,22 +30,65 @@
return diffParser.generateDiffJson(diffInput); 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 * Generates pretty html from a json object
*/ */
Diff2Html.prototype.getPrettyHtmlFromJson = function(diffJson, config) { Diff2Html.prototype.getPrettyHtmlFromJson = function(diffJson, config) {
var configOrEmpty = 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 * Generates pretty side by side html from string diff input
*/ */
Diff2Html.prototype.getPrettySideBySideHtmlFromDiff = function(diffInput, config) { Diff2Html.prototype.getPrettySideBySideHtmlFromDiff = function(diffInput, config) {
var diffJson = diffParser.generateDiffJson(diffInput);
var configOrEmpty = config || {}; var configOrEmpty = config || {};
return htmlPrinter.generateSideBySideJsonHtml(diffJson, configOrEmpty); configOrEmpty['inputFormat'] = 'diff';
configOrEmpty['outputFormat'] = 'side-by-side';
return this.getPrettyHtml(diffInput, configOrEmpty)
}; };
/* /*
@ -61,7 +96,9 @@
*/ */
Diff2Html.prototype.getPrettySideBySideHtmlFromJson = function(diffJson, config) { Diff2Html.prototype.getPrettySideBySideHtmlFromJson = function(diffJson, config) {
var configOrEmpty = 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'; var diffName = 'Diff2Html';

41
src/file-list-printer.js Normal file
View file

@ -0,0 +1,41 @@
/*
*
* FileListPrinter (file-list-printer.js)
* Author: nmatpt
*
*/
(function (ctx, undefined) {
var printerUtils = require('./printer-utils.js').PrinterUtils;
var utils = require('./utils.js').Utils;
function FileListPrinter() {
}
FileListPrinter.prototype.generateFileList = function (diffFiles) {
var hideId = utils.getRandomId("d2h-hide");
var showId = utils.getRandomId("d2h-show");
return '<div class="d2h-file-list-wrapper">\n' +
' <div class="d2h-file-list-header">Files changed (' + diffFiles.length + ')&nbsp&nbsp</div>\n' +
' <a id="' + hideId + '" class="d2h-hide" href="#' + hideId + '">+</a>\n' +
' <a id="' + showId + 'd2h-show" class="d2h-show" href="#' + showId + '">-</a>\n' +
' <div class="d2h-clear"></div>\n' +
' <div class="d2h-file-list">\n' +
diffFiles.map(function (file) {
return ' <div class="d2h-file-list-line">\n' +
' <div class="d2h-file-stats">\n' +
' <span class="d2h-lines-added">+' + file.addedLines + '</span>\n' +
' <span class="d2h-lines-deleted">-' + file.deletedLines + '</span>\n' +
' </div>\n' +
' <div class="d2h-file-name"><a href="#' + printerUtils.getHtmlId(file) + '">&nbsp;' + printerUtils.getDiffName(file) + '</a></div>\n' +
' </div>\n'
}).join('\n') +
'</div></div>\n';
};
module.exports['FileListPrinter'] = new FileListPrinter();
})(this);

View file

@ -25,7 +25,7 @@
diffs = generateEmptyDiff(); diffs = generateEmptyDiff();
} }
return '<div class="d2h-file-wrapper" data-lang="' + file.language + '">\n' + return '<div id="' + printerUtils.getHtmlId(file) + '" class="d2h-file-wrapper" data-lang="' + file.language + '">\n' +
' <div class="d2h-file-header">\n' + ' <div class="d2h-file-header">\n' +
' <div class="d2h-file-stats">\n' + ' <div class="d2h-file-stats">\n' +
' <span class="d2h-lines-added">+' + file.addedLines + '</span>\n' + ' <span class="d2h-lines-added">+' + file.addedLines + '</span>\n' +

View file

@ -13,6 +13,10 @@
function PrinterUtils() { function PrinterUtils() {
} }
PrinterUtils.prototype.getHtmlId = function(file) {
return "d2h-" + this.getDiffName(file);
};
PrinterUtils.prototype.getDiffName = function(file) { PrinterUtils.prototype.getDiffName = function(file) {
var oldFilename = file.oldName; var oldFilename = file.oldName;
var newFilename = file.newName; var newFilename = file.newName;

View file

@ -25,7 +25,7 @@
diffs = generateEmptyDiff(); diffs = generateEmptyDiff();
} }
return '<div class="d2h-file-wrapper" data-lang="' + file.language + '">\n' + return '<div id="' + printerUtils.getHtmlId(file) + '" class="d2h-file-wrapper" data-lang="' + file.language + '">\n' +
' <div class="d2h-file-header">\n' + ' <div class="d2h-file-header">\n' +
' <div class="d2h-file-stats">\n' + ' <div class="d2h-file-stats">\n' +
' <span class="d2h-lines-added">+' + file.addedLines + '</span>\n' + ' <span class="d2h-lines-added">+' + file.addedLines + '</span>\n' +

View file

@ -18,6 +18,10 @@
.replace(/\t/g, ' '); .replace(/\t/g, ' ');
}; };
Utils.prototype.getRandomId = function(prefix) {
return prefix + "-" + Math.random().toString(36).slice(-3);
};
Utils.prototype.startsWith = function(str, start) { Utils.prototype.startsWith = function(str, start) {
if (typeof start === 'object') { if (typeof start === 'object') {
var result = false; var result = false;