Merge branch 'arg-options' into node-lib

This commit is contained in:
d98762625 2018-12-21 09:48:01 +00:00
commit 3efe9309ef
3 changed files with 121 additions and 15 deletions

View File

@ -11,7 +11,7 @@
import SyncDish from "./SyncDish";
import NodeRecipe from "./NodeRecipe";
import OperationConfig from "./config/OperationConfig.json";
import { sanitise } from "./apiUtils";
import { sanitise, removeSubheadingsFromArray, sentenceToCamelCase } from "./apiUtils";
import ExludedOperationError from "../core/errors/ExcludedOperationError";
@ -58,12 +58,7 @@ function transformArgs(originalArgs, newArgs) {
// See Strings op for example.
const allArgs = Object.assign([], originalArgs).map((a) => {
if (Array.isArray(a.value)) {
a.value = a.value.filter((v) => {
if (typeof v === "string") {
return !v.match(/^\[[\s\S]*\]$/); // Matches anything surrounded in [ ]
}
return true;
});
a.value = removeSubheadingsFromArray(a.value);
}
return a;
});
@ -96,6 +91,7 @@ function transformArgs(originalArgs, newArgs) {
return allArgs.map(extractArg);
}
/**
* Ensure an input is a SyncDish object.
* @param input
@ -112,6 +108,7 @@ function ensureIsDish(input) {
}
}
/**
* prepareOp: transform args, make input the right type.
* Also convert any Buffers to ArrayBuffers.
@ -132,6 +129,32 @@ function prepareOp(opInstance, input, args) {
return {transformedInput, transformedArgs};
}
/**
* createArgOptions
*
* Create an object of options for each option or togglestring argument
* in the given operation.
*
* Argument names are converted to camel case for consistency.
*
* @param {Operation} op - the operation to extract args from
* @returns {{}} - arrays of options for option and toggleString args.
*/
function createArgOptions(op) {
const result = {};
op.args.forEach((a) => {
if (a.type === "option") {
result[sentenceToCamelCase(a.name)] = removeSubheadingsFromArray(a.value);
} else if (a.type === "toggleString") {
result[sentenceToCamelCase(a.name)] = removeSubheadingsFromArray(a.toggleValues);
}
});
return result;
}
/**
* Wrap an operation to be consumed by node API.
* Checks to see if run function is async or not.
@ -187,13 +210,16 @@ export function wrap(OpClass) {
// used in chef.help
wrapped.opName = OpClass.name;
wrapped.argOptions = createArgOptions(opInstance);
return wrapped;
}
/**
* @namespace Api
* help: Give information about operations matching the given search term,
* or inputted operation.
*
* @param {String || wrapped operation} input - the name of the operation to get help for.
* Case and whitespace are ignored in search.
* @returns {Object[]} Config of matching operations.
@ -248,6 +274,7 @@ export function help(input) {
return null;
}
/**
* bake [Wrapped] - Perform an array of operations on some input.
* @param operations array of chef's operations (used in wrapping stage)
@ -271,7 +298,10 @@ export function bake(operations){
};
}
/**
* explainExcludedFunction
*
* Explain that the given operation is not included in the Node.js version.
* @param {String} name - name of operation
*/

View File

@ -6,24 +6,61 @@
* @license Apache-2.0
*/
/**
* someName => Somename
*
* @param {String} str = string to be altered
* @returns {String}
*/
const capitalise = function capitalise(str) {
// Don't edit names that start with 2+ caps
if (/^[A-Z0-9]{2,}/g.test(str)) {
return str;
}
// reserved. Don't change for now.
if (str === "Return") {
return str;
}
return `${str.charAt(0).toUpperCase()}${str.substr(1).toLowerCase()}`;
};
/**
* SomeName => someName
* @param {String} name - string to be altered
* @returns {String} decapitalised
*/
export function decapitalise(name) {
// Don't decapitalise names that start with 2+ caps
if (/^[A-Z0-9]{2,}/g.test(name)) {
return name;
export function decapitalise(str) {
// Don't decapitalise str that start with 2+ caps
if (/^[A-Z0-9]{2,}/g.test(str)) {
return str;
}
// reserved. Don't change for now.
if (name === "Return") {
return name;
if (str === "Return") {
return str;
}
return `${name.charAt(0).toLowerCase()}${name.substr(1)}`;
return `${str.charAt(0).toLowerCase()}${str.substr(1)}`;
}
/**
* Remove strings surrounded with [] from the given array.
*/
export function removeSubheadingsFromArray(array) {
if (Array.isArray(array)) {
return array.filter((i) => {
if (typeof i === "string") {
return !i.match(/^\[[\s\S]*\]$/);
}
return true;
});
}
}
/**
* Remove spaces, make lower case.
* @param str
@ -31,3 +68,22 @@ export function decapitalise(name) {
export function sanitise(str) {
return str.replace(/ /g, "").toLowerCase();
}
/**
* sonething like this => somethingLikeThis
* ABC a sentence => ABCASentence
*/
export function sentenceToCamelCase(str) {
return str.split(" ")
.map((s, index) => {
if (index === 0) {
return decapitalise(s);
}
return capitalise(s);
})
.reduce((prev, curr) => `${prev}${curr}`, "");
}

View File

@ -383,6 +383,26 @@ TestRegister.addApiTests([
assert.strictEqual(e.type, "ExcludedOperationError");
assert.strictEqual(e.message, "Sorry, the RenderImage operation is not available in the Node.js version of CyberChef.");
}
}),
it("Operation arguments: should be accessible from operation object if op has array arg", () => {
assert.ok(chef.toCharcode.argOptions);
assert.equal(chef.unzip.argOptions, undefined);
}),
it("Operation arguments: should have key for each array-based argument in operation", () => {
assert.ok(chef.convertDistance.argOptions.inputUnits);
assert.ok(chef.convertDistance.argOptions.outputUnits);
assert.ok(chef.bitShiftRight.argOptions.type);
// is a number type, so not included.
assert.equal(chef.bitShiftRight.argOptions.amount, undefined);
}),
it("Operation arguments: should list all options excluding subheadings", () => {
// First element (subheading) removed
assert.equal(chef.convertDistance.argOptions.inputUnits[0], "Nanometres (nm)");
assert.equal(chef.defangURL.argOptions.process[1], "Only full URLs");
})
]);