Files
CyberChef/src/core/operations/Diff.mjs
T

136 lines
4.0 KiB
JavaScript
Raw Normal View History

2018-05-21 18:23:05 +00:00
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2016
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
2018-05-28 15:42:43 -07:00
import * as JsDiff from "diff";
import OperationError from "../errors/OperationError.mjs";
2018-05-21 18:23:05 +00:00
/**
* Diff operation
*/
class Diff extends Operation {
/**
* Diff constructor
*/
constructor() {
super();
this.name = "Diff";
this.module = "Diff";
this.description = "Compares two inputs (separated by the specified delimiter) and highlights the differences between them.";
this.infoURL = "https://wikipedia.org/wiki/File_comparison";
2018-05-21 18:23:05 +00:00
this.inputType = "string";
this.outputType = "html";
this.args = [
{
"name": "Sample delimiter",
"type": "binaryString",
"value": "\\n\\n"
},
{
"name": "Diff by",
"type": "option",
"value": ["Character", "Word", "Line", "Sentence", "CSS", "JSON"]
},
{
"name": "Show added",
"type": "boolean",
"value": true
},
{
"name": "Show removed",
"type": "boolean",
"value": true
},
2019-10-29 23:12:24 +00:00
{
"name": "Show subtraction",
"type": "boolean",
2019-10-29 23:35:35 +00:00
"value": false
2019-10-29 23:12:24 +00:00
},
2018-05-21 18:23:05 +00:00
{
2018-07-15 13:25:44 +01:00
"name": "Ignore whitespace",
2018-05-21 18:23:05 +00:00
"type": "boolean",
2018-07-15 13:25:44 +01:00
"value": false,
"hint": "Relevant for word and line"
2018-05-21 18:23:05 +00:00
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {html}
*/
run(input, args) {
const [
sampleDelim,
diffBy,
showAdded,
showRemoved,
2019-10-29 23:12:24 +00:00
showSubtraction,
2018-05-21 18:23:05 +00:00
ignoreWhitespace
] = args,
samples = input.split(sampleDelim);
let output = "",
diff;
2018-05-28 15:42:43 -07:00
// Node and Webpack load modules slightly differently
const jsdiff = JsDiff.default ? JsDiff.default : JsDiff;
2018-05-21 18:23:05 +00:00
if (!samples || samples.length !== 2) {
throw new OperationError("Incorrect number of samples, perhaps you need to modify the sample delimiter or add more samples?");
}
switch (diffBy) {
case "Character":
2018-05-28 15:42:43 -07:00
diff = jsdiff.diffChars(samples[0], samples[1]);
2018-05-21 18:23:05 +00:00
break;
case "Word":
if (ignoreWhitespace) {
2018-05-28 15:42:43 -07:00
diff = jsdiff.diffWords(samples[0], samples[1]);
2018-05-21 18:23:05 +00:00
} else {
2018-05-28 15:42:43 -07:00
diff = jsdiff.diffWordsWithSpace(samples[0], samples[1]);
2018-05-21 18:23:05 +00:00
}
break;
case "Line":
if (ignoreWhitespace) {
2018-05-28 15:42:43 -07:00
diff = jsdiff.diffTrimmedLines(samples[0], samples[1]);
2018-05-21 18:23:05 +00:00
} else {
2018-05-28 15:42:43 -07:00
diff = jsdiff.diffLines(samples[0], samples[1]);
2018-05-21 18:23:05 +00:00
}
break;
case "Sentence":
2018-05-28 15:42:43 -07:00
diff = jsdiff.diffSentences(samples[0], samples[1]);
2018-05-21 18:23:05 +00:00
break;
case "CSS":
2018-05-28 15:42:43 -07:00
diff = jsdiff.diffCss(samples[0], samples[1]);
2018-05-21 18:23:05 +00:00
break;
case "JSON":
2018-05-28 15:42:43 -07:00
diff = jsdiff.diffJson(samples[0], samples[1]);
2018-05-21 18:23:05 +00:00
break;
default:
throw new OperationError("Invalid 'Diff by' option.");
}
for (let i = 0; i < diff.length; i++) {
if (diff[i].added) {
if (showAdded) output += "<span class='hl5'>" + Utils.escapeHtml(diff[i].value) + "</span>";
} else if (diff[i].removed) {
if (showRemoved) output += "<span class='hl3'>" + Utils.escapeHtml(diff[i].value) + "</span>";
2019-10-29 23:12:24 +00:00
} else if (!showSubtraction) {
2019-10-29 23:35:35 +00:00
output += Utils.escapeHtml(diff[i].value);
2018-05-21 18:23:05 +00:00
}
}
return output;
}
}
export default Diff;