Skip to content

Commit b88c775

Browse files
authored
Merge pull request #145 from rtfpessoa/fix-stuck
Fix generation of diff with long lines
2 parents 1b0af44 + 16d63a9 commit b88c775

File tree

6 files changed

+121
-55
lines changed

6 files changed

+121
-55
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ The HTML output accepts a Javascript object with configuration. Possible options
9797
- `matching`: matching level: `'lines'` for matching lines, `'words'` for matching lines and words or `'none'`, default is `none`
9898
- `matchWordsThreshold`: similarity threshold for word matching, default is 0.25
9999
- `matchingMaxComparisons`: perform at most this much comparisons for line matching a block of changes, default is `2500`
100+
- `maxLineLengthHighlight`: only perform diff changes highlight if lines are smaller than this, default is `10000`
100101
- `templates`: object with previously compiled templates to replace parts of the html
101102
- `rawTemplates`: object with raw not compiled templates to replace parts of the html
102103
> For more information regarding the possible templates look into [src/templates](https://github.com/rtfpessoa/diff2html/tree/master/src/templates)

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"dependencies": {
5858
"diff": "^3.3.1",
5959
"hogan.js": "^3.0.2",
60+
"lodash": "^4.17.4",
6061
"whatwg-fetch": "^2.0.3"
6162
},
6263
"devDependencies": {

src/diff2html.js

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,48 +8,49 @@
88
(function() {
99
var diffParser = require('./diff-parser.js').DiffParser;
1010
var htmlPrinter = require('./html-printer.js').HtmlPrinter;
11+
var utils = require('./utils.js').Utils;
1112

1213
function Diff2Html() {
1314
}
1415

15-
/*
16-
* Line diff type configuration
17-
var config = {
18-
'wordByWord': true, // (default)
19-
// OR
20-
'charByChar': true
21-
};
22-
*/
16+
var defaultConfig = {
17+
wordByWord: true,
18+
outputFormat: 'line-by-line',
19+
matching: 'none',
20+
matchWordsThreshold: 0.25,
21+
matchingMaxComparisons: 2500,
22+
maxLineLengthHighlight: 10000
23+
};
2324

2425
/*
2526
* Generates json object from string diff input
2627
*/
2728
Diff2Html.prototype.getJsonFromDiff = function(diffInput, config) {
28-
var configOrEmpty = config || {};
29-
return diffParser.generateDiffJson(diffInput, configOrEmpty);
29+
var cfg = utils.safeConfig(config, defaultConfig);
30+
return diffParser.generateDiffJson(diffInput, cfg);
3031
};
3132

3233
/*
3334
* Generates the html diff. The config parameter configures the output/input formats and other options
3435
*/
3536
Diff2Html.prototype.getPrettyHtml = function(diffInput, config) {
36-
var configOrEmpty = config || {};
37+
var cfg = utils.safeConfig(config, defaultConfig);
3738

3839
var diffJson = diffInput;
39-
if (!configOrEmpty.inputFormat || configOrEmpty.inputFormat === 'diff') {
40-
diffJson = diffParser.generateDiffJson(diffInput, configOrEmpty);
40+
if (!cfg.inputFormat || cfg.inputFormat === 'diff') {
41+
diffJson = diffParser.generateDiffJson(diffInput, cfg);
4142
}
4243

4344
var fileList = '';
44-
if (configOrEmpty.showFiles === true) {
45-
fileList = htmlPrinter.generateFileListSummary(diffJson, configOrEmpty);
45+
if (cfg.showFiles === true) {
46+
fileList = htmlPrinter.generateFileListSummary(diffJson, cfg);
4647
}
4748

4849
var diffOutput = '';
49-
if (configOrEmpty.outputFormat === 'side-by-side') {
50-
diffOutput = htmlPrinter.generateSideBySideJsonHtml(diffJson, configOrEmpty);
50+
if (cfg.outputFormat === 'side-by-side') {
51+
diffOutput = htmlPrinter.generateSideBySideJsonHtml(diffJson, cfg);
5152
} else {
52-
diffOutput = htmlPrinter.generateLineByLineJsonHtml(diffJson, configOrEmpty);
53+
diffOutput = htmlPrinter.generateLineByLineJsonHtml(diffJson, cfg);
5354
}
5455

5556
return fileList + diffOutput;
@@ -63,40 +64,40 @@
6364
* Generates pretty html from string diff input
6465
*/
6566
Diff2Html.prototype.getPrettyHtmlFromDiff = function(diffInput, config) {
66-
var configOrEmpty = config || {};
67-
configOrEmpty.inputFormat = 'diff';
68-
configOrEmpty.outputFormat = 'line-by-line';
69-
return this.getPrettyHtml(diffInput, configOrEmpty);
67+
var cfg = utils.safeConfig(config, defaultConfig);
68+
cfg.inputFormat = 'diff';
69+
cfg.outputFormat = 'line-by-line';
70+
return this.getPrettyHtml(diffInput, cfg);
7071
};
7172

7273
/*
7374
* Generates pretty html from a json object
7475
*/
7576
Diff2Html.prototype.getPrettyHtmlFromJson = function(diffJson, config) {
76-
var configOrEmpty = config || {};
77-
configOrEmpty.inputFormat = 'json';
78-
configOrEmpty.outputFormat = 'line-by-line';
79-
return this.getPrettyHtml(diffJson, configOrEmpty);
77+
var cfg = utils.safeConfig(config, defaultConfig);
78+
cfg.inputFormat = 'json';
79+
cfg.outputFormat = 'line-by-line';
80+
return this.getPrettyHtml(diffJson, cfg);
8081
};
8182

8283
/*
8384
* Generates pretty side by side html from string diff input
8485
*/
8586
Diff2Html.prototype.getPrettySideBySideHtmlFromDiff = function(diffInput, config) {
86-
var configOrEmpty = config || {};
87-
configOrEmpty.inputFormat = 'diff';
88-
configOrEmpty.outputFormat = 'side-by-side';
89-
return this.getPrettyHtml(diffInput, configOrEmpty);
87+
var cfg = utils.safeConfig(config, defaultConfig);
88+
cfg.inputFormat = 'diff';
89+
cfg.outputFormat = 'side-by-side';
90+
return this.getPrettyHtml(diffInput, cfg);
9091
};
9192

9293
/*
9394
* Generates pretty side by side html from a json object
9495
*/
9596
Diff2Html.prototype.getPrettySideBySideHtmlFromJson = function(diffJson, config) {
96-
var configOrEmpty = config || {};
97-
configOrEmpty.inputFormat = 'json';
98-
configOrEmpty.outputFormat = 'side-by-side';
99-
return this.getPrettyHtml(diffJson, configOrEmpty);
97+
var cfg = utils.safeConfig(config, defaultConfig);
98+
cfg.inputFormat = 'json';
99+
cfg.outputFormat = 'side-by-side';
100+
return this.getPrettyHtml(diffJson, cfg);
100101
};
101102

102103
var diffObject = new Diff2Html();

src/printer-utils.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,20 @@
144144
unprefixedLine1 = diffLine1.substr(prefixSize);
145145
unprefixedLine2 = diffLine2.substr(prefixSize);
146146

147+
if (unprefixedLine1.length > config.maxLineLengthHighlight ||
148+
unprefixedLine2.length > config.maxLineLengthHighlight) {
149+
return {
150+
first: {
151+
prefix: linePrefix1,
152+
line: utils.escape(unprefixedLine1)
153+
},
154+
second: {
155+
prefix: linePrefix2,
156+
line: utils.escape(unprefixedLine2)
157+
}
158+
};
159+
}
160+
147161
var diff;
148162
if (config.charByChar) {
149163
diff = jsDiff.diffChars(unprefixedLine1, unprefixedLine2);

src/utils.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
*/
77

88
(function() {
9+
var lodash = require('lodash');
10+
911
function Utils() {
1012
}
1113

@@ -39,5 +41,11 @@
3941
return value || '';
4042
};
4143

44+
Utils.prototype.safeConfig = function(cfg, defaultConfig) {
45+
var newCfg = {};
46+
lodash.merge(newCfg, defaultConfig, cfg);
47+
return newCfg;
48+
};
49+
4250
module.exports.Utils = new Utils();
4351
})();

website/templates/pages/demo/demo.js

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ $(document).ready(function() {
2424
var $outputFormat = $('#diff-url-options-output-format');
2525
var $showFiles = $('#diff-url-options-show-files');
2626
var $matching = $('#diff-url-options-matching');
27-
var $wordThreshold = $('#diff-url-options-match-words-threshold');
27+
var $wordsThreshold = $('#diff-url-options-match-words-threshold');
2828
var $matchingMaxComparisons = $('#diff-url-options-matching-max-comparisons');
2929

3030
if (window.location.search) {
@@ -38,10 +38,13 @@ $(document).ready(function() {
3838
$outputFormat
3939
.add($showFiles)
4040
.add($matching)
41-
.add($wordThreshold)
41+
.add($wordsThreshold)
4242
.add($matchingMaxComparisons)
43-
.change(function() {
44-
smartDraw();
43+
.change(function(e) {
44+
console.log('');
45+
console.log(e);
46+
console.log('');
47+
smartDraw(null, true);
4548
});
4649

4750
function getUrlFromSearch(search) {
@@ -56,6 +59,22 @@ $(document).ready(function() {
5659
return null;
5760
}
5861

62+
function getParamsFromSearch(search) {
63+
var map = {};
64+
try {
65+
search
66+
.split('?')[1]
67+
.split('&')
68+
.map(function(e) {
69+
var values = e.split('=');
70+
map[values[0]] = values[1];
71+
});
72+
} catch (_ignore) {
73+
}
74+
75+
return map;
76+
}
77+
5978
function bind() {
6079
$('#url-btn').click(function(e) {
6180
e.preventDefault();
@@ -124,13 +143,13 @@ $(document).ready(function() {
124143
};
125144
}
126145

127-
function smartDraw(urlOpt) {
146+
function smartDraw(urlOpt, forced) {
128147
var url = urlOpt || $url.val();
129148
var req = prepareUrl(url);
130-
draw(req);
149+
draw(req, forced);
131150
}
132151

133-
function draw(req) {
152+
function draw(req, forced) {
134153
if (!validateUrl(req.url)) {
135154
console.error('Invalid url provided!');
136155
return;
@@ -141,7 +160,7 @@ $(document).ready(function() {
141160
var outputFormat = $outputFormat.val();
142161
var showFiles = $showFiles.is(':checked');
143162
var matching = $matching.val();
144-
var wordThreshold = $wordThreshold.val();
163+
var wordsThreshold = $wordsThreshold.val();
145164
var matchingMaxComparisons = $matchingMaxComparisons.val();
146165

147166
fetch(req.url, {
@@ -163,16 +182,34 @@ $(document).ready(function() {
163182
$container.css({'width': ''});
164183
}
165184

166-
diff2htmlUi.draw(container, {
167-
outputFormat: outputFormat,
168-
showFiles: showFiles,
169-
matching: matching,
170-
matchWordsThreshold: wordThreshold,
171-
matchingMaxComparisons: matchingMaxComparisons,
172-
synchronisedScroll: true
173-
});
174-
diff2htmlUi.fileListCloseable(container, false);
175-
diff2htmlUi.highlightCode(container);
185+
var params = getParamsFromSearch(window.location.search);
186+
delete params[searchParam];
187+
188+
if (forced) {
189+
params['outputFormat'] = outputFormat;
190+
params['showFiles'] = showFiles;
191+
params['matching'] = matching;
192+
params['wordsThreshold'] = wordsThreshold;
193+
params['matchingMaxComparisons'] = matchingMaxComparisons;
194+
} else {
195+
params['outputFormat'] = params['outputFormat'] || outputFormat;
196+
params['showFiles'] = String(params['showFiles']) !== 'false' || (params['showFiles'] === null && showFiles);
197+
params['matching'] = params['matching'] || matching;
198+
params['wordsThreshold'] = params['wordsThreshold'] || wordsThreshold;
199+
params['matchingMaxComparisons'] = params['matchingMaxComparisons'] || matchingMaxComparisons;
200+
201+
$outputFormat.val(params['outputFormat']);
202+
$showFiles.prop('checked', params['showFiles']);
203+
$matching.val(params['matching']);
204+
$wordsThreshold.val(params['wordsThreshold']);
205+
$matchingMaxComparisons.val(params['matchingMaxComparisons']);
206+
}
207+
208+
params['synchronisedScroll'] = params['synchronisedScroll'] || true;
209+
210+
diff2htmlUi.draw(container, params);
211+
diff2htmlUi.fileListCloseable(container, params['fileListCloseable'] || false);
212+
params['highlight'] && diff2htmlUi.highlightCode(container);
176213
});
177214
}
178215

@@ -181,10 +218,14 @@ $(document).ready(function() {
181218
}
182219

183220
function updateUrl(url) {
184-
var currentUrl = getUrlFromSearch(window.location.search);
221+
var params = getParamsFromSearch(window.location.search);
222+
223+
if (params[searchParam] === url) return;
224+
225+
params[searchParam] = url;
185226

186-
if (currentUrl === url) return;
227+
var paramString = Object.keys(params).map(function(k) { return k + '=' + params[k]; }).join('&');
187228

188-
window.location = 'demo.html?' + searchParam + '=' + url;
229+
window.location = 'demo.html?' + paramString;
189230
}
190231
});

0 commit comments

Comments
 (0)