UNPKG

jsondiffpatch

Version:
198 lines (175 loc) 6.53 kB
var base = require('./base'); var BaseFormatter = base.BaseFormatter; var AnnotatedFormatter = function AnnotatedFormatter() { this.includeMoveDestinations = false; }; AnnotatedFormatter.prototype = new BaseFormatter(); AnnotatedFormatter.prototype.prepareContext = function(context) { BaseFormatter.prototype.prepareContext.call(this, context); context.indent = function(levels) { this.indentLevel = (this.indentLevel || 0) + (typeof levels === 'undefined' ? 1 : levels); this.indentPad = new Array(this.indentLevel + 1).join('&nbsp;&nbsp;'); }; context.row = function(json, htmlNote) { context.out('<tr><td style="white-space: nowrap;">' + '<pre class="jsondiffpatch-annotated-indent" style="display: inline-block">'); context.out(context.indentPad); context.out('</pre><pre style="display: inline-block">'); context.out(json); context.out('</pre></td><td class="jsondiffpatch-delta-note"><div>'); context.out(htmlNote); context.out('</div></td></tr>'); }; }; AnnotatedFormatter.prototype.typeFormattterErrorFormatter = function(context, err) { context.row('', '<pre class="jsondiffpatch-error">' + err + '</pre>'); }; AnnotatedFormatter.prototype.formatTextDiffString = function(context, value) { var lines = this.parseTextDiff(value); context.out('<ul class="jsondiffpatch-textdiff">'); for (var i = 0, l = lines.length; i < l; i++) { var line = lines[i]; context.out('<li>' + '<div class="jsondiffpatch-textdiff-location">' + '<span class="jsondiffpatch-textdiff-line-number">' + line.location.line + '</span>' + '<span class="jsondiffpatch-textdiff-char">' + line.location.chr + '</span>' + '</div>' + '<div class="jsondiffpatch-textdiff-line">'); var pieces = line.pieces; for (var pieceIndex = 0, piecesLength = pieces.length; pieceIndex < piecesLength; pieceIndex++) { var piece = pieces[pieceIndex]; context.out('<span class="jsondiffpatch-textdiff-' + piece.type + '">' + piece.text + '</span>'); } context.out('</div></li>'); } context.out('</ul>'); }; AnnotatedFormatter.prototype.rootBegin = function(context, type, nodeType) { context.out('<table class="jsondiffpatch-annotated-delta">'); if (type === 'node') { context.row('{'); context.indent(); } if (nodeType === 'array') { context.row('"_t": "a",', 'Array delta (member names indicate array indices)'); } }; AnnotatedFormatter.prototype.rootEnd = function(context, type) { if (type === 'node') { context.indent(-1); context.row('}'); } context.out('</table>'); }; AnnotatedFormatter.prototype.nodeBegin = function(context, key, leftKey, type, nodeType) { context.row('&quot;' + key + '&quot;: {'); if (type === 'node') { context.indent(); } if (nodeType === 'array') { context.row('"_t": "a",', 'Array delta (member names indicate array indices)'); } }; AnnotatedFormatter.prototype.nodeEnd = function(context, key, leftKey, type, nodeType, isLast) { if (type === 'node') { context.indent(-1); } context.row('}' + (isLast ? '' : ',')); }; /* jshint camelcase: false */ AnnotatedFormatter.prototype.format_unchanged = function() { return; }; AnnotatedFormatter.prototype.format_movedestination = function() { return; }; AnnotatedFormatter.prototype.format_node = function(context, delta, left) { // recurse this.formatDeltaChildren(context, delta, left); }; var wrapPropertyName = function(name) { return '<pre style="display:inline-block">&quot;' + name + '&quot;</pre>'; }; var deltaAnnotations = { added: function(delta, left, key, leftKey) { var formatLegend = ' <pre>([newValue])</pre>'; if (typeof leftKey === 'undefined') { return 'new value' + formatLegend; } if (typeof leftKey === 'number') { return 'insert at index ' + leftKey + formatLegend; } return 'add property ' + wrapPropertyName(leftKey) + formatLegend; }, modified: function(delta, left, key, leftKey) { var formatLegend = ' <pre>([previousValue, newValue])</pre>'; if (typeof leftKey === 'undefined') { return 'modify value' + formatLegend; } if (typeof leftKey === 'number') { return 'modify at index ' + leftKey + formatLegend; } return 'modify property ' + wrapPropertyName(leftKey) + formatLegend; }, deleted: function(delta, left, key, leftKey) { var formatLegend = ' <pre>([previousValue, 0, 0])</pre>'; if (typeof leftKey === 'undefined') { return 'delete value' + formatLegend; } if (typeof leftKey === 'number') { return 'remove index ' + leftKey + formatLegend; } return 'delete property ' + wrapPropertyName(leftKey) + formatLegend; }, moved: function(delta, left, key, leftKey) { return 'move from <span title="(position to remove at original state)">index ' + leftKey + '</span> to ' + '<span title="(position to insert at final state)">index ' + delta[1] + '</span>'; }, textdiff: function(delta, left, key, leftKey) { var location = (typeof leftKey === 'undefined') ? '' : ( (typeof leftKey === 'number') ? ' at index ' + leftKey : ' at property ' + wrapPropertyName(leftKey) ); return 'text diff' + location + ', format is ' + '<a href="https://code.google.com/p/google-diff-match-patch/wiki/Unidiff">' + 'a variation of Unidiff</a>'; } }; var formatAnyChange = function(context, delta) { var deltaType = this.getDeltaType(delta); var annotator = deltaAnnotations[deltaType]; var htmlNote = annotator && annotator.apply(annotator, Array.prototype.slice.call(arguments, 1)); var json = JSON.stringify(delta, null, 2); if (deltaType === 'textdiff') { // split text diffs lines json = json.split('\\n').join('\\n"+\n "'); } context.indent(); context.row(json, htmlNote); context.indent(-1); }; AnnotatedFormatter.prototype.format_added = formatAnyChange; AnnotatedFormatter.prototype.format_modified = formatAnyChange; AnnotatedFormatter.prototype.format_deleted = formatAnyChange; AnnotatedFormatter.prototype.format_moved = formatAnyChange; AnnotatedFormatter.prototype.format_textdiff = formatAnyChange; /* jshint camelcase: true */ exports.AnnotatedFormatter = AnnotatedFormatter; var defaultInstance; exports.format = function(delta, left) { if (!defaultInstance) { defaultInstance = new AnnotatedFormatter(); } return defaultInstance.format(delta, left); };