diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index 3404dc6d..dd6918dc 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -304,6 +304,7 @@ "Diff", "Remove whitespace", "Remove null bytes", + "Remove ANSI Escape Codes", "To Upper case", "To Lower case", "Swap case", diff --git a/src/core/operations/RemoveANSIEscapeCodes.mjs b/src/core/operations/RemoveANSIEscapeCodes.mjs new file mode 100644 index 00000000..2301f852 --- /dev/null +++ b/src/core/operations/RemoveANSIEscapeCodes.mjs @@ -0,0 +1,41 @@ +/** + * @author Louis-Ladd [lewisharshman1@gmail.com] + * @copyright Crown Copyright 2025 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; + +/** + * Remove ANSI Escape Codes operation + */ +class RemoveANSIEscapeCodes extends Operation { + + /** + * RemoveANSIEscapeCodes constructor + */ + constructor() { + super(); + + this.name = "Remove ANSI Escape Codes"; + this.module = "Default"; + this.description = "Removes ANSI Escape Codes."; + this.infoURL = "https://wikipedia.org/wiki/ANSI_escape_code"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const ansiRegex = /\x1B\[[0-?]*[ -/]*[@-~]/g; + return input.replace(ansiRegex, ""); + } + +} + +export default RemoveANSIEscapeCodes; diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index c12c2710..c44270fd 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -148,6 +148,7 @@ import "./tests/Rabbit.mjs"; import "./tests/RAKE.mjs"; import "./tests/Regex.mjs"; import "./tests/Register.mjs"; +import "./tests/RemoveANSIEscapeCodes.mjs"; import "./tests/RegularExpression.mjs"; import "./tests/RenderMarkdown.mjs"; import "./tests/RisonEncodeDecode.mjs"; diff --git a/tests/operations/tests/RemoveANSIEscapeCodes.mjs b/tests/operations/tests/RemoveANSIEscapeCodes.mjs new file mode 100644 index 00000000..491795c3 --- /dev/null +++ b/tests/operations/tests/RemoveANSIEscapeCodes.mjs @@ -0,0 +1,62 @@ +/** + * @author Louis-Ladd [lewisharshman1@gmail.com] + * @copyright Crown Copyright 2025 + * @license Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + "name": "Remove ANSI Escape Codes: text using x1b escape code", + "input": "\x1b[31mHello, \x1b[31mWorld!", + "expectedOutput": "Hello, World!", + "recipeConfig": [ + { + "op": "Remove ANSI Escape Codes", + "args": [], + }, + ], + }, + { + "name": "Remove ANSI Escape Codes: text with incomplete codes", + "input": "\x1b[31 Hello, World!", + "expectedOutput": "ello, World!", + "recipeConfig": [ + { + "op": "Remove ANSI Escape Codes", + "args": [], + }, + ], + }, + { + "name": "Remove ANSI Escape Codes: cursor commands and clear screen", + "input": "\x1b[2J\x1b[H\x1b[3BHello, World!", + "expectedOutput": "Hello, World!", + "recipeConfig": [ + { + "op": "Remove ANSI Escape Codes", + "args": [], + }, + ], + }, + { + "name": "Remove ANSI Escape Codes: text containing javascript escape representation of ansi escape codes", + // input/output expressed in hex to avoid accidental interpretation of Javascript escapes and to make the test case explicit + "input": "5c 30 33 33 5b 33 32 3b 31 3b 33 3b 34 3b 39 6d 48 65 6c 6c 6f 2c 20 5c 30 33 33 5b 33 32 3b 31 3b 33 3b 34 3b 39 6d 57 6f 72 6c 64 21", + "expectedOutput": "5c 30 33 33 5b 33 32 3b 31 3b 33 3b 34 3b 39 6d 48 65 6c 6c 6f 2c 20 5c 30 33 33 5b 33 32 3b 31 3b 33 3b 34 3b 39 6d 57 6f 72 6c 64 21", + "recipeConfig": [ + { + "op": "From Hex", + "args": ["Auto"] + }, + { + "op": "Remove ANSI Escape Codes", + "args": [] + }, + { + "op": "To Hex", + "args": ["Space", 0] + } + ], + }, +]);