/* * * Diff to HTML (diff2html-ui.js) * Author: rtfpessoa * * Depends on: [ jQuery ] * Optional dependencies on: [ highlight.js ] * */ /*global $, hljs, Diff2Html*/ (function() { var highlightJS = require('./highlight.js-internals.js').HighlightJS; var diffJson = null; var defaultTarget = 'body'; var currentSelectionColumnId = -1; function Diff2HtmlUI(config) { var cfg = config || {}; if (cfg.diff) { diffJson = Diff2Html.getJsonFromDiff(cfg.diff); } else if (cfg.json) { diffJson = cfg.json; } this._initSelection(); } Diff2HtmlUI.prototype.draw = function(targetId, config) { var cfg = config || {}; cfg.inputFormat = 'json'; var $target = this._getTarget(targetId); $target.html(Diff2Html.getPrettyHtml(diffJson, cfg)); if (cfg.synchronisedScroll) { this.synchronisedScroll($target, cfg); } }; Diff2HtmlUI.prototype.synchronisedScroll = function(targetId) { var $target = this._getTarget(targetId); $target.find('.d2h-file-side-diff').scroll(function() { var $this = $(this); $this.closest('.d2h-file-wrapper').find('.d2h-file-side-diff') .scrollLeft($this.scrollLeft()); }); }; Diff2HtmlUI.prototype.fileListCloseable = function(targetId, startVisible) { var $target = this._getTarget(targetId); var hashTag = this._getHashTag(); var $showBtn = $target.find('.d2h-show'); var $hideBtn = $target.find('.d2h-hide'); var $fileList = $target.find('.d2h-file-list'); if (hashTag === 'files-summary-show') show(); else if (hashTag === 'files-summary-hide') hide(); else if (startVisible) show(); else hide(); $showBtn.click(show); $hideBtn.click(hide); function show() { $showBtn.hide(); $hideBtn.show(); $fileList.show(); } function hide() { $hideBtn.hide(); $showBtn.show(); $fileList.hide(); } }; Diff2HtmlUI.prototype.highlightCode = function(targetId) { var that = this; var $target = that._getTarget(targetId); // collect all the diff files and execute the highlight on their lines var $files = $target.find('.d2h-file-wrapper'); $files.map(function(_i, file) { var oldLinesState; var newLinesState; var $file = $(file); var language = $file.data('lang'); // collect all the code lines and execute the highlight on them var $codeLines = $file.find('.d2h-code-line-ctn'); $codeLines.map(function(_j, line) { var $line = $(line); var text = line.textContent; var lineParent = line.parentNode; var lineState; if (lineParent.className.indexOf('d2h-del') !== -1) { lineState = oldLinesState; } else { lineState = newLinesState; } var result = hljs.getLanguage(language) ? hljs.highlight(language, text, true, lineState) : hljs.highlightAuto(text); if (lineParent.className.indexOf('d2h-del') !== -1) { oldLinesState = result.top; } else if (lineParent.className.indexOf('d2h-ins') !== -1) { newLinesState = result.top; } else { oldLinesState = result.top; newLinesState = result.top; } var originalStream = highlightJS.nodeStream(line); if (originalStream.length) { var resultNode = document.createElementNS('http://www.w3.org/1999/xhtml', 'div'); resultNode.innerHTML = result.value; result.value = highlightJS.mergeStreams(originalStream, highlightJS.nodeStream(resultNode), text); } $line.addClass('hljs'); $line.addClass(result.language); $line.html(result.value); }); }); }; Diff2HtmlUI.prototype._getTarget = function(targetId) { var $target; if (typeof targetId === 'object' && targetId instanceof jQuery) { $target = targetId; } else if (typeof targetId === 'string') { $target = $(targetId); } else { console.error("Wrong target provided! Falling back to default value 'body'."); console.log('Please provide a jQuery object or a valid DOM query string.'); $target = $(defaultTarget); } return $target; }; Diff2HtmlUI.prototype._getHashTag = function() { var docUrl = document.URL; var hashTagIndex = docUrl.indexOf('#'); var hashTag = null; if (hashTagIndex !== -1) { hashTag = docUrl.substr(hashTagIndex + 1); } return hashTag; }; Diff2HtmlUI.prototype._distinct = function(collection) { return collection.filter(function(v, i) { return collection.indexOf(v) === i; }); }; Diff2HtmlUI.prototype._initSelection = function() { var body = $('body'); var that = this; body.on('mousedown', '.d2h-diff-table', function(event) { var target = $(event.target); var table = target.closest('.d2h-diff-table'); if (target.closest('.d2h-code-line,.d2h-code-side-line').length) { table.removeClass('selecting-left'); table.addClass('selecting-right'); currentSelectionColumnId = 1; } else if (target.closest('.d2h-code-linenumber,.d2h-code-side-linenumber').length) { table.removeClass('selecting-right'); table.addClass('selecting-left'); currentSelectionColumnId = 0; } }); body.on('copy', '.d2h-diff-table', function(event) { var clipboardData = event.originalEvent.clipboardData; var text = that._getSelectedText(); clipboardData.setData('text', text); event.preventDefault(); }); }; Diff2HtmlUI.prototype._getSelectedText = function() { var sel = window.getSelection(); var range = sel.getRangeAt(0); var doc = range.cloneContents(); var nodes = doc.querySelectorAll('tr'); var text = ''; var idx = currentSelectionColumnId; if (nodes.length === 0) { text = doc.textContent; } else { [].forEach.call(nodes, function(tr, i) { var td = tr.cells[tr.cells.length === 1 ? 0 : idx]; text += (i ? '\n' : '') + td.textContent.replace(/(?:\r\n|\r|\n)/g, ''); }); } return text; }; module.exports.Diff2HtmlUI = Diff2HtmlUI; // Expose diff2html in the browser global.Diff2HtmlUI = Diff2HtmlUI; })();