Fix diff generation for long lines
This commit is contained in:
parent
1b0af44179
commit
16d63a92ab
6 changed files with 121 additions and 55 deletions
|
|
@ -97,6 +97,7 @@ The HTML output accepts a Javascript object with configuration. Possible options
|
|||
- `matching`: matching level: `'lines'` for matching lines, `'words'` for matching lines and words or `'none'`, default is `none`
|
||||
- `matchWordsThreshold`: similarity threshold for word matching, default is 0.25
|
||||
- `matchingMaxComparisons`: perform at most this much comparisons for line matching a block of changes, default is `2500`
|
||||
- `maxLineLengthHighlight`: only perform diff changes highlight if lines are smaller than this, default is `10000`
|
||||
- `templates`: object with previously compiled templates to replace parts of the html
|
||||
- `rawTemplates`: object with raw not compiled templates to replace parts of the html
|
||||
> For more information regarding the possible templates look into [src/templates](https://github.com/rtfpessoa/diff2html/tree/master/src/templates)
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@
|
|||
"dependencies": {
|
||||
"diff": "^3.3.1",
|
||||
"hogan.js": "^3.0.2",
|
||||
"lodash": "^4.17.4",
|
||||
"whatwg-fetch": "^2.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -8,48 +8,49 @@
|
|||
(function() {
|
||||
var diffParser = require('./diff-parser.js').DiffParser;
|
||||
var htmlPrinter = require('./html-printer.js').HtmlPrinter;
|
||||
var utils = require('./utils.js').Utils;
|
||||
|
||||
function Diff2Html() {
|
||||
}
|
||||
|
||||
/*
|
||||
* Line diff type configuration
|
||||
var config = {
|
||||
'wordByWord': true, // (default)
|
||||
// OR
|
||||
'charByChar': true
|
||||
var defaultConfig = {
|
||||
wordByWord: true,
|
||||
outputFormat: 'line-by-line',
|
||||
matching: 'none',
|
||||
matchWordsThreshold: 0.25,
|
||||
matchingMaxComparisons: 2500,
|
||||
maxLineLengthHighlight: 10000
|
||||
};
|
||||
*/
|
||||
|
||||
/*
|
||||
* Generates json object from string diff input
|
||||
*/
|
||||
Diff2Html.prototype.getJsonFromDiff = function(diffInput, config) {
|
||||
var configOrEmpty = config || {};
|
||||
return diffParser.generateDiffJson(diffInput, configOrEmpty);
|
||||
var cfg = utils.safeConfig(config, defaultConfig);
|
||||
return diffParser.generateDiffJson(diffInput, cfg);
|
||||
};
|
||||
|
||||
/*
|
||||
* 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 cfg = utils.safeConfig(config, defaultConfig);
|
||||
|
||||
var diffJson = diffInput;
|
||||
if (!configOrEmpty.inputFormat || configOrEmpty.inputFormat === 'diff') {
|
||||
diffJson = diffParser.generateDiffJson(diffInput, configOrEmpty);
|
||||
if (!cfg.inputFormat || cfg.inputFormat === 'diff') {
|
||||
diffJson = diffParser.generateDiffJson(diffInput, cfg);
|
||||
}
|
||||
|
||||
var fileList = '';
|
||||
if (configOrEmpty.showFiles === true) {
|
||||
fileList = htmlPrinter.generateFileListSummary(diffJson, configOrEmpty);
|
||||
if (cfg.showFiles === true) {
|
||||
fileList = htmlPrinter.generateFileListSummary(diffJson, cfg);
|
||||
}
|
||||
|
||||
var diffOutput = '';
|
||||
if (configOrEmpty.outputFormat === 'side-by-side') {
|
||||
diffOutput = htmlPrinter.generateSideBySideJsonHtml(diffJson, configOrEmpty);
|
||||
if (cfg.outputFormat === 'side-by-side') {
|
||||
diffOutput = htmlPrinter.generateSideBySideJsonHtml(diffJson, cfg);
|
||||
} else {
|
||||
diffOutput = htmlPrinter.generateLineByLineJsonHtml(diffJson, configOrEmpty);
|
||||
diffOutput = htmlPrinter.generateLineByLineJsonHtml(diffJson, cfg);
|
||||
}
|
||||
|
||||
return fileList + diffOutput;
|
||||
|
|
@ -63,40 +64,40 @@
|
|||
* 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);
|
||||
var cfg = utils.safeConfig(config, defaultConfig);
|
||||
cfg.inputFormat = 'diff';
|
||||
cfg.outputFormat = 'line-by-line';
|
||||
return this.getPrettyHtml(diffInput, cfg);
|
||||
};
|
||||
|
||||
/*
|
||||
* Generates pretty html from a json object
|
||||
*/
|
||||
Diff2Html.prototype.getPrettyHtmlFromJson = function(diffJson, config) {
|
||||
var configOrEmpty = config || {};
|
||||
configOrEmpty.inputFormat = 'json';
|
||||
configOrEmpty.outputFormat = 'line-by-line';
|
||||
return this.getPrettyHtml(diffJson, configOrEmpty);
|
||||
var cfg = utils.safeConfig(config, defaultConfig);
|
||||
cfg.inputFormat = 'json';
|
||||
cfg.outputFormat = 'line-by-line';
|
||||
return this.getPrettyHtml(diffJson, cfg);
|
||||
};
|
||||
|
||||
/*
|
||||
* Generates pretty side by side html from string diff input
|
||||
*/
|
||||
Diff2Html.prototype.getPrettySideBySideHtmlFromDiff = function(diffInput, config) {
|
||||
var configOrEmpty = config || {};
|
||||
configOrEmpty.inputFormat = 'diff';
|
||||
configOrEmpty.outputFormat = 'side-by-side';
|
||||
return this.getPrettyHtml(diffInput, configOrEmpty);
|
||||
var cfg = utils.safeConfig(config, defaultConfig);
|
||||
cfg.inputFormat = 'diff';
|
||||
cfg.outputFormat = 'side-by-side';
|
||||
return this.getPrettyHtml(diffInput, cfg);
|
||||
};
|
||||
|
||||
/*
|
||||
* Generates pretty side by side html from a json object
|
||||
*/
|
||||
Diff2Html.prototype.getPrettySideBySideHtmlFromJson = function(diffJson, config) {
|
||||
var configOrEmpty = config || {};
|
||||
configOrEmpty.inputFormat = 'json';
|
||||
configOrEmpty.outputFormat = 'side-by-side';
|
||||
return this.getPrettyHtml(diffJson, configOrEmpty);
|
||||
var cfg = utils.safeConfig(config, defaultConfig);
|
||||
cfg.inputFormat = 'json';
|
||||
cfg.outputFormat = 'side-by-side';
|
||||
return this.getPrettyHtml(diffJson, cfg);
|
||||
};
|
||||
|
||||
var diffObject = new Diff2Html();
|
||||
|
|
|
|||
|
|
@ -144,6 +144,20 @@
|
|||
unprefixedLine1 = diffLine1.substr(prefixSize);
|
||||
unprefixedLine2 = diffLine2.substr(prefixSize);
|
||||
|
||||
if (unprefixedLine1.length > config.maxLineLengthHighlight ||
|
||||
unprefixedLine2.length > config.maxLineLengthHighlight) {
|
||||
return {
|
||||
first: {
|
||||
prefix: linePrefix1,
|
||||
line: utils.escape(unprefixedLine1)
|
||||
},
|
||||
second: {
|
||||
prefix: linePrefix2,
|
||||
line: utils.escape(unprefixedLine2)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var diff;
|
||||
if (config.charByChar) {
|
||||
diff = jsDiff.diffChars(unprefixedLine1, unprefixedLine2);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
|
||||
(function() {
|
||||
var lodash = require('lodash');
|
||||
|
||||
function Utils() {
|
||||
}
|
||||
|
||||
|
|
@ -39,5 +41,11 @@
|
|||
return value || '';
|
||||
};
|
||||
|
||||
Utils.prototype.safeConfig = function(cfg, defaultConfig) {
|
||||
var newCfg = {};
|
||||
lodash.merge(newCfg, defaultConfig, cfg);
|
||||
return newCfg;
|
||||
};
|
||||
|
||||
module.exports.Utils = new Utils();
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ $(document).ready(function() {
|
|||
var $outputFormat = $('#diff-url-options-output-format');
|
||||
var $showFiles = $('#diff-url-options-show-files');
|
||||
var $matching = $('#diff-url-options-matching');
|
||||
var $wordThreshold = $('#diff-url-options-match-words-threshold');
|
||||
var $wordsThreshold = $('#diff-url-options-match-words-threshold');
|
||||
var $matchingMaxComparisons = $('#diff-url-options-matching-max-comparisons');
|
||||
|
||||
if (window.location.search) {
|
||||
|
|
@ -38,10 +38,13 @@ $(document).ready(function() {
|
|||
$outputFormat
|
||||
.add($showFiles)
|
||||
.add($matching)
|
||||
.add($wordThreshold)
|
||||
.add($wordsThreshold)
|
||||
.add($matchingMaxComparisons)
|
||||
.change(function() {
|
||||
smartDraw();
|
||||
.change(function(e) {
|
||||
console.log('');
|
||||
console.log(e);
|
||||
console.log('');
|
||||
smartDraw(null, true);
|
||||
});
|
||||
|
||||
function getUrlFromSearch(search) {
|
||||
|
|
@ -56,6 +59,22 @@ $(document).ready(function() {
|
|||
return null;
|
||||
}
|
||||
|
||||
function getParamsFromSearch(search) {
|
||||
var map = {};
|
||||
try {
|
||||
search
|
||||
.split('?')[1]
|
||||
.split('&')
|
||||
.map(function(e) {
|
||||
var values = e.split('=');
|
||||
map[values[0]] = values[1];
|
||||
});
|
||||
} catch (_ignore) {
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
function bind() {
|
||||
$('#url-btn').click(function(e) {
|
||||
e.preventDefault();
|
||||
|
|
@ -124,13 +143,13 @@ $(document).ready(function() {
|
|||
};
|
||||
}
|
||||
|
||||
function smartDraw(urlOpt) {
|
||||
function smartDraw(urlOpt, forced) {
|
||||
var url = urlOpt || $url.val();
|
||||
var req = prepareUrl(url);
|
||||
draw(req);
|
||||
draw(req, forced);
|
||||
}
|
||||
|
||||
function draw(req) {
|
||||
function draw(req, forced) {
|
||||
if (!validateUrl(req.url)) {
|
||||
console.error('Invalid url provided!');
|
||||
return;
|
||||
|
|
@ -141,7 +160,7 @@ $(document).ready(function() {
|
|||
var outputFormat = $outputFormat.val();
|
||||
var showFiles = $showFiles.is(':checked');
|
||||
var matching = $matching.val();
|
||||
var wordThreshold = $wordThreshold.val();
|
||||
var wordsThreshold = $wordsThreshold.val();
|
||||
var matchingMaxComparisons = $matchingMaxComparisons.val();
|
||||
|
||||
fetch(req.url, {
|
||||
|
|
@ -163,16 +182,34 @@ $(document).ready(function() {
|
|||
$container.css({'width': ''});
|
||||
}
|
||||
|
||||
diff2htmlUi.draw(container, {
|
||||
outputFormat: outputFormat,
|
||||
showFiles: showFiles,
|
||||
matching: matching,
|
||||
matchWordsThreshold: wordThreshold,
|
||||
matchingMaxComparisons: matchingMaxComparisons,
|
||||
synchronisedScroll: true
|
||||
});
|
||||
diff2htmlUi.fileListCloseable(container, false);
|
||||
diff2htmlUi.highlightCode(container);
|
||||
var params = getParamsFromSearch(window.location.search);
|
||||
delete params[searchParam];
|
||||
|
||||
if (forced) {
|
||||
params['outputFormat'] = outputFormat;
|
||||
params['showFiles'] = showFiles;
|
||||
params['matching'] = matching;
|
||||
params['wordsThreshold'] = wordsThreshold;
|
||||
params['matchingMaxComparisons'] = matchingMaxComparisons;
|
||||
} else {
|
||||
params['outputFormat'] = params['outputFormat'] || outputFormat;
|
||||
params['showFiles'] = String(params['showFiles']) !== 'false' || (params['showFiles'] === null && showFiles);
|
||||
params['matching'] = params['matching'] || matching;
|
||||
params['wordsThreshold'] = params['wordsThreshold'] || wordsThreshold;
|
||||
params['matchingMaxComparisons'] = params['matchingMaxComparisons'] || matchingMaxComparisons;
|
||||
|
||||
$outputFormat.val(params['outputFormat']);
|
||||
$showFiles.prop('checked', params['showFiles']);
|
||||
$matching.val(params['matching']);
|
||||
$wordsThreshold.val(params['wordsThreshold']);
|
||||
$matchingMaxComparisons.val(params['matchingMaxComparisons']);
|
||||
}
|
||||
|
||||
params['synchronisedScroll'] = params['synchronisedScroll'] || true;
|
||||
|
||||
diff2htmlUi.draw(container, params);
|
||||
diff2htmlUi.fileListCloseable(container, params['fileListCloseable'] || false);
|
||||
params['highlight'] && diff2htmlUi.highlightCode(container);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -181,10 +218,14 @@ $(document).ready(function() {
|
|||
}
|
||||
|
||||
function updateUrl(url) {
|
||||
var currentUrl = getUrlFromSearch(window.location.search);
|
||||
var params = getParamsFromSearch(window.location.search);
|
||||
|
||||
if (currentUrl === url) return;
|
||||
if (params[searchParam] === url) return;
|
||||
|
||||
window.location = 'demo.html?' + searchParam + '=' + url;
|
||||
params[searchParam] = url;
|
||||
|
||||
var paramString = Object.keys(params).map(function(k) { return k + '=' + params[k]; }).join('&');
|
||||
|
||||
window.location = 'demo.html?' + paramString;
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue