new release method
This commit is contained in:
parent
8eabdd6642
commit
9be801d610
13 changed files with 1368 additions and 1375 deletions
1361
diff2html.js
Normal file
1361
diff2html.js
Normal file
File diff suppressed because it is too large
Load diff
1
diff2html.min.css
vendored
Normal file
1
diff2html.min.css
vendored
Normal file
|
|
@ -0,0 +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}.d2h-file-side-diff{display:inline-block;overflow-x:scroll;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.hljs{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}.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}
|
||||
1
diff2html.min.js
vendored
Normal file
1
diff2html.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
index.html
18
index.html
|
|
@ -5,27 +5,19 @@
|
|||
<title>Diff to HTML by rtfpessoa</title>
|
||||
|
||||
<!--
|
||||
Diff to HTML (template.html)
|
||||
Diff to HTML (index.html)
|
||||
Author: rtfpessoa
|
||||
-->
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/styles/default.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="diff2html.css">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="diff2html.min.css">
|
||||
<script type="text/javascript" src="diff2html.min.js"></script>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
|
||||
|
||||
<script type="text/javascript" src="lib/diff.js"></script>
|
||||
<script type="text/javascript" src="lib/fakeRequire.js"></script>
|
||||
|
||||
<script type="text/javascript" src="src/utils.js"></script>
|
||||
<script type="text/javascript" src="src/diff-parser.js"></script>
|
||||
<script type="text/javascript" src="src/printer-utils.js"></script>
|
||||
<script type="text/javascript" src="src/side-by-side-printer.js"></script>
|
||||
<script type="text/javascript" src="src/line-by-line-printer.js"></script>
|
||||
<script type="text/javascript" src="src/html-printer.js"></script>
|
||||
<script type="text/javascript" src="src/diff2html.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/highlight.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/languages/scala.min.js"></script>
|
||||
|
||||
<script>
|
||||
var lineDiffExample = 'diff --git a/src/attributes/attr.js b/src/attributes/attr.js\n' +
|
||||
'index facdd41..b627fe8 100644\n' +
|
||||
|
|
|
|||
565
lib/diff.js
565
lib/diff.js
|
|
@ -1,565 +0,0 @@
|
|||
/* See LICENSE file for terms of use */
|
||||
|
||||
/*
|
||||
* Text diff implementation.
|
||||
*
|
||||
* This library supports the following APIS:
|
||||
* JsDiff.diffChars: Character by character diff
|
||||
* JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace
|
||||
* JsDiff.diffLines: Line based diff
|
||||
*
|
||||
* JsDiff.diffCss: Diff targeted at CSS content
|
||||
*
|
||||
* These methods are based on the implementation proposed in
|
||||
* "An O(ND) Difference Algorithm and its Variations" (Myers, 1986).
|
||||
* http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927
|
||||
*
|
||||
* AUTHOR: https://github.com/kpdecker/jsdiff
|
||||
*/
|
||||
(function(global, undefined) {
|
||||
|
||||
var JsDiff = (function() {
|
||||
/*jshint maxparams: 5*/
|
||||
/*istanbul ignore next*/
|
||||
function map(arr, mapper, that) {
|
||||
if (Array.prototype.map) {
|
||||
return Array.prototype.map.call(arr, mapper, that);
|
||||
}
|
||||
|
||||
var other = new Array(arr.length);
|
||||
|
||||
for (var i = 0, n = arr.length; i < n; i++) {
|
||||
other[i] = mapper.call(that, arr[i], i, arr);
|
||||
}
|
||||
return other;
|
||||
}
|
||||
function clonePath(path) {
|
||||
return { newPos: path.newPos, components: path.components.slice(0) };
|
||||
}
|
||||
function removeEmpty(array) {
|
||||
var ret = [];
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
if (array[i]) {
|
||||
ret.push(array[i]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
function escapeHTML(s) {
|
||||
var n = s;
|
||||
n = n.replace(/&/g, '&');
|
||||
n = n.replace(/</g, '<');
|
||||
n = n.replace(/>/g, '>');
|
||||
n = n.replace(/"/g, '"');
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
function buildValues(components, newString, oldString, useLongestToken) {
|
||||
var componentPos = 0,
|
||||
componentLen = components.length,
|
||||
newPos = 0,
|
||||
oldPos = 0;
|
||||
|
||||
for (; componentPos < componentLen; componentPos++) {
|
||||
var component = components[componentPos];
|
||||
if (!component.removed) {
|
||||
if (!component.added && useLongestToken) {
|
||||
var value = newString.slice(newPos, newPos + component.count);
|
||||
value = map(value, function(value, i) {
|
||||
var oldValue = oldString[oldPos + i];
|
||||
return oldValue.length > value.length ? oldValue : value;
|
||||
});
|
||||
|
||||
component.value = value.join('');
|
||||
} else {
|
||||
component.value = newString.slice(newPos, newPos + component.count).join('');
|
||||
}
|
||||
newPos += component.count;
|
||||
|
||||
// Common case
|
||||
if (!component.added) {
|
||||
oldPos += component.count;
|
||||
}
|
||||
} else {
|
||||
component.value = oldString.slice(oldPos, oldPos + component.count).join('');
|
||||
oldPos += component.count;
|
||||
}
|
||||
}
|
||||
|
||||
return components;
|
||||
}
|
||||
|
||||
var Diff = function(ignoreWhitespace) {
|
||||
this.ignoreWhitespace = ignoreWhitespace;
|
||||
};
|
||||
Diff.prototype = {
|
||||
diff: function(oldString, newString, callback) {
|
||||
var self = this;
|
||||
|
||||
function done(value) {
|
||||
if (callback) {
|
||||
setTimeout(function() { callback(undefined, value); }, 0);
|
||||
return true;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the identity case (this is due to unrolling editLength == 0
|
||||
if (newString === oldString) {
|
||||
return done([{ value: newString }]);
|
||||
}
|
||||
if (!newString) {
|
||||
return done([{ value: oldString, removed: true }]);
|
||||
}
|
||||
if (!oldString) {
|
||||
return done([{ value: newString, added: true }]);
|
||||
}
|
||||
|
||||
newString = this.tokenize(newString);
|
||||
oldString = this.tokenize(oldString);
|
||||
|
||||
var newLen = newString.length, oldLen = oldString.length;
|
||||
var maxEditLength = newLen + oldLen;
|
||||
var bestPath = [{ newPos: -1, components: [] }];
|
||||
|
||||
// Seed editLength = 0, i.e. the content starts with the same values
|
||||
var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);
|
||||
if (bestPath[0].newPos+1 >= newLen && oldPos+1 >= oldLen) {
|
||||
// Identity per the equality and tokenizer
|
||||
return done([{value: newString.join('')}]);
|
||||
}
|
||||
|
||||
// Main worker method. checks all permutations of a given edit length for acceptance.
|
||||
function execEditLength() {
|
||||
for (var diagonalPath = -1*editLength; diagonalPath <= editLength; diagonalPath+=2) {
|
||||
var basePath;
|
||||
var addPath = bestPath[diagonalPath-1],
|
||||
removePath = bestPath[diagonalPath+1];
|
||||
oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
|
||||
if (addPath) {
|
||||
// No one else is going to attempt to use this value, clear it
|
||||
bestPath[diagonalPath-1] = undefined;
|
||||
}
|
||||
|
||||
var canAdd = addPath && addPath.newPos+1 < newLen;
|
||||
var canRemove = removePath && 0 <= oldPos && oldPos < oldLen;
|
||||
if (!canAdd && !canRemove) {
|
||||
// If this path is a terminal then prune
|
||||
bestPath[diagonalPath] = undefined;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Select the diagonal that we want to branch from. We select the prior
|
||||
// path whose position in the new string is the farthest from the origin
|
||||
// and does not pass the bounds of the diff graph
|
||||
if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) {
|
||||
basePath = clonePath(removePath);
|
||||
self.pushComponent(basePath.components, undefined, true);
|
||||
} else {
|
||||
basePath = addPath; // No need to clone, we've pulled it from the list
|
||||
basePath.newPos++;
|
||||
self.pushComponent(basePath.components, true, undefined);
|
||||
}
|
||||
|
||||
var oldPos = self.extractCommon(basePath, newString, oldString, diagonalPath);
|
||||
|
||||
// If we have hit the end of both strings, then we are done
|
||||
if (basePath.newPos+1 >= newLen && oldPos+1 >= oldLen) {
|
||||
return done(buildValues(basePath.components, newString, oldString, self.useLongestToken));
|
||||
} else {
|
||||
// Otherwise track this path as a potential candidate and continue.
|
||||
bestPath[diagonalPath] = basePath;
|
||||
}
|
||||
}
|
||||
|
||||
editLength++;
|
||||
}
|
||||
|
||||
// Performs the length of edit iteration. Is a bit fugly as this has to support the
|
||||
// sync and async mode which is never fun. Loops over execEditLength until a value
|
||||
// is produced.
|
||||
var editLength = 1;
|
||||
if (callback) {
|
||||
(function exec() {
|
||||
setTimeout(function() {
|
||||
// This should not happen, but we want to be safe.
|
||||
/*istanbul ignore next */
|
||||
if (editLength > maxEditLength) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
if (!execEditLength()) {
|
||||
exec();
|
||||
}
|
||||
}, 0);
|
||||
})();
|
||||
} else {
|
||||
while(editLength <= maxEditLength) {
|
||||
var ret = execEditLength();
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
pushComponent: function(components, added, removed) {
|
||||
var last = components[components.length-1];
|
||||
if (last && last.added === added && last.removed === removed) {
|
||||
// We need to clone here as the component clone operation is just
|
||||
// as shallow array clone
|
||||
components[components.length-1] = {count: last.count + 1, added: added, removed: removed };
|
||||
} else {
|
||||
components.push({count: 1, added: added, removed: removed });
|
||||
}
|
||||
},
|
||||
extractCommon: function(basePath, newString, oldString, diagonalPath) {
|
||||
var newLen = newString.length,
|
||||
oldLen = oldString.length,
|
||||
newPos = basePath.newPos,
|
||||
oldPos = newPos - diagonalPath,
|
||||
|
||||
commonCount = 0;
|
||||
while (newPos+1 < newLen && oldPos+1 < oldLen && this.equals(newString[newPos+1], oldString[oldPos+1])) {
|
||||
newPos++;
|
||||
oldPos++;
|
||||
commonCount++;
|
||||
}
|
||||
|
||||
if (commonCount) {
|
||||
basePath.components.push({count: commonCount});
|
||||
}
|
||||
|
||||
basePath.newPos = newPos;
|
||||
return oldPos;
|
||||
},
|
||||
|
||||
equals: function(left, right) {
|
||||
var reWhitespace = /\S/;
|
||||
return left === right || (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right));
|
||||
},
|
||||
tokenize: function(value) {
|
||||
return value.split('');
|
||||
}
|
||||
};
|
||||
|
||||
var CharDiff = new Diff();
|
||||
|
||||
var WordDiff = new Diff(true);
|
||||
var WordWithSpaceDiff = new Diff();
|
||||
WordDiff.tokenize = WordWithSpaceDiff.tokenize = function(value) {
|
||||
return removeEmpty(value.split(/(\s+|\b)/));
|
||||
};
|
||||
|
||||
var CssDiff = new Diff(true);
|
||||
CssDiff.tokenize = function(value) {
|
||||
return removeEmpty(value.split(/([{}:;,]|\s+)/));
|
||||
};
|
||||
|
||||
var LineDiff = new Diff();
|
||||
|
||||
var TrimmedLineDiff = new Diff();
|
||||
TrimmedLineDiff.ignoreTrim = true;
|
||||
|
||||
LineDiff.tokenize = TrimmedLineDiff.tokenize = function(value) {
|
||||
var retLines = [],
|
||||
lines = value.split(/^/m);
|
||||
for(var i = 0; i < lines.length; i++) {
|
||||
var line = lines[i],
|
||||
lastLine = lines[i - 1],
|
||||
lastLineLastChar = lastLine ? lastLine[lastLine.length - 1] : '';
|
||||
|
||||
// Merge lines that may contain windows new lines
|
||||
if (line === '\n' && lastLineLastChar === '\r') {
|
||||
retLines[retLines.length - 1] = retLines[retLines.length - 1].slice(0,-1) + '\r\n';
|
||||
} else if (line) {
|
||||
if (this.ignoreTrim) {
|
||||
line = line.trim();
|
||||
//add a newline unless this is the last line.
|
||||
if (i < lines.length - 1) {
|
||||
line += '\n';
|
||||
}
|
||||
}
|
||||
retLines.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
return retLines;
|
||||
};
|
||||
|
||||
|
||||
var SentenceDiff = new Diff();
|
||||
SentenceDiff.tokenize = function (value) {
|
||||
return removeEmpty(value.split(/(\S.+?[.!?])(?=\s+|$)/));
|
||||
};
|
||||
|
||||
var JsonDiff = new Diff();
|
||||
// Discriminate between two lines of pretty-printed, serialized JSON where one of them has a
|
||||
// dangling comma and the other doesn't. Turns out including the dangling comma yields the nicest output:
|
||||
JsonDiff.useLongestToken = true;
|
||||
JsonDiff.tokenize = LineDiff.tokenize;
|
||||
JsonDiff.equals = function(left, right) {
|
||||
return LineDiff.equals(left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1'));
|
||||
};
|
||||
|
||||
var objectPrototypeToString = Object.prototype.toString;
|
||||
|
||||
// This function handles the presence of circular references by bailing out when encountering an
|
||||
// object that is already on the "stack" of items being processed.
|
||||
function canonicalize(obj, stack, replacementStack) {
|
||||
stack = stack || [];
|
||||
replacementStack = replacementStack || [];
|
||||
|
||||
var i;
|
||||
|
||||
for (var i = 0 ; i < stack.length ; i += 1) {
|
||||
if (stack[i] === obj) {
|
||||
return replacementStack[i];
|
||||
}
|
||||
}
|
||||
|
||||
var canonicalizedObj;
|
||||
|
||||
if ('[object Array]' === objectPrototypeToString.call(obj)) {
|
||||
stack.push(obj);
|
||||
canonicalizedObj = new Array(obj.length);
|
||||
replacementStack.push(canonicalizedObj);
|
||||
for (i = 0 ; i < obj.length ; i += 1) {
|
||||
canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack);
|
||||
}
|
||||
stack.pop();
|
||||
replacementStack.pop();
|
||||
} else if (typeof obj === 'object' && obj !== null) {
|
||||
stack.push(obj);
|
||||
canonicalizedObj = {};
|
||||
replacementStack.push(canonicalizedObj);
|
||||
var sortedKeys = [];
|
||||
for (var key in obj) {
|
||||
sortedKeys.push(key);
|
||||
}
|
||||
sortedKeys.sort();
|
||||
for (i = 0 ; i < sortedKeys.length ; i += 1) {
|
||||
var key = sortedKeys[i];
|
||||
canonicalizedObj[key] = canonicalize(obj[key], stack, replacementStack);
|
||||
}
|
||||
stack.pop();
|
||||
replacementStack.pop();
|
||||
} else {
|
||||
canonicalizedObj = obj;
|
||||
}
|
||||
return canonicalizedObj;
|
||||
}
|
||||
|
||||
return {
|
||||
Diff: Diff,
|
||||
|
||||
diffChars: function(oldStr, newStr, callback) { return CharDiff.diff(oldStr, newStr, callback); },
|
||||
diffWords: function(oldStr, newStr, callback) { return WordDiff.diff(oldStr, newStr, callback); },
|
||||
diffWordsWithSpace: function(oldStr, newStr, callback) { return WordWithSpaceDiff.diff(oldStr, newStr, callback); },
|
||||
diffLines: function(oldStr, newStr, callback) { return LineDiff.diff(oldStr, newStr, callback); },
|
||||
diffTrimmedLines: function(oldStr, newStr, callback) { return TrimmedLineDiff.diff(oldStr, newStr, callback); },
|
||||
|
||||
diffSentences: function(oldStr, newStr, callback) { return SentenceDiff.diff(oldStr, newStr, callback); },
|
||||
|
||||
diffCss: function(oldStr, newStr, callback) { return CssDiff.diff(oldStr, newStr, callback); },
|
||||
diffJson: function(oldObj, newObj, callback) {
|
||||
return JsonDiff.diff(
|
||||
typeof oldObj === 'string' ? oldObj : JSON.stringify(canonicalize(oldObj), undefined, ' '),
|
||||
typeof newObj === 'string' ? newObj : JSON.stringify(canonicalize(newObj), undefined, ' '),
|
||||
callback
|
||||
);
|
||||
},
|
||||
|
||||
createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) {
|
||||
var ret = [];
|
||||
|
||||
ret.push('Index: ' + fileName);
|
||||
ret.push('===================================================================');
|
||||
ret.push('--- ' + fileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader));
|
||||
ret.push('+++ ' + fileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader));
|
||||
|
||||
var diff = LineDiff.diff(oldStr, newStr);
|
||||
if (!diff[diff.length-1].value) {
|
||||
diff.pop(); // Remove trailing newline add
|
||||
}
|
||||
diff.push({value: '', lines: []}); // Append an empty value to make cleanup easier
|
||||
|
||||
function contextLines(lines) {
|
||||
return map(lines, function(entry) { return ' ' + entry; });
|
||||
}
|
||||
function eofNL(curRange, i, current) {
|
||||
var last = diff[diff.length-2],
|
||||
isLast = i === diff.length-2,
|
||||
isLastOfType = i === diff.length-3 && (current.added !== last.added || current.removed !== last.removed);
|
||||
|
||||
// Figure out if this is the last line for the given file and missing NL
|
||||
if (!/\n$/.test(current.value) && (isLast || isLastOfType)) {
|
||||
curRange.push('\\ No newline at end of file');
|
||||
}
|
||||
}
|
||||
|
||||
var oldRangeStart = 0, newRangeStart = 0, curRange = [],
|
||||
oldLine = 1, newLine = 1;
|
||||
for (var i = 0; i < diff.length; i++) {
|
||||
var current = diff[i],
|
||||
lines = current.lines || current.value.replace(/\n$/, '').split('\n');
|
||||
current.lines = lines;
|
||||
|
||||
if (current.added || current.removed) {
|
||||
if (!oldRangeStart) {
|
||||
var prev = diff[i-1];
|
||||
oldRangeStart = oldLine;
|
||||
newRangeStart = newLine;
|
||||
|
||||
if (prev) {
|
||||
curRange = contextLines(prev.lines.slice(-4));
|
||||
oldRangeStart -= curRange.length;
|
||||
newRangeStart -= curRange.length;
|
||||
}
|
||||
}
|
||||
curRange.push.apply(curRange, map(lines, function(entry) { return (current.added?'+':'-') + entry; }));
|
||||
eofNL(curRange, i, current);
|
||||
|
||||
if (current.added) {
|
||||
newLine += lines.length;
|
||||
} else {
|
||||
oldLine += lines.length;
|
||||
}
|
||||
} else {
|
||||
if (oldRangeStart) {
|
||||
// Close out any changes that have been output (or join overlapping)
|
||||
if (lines.length <= 8 && i < diff.length-2) {
|
||||
// Overlapping
|
||||
curRange.push.apply(curRange, contextLines(lines));
|
||||
} else {
|
||||
// end the range and output
|
||||
var contextSize = Math.min(lines.length, 4);
|
||||
ret.push(
|
||||
'@@ -' + oldRangeStart + ',' + (oldLine-oldRangeStart+contextSize)
|
||||
+ ' +' + newRangeStart + ',' + (newLine-newRangeStart+contextSize)
|
||||
+ ' @@');
|
||||
ret.push.apply(ret, curRange);
|
||||
ret.push.apply(ret, contextLines(lines.slice(0, contextSize)));
|
||||
if (lines.length <= 4) {
|
||||
eofNL(ret, i, current);
|
||||
}
|
||||
|
||||
oldRangeStart = 0; newRangeStart = 0; curRange = [];
|
||||
}
|
||||
}
|
||||
oldLine += lines.length;
|
||||
newLine += lines.length;
|
||||
}
|
||||
}
|
||||
|
||||
return ret.join('\n') + '\n';
|
||||
},
|
||||
|
||||
applyPatch: function(oldStr, uniDiff) {
|
||||
var diffstr = uniDiff.split('\n');
|
||||
var diff = [];
|
||||
var i = 0,
|
||||
remEOFNL = false,
|
||||
addEOFNL = false;
|
||||
|
||||
// Skip to the first change chunk
|
||||
while (i < diffstr.length && !/^@@/.test(diffstr[i])) {
|
||||
i++;
|
||||
}
|
||||
|
||||
for (; i < diffstr.length; i++) {
|
||||
if (diffstr[i][0] === '@') {
|
||||
var meh = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/);
|
||||
diff.unshift({
|
||||
start:meh[3],
|
||||
oldlength:meh[2],
|
||||
oldlines:[],
|
||||
newlength:meh[4],
|
||||
newlines:[]
|
||||
});
|
||||
} else if (diffstr[i][0] === '+') {
|
||||
diff[0].newlines.push(diffstr[i].substr(1));
|
||||
} else if (diffstr[i][0] === '-') {
|
||||
diff[0].oldlines.push(diffstr[i].substr(1));
|
||||
} else if (diffstr[i][0] === ' ') {
|
||||
diff[0].newlines.push(diffstr[i].substr(1));
|
||||
diff[0].oldlines.push(diffstr[i].substr(1));
|
||||
} else if (diffstr[i][0] === '\\') {
|
||||
if (diffstr[i-1][0] === '+') {
|
||||
remEOFNL = true;
|
||||
} else if (diffstr[i-1][0] === '-') {
|
||||
addEOFNL = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var str = oldStr.split('\n');
|
||||
for (var i = diff.length - 1; i >= 0; i--) {
|
||||
var d = diff[i];
|
||||
for (var j = 0; j < d.oldlength; j++) {
|
||||
if (str[d.start-1+j] !== d.oldlines[j]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Array.prototype.splice.apply(str,[d.start-1,+d.oldlength].concat(d.newlines));
|
||||
}
|
||||
|
||||
if (remEOFNL) {
|
||||
while (!str[str.length-1]) {
|
||||
str.pop();
|
||||
}
|
||||
} else if (addEOFNL) {
|
||||
str.push('');
|
||||
}
|
||||
return str.join('\n');
|
||||
},
|
||||
|
||||
convertChangesToXML: function(changes){
|
||||
var ret = [];
|
||||
for ( var i = 0; i < changes.length; i++) {
|
||||
var change = changes[i];
|
||||
if (change.added) {
|
||||
ret.push('<ins>');
|
||||
} else if (change.removed) {
|
||||
ret.push('<del>');
|
||||
}
|
||||
|
||||
ret.push(escapeHTML(change.value));
|
||||
|
||||
if (change.added) {
|
||||
ret.push('</ins>');
|
||||
} else if (change.removed) {
|
||||
ret.push('</del>');
|
||||
}
|
||||
}
|
||||
return ret.join('');
|
||||
},
|
||||
|
||||
// See: http://code.google.com/p/google-diff-match-patch/wiki/API
|
||||
convertChangesToDMP: function(changes){
|
||||
var ret = [], change;
|
||||
for ( var i = 0; i < changes.length; i++) {
|
||||
change = changes[i];
|
||||
ret.push([(change.added ? 1 : change.removed ? -1 : 0), change.value]);
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
|
||||
canonicalize: canonicalize
|
||||
};
|
||||
})();
|
||||
|
||||
/*istanbul ignore next */
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = JsDiff;
|
||||
}
|
||||
else if (typeof define === 'function' && define.amd) {
|
||||
/*global define */
|
||||
define([], function() { return JsDiff; });
|
||||
}
|
||||
else if (typeof global.JsDiff === 'undefined') {
|
||||
global.JsDiff = JsDiff;
|
||||
}
|
||||
})(this);
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
var global = this;
|
||||
function require() {
|
||||
return global;
|
||||
}
|
||||
|
|
@ -1,222 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Diff Parser (diff-parser.js)
|
||||
* Author: rtfpessoa
|
||||
*
|
||||
*/
|
||||
|
||||
(function (global, undefined) {
|
||||
|
||||
var utils = require("./utils.js").Utils;
|
||||
|
||||
var LINE_TYPE = {
|
||||
INSERTS: "d2h-ins",
|
||||
DELETES: "d2h-del",
|
||||
CONTEXT: "d2h-cntx",
|
||||
INFO: "d2h-info"
|
||||
};
|
||||
|
||||
function DiffParser() {
|
||||
}
|
||||
|
||||
DiffParser.prototype.LINE_TYPE = LINE_TYPE;
|
||||
|
||||
DiffParser.prototype.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;
|
||||
|
||||
if (values = /^@@ -(\d+),\d+ \+(\d+),\d+ @@.*/.exec(line)) {
|
||||
currentFile.isCombined = false;
|
||||
} else if (values = /^@@@ -(\d+),\d+ -\d+,\d+ \+(\d+),\d+ @@@.*/.exec(line)) {
|
||||
currentFile.isCombined = true;
|
||||
} else {
|
||||
values = [0, 0];
|
||||
currentFile.isCombined = false;
|
||||
}
|
||||
|
||||
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 (utils.startsWith(line, "+") || utils.startsWith(line, " +")) {
|
||||
currentFile.addedLines++;
|
||||
|
||||
currentLine.type = LINE_TYPE.INSERTS;
|
||||
currentLine.oldNumber = null;
|
||||
currentLine.newNumber = newLine++;
|
||||
|
||||
currentBlock.lines.push(currentLine);
|
||||
|
||||
} else if (utils.startsWith(line, "-") || utils.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 || utils.startsWith(line, "*")) {
|
||||
//|| utils.startsWith(line, "new") || utils.startsWith(line, "index")
|
||||
return;
|
||||
}
|
||||
|
||||
/* Diff */
|
||||
var oldMode = /old mode (\d{6})/;
|
||||
var newMode = /new mode (\d{6})/;
|
||||
var deletedFileMode = /deleted file mode (\d{6})/;
|
||||
var newFileMode = /new file mode (\d{6})/;
|
||||
|
||||
var copyFrom = /copy from (.+)/;
|
||||
var copyTo = /copy to (.+)/;
|
||||
|
||||
var renameFrom = /rename from (.+)/;
|
||||
var renameTo = /rename to (.+)/;
|
||||
|
||||
var similarityIndex = /similarity index (\d+)%/;
|
||||
var dissimilarityIndex = /dissimilarity index (\d+)%/;
|
||||
var index = /index ([0-9a-z]+)..([0-9a-z]+) (\d{6})?/;
|
||||
|
||||
/* Combined Diff */
|
||||
var combinedIndex = /index ([0-9a-z]+),([0-9a-z]+)..([0-9a-z]+)/;
|
||||
var combinedMode = /mode (\d{6}),(\d{6})..(\d{6})/;
|
||||
var combinedNewFile = /new file mode (\d{6})/;
|
||||
var combinedDeletedFile = /deleted file mode (\d{6}),(\d{6})/;
|
||||
|
||||
var values = [];
|
||||
if (utils.startsWith(line, "diff")) {
|
||||
startFile();
|
||||
} else if (currentFile && !currentFile.oldName && (values = /^--- a\/(\S+).*$/.exec(line))) {
|
||||
currentFile.oldName = values[1];
|
||||
currentFile.language = getExtension(currentFile.oldName, currentFile.language);
|
||||
} else if (currentFile && !currentFile.newName && (values = /^\+\+\+ [b]?\/(\S+).*$/.exec(line))) {
|
||||
currentFile.newName = values[1];
|
||||
currentFile.language = getExtension(currentFile.newName, currentFile.language);
|
||||
} else if (currentFile && utils.startsWith(line, "@@")) {
|
||||
startBlock(line);
|
||||
} else if ((values = oldMode.exec(line))) {
|
||||
currentFile.oldMode = values[1];
|
||||
} else if ((values = newMode.exec(line))) {
|
||||
currentFile.newMode = values[1];
|
||||
} else if ((values = deletedFileMode.exec(line))) {
|
||||
currentFile.deletedFileMode = values[1];
|
||||
} else if ((values = newFileMode.exec(line))) {
|
||||
currentFile.newFileMode = values[1];
|
||||
} else if ((values = copyFrom.exec(line))) {
|
||||
currentFile.oldName = values[1];
|
||||
currentFile.isCopy = true;
|
||||
} else if ((values = copyTo.exec(line))) {
|
||||
currentFile.newName = values[1];
|
||||
currentFile.isCopy = true;
|
||||
} else if ((values = renameFrom.exec(line))) {
|
||||
currentFile.oldName = values[1];
|
||||
currentFile.isRename = true;
|
||||
} else if ((values = renameTo.exec(line))) {
|
||||
currentFile.newName = values[1];
|
||||
currentFile.isRename = true;
|
||||
} else if ((values = similarityIndex.exec(line))) {
|
||||
currentFile.unchangedPercentage = values[1];
|
||||
} else if ((values = dissimilarityIndex.exec(line))) {
|
||||
currentFile.changedPercentage = values[1];
|
||||
} else if ((values = index.exec(line))) {
|
||||
currentFile.checksumBefore = values[1];
|
||||
currentFile.checksumAfter = values[2];
|
||||
values[2] && (currentFile.mode = values[3]);
|
||||
} else if ((values = combinedIndex.exec(line))) {
|
||||
currentFile.checksumBefore = [values[2], values[3]];
|
||||
currentFile.checksumAfter = values[1];
|
||||
} else if ((values = combinedMode.exec(line))) {
|
||||
currentFile.oldMode = [values[2], values[3]];
|
||||
currentFile.newMode = values[1];
|
||||
} else if ((values = combinedNewFile.exec(line))) {
|
||||
currentFile.newFileMode = values[1];
|
||||
} else if ((values = combinedDeletedFile.exec(line))) {
|
||||
currentFile.deletedFileMode = values[1];
|
||||
} else if (currentBlock) {
|
||||
createLine(line);
|
||||
}
|
||||
});
|
||||
|
||||
saveBlock();
|
||||
saveFile();
|
||||
|
||||
return files;
|
||||
};
|
||||
|
||||
function getExtension(filename, language) {
|
||||
var nameSplit = filename.split(".");
|
||||
if (nameSplit.length > 1) return nameSplit[nameSplit.length - 1];
|
||||
else return language;
|
||||
}
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports.DiffParser = new DiffParser();
|
||||
} else if (typeof global.DiffParser === 'undefined') {
|
||||
global.DiffParser = new DiffParser();
|
||||
}
|
||||
|
||||
})(this);
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Diff to HTML (diff2html.js)
|
||||
* Author: rtfpessoa
|
||||
*
|
||||
* Diff commands:
|
||||
* git diff
|
||||
*/
|
||||
|
||||
(function (global, undefined) {
|
||||
|
||||
var diffParser = require("./diff-parser.js").DiffParser;
|
||||
var htmlPrinter = require("./html-printer.js").HtmlPrinter;
|
||||
|
||||
function Diff2Html() {
|
||||
}
|
||||
|
||||
/*
|
||||
* config
|
||||
* {
|
||||
* "wordByWord" : true (default)
|
||||
* OR
|
||||
* "charByChar" : true
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
Diff2Html.prototype.getJsonFromDiff = function (diffInput) {
|
||||
return diffParser.generateDiffJson(diffInput);
|
||||
};
|
||||
|
||||
/*
|
||||
* Generates pretty html from a json object
|
||||
*/
|
||||
Diff2Html.prototype.getPrettyHtmlFromJson = function (diffJson, config) {
|
||||
var configOrEmpty = config || {};
|
||||
return htmlPrinter.generateLineByLineJsonHtml(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);
|
||||
};
|
||||
|
||||
/*
|
||||
* Generates pretty side by side html from a json object
|
||||
*/
|
||||
Diff2Html.prototype.getPrettySideBySideHtmlFromJson = function (diffJson, config) {
|
||||
var configOrEmpty = config || {};
|
||||
return htmlPrinter.generateSideBySideJsonHtml(diffJson, configOrEmpty);
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports.Diff2Html = new Diff2Html();
|
||||
} else if (typeof global.Diff2Html === 'undefined') {
|
||||
global.Diff2Html = new Diff2Html();
|
||||
}
|
||||
|
||||
})(this);
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* HtmlPrinter (html-printer.js)
|
||||
* Author: rtfpessoa
|
||||
*
|
||||
*/
|
||||
|
||||
(function (global, undefined) {
|
||||
|
||||
var lineByLinePrinter = require("./line-by-line-printer.js").LineByLinePrinter;
|
||||
var sideBySidePrinter = require("./side-by-side-printer.js").SideBySidePrinter;
|
||||
|
||||
function HtmlPrinter() {
|
||||
}
|
||||
|
||||
HtmlPrinter.prototype.generateLineByLineJsonHtml = lineByLinePrinter.generateLineByLineJsonHtml;
|
||||
|
||||
HtmlPrinter.prototype.generateSideBySideJsonHtml = sideBySidePrinter.generateSideBySideJsonHtml;
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports.HtmlPrinter = new HtmlPrinter();
|
||||
} else if (typeof global.HtmlPrinter === 'undefined') {
|
||||
global.HtmlPrinter = new HtmlPrinter();
|
||||
}
|
||||
|
||||
})(this);
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* LineByLinePrinter (line-by-line-printer.js)
|
||||
* Author: rtfpessoa
|
||||
*
|
||||
*/
|
||||
|
||||
(function (global, undefined) {
|
||||
|
||||
var diffParser = require("./diff-parser.js").DiffParser;
|
||||
var printerUtils = require("./printer-utils.js").PrinterUtils;
|
||||
var utils = require("./utils.js").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 = [], newLines = [];
|
||||
var processedOldLines = [], 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;
|
||||
var oldEscapedLine, newEscapedLine;
|
||||
|
||||
if (oldLines.length === newLines.length) {
|
||||
for (j = 0; j < oldLines.length; j++) {
|
||||
oldLine = oldLines[j];
|
||||
newLine = newLines[j];
|
||||
oldEscapedLine = utils.escape(oldLine.content);
|
||||
newEscapedLine = utils.escape(newLine.content);
|
||||
|
||||
config.isCombined = file.isCombined;
|
||||
var diff = printerUtils.diffHighlight(oldEscapedLine, newEscapedLine, config);
|
||||
|
||||
processedOldLines += generateLineHtml(oldLine.type, oldLine.oldNumber, oldLine.newNumber, diff.o);
|
||||
processedNewLines += generateLineHtml(newLine.type, newLine.oldNumber, newLine.newNumber, diff.n);
|
||||
}
|
||||
|
||||
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) {
|
||||
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 + "\">" + content + "</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";
|
||||
}
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports.LineByLinePrinter = new LineByLinePrinter();
|
||||
} else if (typeof global.LineByLinePrinter === 'undefined') {
|
||||
global.LineByLinePrinter = new LineByLinePrinter();
|
||||
}
|
||||
|
||||
})(this);
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* PrinterUtils (printer-utils.js)
|
||||
* Author: rtfpessoa
|
||||
*
|
||||
*/
|
||||
|
||||
(function (global, undefined) {
|
||||
|
||||
// dirty hack for browser compatibility
|
||||
var jsDiff = (typeof JsDiff !== "undefined" && JsDiff) || require("../lib/diff.js");
|
||||
|
||||
function PrinterUtils() {
|
||||
}
|
||||
|
||||
PrinterUtils.prototype.getDiffName = function (file) {
|
||||
var oldFilename = file.oldName;
|
||||
var newFilename = file.newName;
|
||||
|
||||
if (oldFilename && newFilename
|
||||
&& oldFilename !== newFilename
|
||||
&& !isDeletedName(newFilename)) {
|
||||
return oldFilename + " -> " + newFilename;
|
||||
} else if (newFilename && !isDeletedName(newFilename)) {
|
||||
return newFilename;
|
||||
} else if (oldFilename) {
|
||||
return oldFilename;
|
||||
} else {
|
||||
return "Unknown filename";
|
||||
}
|
||||
};
|
||||
|
||||
PrinterUtils.prototype.diffHighlight = function (diffLine1, diffLine2, config) {
|
||||
var lineStart1, lineStart2;
|
||||
|
||||
var prefixSize = 1;
|
||||
|
||||
if (config.isCombined) prefixSize = 2;
|
||||
|
||||
lineStart1 = diffLine1.substr(0, prefixSize);
|
||||
lineStart2 = diffLine2.substr(0, prefixSize);
|
||||
|
||||
diffLine1 = diffLine1.substr(prefixSize);
|
||||
diffLine2 = diffLine2.substr(prefixSize);
|
||||
|
||||
var diff;
|
||||
if (config.charByChar) diff = jsDiff.diffChars(diffLine1, diffLine2);
|
||||
else diff = jsDiff.diffWordsWithSpace(diffLine1, diffLine2);
|
||||
|
||||
//var diff = jsDiff.diffChars(diffLine1, diffLine2);
|
||||
//var diff = jsDiff.diffWordsWithSpace(diffLine1, diffLine2);
|
||||
|
||||
var highlightedLine = "";
|
||||
|
||||
diff.forEach(function (part) {
|
||||
var elemType = part.added ? 'ins' : part.removed ? 'del' : null;
|
||||
|
||||
if (elemType !== null) highlightedLine += "<" + elemType + ">" + part.value + "</" + elemType + ">";
|
||||
else highlightedLine += part.value;
|
||||
});
|
||||
|
||||
return {
|
||||
o: lineStart1 + removeIns(highlightedLine),
|
||||
n: lineStart2 + removeDel(highlightedLine)
|
||||
}
|
||||
};
|
||||
|
||||
function isDeletedName(name) {
|
||||
return name === "dev/null";
|
||||
}
|
||||
|
||||
function removeIns(line) {
|
||||
return line.replace(/(<ins>((.|\n)*?)<\/ins>)/g, "");
|
||||
}
|
||||
|
||||
function removeDel(line) {
|
||||
return line.replace(/(<del>((.|\n)*?)<\/del>)/g, "");
|
||||
}
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports.PrinterUtils = new PrinterUtils();
|
||||
} else if (typeof global.PrinterUtils === 'undefined') {
|
||||
global.PrinterUtils = new PrinterUtils();
|
||||
}
|
||||
|
||||
})(this);
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* HtmlPrinter (html-printer.js)
|
||||
* Author: rtfpessoa
|
||||
*
|
||||
*/
|
||||
|
||||
(function (global, undefined) {
|
||||
|
||||
var diffParser = require("./diff-parser.js").DiffParser;
|
||||
var printerUtils = require("./printer-utils.js").PrinterUtils;
|
||||
var utils = require("./utils.js").Utils;
|
||||
|
||||
function SideBySidePrinter() {
|
||||
}
|
||||
|
||||
SideBySidePrinter.prototype.generateSideBySideJsonHtml = function (diffFiles, config) {
|
||||
return "<div class=\"d2h-wrapper\">\n" +
|
||||
diffFiles.map(function (file) {
|
||||
|
||||
var diffs;
|
||||
if (file.blocks.length) diffs = generateSideBySideFileHtml(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-files-diff\">\n" +
|
||||
" <div class=\"d2h-file-side-diff\">\n" +
|
||||
" <div class=\"d2h-code-wrapper\">\n" +
|
||||
" <table class=\"d2h-diff-table\">\n" +
|
||||
" <tbody class=\"d2h-diff-tbody\">\n" +
|
||||
" " + diffs.left +
|
||||
" </tbody>\n" +
|
||||
" </table>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"d2h-file-side-diff\">\n" +
|
||||
" <div class=\"d2h-code-wrapper\">\n" +
|
||||
" <table class=\"d2h-diff-table\">\n" +
|
||||
" <tbody class=\"d2h-diff-tbody\">\n" +
|
||||
" " + diffs.right +
|
||||
" </tbody>\n" +
|
||||
" </table>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n";
|
||||
}).join("\n") +
|
||||
"</div>\n";
|
||||
};
|
||||
|
||||
function generateSideBySideFileHtml(file, config) {
|
||||
var fileHtml = {};
|
||||
fileHtml.left = "";
|
||||
fileHtml.right = "";
|
||||
|
||||
file.blocks.forEach(function (block) {
|
||||
|
||||
fileHtml.left += "<tr>\n" +
|
||||
" <td class=\"d2h-code-side-linenumber " + diffParser.LINE_TYPE.INFO + "\"></td>\n" +
|
||||
" <td class=\"" + diffParser.LINE_TYPE.INFO + "\">" +
|
||||
" <div class=\"d2h-code-side-line " + diffParser.LINE_TYPE.INFO + "\">" + utils.escape(block.header) + "</div>" +
|
||||
" </td>\n" +
|
||||
"</tr>\n";
|
||||
|
||||
fileHtml.right += "<tr>\n" +
|
||||
" <td class=\"d2h-code-side-linenumber " + diffParser.LINE_TYPE.INFO + "\"></td>\n" +
|
||||
" <td class=\"" + diffParser.LINE_TYPE.INFO + "\">" +
|
||||
" <div class=\"d2h-code-side-line " + diffParser.LINE_TYPE.INFO + "\"></div>" +
|
||||
" </td>\n" +
|
||||
"</tr>\n";
|
||||
|
||||
var oldLines = [], newLines = [];
|
||||
var tmpHtml = "";
|
||||
|
||||
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) {
|
||||
fileHtml.left += generateSingleLineHtml(line.type, line.oldNumber, escapedLine);
|
||||
fileHtml.right += generateSingleLineHtml(line.type, line.newNumber, escapedLine);
|
||||
} else if (line.type == diffParser.LINE_TYPE.INSERTS && !oldLines.length && !newLines.length) {
|
||||
fileHtml.left += generateSingleLineHtml(diffParser.LINE_TYPE.CONTEXT, "", "", "");
|
||||
fileHtml.right += generateSingleLineHtml(line.type, 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;
|
||||
var oldEscapedLine, newEscapedLine;
|
||||
|
||||
if (oldLines.length === newLines.length) {
|
||||
for (j = 0; j < oldLines.length; j++) {
|
||||
oldLine = oldLines[j];
|
||||
newLine = newLines[j];
|
||||
oldEscapedLine = utils.escape(oldLine.content);
|
||||
newEscapedLine = utils.escape(newLine.content);
|
||||
|
||||
config.isCombined = file.isCombined;
|
||||
|
||||
var diff = printerUtils.diffHighlight(oldEscapedLine, newEscapedLine, config);
|
||||
|
||||
fileHtml.left += generateSingleLineHtml(oldLine.type, oldLine.oldNumber, diff.o);
|
||||
fileHtml.right += generateSingleLineHtml(newLine.type, newLine.newNumber, diff.n);
|
||||
}
|
||||
} else {
|
||||
tmpHtml = processLines(oldLines, newLines);
|
||||
fileHtml.left += tmpHtml.left;
|
||||
fileHtml.right += tmpHtml.right;
|
||||
}
|
||||
|
||||
oldLines = [];
|
||||
newLines = [];
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
tmpHtml = processLines(oldLines, newLines);
|
||||
fileHtml.left += tmpHtml.left;
|
||||
fileHtml.right += tmpHtml.right;
|
||||
});
|
||||
|
||||
return fileHtml;
|
||||
}
|
||||
|
||||
function processLines(oldLines, newLines) {
|
||||
var fileHtml = {};
|
||||
fileHtml.left = "";
|
||||
fileHtml.right = "";
|
||||
|
||||
var maxLinesNumber = Math.max(oldLines.length, newLines.length);
|
||||
for (j = 0; j < maxLinesNumber; j++) {
|
||||
var oldLine = oldLines[j];
|
||||
var newLine = newLines[j];
|
||||
|
||||
if (oldLine && newLine) {
|
||||
fileHtml.left += generateSingleLineHtml(oldLine.type, oldLine.oldNumber, utils.escape(oldLine.content));
|
||||
fileHtml.right += generateSingleLineHtml(newLine.type, newLine.newNumber, utils.escape(newLine.content));
|
||||
} else if (oldLine) {
|
||||
fileHtml.left += generateSingleLineHtml(oldLine.type, oldLine.oldNumber, utils.escape(oldLine.content));
|
||||
fileHtml.right += generateSingleLineHtml(diffParser.LINE_TYPE.CONTEXT, "", "", "");
|
||||
} else if (newLine) {
|
||||
fileHtml.left += generateSingleLineHtml(diffParser.LINE_TYPE.CONTEXT, "", "", "");
|
||||
fileHtml.right += generateSingleLineHtml(newLine.type, newLine.newNumber, utils.escape(newLine.content));
|
||||
} else {
|
||||
console.error("How did it get here?");
|
||||
}
|
||||
}
|
||||
|
||||
return fileHtml;
|
||||
}
|
||||
|
||||
function generateSingleLineHtml(type, number, content) {
|
||||
return "<tr>\n" +
|
||||
" <td class=\"d2h-code-side-linenumber " + type + "\">" + number + "</td>\n" +
|
||||
" <td class=\"" + type + "\">" +
|
||||
" <div class=\"d2h-code-side-line " + type + "\">" + content + "</div>" +
|
||||
" </td>\n" +
|
||||
" </tr>\n";
|
||||
}
|
||||
|
||||
function generateEmptyDiff() {
|
||||
var fileHtml = {};
|
||||
fileHtml.right = "";
|
||||
|
||||
fileHtml.left = "<tr>\n" +
|
||||
" <td class=\"" + diffParser.LINE_TYPE.INFO + "\">" +
|
||||
" <div class=\"d2h-code-side-line " + diffParser.LINE_TYPE.INFO + "\">" +
|
||||
"File without changes" +
|
||||
" </div>" +
|
||||
" </td>\n" +
|
||||
"</tr>\n";
|
||||
|
||||
return fileHtml;
|
||||
}
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports.SideBySidePrinter = new SideBySidePrinter();
|
||||
} else if (typeof global.SideBySidePrinter === 'undefined') {
|
||||
global.SideBySidePrinter = new SideBySidePrinter();
|
||||
}
|
||||
|
||||
})(this);
|
||||
35
src/utils.js
35
src/utils.js
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Utils (utils.js)
|
||||
* Author: rtfpessoa
|
||||
*
|
||||
*/
|
||||
|
||||
(function (global, undefined) {
|
||||
|
||||
function Utils() {
|
||||
}
|
||||
|
||||
Utils.prototype.escape = function (str) {
|
||||
return str.slice(0)
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/\t/g, " ");
|
||||
};
|
||||
|
||||
Utils.prototype.startsWith = function (str, start) {
|
||||
return str.indexOf(start) === 0;
|
||||
};
|
||||
|
||||
Utils.prototype.valueOrEmpty = function (value) {
|
||||
return value ? value : "";
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports.Utils = new Utils();
|
||||
} else if (typeof global.Utils === 'undefined') {
|
||||
global.Utils = new Utils();
|
||||
}
|
||||
|
||||
})(this);
|
||||
Loading…
Reference in a new issue