diff --git a/package.json b/package.json
index 8b234479..194665af 100644
--- a/package.json
+++ b/package.json
@@ -72,6 +72,7 @@
"jquery": "^3.1.1",
"jsbn": "^1.1.0",
"jsrsasign": "^7.1.0",
+ "lodash": "^4.17.4",
"moment": "^2.17.1",
"moment-timezone": "^0.5.11",
"sladex-blowfish": "^0.8.1",
diff --git a/src/core/config/Categories.js b/src/core/config/Categories.js
index da0c9f0a..1de8ba50 100755
--- a/src/core/config/Categories.js
+++ b/src/core/config/Categories.js
@@ -271,6 +271,9 @@ const Categories = [
"CSS selector",
"Strip HTML tags",
"Diff",
+ "To Snake case",
+ "To Camel case",
+ "To Kebab case",
]
},
{
diff --git a/src/core/config/OperationConfig.js b/src/core/config/OperationConfig.js
index ca6bdbbd..c4276465 100755
--- a/src/core/config/OperationConfig.js
+++ b/src/core/config/OperationConfig.js
@@ -3249,6 +3249,69 @@ const OperationConfig = {
},
]
},
+ "To Snake case": {
+ description: [
+ "Converts the input string to snake case.",
+ "
",
+ "Snake case is all lower case with underscores as word boundaries.",
+ "
",
+ "e.g. this_is_snake_case",
+ "
",
+ "'Attempt to be context aware' will make the operation attempt to nicely transform variable and function names.",
+ ].join("\n"),
+ run: Code.runToSnakeCase,
+ inputType: "string",
+ outputType: "string",
+ args: [
+ {
+ name: "Attempt to be context aware",
+ type: "boolean",
+ value: false,
+ },
+ ]
+ },
+ "To Camel case": {
+ description: [
+ "Converts the input string to camel case.",
+ "
",
+ "Camel case is all lower case except letters after word boundaries which are uppercase.",
+ "
",
+ "e.g. thisIsCamelCase",
+ "
",
+ "'Attempt to be context aware' will make the operation attempt to nicely transform variable and function names.",
+ ].join("\n"),
+ run: Code.runToCamelCase,
+ inputType: "string",
+ outputType: "string",
+ args: [
+ {
+ name: "Attempt to be context aware",
+ type: "boolean",
+ value: false,
+ },
+ ]
+ },
+ "To Kebab case": {
+ description: [
+ "Converts the input string to kebab case.",
+ "
",
+ "Kebab case is all lower case with dashes as word boundaries.",
+ "
",
+ "e.g. this-is-kebab-case",
+ "
",
+ "'Attempt to be context aware' will make the operation attempt to nicely transform variable and function names.",
+ ].join("\n"),
+ run: Code.runToKebabCase,
+ inputType: "string",
+ outputType: "string",
+ args: [
+ {
+ name: "Attempt to be context aware",
+ type: "boolean",
+ value: false,
+ },
+ ]
+ },
};
export default OperationConfig;
diff --git a/src/core/operations/Code.js b/src/core/operations/Code.js
index 613c6b42..7d59b4b0 100755
--- a/src/core/operations/Code.js
+++ b/src/core/operations/Code.js
@@ -1,3 +1,5 @@
+import {camelCase, kebabCase, snakeCase} from "lodash";
+
import Utils from "../Utils.js";
import vkbeautify from "vkbeautify";
import {DOMParser as dom} from "xmldom";
@@ -415,6 +417,84 @@ const Code = {
.join(delimiter);
},
+ /**
+ * This tries to rename variable names in a code snippet according to a function.
+ *
+ * @param {string} input
+ * @param {function} replacer - this function will be fed the token which should be renamed.
+ * @returns {string}
+ */
+ _replaceVariableNames(input, replacer) {
+ let tokenRegex = /\\"|"(?:\\"|[^"])*"|(\b[a-z0-9\-_]+\b)/ig;
+
+ return input.replace(tokenRegex, (...args) => {
+ let match = args[0],
+ quotes = args[1];
+
+ if (!quotes) {
+ return match;
+ } else {
+ return replacer(match);
+ }
+ });
+ },
+
+
+ /**
+ * Converts to snake_case.
+ *
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {string}
+ *
+ */
+ runToSnakeCase(input, args) {
+ let smart = args[0];
+
+ if (smart) {
+ return Code._replaceVariableNames(input, snakeCase);
+ } else {
+ return snakeCase(input);
+ }
+ },
+
+
+ /**
+ * Converts to camelCase.
+ *
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {string}
+ *
+ */
+ runToCamelCase(input, args) {
+ let smart = args[0];
+
+ if (smart) {
+ return Code._replaceVariableNames(input, camelCase);
+ } else {
+ return camelCase(input);
+ }
+ },
+
+
+ /**
+ * Converts to kebab-case.
+ *
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {string}
+ *
+ */
+ runToKebabCase(input, args) {
+ let smart = args[0];
+
+ if (smart) {
+ return Code._replaceVariableNames(input, kebabCase);
+ } else {
+ return kebabCase(input);
+ }
+ },
};
export default Code;
diff --git a/src/core/operations/StrUtils.js b/src/core/operations/StrUtils.js
index 00d2c561..54f82282 100755
--- a/src/core/operations/StrUtils.js
+++ b/src/core/operations/StrUtils.js
@@ -592,7 +592,6 @@ const StrUtils = {
return output;
},
-
};
export default StrUtils;
diff --git a/test/index.js b/test/index.js
index 13d82b10..5f82a727 100644
--- a/test/index.js
+++ b/test/index.js
@@ -13,6 +13,7 @@ import "babel-polyfill";
import TestRegister from "./TestRegister.js";
import "./tests/operations/Base58.js";
import "./tests/operations/ByteRepr.js";
+import "./tests/operations/Code.js";
import "./tests/operations/Compress.js";
import "./tests/operations/FlowControl.js";
import "./tests/operations/MorseCode.js";
diff --git a/test/tests/operations/Code.js b/test/tests/operations/Code.js
new file mode 100644
index 00000000..5f6a4329
--- /dev/null
+++ b/test/tests/operations/Code.js
@@ -0,0 +1,132 @@
+/**
+ * Code tests.
+ *
+ * @author tlwr [toby@toby.codes]
+ *
+ * @copyright Crown Copyright 2017
+ * @license Apache-2.0
+ */
+import TestRegister from "../../TestRegister.js";
+
+TestRegister.addTests([
+ {
+ name: "To Camel case (dumb)",
+ input: "hello world",
+ expectedOutput: "helloWorld",
+ recipeConfig: [
+ {
+ "op": "To Camel case",
+ "args": [false]
+ }
+ ],
+ },
+ {
+ name: "To Snake case (dumb)",
+ input: "hello world",
+ expectedOutput: "hello_world",
+ recipeConfig: [
+ {
+ "op": "To Snake case",
+ "args": [false]
+ }
+ ],
+ },
+ {
+ name: "To Kebab case (dumb)",
+ input: "hello world",
+ expectedOutput: "hello-world",
+ recipeConfig: [
+ {
+ "op": "To Kebab case",
+ "args": [false]
+ }
+ ],
+ },
+ {
+ name: "To Camel case (smart)",
+ input: [
+ "test='hello'",
+ "echo $test",
+ "a_camel_case_function",
+ "$a_camel_case_variable;",
+ "function function_name() {",
+ " console.log('things inside quotes do not get broken');",
+ " console.log(\"things inside quotes do not get broken\");",
+ "}",
+ ].join("\n"),
+ expectedOutput: [
+ "test='hello'",
+ "echo $test",
+ "aCamelCaseFunction",
+ "$aCamelCaseVariable;",
+ "function functionName() {",
+ " console.log('things inside quotes do not get broken');",
+ " console.log(\"things inside quotes do not get broken\");",
+ "}",
+ ].join("\n"),
+ recipeConfig: [
+ {
+ "op": "To Camel case",
+ "args": [true]
+ }
+ ],
+ },
+ {
+ name: "To Snake case (smart)",
+ input: [
+ "test='hello'",
+ "echo $test",
+ "aSnakeCaseFunction",
+ "$aSnakeCaseVariable;",
+ "function functionName() {",
+ " console.log('things inside quotes do not get broken');",
+ " console.log(\"things inside quotes do not get broken\");",
+ "}",
+ ].join("\n"),
+ expectedOutput: [
+ "test='hello'",
+ "echo $test",
+ "a_snake_case_function",
+ "$a_snake_case_variable;",
+ "function function_name() {",
+ " console.log('things inside quotes do not get broken');",
+ " console.log(\"things inside quotes do not get broken\");",
+ "}",
+ ].join("\n"),
+ recipeConfig: [
+ {
+ "op": "To Snake case",
+ "args": [true]
+ }
+ ],
+ },
+ {
+ name: "To Kebab case (smart)",
+ input: [
+ "test='hello'",
+ "echo $test",
+ "aKebabCaseFunction",
+ "$aKebabCaseVariable;",
+ "function functionName() {",
+ " console.log('things inside quotes do not get broken');",
+ " console.log(\"things inside quotes do not get broken\");",
+ "}",
+ ].join("\n"),
+ expectedOutput: [
+ "test='hello'",
+ "echo $test",
+ "a-kebab-case-function",
+ "$a-kebab-case-variable;",
+ "function function-name() {",
+ " console.log('things inside quotes do not get broken');",
+ " console.log(\"things inside quotes do not get broken\");",
+ "}",
+ ].join("\n"),
+ recipeConfig: [
+ {
+ "op": "To Kebab case",
+ "args": [true]
+ }
+ ],
+ },
+]);