diff --git a/README.md b/README.md index 7d0dadc..5ab7532 100644 --- a/README.md +++ b/README.md @@ -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) diff --git a/package.json b/package.json index 8051ca1..5a1b58e 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "dependencies": { "diff": "^3.3.1", "hogan.js": "^3.0.2", + "lodash": "^4.17.4", "whatwg-fetch": "^2.0.3" }, "devDependencies": { diff --git a/src/diff2html.js b/src/diff2html.js index 64e138f..7931496 100644 --- a/src/diff2html.js +++ b/src/diff2html.js @@ -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(); diff --git a/src/printer-utils.js b/src/printer-utils.js index 3e0ab0d..d6edef8 100644 --- a/src/printer-utils.js +++ b/src/printer-utils.js @@ -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); diff --git a/src/utils.js b/src/utils.js index 35ea3e2..f46983f 100644 --- a/src/utils.js +++ b/src/utils.js @@ -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(); })(); diff --git a/website/templates/pages/demo/demo.js b/website/templates/pages/demo/demo.js index 4e97733..9d7874f 100644 --- a/website/templates/pages/demo/demo.js +++ b/website/templates/pages/demo/demo.js @@ -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; } });