mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Add dual text-diff
This commit is contained in:
parent
9a2fd0e2b2
commit
51bad3bf3c
@ -11,6 +11,15 @@ RED.diff = (function() {
|
|||||||
// RED.keyboard.add("*","ctrl-shift-l","core:show-current-diff");
|
// RED.keyboard.add("*","ctrl-shift-l","core:show-current-diff");
|
||||||
RED.keyboard.add("*","ctrl-shift-r","core:show-remote-diff");
|
RED.keyboard.add("*","ctrl-shift-r","core:show-remote-diff");
|
||||||
|
|
||||||
|
|
||||||
|
RED.actions.add("core:show-test-flow-diff-1",function(){showTestFlowDiff(1)});
|
||||||
|
RED.keyboard.add("*","ctrl-shift-f 1","core:show-test-flow-diff-1");
|
||||||
|
|
||||||
|
RED.actions.add("core:show-test-flow-diff-2",function(){showTestFlowDiff(2)});
|
||||||
|
RED.keyboard.add("*","ctrl-shift-f 2","core:show-test-flow-diff-2");
|
||||||
|
RED.actions.add("core:show-test-flow-diff-3",function(){showTestFlowDiff(3)});
|
||||||
|
RED.keyboard.add("*","ctrl-shift-f 3","core:show-test-flow-diff-3");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildDiffPanel(container) {
|
function buildDiffPanel(container) {
|
||||||
@ -794,6 +803,15 @@ RED.diff = (function() {
|
|||||||
remoteCell.addClass("node-diff-empty");
|
remoteCell.addClass("node-diff-empty");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (localNode && remoteNode && typeof localNode[d] === "string") {
|
||||||
|
if (/\n/.test(localNode[d]) || /\n/.test(remoteNode[d])) {
|
||||||
|
$('<button class="editor-button editor-button-small node-diff-text-diff-button"><i class="fa fa-file-o"> <i class="fa fa-caret-left"></i> <i class="fa fa-caret-right"></i> <i class="fa fa-file-o"></i></button>').click(function() {
|
||||||
|
showTextDiff(localNode[d],remoteNode[d]);
|
||||||
|
}).appendTo(propertyNameCell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
return nodePropertiesDiv;
|
return nodePropertiesDiv;
|
||||||
}
|
}
|
||||||
@ -1333,6 +1351,304 @@ RED.diff = (function() {
|
|||||||
RED.workspaces.refresh();
|
RED.workspaces.refresh();
|
||||||
RED.sidebar.config.refresh();
|
RED.sidebar.config.refresh();
|
||||||
}
|
}
|
||||||
|
function showTestFlowDiff(index) {
|
||||||
|
if (index === 1) {
|
||||||
|
var localFlow = RED.nodes.createCompleteNodeSet();
|
||||||
|
var originalFlow = RED.nodes.originalFlow();
|
||||||
|
showTextDiff(JSON.stringify(localFlow,null,4),JSON.stringify(originalFlow,null,4))
|
||||||
|
} else if (index === 2) {
|
||||||
|
var local = "1\n2\n3\n4\n5\nA\n6\n7\n8\n9\n";
|
||||||
|
var remote = "1\nA\n2\n3\nD\nE\n6\n7\n8\n9\n";
|
||||||
|
showTextDiff(local,remote);
|
||||||
|
} else if (index === 3) {
|
||||||
|
var local = "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22";
|
||||||
|
var remote = "1\nTWO\nTHREE\nEXTRA\n4\n5\n6\n7\n8\n9\n10\n11\n12\nTHIRTEEN\n14\n15\n16\n17\n18\n19\n20\n21\n22";
|
||||||
|
showTextDiff(local,remote);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showTextDiff(textA,textB) {
|
||||||
|
var trayOptions = {
|
||||||
|
title: "Compare Changes", //TODO: nls
|
||||||
|
width: Infinity,
|
||||||
|
overlay: true,
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
text: RED._("common.label.done"),
|
||||||
|
click: function() {
|
||||||
|
RED.tray.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
resize: function(dimensions) {
|
||||||
|
// trayWidth = dimensions.width;
|
||||||
|
},
|
||||||
|
open: function(tray) {
|
||||||
|
var trayBody = tray.find('.editor-tray-body');
|
||||||
|
var diffPanel = $('<div class="node-text-diff"></div>').appendTo(trayBody);
|
||||||
|
|
||||||
|
var codeTable = $("<table>").appendTo(diffPanel);
|
||||||
|
$('<colgroup><col width="50"><col width="50%"><col width="50"><col width="50%"></colgroup>').appendTo(codeTable);
|
||||||
|
var codeBody = $('<tbody>').appendTo(codeTable);
|
||||||
|
var diffSummary = diffText(textA||"",textB||"");
|
||||||
|
var aIndex = 0;
|
||||||
|
var bIndex = 0;
|
||||||
|
var diffLength = Math.max(diffSummary.a.length, diffSummary.b.length);
|
||||||
|
|
||||||
|
var diffLines = [];
|
||||||
|
var diffBlocks = [];
|
||||||
|
var currentBlock;
|
||||||
|
var blockLength = 0;
|
||||||
|
var blockType = 0;
|
||||||
|
|
||||||
|
for (var i=0;i<diffLength;i++) {
|
||||||
|
var diffLine = diffSummary[i];
|
||||||
|
var Adiff = (aIndex < diffSummary.a.length)?diffSummary.a[aIndex]:{type:2,line:""};
|
||||||
|
var Bdiff = (bIndex < diffSummary.b.length)?diffSummary.b[bIndex]:{type:2,line:""};
|
||||||
|
if (Adiff.type === 0 && Bdiff.type !== 0) {
|
||||||
|
Adiff = {type:2,line:""};
|
||||||
|
bIndex++;
|
||||||
|
} else if (Bdiff.type === 0 && Adiff.type !== 0) {
|
||||||
|
Bdiff = {type:2,line:""};
|
||||||
|
aIndex++;
|
||||||
|
} else {
|
||||||
|
aIndex++;
|
||||||
|
bIndex++;
|
||||||
|
}
|
||||||
|
diffLines.push({
|
||||||
|
a: Adiff,
|
||||||
|
b: Bdiff
|
||||||
|
});
|
||||||
|
if (currentBlock === undefined) {
|
||||||
|
currentBlock = {start:i,end:i};
|
||||||
|
blockLength = 0;
|
||||||
|
blockType = (Adiff.type === 0 && Bdiff.type === 0)?0:1;
|
||||||
|
} else {
|
||||||
|
if (Adiff.type === 0 && Bdiff.type === 0) {
|
||||||
|
// Unchanged line
|
||||||
|
if (blockType === 0) {
|
||||||
|
// still unchanged - extend the block
|
||||||
|
currentBlock.end = i;
|
||||||
|
blockLength++;
|
||||||
|
} else if (blockType === 1) {
|
||||||
|
// end of a change
|
||||||
|
currentBlock.end = i;
|
||||||
|
blockType = 2;
|
||||||
|
blockLength = 0;
|
||||||
|
} else if (blockType === 2) {
|
||||||
|
// post-change unchanged
|
||||||
|
currentBlock.end = i;
|
||||||
|
blockLength++;
|
||||||
|
if (blockLength === 8) {
|
||||||
|
currentBlock.end -= 5; // rollback the end
|
||||||
|
diffBlocks.push(currentBlock);
|
||||||
|
currentBlock = {start:i-5,end:i-5};
|
||||||
|
blockType = 0;
|
||||||
|
blockLength = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// in a change
|
||||||
|
currentBlock.end = i;
|
||||||
|
blockLength++;
|
||||||
|
if (blockType === 0) {
|
||||||
|
if (currentBlock.end > 3) {
|
||||||
|
currentBlock.end -= 3;
|
||||||
|
currentBlock.empty = true;
|
||||||
|
diffBlocks.push(currentBlock);
|
||||||
|
currentBlock = {start:i-3,end:i-3};
|
||||||
|
}
|
||||||
|
blockType = 1;
|
||||||
|
} else if (blockType === 2) {
|
||||||
|
// we were in unchanged, but hit a change again
|
||||||
|
blockType = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (blockType === 0) {
|
||||||
|
currentBlock.empty = true;
|
||||||
|
}
|
||||||
|
currentBlock.end = diffLength;
|
||||||
|
diffBlocks.push(currentBlock);
|
||||||
|
console.table(diffBlocks);
|
||||||
|
var diffRow;
|
||||||
|
for (var b = 0; b<diffBlocks.length; b++) {
|
||||||
|
currentBlock = diffBlocks[b];
|
||||||
|
if (currentBlock.empty) {
|
||||||
|
diffRow = createExpandLine(currentBlock.start,currentBlock.end,diffLines).appendTo(codeBody);
|
||||||
|
} else {
|
||||||
|
for (var i=currentBlock.start;i<currentBlock.end;i++) {
|
||||||
|
var row = createDiffLine(diffLines[i]).appendTo(codeBody);
|
||||||
|
if (i === currentBlock.start) {
|
||||||
|
row.addClass("start-block");
|
||||||
|
} else if (i === currentBlock.end-1) {
|
||||||
|
row.addClass("end-block");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
close: function() {
|
||||||
|
diffVisible = false;
|
||||||
|
|
||||||
|
},
|
||||||
|
show: function() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RED.tray.show(trayOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createExpandLine(start,end,diffLines) {
|
||||||
|
diffRow = $('<tr class="node-text-diff-expand">');
|
||||||
|
var content = $('<td colspan="4"> <i class="fa fa-arrows-v"></i> </td>').appendTo(diffRow);
|
||||||
|
var label = $('<span></span>').appendTo(content);
|
||||||
|
if (end < diffLines.length-1) {
|
||||||
|
label.text("@@ -"+(diffLines[end-1].a.i+1)+" +"+(diffLines[end-1].b.i+1));
|
||||||
|
}
|
||||||
|
diffRow.click(function(evt) {
|
||||||
|
console.log(start,end,diffLines.length);
|
||||||
|
if (end - start > 20) {
|
||||||
|
var startPos = $(this).offset();
|
||||||
|
console.log(startPos);
|
||||||
|
if (start > 0) {
|
||||||
|
for (var i=start;i<start+10;i++) {
|
||||||
|
createDiffLine(diffLines[i]).addClass("unchanged").insertBefore($(this));
|
||||||
|
}
|
||||||
|
start += 10;
|
||||||
|
}
|
||||||
|
if (end < diffLines.length-1) {
|
||||||
|
for (var i=end-1;i>end-11;i--) {
|
||||||
|
createDiffLine(diffLines[i]).addClass("unchanged").insertAfter($(this));
|
||||||
|
}
|
||||||
|
end -= 10;
|
||||||
|
}
|
||||||
|
if (end < diffLines.length-1) {
|
||||||
|
label.text("@@ -"+(diffLines[end-1].a.i+1)+" +"+(diffLines[end-1].b.i+1));
|
||||||
|
}
|
||||||
|
var endPos = $(this).offset();
|
||||||
|
var delta = endPos.top - startPos.top;
|
||||||
|
$(".node-text-diff").scrollTop($(".node-text-diff").scrollTop() + delta);
|
||||||
|
} else {
|
||||||
|
for (var i=start;i<end;i++) {
|
||||||
|
createDiffLine(diffLines[i]).addClass("unchanged").insertBefore($(this));
|
||||||
|
}
|
||||||
|
$(this).remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return diffRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createDiffLine(diffLine) {
|
||||||
|
var diffRow = $('<tr>');
|
||||||
|
var Adiff = diffLine.a;
|
||||||
|
var Bdiff = diffLine.b;
|
||||||
|
//console.log(diffLine);
|
||||||
|
var cellNo = $("<td>").text(Adiff.type === 2?"":Adiff.i).appendTo(diffRow);
|
||||||
|
var cellLine = $("<td>").text(Adiff.line).appendTo(diffRow);
|
||||||
|
if (Adiff.type === 2) {
|
||||||
|
cellNo.addClass('blank');
|
||||||
|
cellLine.addClass('blank');
|
||||||
|
} else if (Adiff.type === 1) {
|
||||||
|
cellNo.addClass('added');
|
||||||
|
cellLine.addClass('added');
|
||||||
|
} else if (Adiff.type === 4) {
|
||||||
|
cellNo.addClass('removed');
|
||||||
|
cellLine.addClass('removed');
|
||||||
|
}
|
||||||
|
cellNo = $("<td>").text(Bdiff.type === 2?"":Bdiff.i).appendTo(diffRow);
|
||||||
|
cellLine = $("<td>").text(Bdiff.line).appendTo(diffRow);
|
||||||
|
if (Bdiff.type === 2) {
|
||||||
|
cellNo.addClass('blank');
|
||||||
|
cellLine.addClass('blank');
|
||||||
|
} else if (Bdiff.type === 1) {
|
||||||
|
cellNo.addClass('added');
|
||||||
|
cellLine.addClass('added');
|
||||||
|
} else if (Bdiff.type === 4) {
|
||||||
|
cellNo.addClass('removed');
|
||||||
|
cellLine.addClass('removed');
|
||||||
|
}
|
||||||
|
return diffRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
function diffText(string1, string2,ignoreWhitespace) {
|
||||||
|
var lines1 = string1.split(/\r?\n/);
|
||||||
|
var lines2 = string2.split(/\r?\n/);
|
||||||
|
var i = lines1.length;
|
||||||
|
var j = lines2.length;
|
||||||
|
var k;
|
||||||
|
var m;
|
||||||
|
var diffSummary = {a:[],b:[]};
|
||||||
|
var diffMap = [];
|
||||||
|
for (k = 0; k < i + 1; k++) {
|
||||||
|
diffMap[k] = [];
|
||||||
|
for (m = 0; m < j + 1; m++) {
|
||||||
|
diffMap[k][m] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var c = 0;
|
||||||
|
for (k = i - 1; k >= 0; k--) {
|
||||||
|
for (m = j - 1; m >=0; m--) {
|
||||||
|
c++;
|
||||||
|
if (compareLines(lines1[k],lines2[m],ignoreWhitespace) !== 1) {
|
||||||
|
diffMap[k][m] = diffMap[k+1][m+1]+1;
|
||||||
|
} else {
|
||||||
|
diffMap[k][m] = Math.max(diffMap[(k + 1)][m], diffMap[k][(m + 1)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//console.log(c);
|
||||||
|
k = 0;
|
||||||
|
m = 0;
|
||||||
|
|
||||||
|
while ((k < i) && (m < j)) {
|
||||||
|
var n = compareLines(lines1[k],lines2[m],ignoreWhitespace);
|
||||||
|
if (n !== 1) {
|
||||||
|
var d = 0;
|
||||||
|
if (n===0) {
|
||||||
|
d = 0;
|
||||||
|
} else if (n==2) {
|
||||||
|
d = 3;
|
||||||
|
}
|
||||||
|
diffSummary.a.push({i:k+1,j:m+1,line:lines1[k],type:d});
|
||||||
|
diffSummary.b.push({i:m+1,j:k+1,line:lines2[m],type:d});
|
||||||
|
k++;
|
||||||
|
m++;
|
||||||
|
} else if (diffMap[(k + 1)][m] >= diffMap[k][(m + 1)]) {
|
||||||
|
diffSummary.a.push({i:k+1,line:lines1[k],type:1});
|
||||||
|
k++;
|
||||||
|
} else {
|
||||||
|
diffSummary.b.push({i:m+1,line:lines2[m],type:4});
|
||||||
|
m++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ((k < i) || (m < j)) {
|
||||||
|
if (k == i) {
|
||||||
|
diffSummary.b.push({i:m+1,line:lines2[m],type:4});
|
||||||
|
m++;
|
||||||
|
} else if (m == j) {
|
||||||
|
diffSummary.a.push({i:k+1,line:lines1[k],type:1});
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return diffSummary;
|
||||||
|
}
|
||||||
|
|
||||||
|
function compareLines(string1, string2, ignoreWhitespace) {
|
||||||
|
if (ignoreWhitespace) {
|
||||||
|
if (string1 === string2) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return string1.trim() === string2.trime() ? 2 : 1;
|
||||||
|
}
|
||||||
|
return string1 === string2 ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
init: init,
|
init: init,
|
||||||
getRemoteDiff: getRemoteDiff,
|
getRemoteDiff: getRemoteDiff,
|
||||||
|
@ -210,7 +210,7 @@ RED.tray = (function() {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
show: function show(options) {
|
show: function show(options) {
|
||||||
if (stack.length > 0) {
|
if (stack.length > 0 && !options.overlay) {
|
||||||
var oldTray = stack[stack.length-1];
|
var oldTray = stack[stack.length-1];
|
||||||
oldTray.tray.css({
|
oldTray.tray.css({
|
||||||
right: -(oldTray.tray.width()+10)+"px"
|
right: -(oldTray.tray.width()+10)+"px"
|
||||||
@ -238,14 +238,21 @@ RED.tray = (function() {
|
|||||||
tray.tray.remove();
|
tray.tray.remove();
|
||||||
if (stack.length > 0) {
|
if (stack.length > 0) {
|
||||||
var oldTray = stack[stack.length-1];
|
var oldTray = stack[stack.length-1];
|
||||||
oldTray.tray.appendTo("#editor-stack");
|
if (!oldTray.options.overlay) {
|
||||||
setTimeout(function() {
|
oldTray.tray.appendTo("#editor-stack");
|
||||||
|
setTimeout(function() {
|
||||||
|
handleWindowResize();
|
||||||
|
oldTray.tray.css({right:0});
|
||||||
|
if (oldTray.options.show) {
|
||||||
|
oldTray.options.show();
|
||||||
|
}
|
||||||
|
},0);
|
||||||
|
} else {
|
||||||
handleWindowResize();
|
handleWindowResize();
|
||||||
oldTray.tray.css({right:0});
|
|
||||||
if (oldTray.options.show) {
|
if (oldTray.options.show) {
|
||||||
oldTray.options.show();
|
oldTray.options.show();
|
||||||
}
|
}
|
||||||
},0);
|
}
|
||||||
}
|
}
|
||||||
if (done) {
|
if (done) {
|
||||||
done();
|
done();
|
||||||
|
@ -49,6 +49,10 @@
|
|||||||
height: 25px;
|
height: 25px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
padding-top: 2px;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
background: #f9f9f9;
|
background: #f9f9f9;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -535,3 +539,67 @@
|
|||||||
#node-diff-toolbar-resolved-conflicts .node-diff-status {
|
#node-diff-toolbar-resolved-conflicts .node-diff-status {
|
||||||
margin:0;
|
margin:0;
|
||||||
}
|
}
|
||||||
|
.node-diff-text-diff-button {
|
||||||
|
float: right;
|
||||||
|
margin: 2px 3px;
|
||||||
|
line-height: 14px;
|
||||||
|
height: 16px;
|
||||||
|
|
||||||
|
}
|
||||||
|
.node-text-diff {
|
||||||
|
height: 100%;
|
||||||
|
overflow-y:auto;
|
||||||
|
table {
|
||||||
|
margin: 10px;
|
||||||
|
border: 1px solid $secondary-border-color;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-family: monospace;
|
||||||
|
table-layout: fixed;
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
vertical-align: top;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
td:nth-child(odd) {
|
||||||
|
text-align: right;
|
||||||
|
color: #999;
|
||||||
|
background: #fafafa;
|
||||||
|
padding: 1px 5px;
|
||||||
|
}
|
||||||
|
td:nth-child(3) {
|
||||||
|
border-left: 1px solid $secondary-border-color;
|
||||||
|
}
|
||||||
|
td:nth-child(even) {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
padding: 1px 5px;
|
||||||
|
}
|
||||||
|
td.blank {
|
||||||
|
background: #f6f6f6;
|
||||||
|
}
|
||||||
|
td.added {
|
||||||
|
background: #eefaee;
|
||||||
|
}
|
||||||
|
td.removed {
|
||||||
|
background: #fadddd;
|
||||||
|
}
|
||||||
|
tr.unchanged {
|
||||||
|
background: #fefefe;
|
||||||
|
}
|
||||||
|
tr.start-block {
|
||||||
|
border-top: 1px solid #f3f3f3;
|
||||||
|
}
|
||||||
|
tr.end-block {
|
||||||
|
border-bottom: 1px solid #f3f3f3;
|
||||||
|
}
|
||||||
|
tr.node-text-diff-expand td {
|
||||||
|
text-align: left;
|
||||||
|
color: #999;
|
||||||
|
background: #ffd;
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background: #ffc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user