Forráskód Böngészése

Merge branch 'arg-options' into node-lib

d98762625 6 éve
szülő
commit
3efe9309ef
3 módosított fájl, 121 hozzáadás és 15 törlés
  1. 38 8
      src/node/api.mjs
  2. 63 7
      src/node/apiUtils.mjs
  3. 20 0
      test/tests/nodeApi/nodeApi.mjs

+ 38 - 8
src/node/api.mjs

@@ -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
  */

+ 63 - 7
src/node/apiUtils.mjs

@@ -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}`, "");
+}
+
+
+

+ 20 - 0
test/tests/nodeApi/nodeApi.mjs

@@ -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");
     })
 
 ]);